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 <cinttypes> 17 18 #include "pw_assert/assert.h" 19 #include "pw_rpc/internal/client_server_testing.h" 20 #include "pw_rpc/pwpb/fake_channel_output.h" 21 22 namespace pw::rpc { 23 namespace internal { 24 25 template <size_t kOutputSize, 26 size_t kMaxPackets, 27 size_t kPayloadsBufferSizeBytes> 28 class PwpbForwardingChannelOutput final 29 : public ForwardingChannelOutput< 30 PwpbFakeChannelOutput<kMaxPackets, kPayloadsBufferSizeBytes>, 31 kOutputSize, 32 kMaxPackets, 33 kPayloadsBufferSizeBytes> { 34 private: 35 template <auto kMethod> 36 using MethodInfo = internal::MethodInfo<kMethod>; 37 template <auto kMethod> 38 using Response = typename MethodInfo<kMethod>::Response; 39 template <auto kMethod> 40 using Request = typename MethodInfo<kMethod>::Request; 41 42 using Base = ForwardingChannelOutput< 43 PwpbFakeChannelOutput<kMaxPackets, kPayloadsBufferSizeBytes>, 44 kOutputSize, 45 kMaxPackets, 46 kPayloadsBufferSizeBytes>; 47 48 public: 49 explicit PwpbForwardingChannelOutput( 50 TestPacketProcessor&& server_packet_processor = nullptr, 51 TestPacketProcessor&& client_packet_processor = nullptr) Base(std::move (server_packet_processor),std::move (client_packet_processor))52 : Base(std::move(server_packet_processor), 53 std::move(client_packet_processor)) {} 54 55 template <auto kMethod> response(uint32_t channel_id,uint32_t index)56 Response<kMethod> response(uint32_t channel_id, uint32_t index) { 57 PW_ASSERT(Base::PacketCount() >= index); 58 return Base::output_.template responses<kMethod>(channel_id)[index]; 59 } 60 61 template <auto kMethod> response(uint32_t channel_id,uint32_t index,Response<kMethod> & response)62 void response(uint32_t channel_id, 63 uint32_t index, 64 Response<kMethod>& response) { 65 PW_ASSERT(Base::PacketCount() >= index); 66 auto payloads_view = Base::output_.template responses<kMethod>(channel_id); 67 PW_ASSERT(payloads_view.serde() 68 .Decode(payloads_view.payloads()[index], response) 69 .ok()); 70 } 71 72 template <auto kMethod> request(uint32_t channel_id,uint32_t index)73 Request<kMethod> request(uint32_t channel_id, uint32_t index) { 74 PW_ASSERT(Base::PacketCount() >= index); 75 return Base::output_.template requests<kMethod>(channel_id)[index]; 76 } 77 }; 78 79 } // namespace internal 80 81 template <size_t kOutputSize = 128, 82 size_t kMaxPackets = 16, 83 size_t kPayloadsBufferSizeBytes = 128> 84 class PwpbClientServerTestContext final 85 : public internal::ClientServerTestContext< 86 internal::PwpbForwardingChannelOutput<kOutputSize, 87 kMaxPackets, 88 kPayloadsBufferSizeBytes>, 89 kOutputSize, 90 kMaxPackets, 91 kPayloadsBufferSizeBytes> { 92 private: 93 template <auto kMethod> 94 using MethodInfo = internal::MethodInfo<kMethod>; 95 template <auto kMethod> 96 using Response = typename MethodInfo<kMethod>::Response; 97 template <auto kMethod> 98 using Request = typename MethodInfo<kMethod>::Request; 99 100 using Base = internal::ClientServerTestContext< 101 internal::PwpbForwardingChannelOutput<kOutputSize, 102 kMaxPackets, 103 kPayloadsBufferSizeBytes>, 104 kOutputSize, 105 kMaxPackets, 106 kPayloadsBufferSizeBytes>; 107 108 public: 109 PwpbClientServerTestContext( 110 TestPacketProcessor&& server_packet_processor = nullptr, 111 TestPacketProcessor&& client_packet_processor = nullptr) Base(std::move (server_packet_processor),std::move (client_packet_processor))112 : Base(std::move(server_packet_processor), 113 std::move(client_packet_processor)) {} 114 115 // Retrieve copy of request indexed by order of occurance 116 template <auto kMethod> request(uint32_t index)117 Request<kMethod> request(uint32_t index) { 118 return Base::channel_output_.template request<kMethod>(Base::channel().id(), 119 index); 120 } 121 122 // Retrieve copy of response indexed by order of occurance 123 template <auto kMethod> response(uint32_t index)124 Response<kMethod> response(uint32_t index) { 125 return Base::channel_output_.template response<kMethod>( 126 Base::channel().id(), index); 127 } 128 129 // Gives access to the RPC's indexed by order of occurance using passed 130 // Response object to parse using pw_protobuf. Use this version when you need 131 // to set callback fields in the Response object before parsing. 132 template <auto kMethod> response(uint32_t index,Response<kMethod> & response)133 void response(uint32_t index, Response<kMethod>& response) { 134 return Base::channel_output_.template response<kMethod>( 135 Base::channel().id(), index, response); 136 } 137 }; 138 139 } // namespace pw::rpc 140