xref: /aosp_15_r20/external/pigweed/pw_rpc/pwpb/public/pw_rpc/pwpb/client_server_testing_threaded.h (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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