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