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 "pw_log_multisink/log_queue.h"
17 #include "gtest/gtest.h"
18 #include "pw_log/levels.h"
19 #include "pw_log_proto/log.pwpb.h"
20 #include "pw_protobuf/decoder.h"
22 namespace pw::log_rpc {
25 constexpr size_t kEncodeBufferSize = 512;
27 constexpr const char kTokenizedMessage[] = "msg_token";
28 constexpr uint32_t kFlags = 0xF;
29 constexpr uint32_t kLevel = 0b010;
30 constexpr uint32_t kLine = 0b101011000;
31 constexpr uint32_t kTokenizedThread = 0xF;
32 constexpr int64_t kTimestamp = 0;
34 constexpr size_t kLogBufferSize = kEncodeBufferSize * 3;
36 void VerifyLogEntry(pw::protobuf::Decoder& log_decoder,
37 const char* expected_tokenized_message,
38 const uint32_t expected_flags,
39 const uint32_t expected_level,
40 const uint32_t expected_line,
41 const uint32_t expected_tokenized_thread,
42 const int64_t expected_timestamp) {
43 ConstByteSpan log_entry_message;
44 EXPECT_TRUE(log_decoder.Next().ok()); // preamble
45 EXPECT_EQ(1U, log_decoder.FieldNumber());
46 EXPECT_TRUE(log_decoder.ReadBytes(&log_entry_message).ok());
48 pw::protobuf::Decoder entry_decoder(log_entry_message);
49 ConstByteSpan tokenized_message;
50 EXPECT_TRUE(entry_decoder.Next().ok()); // tokenized_message
51 EXPECT_EQ(1U, entry_decoder.FieldNumber());
52 EXPECT_TRUE(entry_decoder.ReadBytes(&tokenized_message).ok());
53 EXPECT_TRUE(std::memcmp(tokenized_message.begin(),
54 (const void*)expected_tokenized_message,
55 tokenized_message.size()) == 0);
58 EXPECT_TRUE(entry_decoder.Next().ok()); // line_level
59 EXPECT_EQ(2U, entry_decoder.FieldNumber());
60 EXPECT_TRUE(entry_decoder.ReadUint32(&line_level).ok());
61 EXPECT_EQ(expected_level, line_level & PW_LOG_LEVEL_BITMASK);
62 EXPECT_EQ(expected_line,
63 (line_level & ~PW_LOG_LEVEL_BITMASK) >> PW_LOG_LEVEL_BITWIDTH);
66 EXPECT_TRUE(entry_decoder.Next().ok()); // flags
67 EXPECT_EQ(3U, entry_decoder.FieldNumber());
68 EXPECT_TRUE(entry_decoder.ReadUint32(&flags).ok());
69 EXPECT_EQ(expected_flags, flags);
71 uint32_t tokenized_thread;
72 EXPECT_TRUE(entry_decoder.Next().ok()); // tokenized_thread
73 EXPECT_EQ(4U, entry_decoder.FieldNumber());
74 EXPECT_TRUE(entry_decoder.ReadUint32(&tokenized_thread).ok());
75 EXPECT_EQ(expected_tokenized_thread, tokenized_thread);
78 EXPECT_TRUE(entry_decoder.Next().ok()); // timestamp
79 EXPECT_EQ(5U, entry_decoder.FieldNumber());
80 EXPECT_TRUE(entry_decoder.ReadInt64(×tamp).ok());
81 EXPECT_EQ(expected_timestamp, timestamp);
86 TEST(LogQueue, SinglePushPopTokenizedMessage) {
87 std::byte log_buffer[kLogBufferSize];
88 LogQueueWithEncodeBuffer<kEncodeBufferSize> log_queue(log_buffer);
91 log_queue.PushTokenizedMessage(
92 std::as_bytes(std::span(kTokenizedMessage)),
99 std::byte log_entry[kEncodeBufferSize];
100 Result<LogEntries> pop_result = log_queue.Pop(std::span(log_entry));
101 EXPECT_TRUE(pop_result.ok());
103 pw::protobuf::Decoder log_decoder(pop_result.value().entries);
104 EXPECT_EQ(pop_result.value().entry_count, 1U);
105 VerifyLogEntry(log_decoder,
114 TEST(LogQueue, MultiplePushPopTokenizedMessage) {
115 constexpr size_t kEntryCount = 3;
117 std::byte log_buffer[1024];
118 LogQueueWithEncodeBuffer<kEncodeBufferSize> log_queue(log_buffer);
120 for (size_t i = 0; i < kEntryCount; i++) {
121 EXPECT_EQ(OkStatus(),
122 log_queue.PushTokenizedMessage(
123 std::as_bytes(std::span(kTokenizedMessage)),
131 std::byte log_entry[kEncodeBufferSize];
132 for (size_t i = 0; i < kEntryCount; i++) {
133 Result<LogEntries> pop_result = log_queue.Pop(std::span(log_entry));
134 EXPECT_TRUE(pop_result.ok());
136 pw::protobuf::Decoder log_decoder(pop_result.value().entries);
137 EXPECT_EQ(pop_result.value().entry_count, 1U);
138 VerifyLogEntry(log_decoder,
148 TEST(LogQueue, PopMultiple) {
149 constexpr size_t kEntryCount = 3;
151 std::byte log_buffer[kLogBufferSize];
152 LogQueueWithEncodeBuffer<kEncodeBufferSize> log_queue(log_buffer);
154 for (size_t i = 0; i < kEntryCount; i++) {
155 EXPECT_EQ(OkStatus(),
156 log_queue.PushTokenizedMessage(
157 std::as_bytes(std::span(kTokenizedMessage)),
165 std::byte log_entries[kLogBufferSize];
166 Result<LogEntries> pop_result = log_queue.PopMultiple(log_entries);
167 EXPECT_TRUE(pop_result.ok());
169 pw::protobuf::Decoder log_decoder(pop_result.value().entries);
170 EXPECT_EQ(pop_result.value().entry_count, kEntryCount);
171 for (size_t i = 0; i < kEntryCount; i++) {
172 VerifyLogEntry(log_decoder,
182 TEST(LogQueue, TooSmallEncodeBuffer) {
183 constexpr size_t kSmallBuffer = 1;
185 std::byte log_buffer[kLogBufferSize];
186 LogQueueWithEncodeBuffer<kSmallBuffer> log_queue(log_buffer);
187 EXPECT_EQ(Status::Internal(),
188 log_queue.PushTokenizedMessage(
189 std::as_bytes(std::span(kTokenizedMessage)),
197 TEST(LogQueue, TooSmallLogBuffer) {
198 constexpr size_t kSmallerThanPreamble = 1;
199 constexpr size_t kEntryCount = 100;
201 // Expect OUT_OF_RANGE when the buffer is smaller than a preamble.
202 std::byte log_buffer[kLogBufferSize];
203 LogQueueWithEncodeBuffer<kEncodeBufferSize> log_queue_small(
204 std::span(log_buffer, kSmallerThanPreamble));
205 EXPECT_EQ(Status::OutOfRange(),
206 log_queue_small.PushTokenizedMessage(
207 std::as_bytes(std::span(kTokenizedMessage)),
214 // Expect RESOURCE_EXHAUSTED when there's not enough space for the chunk.
215 LogQueueWithEncodeBuffer<kEncodeBufferSize> log_queue_medium(log_buffer);
216 for (size_t i = 0; i < kEntryCount; i++) {
217 log_queue_medium.PushTokenizedMessage(
218 std::as_bytes(std::span(kTokenizedMessage)),
225 EXPECT_EQ(Status::ResourceExhausted(),
226 log_queue_medium.PushTokenizedMessage(
227 std::as_bytes(std::span(kTokenizedMessage)),
235 } // namespace pw::log_rpc