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 <cstring> 17 18 #include "pw_bytes/span.h" 19 #include "pw_rpc/internal/call_context.h" 20 #include "pw_rpc/internal/server_call.h" 21 #include "pw_rpc/method_type.h" 22 23 namespace pw::rpc::internal::test { 24 25 // Fake server reader/writer classes for testing use. These also serve as a 26 // model for how the RPC implementations (raw, pwpb, Nanopb) structure their 27 // reader/writer classes. 28 // 29 // Readers/writers use an unusual inheritance hierarchy. Rather than having the 30 // ServerReaderWriter inherit from both the Reader and Writer classes, the 31 // readers and writers inherit from it, but hide the unsupported functionality. 32 // A ReaderWriter defines conversions to Reader and Writer, so it acts as if it 33 // inherited from both. This approach is unusual but necessary to have all 34 // classes use a single IntrusiveList::Item base and to avoid virtual methods or 35 // virtual inheritance. 36 // 37 // Call's public API is intended for rpc::Server, so hide the public methods 38 // with private inheritance. 39 class FakeServerReaderWriter : private ServerCall { 40 public: 41 constexpr FakeServerReaderWriter() = default; 42 43 // On a real reader/writer, this constructor would not be exposed. 44 FakeServerReaderWriter(const LockedCallContext& context, 45 MethodType type = MethodType::kBidirectionalStreaming) PW_EXCLUSIVE_LOCKS_REQUIRED(rpc_lock ())46 PW_EXCLUSIVE_LOCKS_REQUIRED(rpc_lock()) 47 : ServerCall(context, CallProperties(type, kServerCall, kRawProto)) {} 48 49 FakeServerReaderWriter(FakeServerReaderWriter&&) = default; 50 FakeServerReaderWriter& operator=(FakeServerReaderWriter&&) = default; 51 52 // Pull in protected functions from the hidden Call base as needed. 53 // 54 // Note: these functions all acquire `rpc_lock()`. However, the 55 // `PW_LOCKS_EXCLUDED(rpc_lock())` on their original definitions does not 56 // appear to carry through here. 57 using Call::active; 58 using Call::set_on_error; 59 using Call::set_on_next; 60 using ServerCall::set_on_completion_requested; 61 using ServerCall::set_on_completion_requested_if_enabled; 62 63 Status Finish(Status status = OkStatus()) { 64 return CloseAndSendResponse(status); 65 } 66 67 using Call::Write; 68 69 // Expose a few additional methods for test use. as_server_call()70 ServerCall& as_server_call() { return *this; } 71 using Call::channel_id_locked; 72 using Call::DebugLog; 73 using Call::id; 74 using Call::set_id; 75 }; 76 77 class FakeServerWriter : private FakeServerReaderWriter { 78 public: 79 constexpr FakeServerWriter() = default; 80 81 FakeServerWriter(const LockedCallContext& context) PW_EXCLUSIVE_LOCKS_REQUIRED(rpc_lock ())82 PW_EXCLUSIVE_LOCKS_REQUIRED(rpc_lock()) 83 : FakeServerReaderWriter(context, MethodType::kServerStreaming) {} 84 FakeServerWriter(FakeServerWriter&&) = default; 85 FakeServerWriter& operator=(FakeServerWriter&&) = default; 86 87 // Common reader/writer functions. 88 using FakeServerReaderWriter::active; 89 using FakeServerReaderWriter::Finish; 90 using FakeServerReaderWriter::set_on_completion_requested; 91 using FakeServerReaderWriter::set_on_completion_requested_if_enabled; 92 using FakeServerReaderWriter::set_on_error; 93 using FakeServerReaderWriter::Write; 94 95 // Functions for test use. 96 using FakeServerReaderWriter::as_server_call; 97 }; 98 99 class FakeServerReader : private FakeServerReaderWriter { 100 public: 101 constexpr FakeServerReader() = default; 102 103 FakeServerReader(const LockedCallContext& context) PW_EXCLUSIVE_LOCKS_REQUIRED(rpc_lock ())104 PW_EXCLUSIVE_LOCKS_REQUIRED(rpc_lock()) 105 : FakeServerReaderWriter(context, MethodType::kClientStreaming) {} 106 107 FakeServerReader(FakeServerReader&&) = default; 108 FakeServerReader& operator=(FakeServerReader&&) = default; 109 110 using FakeServerReaderWriter::active; 111 using FakeServerReaderWriter::as_server_call; 112 }; 113 114 } // namespace pw::rpc::internal::test 115