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_rpc/internal/client_server_testing.h" 19 #include "pw_rpc/internal/client_server_testing_threaded.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 PwpbWatchableChannelOutput final 29 : public WatchableChannelOutput< 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 = WatchableChannelOutput< 43 PwpbFakeChannelOutput<kMaxPackets, kPayloadsBufferSizeBytes>, 44 kOutputSize, 45 kMaxPackets, 46 kPayloadsBufferSizeBytes>; 47 48 public: 49 explicit PwpbWatchableChannelOutput( 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_LOCKS_EXCLUDED(Base::mutex_) { 58 std::lock_guard lock(Base::mutex_); 59 PW_ASSERT(Base::PacketCount() >= index); 60 return Base::output_.template responses<kMethod>(channel_id)[index]; 61 } 62 63 template <auto kMethod> response(uint32_t channel_id,uint32_t index,Response<kMethod> & response)64 void response(uint32_t channel_id, 65 uint32_t index, 66 Response<kMethod>& response) PW_LOCKS_EXCLUDED(Base::mutex_) { 67 std::lock_guard lock(Base::mutex_); 68 PW_ASSERT(Base::PacketCount() >= index); 69 auto payloads_view = Base::output_.template responses<kMethod>(channel_id); 70 PW_ASSERT(payloads_view.serde() 71 .Decode(payloads_view.payloads()[index], response) 72 .ok()); 73 } 74 75 template <auto kMethod> request(uint32_t channel_id,uint32_t index)76 Request<kMethod> request(uint32_t channel_id, uint32_t index) 77 PW_LOCKS_EXCLUDED(Base::mutex_) { 78 std::lock_guard lock(Base::mutex_); 79 PW_ASSERT(Base::PacketCount() >= index); 80 return Base::output_.template requests<kMethod>(channel_id)[index]; 81 } 82 }; 83 84 } // namespace internal 85 86 template <size_t kOutputSize = 128, 87 size_t kMaxPackets = 16, 88 size_t kPayloadsBufferSizeBytes = 128> 89 class PwpbClientServerTestContextThreaded final 90 : public internal::ClientServerTestContextThreaded< 91 internal::PwpbWatchableChannelOutput<kOutputSize, 92 kMaxPackets, 93 kPayloadsBufferSizeBytes>, 94 kOutputSize, 95 kMaxPackets, 96 kPayloadsBufferSizeBytes> { 97 private: 98 template <auto kMethod> 99 using MethodInfo = internal::MethodInfo<kMethod>; 100 template <auto kMethod> 101 using Response = typename MethodInfo<kMethod>::Response; 102 template <auto kMethod> 103 using Request = typename MethodInfo<kMethod>::Request; 104 105 using Base = internal::ClientServerTestContextThreaded< 106 internal::PwpbWatchableChannelOutput<kOutputSize, 107 kMaxPackets, 108 kPayloadsBufferSizeBytes>, 109 kOutputSize, 110 kMaxPackets, 111 kPayloadsBufferSizeBytes>; 112 113 public: 114 PwpbClientServerTestContextThreaded( 115 const thread::Options& options, 116 TestPacketProcessor&& server_packet_processor = nullptr, 117 TestPacketProcessor&& client_packet_processor = nullptr) Base(options,std::move (server_packet_processor),std::move (client_packet_processor))118 : Base(options, 119 std::move(server_packet_processor), 120 std::move(client_packet_processor)) {} 121 122 // Retrieve copy of request indexed by order of occurance 123 template <auto kMethod> request(uint32_t index)124 Request<kMethod> request(uint32_t index) { 125 return Base::channel_output_.template request<kMethod>(Base::channel().id(), 126 index); 127 } 128 129 // Retrieve copy of resonse indexed by order of occurance 130 template <auto kMethod> response(uint32_t index)131 Response<kMethod> response(uint32_t index) { 132 return Base::channel_output_.template response<kMethod>( 133 Base::channel().id(), index); 134 } 135 136 // Gives access to the RPC's indexed by order of occurance using passed 137 // Response object to parse using pw_protobuf. Use this version when you need 138 // to set callback fields in the Response object before parsing. 139 template <auto kMethod> response(uint32_t index,Response<kMethod> & response)140 void response(uint32_t index, Response<kMethod>& response) { 141 return Base::channel_output_.template response<kMethod>( 142 Base::channel().id(), index, response); 143 } 144 }; 145 146 } // namespace pw::rpc 147