Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / third_party / pigweed / repo / pw_rpc / pw_rpc_private / internal_test_utils.h
1 // Copyright 2020 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
15 // Internal-only testing utilities. public/pw_rpc/test_method_context.h provides
16 // improved public-facing utilities for testing RPC services.
17 #pragma once
18
19 #include <array>
20 #include <cstddef>
21 #include <cstdint>
22 #include <span>
23
24 #include "pw_assert/light.h"
25 #include "pw_rpc/client.h"
26 #include "pw_rpc/internal/channel.h"
27 #include "pw_rpc/internal/method.h"
28 #include "pw_rpc/internal/packet.h"
29 #include "pw_rpc/internal/server.h"
30
31 namespace pw::rpc {
32
33 template <size_t output_buffer_size>
34 class TestOutput : public ChannelOutput {
35  public:
36   static constexpr size_t buffer_size() { return output_buffer_size; }
37
38   constexpr TestOutput(const char* name = "TestOutput")
39       : ChannelOutput(name), sent_data_{} {}
40
41   std::span<std::byte> AcquireBuffer() override { return buffer_; }
42
43   Status SendAndReleaseBuffer(std::span<const std::byte> buffer) override {
44     if (buffer.empty()) {
45       return OkStatus();
46     }
47
48     PW_ASSERT(buffer.data() == buffer_.data());
49
50     packet_count_ += 1;
51     sent_data_ = buffer;
52     Result<internal::Packet> result = internal::Packet::FromBuffer(sent_data_);
53     EXPECT_EQ(OkStatus(), result.status());
54     sent_packet_ = result.value_or(internal::Packet());
55     return send_status_;
56   }
57
58   std::span<const std::byte> buffer() const { return buffer_; }
59
60   size_t packet_count() const { return packet_count_; }
61
62   void set_send_status(Status status) { send_status_ = status; }
63
64   const std::span<const std::byte>& sent_data() const { return sent_data_; }
65   const internal::Packet& sent_packet() const {
66     EXPECT_GT(packet_count_, 0u);
67     return sent_packet_;
68   }
69
70  private:
71   std::array<std::byte, buffer_size()> buffer_;
72   std::span<const std::byte> sent_data_;
73   internal::Packet sent_packet_;
74   size_t packet_count_ = 0;
75   Status send_status_;
76 };
77
78 // Version of the internal::Server with extra methods exposed for testing.
79 class TestServer : public internal::Server {
80  public:
81   using internal::Server::writers;
82 };
83
84 template <typename Service,
85           size_t output_buffer_size = 128,
86           uint32_t channel_id = 99,
87           uint32_t service_id = 16>
88 class ServerContextForTest {
89  public:
90   static constexpr uint32_t kChannelId = channel_id;
91   static constexpr uint32_t kServiceId = service_id;
92
93   ServerContextForTest(const internal::Method& method)
94       : channel_(Channel::Create<kChannelId>(&output_)),
95         server_(std::span(&channel_, 1)),
96         service_(kServiceId),
97         context_(static_cast<internal::Server&>(server_),
98                  static_cast<internal::Channel&>(channel_),
99                  service_,
100                  method) {
101     server_.RegisterService(service_);
102   }
103
104   // Creates a response packet for this context's channel, service, and method.
105   internal::Packet packet(std::span<const std::byte> payload) const {
106     return internal::Packet(internal::PacketType::RESPONSE,
107                             kChannelId,
108                             kServiceId,
109                             context_.method().id(),
110                             payload,
111                             OkStatus());
112   }
113
114   internal::ServerCall& get() { return context_; }
115   const auto& output() const { return output_; }
116   TestServer& server() { return static_cast<TestServer&>(server_); }
117
118  private:
119   TestOutput<output_buffer_size> output_;
120   Channel channel_;
121   Server server_;
122   Service service_;
123
124   internal::ServerCall context_;
125 };
126
127 template <size_t output_buffer_size = 128,
128           size_t input_buffer_size = 128,
129           uint32_t channel_id = 99,
130           uint32_t service_id = 16,
131           uint32_t method_id = 111>
132 class ClientContextForTest {
133  public:
134   static constexpr uint32_t kChannelId = channel_id;
135   static constexpr uint32_t kServiceId = service_id;
136   static constexpr uint32_t kMethodId = method_id;
137
138   ClientContextForTest()
139       : channel_(Channel::Create<kChannelId>(&output_)),
140         client_(std::span(&channel_, 1)) {}
141
142   const auto& output() const { return output_; }
143   Channel& channel() { return channel_; }
144   Client& client() { return client_; }
145
146   // Sends a packet to be processed by the client. Returns the client's
147   // ProcessPacket status.
148   Status SendPacket(internal::PacketType type,
149                     Status status = OkStatus(),
150                     std::span<const std::byte> payload = {}) {
151     internal::Packet packet(
152         type, kChannelId, kServiceId, kMethodId, payload, status);
153     std::byte buffer[input_buffer_size];
154     Result result = packet.Encode(buffer);
155     EXPECT_EQ(result.status(), OkStatus());
156     return client_.ProcessPacket(result.value_or(ConstByteSpan()));
157   }
158
159   Status SendResponse(Status status, std::span<const std::byte> payload) {
160     return SendPacket(internal::PacketType::RESPONSE, status, payload);
161   }
162
163  private:
164   TestOutput<output_buffer_size> output_;
165   Channel channel_;
166   Client client_;
167 };
168
169 }  // namespace pw::rpc