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::method_id; 59 using Call::service_id; 60 using Call::set_on_error; 61 using Call::set_on_next; 62 using ServerCall::set_on_completion_requested; 63 using ServerCall::set_on_completion_requested_if_enabled; 64 65 Status Finish(Status status = OkStatus()) { 66 return CloseAndSendResponse(status); 67 } 68 69 using Call::Write; 70 71 // Expose a few additional methods for test use. as_server_call()72 ServerCall& as_server_call() { return *this; } 73 using Call::channel_id_locked; 74 using Call::DebugLog; 75 using Call::id; 76 using Call::set_id; 77 }; 78 79 class FakeServerWriter : private FakeServerReaderWriter { 80 public: 81 constexpr FakeServerWriter() = default; 82 83 FakeServerWriter(const LockedCallContext& context) PW_EXCLUSIVE_LOCKS_REQUIRED(rpc_lock ())84 PW_EXCLUSIVE_LOCKS_REQUIRED(rpc_lock()) 85 : FakeServerReaderWriter(context, MethodType::kServerStreaming) {} 86 FakeServerWriter(FakeServerWriter&&) = default; 87 FakeServerWriter& operator=(FakeServerWriter&&) = default; 88 89 // Common reader/writer functions. 90 using FakeServerReaderWriter::active; 91 using FakeServerReaderWriter::Finish; 92 using FakeServerReaderWriter::set_on_completion_requested; 93 using FakeServerReaderWriter::set_on_completion_requested_if_enabled; 94 using FakeServerReaderWriter::set_on_error; 95 using FakeServerReaderWriter::Write; 96 97 // Functions for test use. 98 using FakeServerReaderWriter::as_server_call; 99 }; 100 101 class FakeServerReader : private FakeServerReaderWriter { 102 public: 103 constexpr FakeServerReader() = default; 104 105 FakeServerReader(const LockedCallContext& context) PW_EXCLUSIVE_LOCKS_REQUIRED(rpc_lock ())106 PW_EXCLUSIVE_LOCKS_REQUIRED(rpc_lock()) 107 : FakeServerReaderWriter(context, MethodType::kClientStreaming) {} 108 109 FakeServerReader(FakeServerReader&&) = default; 110 FakeServerReader& operator=(FakeServerReader&&) = default; 111 112 using FakeServerReaderWriter::active; 113 using FakeServerReaderWriter::as_server_call; 114 }; 115 116 } // namespace pw::rpc::internal::test 117