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_log_rpc/logs_rpc.h"
16
17 #include "gtest/gtest.h"
18 #include "pw_log/log.h"
19 #include "pw_rpc/raw_test_method_context.h"
20
21 namespace pw::log_rpc {
22 namespace {
23
24 #define LOGS_METHOD_CONTEXT PW_RAW_TEST_METHOD_CONTEXT(Logs, Get)
25
26 constexpr size_t kEncodeBufferSize = 128;
27 constexpr size_t kLogBufferSize = 4096;
28
29 class LogQueueTester : public LogQueueWithEncodeBuffer<kLogBufferSize> {
30 public:
LogQueueTester(ByteSpan log_queue)31 LogQueueTester(ByteSpan log_queue)
32 : LogQueueWithEncodeBuffer<kLogBufferSize>(log_queue) {}
33
SetPopStatus(Status error_status)34 void SetPopStatus(Status error_status) {
35 pop_status_for_test_ = error_status;
36 }
37 };
38
39 class LogsService : public ::testing::Test {
40 public:
LogsService()41 LogsService() : log_queue_(log_queue_buffer_) {}
42
43 protected:
AddLogs(const size_t log_count=1)44 void AddLogs(const size_t log_count = 1) {
45 constexpr char kTokenizedMessage[] = "message";
46 for (size_t i = 0; i < log_count; i++) {
47 EXPECT_EQ(
48 OkStatus(),
49 log_queue_.PushTokenizedMessage(
50 std::as_bytes(std::span(kTokenizedMessage)), 0, 0, 0, 0, 0));
51 }
52 }
53
GetLogs(LOGS_METHOD_CONTEXT & context)54 static Logs& GetLogs(LOGS_METHOD_CONTEXT& context) {
55 return (Logs&)(context.service());
56 }
57
58 std::array<std::byte, kEncodeBufferSize> log_queue_buffer_;
59 LogQueueWithEncodeBuffer<kLogBufferSize> log_queue_;
60 };
61
TEST_F(LogsService,Get)62 TEST_F(LogsService, Get) {
63 constexpr size_t kLogEntryCount = 3;
64 std::array<std::byte, 1> rpc_buffer;
65 LOGS_METHOD_CONTEXT context(log_queue_);
66
67 context.call(rpc_buffer);
68
69 // Flush all logs from the buffer, then close the RPC.
70 AddLogs(kLogEntryCount);
71 GetLogs(context).Flush();
72 GetLogs(context).Finish();
73
74 EXPECT_TRUE(context.done());
75 EXPECT_EQ(OkStatus(), context.status());
76
77 // Although |kLogEntryCount| messages were in the queue, they are batched
78 // before being written to the client, so there is only one response.
79 EXPECT_EQ(1U, context.total_responses());
80 }
81
TEST_F(LogsService,GetMultiple)82 TEST_F(LogsService, GetMultiple) {
83 constexpr size_t kLogEntryCount = 1;
84 constexpr size_t kFlushCount = 3;
85 std::array<std::byte, 1> rpc_buffer;
86 LOGS_METHOD_CONTEXT context(log_queue_);
87
88 context.call(rpc_buffer);
89
90 for (size_t i = 0; i < kFlushCount; i++) {
91 AddLogs(kLogEntryCount);
92 GetLogs(context).Flush();
93 }
94 GetLogs(context).Finish();
95
96 EXPECT_TRUE(context.done());
97 EXPECT_EQ(OkStatus(), context.status());
98 EXPECT_EQ(kFlushCount, context.total_responses());
99 }
100
TEST_F(LogsService,NoEntriesOnEmptyQueue)101 TEST_F(LogsService, NoEntriesOnEmptyQueue) {
102 std::array<std::byte, 1> rpc_buffer;
103 LOGS_METHOD_CONTEXT context(log_queue_);
104
105 // Invoking flush with no logs in the queue should behave like a no-op.
106 context.call(rpc_buffer);
107 GetLogs(context).Flush();
108 GetLogs(context).Finish();
109
110 EXPECT_TRUE(context.done());
111 EXPECT_EQ(OkStatus(), context.status());
112 EXPECT_EQ(0U, context.total_responses());
113 }
114
TEST_F(LogsService,QueueError)115 TEST_F(LogsService, QueueError) {
116 std::array<std::byte, 1> rpc_buffer;
117 LogQueueTester log_queue_tester(log_queue_buffer_);
118 LOGS_METHOD_CONTEXT context(log_queue_tester);
119
120 // Generate failure on log queue.
121 log_queue_tester.SetPopStatus(Status::Internal());
122 context.call(rpc_buffer);
123 GetLogs(context).Flush();
124 GetLogs(context).Finish();
125
126 EXPECT_TRUE(context.done());
127 EXPECT_EQ(OkStatus(), context.status());
128 EXPECT_EQ(0U, context.total_responses());
129 }
130
131 } // namespace
132 } // namespace pw::log_rpc
133