diff options
Diffstat (limited to 'pw_rpc/public/pw_rpc/internal/client_server_testing.h')
-rw-r--r-- | pw_rpc/public/pw_rpc/internal/client_server_testing.h | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/pw_rpc/public/pw_rpc/internal/client_server_testing.h b/pw_rpc/public/pw_rpc/internal/client_server_testing.h new file mode 100644 index 000000000..01cfd16a3 --- /dev/null +++ b/pw_rpc/public/pw_rpc/internal/client_server_testing.h @@ -0,0 +1,114 @@ +// Copyright 2022 The Pigweed Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +#pragma once + +#include <cinttypes> +#include <mutex> + +#include "pw_rpc/channel.h" +#include "pw_rpc/client_server.h" +#include "pw_rpc/internal/fake_channel_output.h" +#include "pw_rpc/internal/lock.h" +#include "pw_span/span.h" +#include "pw_status/status.h" + +namespace pw::rpc { +namespace internal { + +// Expands on a Fake Channel Output implementation to allow for forwarding of +// packets. +template <typename FakeChannelOutputImpl, + size_t kOutputSize, + size_t kMaxPackets, + size_t kPayloadsBufferSizeBytes> +class ForwardingChannelOutput : public ChannelOutput { + public: + size_t MaximumTransmissionUnit() override { + return output_.MaximumTransmissionUnit(); + } + + Status Send(span<const std::byte> buffer) override { + return output_.Send(buffer); + } + + // Returns true if new packets were available to forward + bool ForwardNextPacket(ClientServer& client_server) { + std::array<std::byte, kOutputSize> packet_buffer; + Result<ConstByteSpan> result = EncodeNextUnsentPacket(packet_buffer); + if (!result.ok()) { + return false; + } + ++sent_packets_; + const auto process_result = client_server.ProcessPacket(*result); + PW_ASSERT(process_result.ok()); + return true; + } + + protected: + constexpr ForwardingChannelOutput() + : ChannelOutput("testing::FakeChannelOutput") {} + + FakeChannelOutputImpl output_; + + // Functions are virtual to allow for their override in threaded version, so + // threading protection can be added. + virtual size_t PacketCount() const { return output_.total_packets(); } + + virtual Result<ConstByteSpan> EncodeNextUnsentPacket( + std::array<std::byte, kPayloadsBufferSizeBytes>& packet_buffer) { + std::lock_guard lock(output_.mutex_); + const auto& packets = output_.packets(); + if (packets.size() <= sent_packets_) { + return Status::NotFound(); + } + return packets[sent_packets_].Encode(packet_buffer); + } + + uint16_t sent_packets_ = 0; +}; + +// Provides a testing context with a real client and server +template <typename ForwardingChannelOutputImpl, + size_t kOutputSize = 128, + size_t kMaxPackets = 16, + size_t kPayloadsBufferSizeBytes = 128> +class ClientServerTestContext { + public: + const pw::rpc::Channel& channel() { return channel_; } + Client& client() { return client_server_.client(); } + Server& server() { return client_server_.server(); } + + // Should be called after each rpc call to synchronously forward all queued + // messages. Otherwise this function can be ignored. + void ForwardNewPackets() { + while (channel_output_.ForwardNextPacket(client_server_)) { + } + } + + protected: + explicit ClientServerTestContext() + : channel_(Channel::Create<1>(&channel_output_)), + client_server_({&channel_, 1}) {} + + ~ClientServerTestContext() = default; + + ForwardingChannelOutputImpl channel_output_; + + private: + pw::rpc::Channel channel_; + ClientServer client_server_; +}; + +} // namespace internal +} // namespace pw::rpc |