• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 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 "gtest/gtest.h"
16 #include "pw_rpc/pwpb/client_server_testing_threaded.h"
17 #include "pw_rpc_test_protos/test.rpc.pwpb.h"
18 #include "pw_sync/binary_semaphore.h"
19 #include "pw_thread/test_threads.h"
20 
21 namespace pw::rpc {
22 namespace {
23 
24 namespace TestRequest = ::pw::rpc::test::pwpb::TestRequest;
25 namespace TestResponse = ::pw::rpc::test::pwpb::TestResponse;
26 namespace TestStreamResponse = ::pw::rpc::test::pwpb::TestStreamResponse;
27 
28 }  // namespace
29 
30 namespace test {
31 
32 using GeneratedService = ::pw::rpc::test::pw_rpc::pwpb::TestService;
33 
34 class TestService final : public GeneratedService::Service<TestService> {
35  public:
TestUnaryRpc(const TestRequest::Message & request,TestResponse::Message & response)36   Status TestUnaryRpc(const TestRequest::Message& request,
37                       TestResponse::Message& response) {
38     response.value = request.integer + 1;
39     return static_cast<Status::Code>(request.status_code);
40   }
41 
TestAnotherUnaryRpc(const TestRequest::Message &,PwpbUnaryResponder<TestResponse::Message> &)42   void TestAnotherUnaryRpc(const TestRequest::Message&,
43                            PwpbUnaryResponder<TestResponse::Message>&) {}
44 
TestServerStreamRpc(const TestRequest::Message &,ServerWriter<TestStreamResponse::Message> &)45   static void TestServerStreamRpc(const TestRequest::Message&,
46                                   ServerWriter<TestStreamResponse::Message>&) {}
47 
TestClientStreamRpc(ServerReader<TestRequest::Message,TestStreamResponse::Message> &)48   void TestClientStreamRpc(
49       ServerReader<TestRequest::Message, TestStreamResponse::Message>&) {}
50 
TestBidirectionalStreamRpc(ServerReaderWriter<TestRequest::Message,TestStreamResponse::Message> &)51   void TestBidirectionalStreamRpc(
52       ServerReaderWriter<TestRequest::Message, TestStreamResponse::Message>&) {}
53 };
54 
55 }  // namespace test
56 
57 namespace {
58 
59 class RpcCaller {
60  public:
BlockOnResponse(uint32_t i,Client & client,uint32_t channel_id)61   void BlockOnResponse(uint32_t i, Client& client, uint32_t channel_id) {
62     TestRequest::Message request{.integer = i,
63                                  .status_code = OkStatus().code()};
64     auto call = test::GeneratedService::TestUnaryRpc(
65         client,
66         channel_id,
67         request,
68         [this](const TestResponse::Message&, Status) { semaphore_.release(); },
69         [](Status) {});
70 
71     semaphore_.acquire();
72   }
73 
74  private:
75   pw::sync::BinarySemaphore semaphore_;
76 };
77 
TEST(PwpbClientServerTestContextThreaded,ReceivesUnaryRpcReponseThreaded)78 TEST(PwpbClientServerTestContextThreaded, ReceivesUnaryRpcReponseThreaded) {
79   PwpbClientServerTestContextThreaded<> ctx(thread::test::TestOptionsThread0());
80   test::TestService service;
81   ctx.server().RegisterService(service);
82 
83   RpcCaller caller;
84   constexpr auto value = 1;
85   caller.BlockOnResponse(value, ctx.client(), ctx.channel().id());
86 
87   const auto request =
88       ctx.request<test::pw_rpc::pwpb::TestService::TestUnaryRpc>(0);
89   const auto response =
90       ctx.response<test::pw_rpc::pwpb::TestService::TestUnaryRpc>(0);
91 
92   EXPECT_EQ(value, request.integer);
93   EXPECT_EQ(value + 1, response.value);
94 }
95 
TEST(PwpbClientServerTestContextThreaded,ReceivesMultipleReponsesThreaded)96 TEST(PwpbClientServerTestContextThreaded, ReceivesMultipleReponsesThreaded) {
97   PwpbClientServerTestContextThreaded<> ctx(thread::test::TestOptionsThread0());
98   test::TestService service;
99   ctx.server().RegisterService(service);
100 
101   RpcCaller caller;
102   constexpr auto value1 = 1;
103   constexpr auto value2 = 2;
104   caller.BlockOnResponse(value1, ctx.client(), ctx.channel().id());
105   caller.BlockOnResponse(value2, ctx.client(), ctx.channel().id());
106 
107   const auto request1 =
108       ctx.request<test::pw_rpc::pwpb::TestService::TestUnaryRpc>(0);
109   const auto request2 =
110       ctx.request<test::pw_rpc::pwpb::TestService::TestUnaryRpc>(1);
111   const auto response1 =
112       ctx.response<test::pw_rpc::pwpb::TestService::TestUnaryRpc>(0);
113   const auto response2 =
114       ctx.response<test::pw_rpc::pwpb::TestService::TestUnaryRpc>(1);
115 
116   EXPECT_EQ(value1, request1.integer);
117   EXPECT_EQ(value2, request2.integer);
118   EXPECT_EQ(value1 + 1, response1.value);
119   EXPECT_EQ(value2 + 1, response2.value);
120 }
121 
122 }  // namespace
123 }  // namespace pw::rpc
124