1 // Copyright 2022 The Pigweed Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 // use this file except in compliance with the License. You may obtain a copy of 5 // the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations under 13 // the License. 14 #pragma once 15 16 #include <cstddef> 17 #include <cstdint> 18 19 #include "pw_bytes/span.h" 20 #include "pw_rpc/client.h" 21 #include "pw_rpc/internal/method_info.h" 22 #include "pw_rpc/pwpb/fake_channel_output.h" 23 #include "pw_rpc/raw/client_testing.h" 24 25 namespace pw::rpc { 26 27 // TODO: b/234878467 - Document the client testing APIs. 28 29 // Sends packets to an RPC client as if it were a pw_rpc server. Accepts 30 // payloads as pw_protobuf message structs. 31 class PwpbFakeServer : public FakeServer { 32 private: 33 template <auto kMethod> 34 using Response = typename internal::MethodInfo<kMethod>::Response; 35 36 public: 37 using FakeServer::FakeServer; 38 39 // Sends a response packet for a server or bidirectional streaming RPC to the 40 // client. 41 template <auto kMethod> SendResponse(Status status)42 void SendResponse(Status status) const { 43 FakeServer::SendResponse<kMethod>(status); 44 } 45 46 // Sends a response packet for a unary or client streaming streaming RPC to 47 // the client. 48 template <auto kMethod, 49 size_t kEncodeBufferSizeBytes = 2 * sizeof(Response<kMethod>)> SendResponse(const Response<kMethod> & payload,Status status)50 void SendResponse(const Response<kMethod>& payload, Status status) const { 51 std::byte buffer[kEncodeBufferSizeBytes] = {}; 52 FakeServer::SendResponse<kMethod>(EncodeResponse<kMethod>(payload, buffer), 53 status); 54 } 55 56 // Sends a stream packet for a server or bidirectional streaming RPC to the 57 // client. 58 template <auto kMethod, 59 size_t kEncodeBufferSizeBytes = 2 * sizeof(Response<kMethod>)> SendServerStream(const Response<kMethod> & payload)60 void SendServerStream(const Response<kMethod>& payload) const { 61 std::byte buffer[kEncodeBufferSizeBytes] = {}; 62 FakeServer::SendServerStream<kMethod>( 63 EncodeResponse<kMethod>(payload, buffer)); 64 } 65 66 private: 67 template <auto kMethod> EncodeResponse(const Response<kMethod> & payload,ByteSpan buffer)68 static ConstByteSpan EncodeResponse(const Response<kMethod>& payload, 69 ByteSpan buffer) { 70 const StatusWithSize result = 71 internal::MethodInfo<kMethod>::serde().response().Encode(payload, 72 buffer); 73 PW_ASSERT(result.ok()); 74 return span(buffer).first(result.size()); 75 } 76 }; 77 78 // Instantiates a PwpbFakeServer, Client, Channel, and PwpbFakeChannelOutput 79 // for testing RPC client calls. These components may be used individually, but 80 // are instantiated together for convenience. 81 template <size_t kMaxPackets = 10, 82 size_t kPacketEncodeBufferSizeBytes = 128, 83 size_t kPayloadsBufferSizeBytes = 256> 84 class PwpbClientTestContext { 85 public: PwpbClientTestContext()86 constexpr PwpbClientTestContext() 87 : channel_(Channel::Create<kDefaultChannelId>(&channel_output_)), 88 client_(span(&channel_, 1)), 89 packet_buffer_{}, 90 fake_server_( 91 channel_output_, client_, kDefaultChannelId, packet_buffer_) {} 92 channel()93 const Channel& channel() const { return channel_; } channel()94 Channel& channel() { return channel_; } 95 server()96 const PwpbFakeServer& server() const { return fake_server_; } server()97 PwpbFakeServer& server() { return fake_server_; } 98 client()99 const Client& client() const { return client_; } client()100 Client& client() { return client_; } 101 output()102 const auto& output() const { return channel_output_; } output()103 auto& output() { return channel_output_; } 104 105 private: 106 static constexpr uint32_t kDefaultChannelId = 1; 107 108 PwpbFakeChannelOutput<kMaxPackets, kPayloadsBufferSizeBytes> channel_output_; 109 Channel channel_; 110 Client client_; 111 std::byte packet_buffer_[kPacketEncodeBufferSizeBytes]; 112 PwpbFakeServer fake_server_; 113 }; 114 115 } // namespace pw::rpc 116