xref: /aosp_15_r20/external/pigweed/pw_rpc/public/pw_rpc/integration_testing.h (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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 <cstdint>
17 
18 #include "pw_function/function.h"
19 #include "pw_rpc/client.h"
20 #include "pw_status/status.h"
21 
22 namespace pw::rpc::integration_test {
23 
24 // The RPC channel for integration test RPCs.
25 inline constexpr uint32_t kChannelId = 1;
26 
27 // An injectable pipe interface that may manipulate packets before they're sent
28 // to the final destination.
29 //
30 // ``ChannelManipulator``s allow application-specific packet handling to be
31 // injected into the packet processing pipeline for an ingress or egress
32 // channel-like pathway. This is particularly useful for integration testing
33 // resilience to things like packet loss on a usually-reliable transport. RPC
34 // server integrations may provide an opportunity to inject a
35 // ``ChannelManipulator`` for this use case.
36 //
37 // A ``ChannelManipulator`` should not set send_packet_, as the consumer of a
38 // ``ChannelManipulator`` will use ``send_packet`` to insert the provided
39 // ``ChannelManipulator`` into a packet processing path.
40 class ChannelManipulator {
41  public:
42   // The expected function signature of the send callback used by a
43   // ChannelManipulator to forward packets to the final destination.
44   //
45   // The only argument is a byte span containing the RPC packet that should
46   // be sent.
47   //
48   // Returns:
49   //   OK - Packet successfully sent.
50   //   Other - Failed to send packet.
51   using SendCallback = Function<Status(span<const std::byte>)>;
52 
ChannelManipulator()53   ChannelManipulator()
54       : send_packet_(
55             [](span<const std::byte>) { return Status::Unimplemented(); }) {}
~ChannelManipulator()56   virtual ~ChannelManipulator() {}
57 
58   // Sets the true send callback that a ChannelManipulator will use to forward
59   // packets to the final destination.
60   //
61   // This should not be used by a ChannelManipulator. The consumer of a
62   // ChannelManipulator will set the send callback.
set_send_packet(SendCallback && send)63   void set_send_packet(SendCallback&& send) { send_packet_ = std::move(send); }
64 
65   // Processes an incoming packet before optionally sending it.
66   //
67   // Implementations of this method may send the processed packet, multiple
68   // packets, or no packets at all via the registered `send_packet()`
69   // handler.
70   virtual Status ProcessAndSend(span<const std::byte> packet) = 0;
71 
72  protected:
send_packet(span<const std::byte> payload)73   Status send_packet(span<const std::byte> payload) {
74     return send_packet_(payload);
75   }
76 
77  private:
78   Function<Status(span<const std::byte>)> send_packet_;
79 };
80 
81 void SetEgressChannelManipulator(ChannelManipulator* new_channel_manipulator);
82 
83 void SetIngressChannelManipulator(ChannelManipulator* new_channel_manipulator);
84 
85 // Returns the global RPC client for integration test use.
86 Client& client();
87 
88 // Configure options for the socket associated with the client.
89 int SetClientSockOpt(int level,
90                      int optname,
91                      const void* optval,
92                      unsigned int optlen);
93 
94 // Initializes logging and the global RPC client for integration testing. Starts
95 // a background thread that processes incoming.
96 Status InitializeClient(int argc,
97                         char* argv[],
98                         const char* usage_args = "PORT");
99 
100 Status InitializeClient(int port);
101 
102 // Terminates the client, joining the RPC dispatch thread.
103 void TerminateClient();
104 
105 }  // namespace pw::rpc::integration_test
106