1 // Copyright 2020 The Pigweed Authors
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
7 // https://www.apache.org/licenses/LICENSE-2.0
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
15 #include "gtest/gtest.h"
16 #include "pw_protobuf/decoder.h"
17 #include "pw_rpc/internal/hash.h"
18 #include "pw_rpc/raw_test_method_context.h"
19 #include "pw_rpc_test_protos/test.pwpb.h"
20 #include "pw_rpc_test_protos/test.raw_rpc.pb.h"
25 class TestService final : public generated::TestService<TestService> {
27 static StatusWithSize TestRpc(ServerContext&,
28 ConstByteSpan request,
32 DecodeRequest(request, integer, status);
34 protobuf::NestedEncoder encoder(response);
35 TestResponse::Encoder test_response(&encoder);
36 test_response.WriteValue(integer + 1);
38 return StatusWithSize(status, encoder.Encode().value().size());
41 void TestStreamRpc(ServerContext&,
42 ConstByteSpan request,
43 RawServerWriter& writer) {
46 DecodeRequest(request, integer, status);
48 for (int i = 0; i < integer; ++i) {
49 ByteSpan buffer = writer.PayloadBuffer();
50 protobuf::NestedEncoder encoder(buffer);
51 TestStreamResponse::Encoder test_stream_response(&encoder);
52 test_stream_response.WriteNumber(i);
53 writer.Write(encoder.Encode().value());
56 writer.Finish(status);
60 static void DecodeRequest(ConstByteSpan request,
63 protobuf::Decoder decoder(request);
65 while (decoder.Next().ok()) {
66 switch (static_cast<TestRequest::Fields>(decoder.FieldNumber())) {
67 case TestRequest::Fields::INTEGER:
68 decoder.ReadInt64(&integer);
70 case TestRequest::Fields::STATUS_CODE: {
72 decoder.ReadUint32(&status_code);
73 status = static_cast<Status::Code>(status_code);
85 TEST(RawCodegen, CompilesProperly) {
86 test::TestService service;
87 EXPECT_EQ(service.id(), internal::Hash("pw.rpc.test.TestService"));
88 EXPECT_STREQ(service.name(), "TestService");
91 TEST(RawCodegen, Server_InvokeUnaryRpc) {
92 PW_RAW_TEST_METHOD_CONTEXT(test::TestService, TestRpc) context;
95 protobuf::NestedEncoder encoder(buffer);
96 test::TestRequest::Encoder test_request(&encoder);
97 test_request.WriteInteger(123);
98 test_request.WriteStatusCode(OkStatus().code());
100 auto sws = context.call(encoder.Encode().value());
101 EXPECT_EQ(OkStatus(), sws.status());
103 protobuf::Decoder decoder(context.response());
105 while (decoder.Next().ok()) {
106 switch (static_cast<test::TestResponse::Fields>(decoder.FieldNumber())) {
107 case test::TestResponse::Fields::VALUE: {
109 decoder.ReadInt32(&value);
110 EXPECT_EQ(value, 124);
117 TEST(RawCodegen, Server_InvokeServerStreamingRpc) {
118 PW_RAW_TEST_METHOD_CONTEXT(test::TestService, TestStreamRpc) context;
120 std::byte buffer[64];
121 protobuf::NestedEncoder encoder(buffer);
122 test::TestRequest::Encoder test_request(&encoder);
123 test_request.WriteInteger(5);
124 test_request.WriteStatusCode(Status::Unauthenticated().code());
126 context.call(encoder.Encode().value());
127 EXPECT_TRUE(context.done());
128 EXPECT_EQ(Status::Unauthenticated(), context.status());
129 EXPECT_EQ(context.total_responses(), 5u);
131 protobuf::Decoder decoder(context.responses().back());
132 while (decoder.Next().ok()) {
134 static_cast<test::TestStreamResponse::Fields>(decoder.FieldNumber())) {
135 case test::TestStreamResponse::Fields::NUMBER: {
137 decoder.ReadInt32(&value);
141 case test::TestStreamResponse::Fields::CHUNK:
149 } // namespace pw::rpc