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 #include "pw_rpc/client_server.h"
16
17 #include "pw_rpc/internal/packet.h"
18 #include "pw_rpc/internal/test_utils.h"
19 #include "pw_rpc/raw/fake_channel_output.h"
20 #include "pw_rpc/raw/internal/method_union.h"
21 #include "pw_rpc/service.h"
22 #include "pw_unit_test/framework.h"
23
24 namespace pw::rpc::internal {
25 namespace {
26
27 constexpr uint32_t kFakeChannelId = 1;
28 constexpr uint32_t kFakeServiceId = 3;
29 constexpr uint32_t kFakeMethodId = 10;
30 constexpr uint32_t kFakeCallId = 239;
31
32 RawFakeChannelOutput<1> output;
33 rpc::Channel channels[] = {Channel::Create<kFakeChannelId>(&output)};
34
FakeMethod(ConstByteSpan,RawUnaryResponder & responder)35 void FakeMethod(ConstByteSpan, RawUnaryResponder& responder) {
36 ASSERT_EQ(OkStatus(), responder.Finish({}, Status::Unimplemented()));
37 }
38
39 class FakeService : public Service {
40 public:
FakeService(uint32_t id)41 FakeService(uint32_t id) : Service(id, kMethods) {}
42
43 static constexpr std::array<RawMethodUnion, 1> kMethods = {
44 RawMethod::AsynchronousUnary<FakeMethod>(kFakeMethodId),
45 };
46 };
47
48 FakeService service(kFakeServiceId);
49
TEST(ClientServer,ProcessPacket_CallsServer)50 TEST(ClientServer, ProcessPacket_CallsServer) {
51 ClientServer client_server(channels);
52 client_server.server().RegisterService(service);
53
54 Packet packet(pwpb::PacketType::REQUEST,
55 kFakeChannelId,
56 kFakeServiceId,
57 kFakeMethodId,
58 kFakeCallId);
59 std::array<std::byte, 32> buffer;
60 Result result = packet.Encode(buffer);
61 EXPECT_EQ(result.status(), OkStatus());
62
63 EXPECT_EQ(client_server.ProcessPacket(result.value()), OkStatus());
64 }
65
TEST(ClientServer,ProcessPacket_CallsClient)66 TEST(ClientServer, ProcessPacket_CallsClient) {
67 ClientServer client_server(channels);
68 client_server.server().RegisterService(service);
69
70 // Same packet as above, but type RESPONSE will skip the server and call into
71 // the client.
72 Packet packet(pwpb::PacketType::RESPONSE,
73 kFakeChannelId,
74 kFakeServiceId,
75 kFakeMethodId,
76 kFakeCallId);
77 std::array<std::byte, 32> buffer;
78 Result result = packet.Encode(buffer);
79 EXPECT_EQ(result.status(), OkStatus());
80
81 // No calls are registered on the client, so nothing should happen. The
82 // ProcessPacket call still returns OK since the client handled it.
83 EXPECT_EQ(client_server.ProcessPacket(result.value()), OkStatus());
84 }
85
TEST(ClientServer,ProcessPacket_BadData)86 TEST(ClientServer, ProcessPacket_BadData) {
87 ClientServer client_server(channels);
88 EXPECT_EQ(client_server.ProcessPacket({}), Status::DataLoss());
89 }
90
91 } // namespace
92 } // namespace pw::rpc::internal
93