1 // Copyright 2021 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/nanopb/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 Nanopb structs. 31 class NanopbFakeServer : 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 void * payload,ByteSpan buffer)68 static ConstByteSpan EncodeResponse(const void* payload, ByteSpan buffer) { 69 const StatusWithSize result = 70 internal::MethodInfo<kMethod>::serde().response().Encode(payload, 71 buffer); 72 PW_ASSERT(result.ok()); 73 return span(buffer).first(result.size()); 74 } 75 }; 76 77 // Instantiates a NanopbFakeServer, Client, Channel, and NanopbFakeChannelOutput 78 // for testing RPC client calls. These components may be used individually, but 79 // are instantiated together for convenience. 80 template <size_t kMaxPackets = 10, 81 size_t kPacketEncodeBufferSizeBytes = 128, 82 size_t kPayloadsBufferSizeBytes = 256> 83 class NanopbClientTestContext { 84 public: NanopbClientTestContext()85 constexpr NanopbClientTestContext() 86 : channel_(Channel::Create<kDefaultChannelId>(&channel_output_)), 87 client_(span(&channel_, 1)), 88 packet_buffer_{}, 89 fake_server_( 90 channel_output_, client_, kDefaultChannelId, packet_buffer_) {} 91 channel()92 const Channel& channel() const { return channel_; } channel()93 Channel& channel() { return channel_; } 94 server()95 const NanopbFakeServer& server() const { return fake_server_; } server()96 NanopbFakeServer& server() { return fake_server_; } 97 client()98 const Client& client() const { return client_; } client()99 Client& client() { return client_; } 100 output()101 const auto& output() const { return channel_output_; } output()102 auto& output() { return channel_output_; } 103 104 private: 105 static constexpr uint32_t kDefaultChannelId = 1; 106 107 NanopbFakeChannelOutput<kMaxPackets, kPayloadsBufferSizeBytes> 108 channel_output_; 109 Channel channel_; 110 Client client_; 111 std::byte packet_buffer_[kPacketEncodeBufferSizeBytes]; 112 NanopbFakeServer fake_server_; 113 }; 114 115 } // namespace pw::rpc 116