xref: /aosp_15_r20/external/pigweed/pw_rpc/fake_channel_output.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker // Copyright 2021 The Pigweed Authors
2*61c4878aSAndroid Build Coastguard Worker //
3*61c4878aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4*61c4878aSAndroid Build Coastguard Worker // use this file except in compliance with the License. You may obtain a copy of
5*61c4878aSAndroid Build Coastguard Worker // the License at
6*61c4878aSAndroid Build Coastguard Worker //
7*61c4878aSAndroid Build Coastguard Worker //     https://www.apache.org/licenses/LICENSE-2.0
8*61c4878aSAndroid Build Coastguard Worker //
9*61c4878aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*61c4878aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11*61c4878aSAndroid Build Coastguard Worker // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12*61c4878aSAndroid Build Coastguard Worker // License for the specific language governing permissions and limitations under
13*61c4878aSAndroid Build Coastguard Worker // the License.
14*61c4878aSAndroid Build Coastguard Worker 
15*61c4878aSAndroid Build Coastguard Worker // clang-format off
16*61c4878aSAndroid Build Coastguard Worker #include "pw_rpc/internal/log_config.h"  // PW_LOG_* macros must be first.
17*61c4878aSAndroid Build Coastguard Worker 
18*61c4878aSAndroid Build Coastguard Worker #include "pw_rpc/internal/fake_channel_output.h"
19*61c4878aSAndroid Build Coastguard Worker // clang-format on
20*61c4878aSAndroid Build Coastguard Worker 
21*61c4878aSAndroid Build Coastguard Worker #include "pw_assert/check.h"
22*61c4878aSAndroid Build Coastguard Worker #include "pw_log/log.h"
23*61c4878aSAndroid Build Coastguard Worker #include "pw_result/result.h"
24*61c4878aSAndroid Build Coastguard Worker #include "pw_rpc/internal/packet.h"
25*61c4878aSAndroid Build Coastguard Worker 
26*61c4878aSAndroid Build Coastguard Worker namespace pw::rpc::internal::test {
27*61c4878aSAndroid Build Coastguard Worker 
clear()28*61c4878aSAndroid Build Coastguard Worker void FakeChannelOutput::clear() {
29*61c4878aSAndroid Build Coastguard Worker   std::lock_guard lock(mutex_);
30*61c4878aSAndroid Build Coastguard Worker   payloads_.clear();
31*61c4878aSAndroid Build Coastguard Worker   packets_.clear();
32*61c4878aSAndroid Build Coastguard Worker   send_status_ = OkStatus();
33*61c4878aSAndroid Build Coastguard Worker   return_after_packet_count_ = -1;
34*61c4878aSAndroid Build Coastguard Worker }
35*61c4878aSAndroid Build Coastguard Worker 
HandlePacket(span<const std::byte> buffer)36*61c4878aSAndroid Build Coastguard Worker Status FakeChannelOutput::HandlePacket(span<const std::byte> buffer) {
37*61c4878aSAndroid Build Coastguard Worker   // If the buffer is empty, this is just releasing an unused buffer.
38*61c4878aSAndroid Build Coastguard Worker   if (buffer.empty()) {
39*61c4878aSAndroid Build Coastguard Worker     return OkStatus();
40*61c4878aSAndroid Build Coastguard Worker   }
41*61c4878aSAndroid Build Coastguard Worker 
42*61c4878aSAndroid Build Coastguard Worker   if (return_after_packet_count_ == 0) {
43*61c4878aSAndroid Build Coastguard Worker     return send_status_;
44*61c4878aSAndroid Build Coastguard Worker   }
45*61c4878aSAndroid Build Coastguard Worker   if (return_after_packet_count_ > 0 &&
46*61c4878aSAndroid Build Coastguard Worker       return_after_packet_count_ == static_cast<int>(packets_.size())) {
47*61c4878aSAndroid Build Coastguard Worker     // Disable behavior.
48*61c4878aSAndroid Build Coastguard Worker     return_after_packet_count_ = -1;
49*61c4878aSAndroid Build Coastguard Worker     return send_status_;
50*61c4878aSAndroid Build Coastguard Worker   }
51*61c4878aSAndroid Build Coastguard Worker 
52*61c4878aSAndroid Build Coastguard Worker   Result<Packet> result = Packet::FromBuffer(buffer);
53*61c4878aSAndroid Build Coastguard Worker   PW_CHECK_OK(result.status());
54*61c4878aSAndroid Build Coastguard Worker 
55*61c4878aSAndroid Build Coastguard Worker   PW_CHECK(!packets_.full(),
56*61c4878aSAndroid Build Coastguard Worker            "Attempted to store more than %u packets. Increase the kMaxPackets "
57*61c4878aSAndroid Build Coastguard Worker            "template arg to store more packets.",
58*61c4878aSAndroid Build Coastguard Worker            static_cast<unsigned>(packets_.size()));
59*61c4878aSAndroid Build Coastguard Worker 
60*61c4878aSAndroid Build Coastguard Worker   packets_.push_back(*result);
61*61c4878aSAndroid Build Coastguard Worker   Packet& packet = packets_.back();
62*61c4878aSAndroid Build Coastguard Worker 
63*61c4878aSAndroid Build Coastguard Worker   CopyPayloadToBuffer(packet);
64*61c4878aSAndroid Build Coastguard Worker 
65*61c4878aSAndroid Build Coastguard Worker   switch (packet.type()) {
66*61c4878aSAndroid Build Coastguard Worker     case pwpb::PacketType::REQUEST:
67*61c4878aSAndroid Build Coastguard Worker       return OkStatus();
68*61c4878aSAndroid Build Coastguard Worker     case pwpb::PacketType::RESPONSE:
69*61c4878aSAndroid Build Coastguard Worker       total_response_packets_ += 1;
70*61c4878aSAndroid Build Coastguard Worker       return OkStatus();
71*61c4878aSAndroid Build Coastguard Worker     case pwpb::PacketType::CLIENT_STREAM:
72*61c4878aSAndroid Build Coastguard Worker       return OkStatus();
73*61c4878aSAndroid Build Coastguard Worker     case pwpb::PacketType::CLIENT_ERROR:
74*61c4878aSAndroid Build Coastguard Worker       PW_LOG_WARN("FakeChannelOutput received client error: %s",
75*61c4878aSAndroid Build Coastguard Worker                   packet.status().str());
76*61c4878aSAndroid Build Coastguard Worker       return OkStatus();
77*61c4878aSAndroid Build Coastguard Worker     case pwpb::PacketType::SERVER_ERROR:
78*61c4878aSAndroid Build Coastguard Worker       PW_LOG_WARN("FakeChannelOutput received server error: %s",
79*61c4878aSAndroid Build Coastguard Worker                   packet.status().str());
80*61c4878aSAndroid Build Coastguard Worker       return OkStatus();
81*61c4878aSAndroid Build Coastguard Worker     case pwpb::PacketType::SERVER_STREAM:
82*61c4878aSAndroid Build Coastguard Worker     case pwpb::PacketType::CLIENT_REQUEST_COMPLETION:
83*61c4878aSAndroid Build Coastguard Worker       return OkStatus();
84*61c4878aSAndroid Build Coastguard Worker   }
85*61c4878aSAndroid Build Coastguard Worker   PW_CRASH("Unhandled PacketType %d", static_cast<int>(result.value().type()));
86*61c4878aSAndroid Build Coastguard Worker }
87*61c4878aSAndroid Build Coastguard Worker 
CopyPayloadToBuffer(Packet & packet)88*61c4878aSAndroid Build Coastguard Worker void FakeChannelOutput::CopyPayloadToBuffer(Packet& packet) {
89*61c4878aSAndroid Build Coastguard Worker   const ConstByteSpan& payload = packet.payload();
90*61c4878aSAndroid Build Coastguard Worker   if (payload.empty()) {
91*61c4878aSAndroid Build Coastguard Worker     return;
92*61c4878aSAndroid Build Coastguard Worker   }
93*61c4878aSAndroid Build Coastguard Worker 
94*61c4878aSAndroid Build Coastguard Worker   const size_t available_bytes = payloads_.max_size() - payloads_.size();
95*61c4878aSAndroid Build Coastguard Worker   PW_CHECK_UINT_GE(available_bytes,
96*61c4878aSAndroid Build Coastguard Worker                    payload.size(),
97*61c4878aSAndroid Build Coastguard Worker                    "Ran out of payload buffer space. Increase "
98*61c4878aSAndroid Build Coastguard Worker                    "kPayloadBufferSizeBytes (%u) or use smaller payloads.",
99*61c4878aSAndroid Build Coastguard Worker                    static_cast<unsigned>(payloads_.max_size()));
100*61c4878aSAndroid Build Coastguard Worker 
101*61c4878aSAndroid Build Coastguard Worker   const size_t start = payloads_.size();
102*61c4878aSAndroid Build Coastguard Worker   payloads_.resize(payloads_.size() + payload.size());
103*61c4878aSAndroid Build Coastguard Worker   std::memcpy(&payloads_[start], payload.data(), payload.size());
104*61c4878aSAndroid Build Coastguard Worker   packet.set_payload(span(&payloads_[start], payload.size()));
105*61c4878aSAndroid Build Coastguard Worker }
106*61c4878aSAndroid Build Coastguard Worker 
LogPackets() const107*61c4878aSAndroid Build Coastguard Worker void FakeChannelOutput::LogPackets() const {
108*61c4878aSAndroid Build Coastguard Worker   std::lock_guard lock(mutex_);
109*61c4878aSAndroid Build Coastguard Worker 
110*61c4878aSAndroid Build Coastguard Worker   PW_LOG_INFO("%u packets have been sent through this FakeChannelOutput",
111*61c4878aSAndroid Build Coastguard Worker               static_cast<unsigned>(packets_.size()));
112*61c4878aSAndroid Build Coastguard Worker 
113*61c4878aSAndroid Build Coastguard Worker   for (unsigned i = 0; i < packets_.size(); ++i) {
114*61c4878aSAndroid Build Coastguard Worker     PW_LOG_INFO("[packet %u/%u]", i + 1, unsigned(packets_.size()));
115*61c4878aSAndroid Build Coastguard Worker     PW_LOG_INFO("        type: %u", unsigned(packets_[i].type()));
116*61c4878aSAndroid Build Coastguard Worker     PW_LOG_INFO("  channel_id: %u", unsigned(packets_[i].channel_id()));
117*61c4878aSAndroid Build Coastguard Worker     PW_LOG_INFO("  service_id: %08x", unsigned(packets_[i].service_id()));
118*61c4878aSAndroid Build Coastguard Worker     PW_LOG_INFO("   method_id: %08x", unsigned(packets_[i].method_id()));
119*61c4878aSAndroid Build Coastguard Worker     PW_LOG_INFO("     call_id: %u", unsigned(packets_[i].call_id()));
120*61c4878aSAndroid Build Coastguard Worker     PW_LOG_INFO("      status: %s", packets_[i].status().str());
121*61c4878aSAndroid Build Coastguard Worker     PW_LOG_INFO("     payload: %u B", unsigned(packets_[i].payload().size()));
122*61c4878aSAndroid Build Coastguard Worker   }
123*61c4878aSAndroid Build Coastguard Worker }
124*61c4878aSAndroid Build Coastguard Worker 
125*61c4878aSAndroid Build Coastguard Worker }  // namespace pw::rpc::internal::test
126