blob: 6ea4fd45cefd42ee315e1562ba40f2d626be9fbc [file] [log] [blame]
Alexei Frolov7fb63af2020-07-09 17:05:52 -07001// 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 "gtest/gtest.h"
Alexei Frolov15255c52020-07-17 08:25:49 -070016#include "pw_rpc/internal/hash.h"
Wyatt Hepler8aa02922020-07-17 08:54:37 -070017#include "pw_rpc/test_method_context.h"
Alexei Frolov3ab26ff2020-07-21 10:44:58 -070018#include "pw_rpc_test_protos/test.rpc.pb.h"
Alexei Frolov7fb63af2020-07-09 17:05:52 -070019
Wyatt Hepler8aa02922020-07-17 08:54:37 -070020namespace pw::rpc {
21namespace test {
22
Alexei Frolov3ab26ff2020-07-21 10:44:58 -070023class TestService final : public generated::TestService<TestService> {
Alexei Frolovabb0f992020-07-17 16:34:41 -070024 public:
25 Status TestRpc(ServerContext&,
26 const pw_rpc_test_TestRequest& request,
27 pw_rpc_test_TestResponse& response) {
28 response.value = request.integer + 1;
29 return static_cast<Status::Code>(request.status_code);
Wyatt Hepler8aa02922020-07-17 08:54:37 -070030 }
31
Alexei Frolovabb0f992020-07-17 16:34:41 -070032 void TestStreamRpc(ServerContext&,
33 const pw_rpc_test_TestRequest& request,
34 ServerWriter<pw_rpc_test_TestStreamResponse>& writer) {
35 for (int i = 0; i < request.integer; ++i) {
36 writer.Write({.number = static_cast<uint32_t>(i)});
37 }
38
39 writer.Finish(static_cast<Status::Code>(request.status_code));
40 }
41};
Wyatt Hepler8aa02922020-07-17 08:54:37 -070042
43} // namespace test
44
45namespace internal {
Alexei Frolov7fb63af2020-07-09 17:05:52 -070046namespace {
47
48TEST(NanopbCodegen, CompilesProperly) {
Alexei Frolov3ab26ff2020-07-21 10:44:58 -070049 test::TestService service;
Alexei Frolov15255c52020-07-17 08:25:49 -070050 EXPECT_EQ(service.id(), Hash("pw.rpc.test.TestService"));
Alexei Frolov7fb63af2020-07-09 17:05:52 -070051 EXPECT_STREQ(service.name(), "TestService");
52}
53
Wyatt Hepler8aa02922020-07-17 08:54:37 -070054TEST(NanopbCodegen, InvokeUnaryRpc) {
Alexei Frolov3ab26ff2020-07-21 10:44:58 -070055 PW_RPC_TEST_METHOD_CONTEXT(test::TestService, TestRpc) context;
Wyatt Hepler8aa02922020-07-17 08:54:37 -070056
57 EXPECT_EQ(Status::OK,
58 context.call({.integer = 123, .status_code = Status::OK}));
59
60 EXPECT_EQ(124, context.response().value);
61
62 EXPECT_EQ(
63 Status::INVALID_ARGUMENT,
64 context.call({.integer = 999, .status_code = Status::INVALID_ARGUMENT}));
65 EXPECT_EQ(1000, context.response().value);
66}
67
68TEST(NanopbCodegen, InvokeStreamingRpc) {
Alexei Frolov3ab26ff2020-07-21 10:44:58 -070069 PW_RPC_TEST_METHOD_CONTEXT(test::TestService, TestStreamRpc) context;
Wyatt Hepler8aa02922020-07-17 08:54:37 -070070
71 context.call({.integer = 0, .status_code = Status::ABORTED});
72
73 EXPECT_EQ(Status::ABORTED, context.status());
74 EXPECT_TRUE(context.done());
75 EXPECT_TRUE(context.responses().empty());
76 EXPECT_EQ(0u, context.total_responses());
77
78 context.call({.integer = 4, .status_code = Status::OK});
79
80 ASSERT_EQ(4u, context.responses().size());
81 ASSERT_EQ(4u, context.total_responses());
82
83 for (size_t i = 0; i < context.responses().size(); ++i) {
84 EXPECT_EQ(context.responses()[i].number, i);
85 }
86
87 EXPECT_EQ(Status::OK, context.status());
88}
89
90TEST(NanopbCodegen, InvokeStreamingRpc_ContextKeepsFixedNumberOfResponses) {
Alexei Frolov3ab26ff2020-07-21 10:44:58 -070091 PW_RPC_TEST_METHOD_CONTEXT(test::TestService, TestStreamRpc, 3) context;
Wyatt Hepler8aa02922020-07-17 08:54:37 -070092
93 ASSERT_EQ(3u, context.responses().max_size());
94
95 context.call({.integer = 5, .status_code = Status::NOT_FOUND});
96
97 ASSERT_EQ(3u, context.responses().size());
98 ASSERT_EQ(5u, context.total_responses());
99
100 EXPECT_EQ(context.responses()[0].number, 0u);
101 EXPECT_EQ(context.responses()[1].number, 1u);
102 EXPECT_EQ(context.responses()[2].number, 4u);
103}
104
Alexei Frolov91172612020-07-21 17:08:03 -0700105TEST(NanopbCodegen, InvokeStreamingRpc_ManualWriting) {
106 PW_RPC_TEST_METHOD_CONTEXT(test::TestService, TestStreamRpc, 3) context;
107
108 ASSERT_EQ(3u, context.responses().max_size());
109
110 auto writer = context.writer();
111
112 writer.Write({.number = 3});
113 writer.Write({.number = 6});
114 writer.Write({.number = 9});
115
116 EXPECT_FALSE(context.done());
117
118 writer.Finish(Status::CANCELLED);
119 ASSERT_TRUE(context.done());
120 EXPECT_EQ(Status::CANCELLED, context.status());
121
122 ASSERT_EQ(3u, context.responses().size());
123 ASSERT_EQ(3u, context.total_responses());
124
125 EXPECT_EQ(context.responses()[0].number, 3u);
126 EXPECT_EQ(context.responses()[1].number, 6u);
127 EXPECT_EQ(context.responses()[2].number, 9u);
128}
129
Alexei Frolov7fb63af2020-07-09 17:05:52 -0700130} // namespace
Wyatt Hepler8aa02922020-07-17 08:54:37 -0700131} // namespace internal
132} // namespace pw::rpc