Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / third_party / pigweed / repo / pw_trace_tokenized / trace_test.cc
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 // clang-format off
16 #define PW_TRACE_MODULE_NAME "TST"
17
18 #include "pw_trace/trace.h"
19 #include "pw_trace_tokenized/trace_tokenized.h"
20 #include "pw_trace_tokenized/trace_callback.h"
21 // clang-format on
22
23 #include <deque>
24 #include "gtest/gtest.h"
25
26 namespace {
27
28 // Moving these to other lines will require updating the variables
29 #define kTraceFunctionLine 32
30 #define kTraceFunctionGroupLine 33
31 #define kTraceFunctionIdLine 35
32 void TraceFunction() { PW_TRACE_FUNCTION(); }
33 void TraceFunctionGroup() { PW_TRACE_FUNCTION("FunctionGroup"); }
34 void TraceFunctionTraceId(uint32_t id) {
35   PW_TRACE_FUNCTION("FunctionGroup", id);
36 }
37
38 // This trace test interface registers as a trace callback to capture trace
39 // events to verify extpected behaviour. It also supports testing common actions
40 // within the callback.
41 class TraceTestInterface {
42  public:
43   struct TraceInfo {
44     uint32_t trace_ref;
45     pw::trace::EventType event_type;
46     const char* module;
47     uint32_t trace_id;
48     bool operator==(const TraceInfo& b) const {
49       return trace_ref == b.trace_ref && event_type == b.event_type &&
50              module == b.module && trace_id == b.trace_id;
51     }
52   };
53
54   TraceTestInterface() {
55     PW_TRACE_SET_ENABLED(true);
56     pw::trace::Callbacks::Instance().RegisterSink(TraceSinkStartBlock,
57                                                   TraceSinkAddBytes,
58                                                   TraceSinkEndBlock,
59                                                   this,
60                                                   &sink_handle_);
61     pw::trace::Callbacks::Instance().RegisterEventCallback(
62         TraceEventCallback,
63         pw::trace::CallbacksImpl::kCallOnlyWhenEnabled,
64         this,
65         &event_callback_handle_);
66   }
67   ~TraceTestInterface() {
68     pw::trace::Callbacks::Instance().UnregisterSink(sink_handle_);
69     pw::trace::Callbacks::Instance().UnregisterEventCallback(
70         event_callback_handle_);
71   }
72   // ActionOnEvent will perform a specific action within the callback when an
73   // event matches one of the characteristics of event_match_.
74   enum class ActionOnEvent { None, Enable, Disable, DisableAfter, Skip };
75   void SetCallbackEventAction(ActionOnEvent action, TraceInfo event) {
76     action_ = action;
77     event_match_ = event;
78   }
79
80   // The trace event callback will save the trace event info and add it to
81   // buffer_ in the TraceSink callback, that way it only gets added to the
82   // buffer if tracing is enabled and the sample was not surpressed.
83   static pw_trace_TraceEventReturnFlags TraceEventCallback(
84       void* user_data,
85       uint32_t trace_ref,
86       pw_trace_EventType event_type,
87       const char* module,
88       uint32_t trace_id,
89       uint8_t flags) {
90     TraceTestInterface* test_interface =
91         reinterpret_cast<TraceTestInterface*>(user_data);
92     PW_UNUSED(flags);
93     pw_trace_TraceEventReturnFlags ret = 0;
94     if (test_interface->action_ != ActionOnEvent::None &&
95         (test_interface->event_match_.trace_ref == trace_ref ||
96          test_interface->event_match_.event_type == event_type ||
97          test_interface->event_match_.module == module ||
98          (trace_id != PW_TRACE_TRACE_ID_DEFAULT &&
99           test_interface->event_match_.trace_id == trace_id))) {
100       if (test_interface->action_ == ActionOnEvent::Skip) {
101         ret |= PW_TRACE_EVENT_RETURN_FLAGS_SKIP_EVENT;
102       } else if (test_interface->action_ == ActionOnEvent::Enable) {
103         PW_TRACE_SET_ENABLED(true);
104       } else if (test_interface->action_ == ActionOnEvent::Disable) {
105         PW_TRACE_SET_ENABLED(false);
106       } else if (test_interface->action_ == ActionOnEvent::DisableAfter) {
107         ret |= PW_TRACE_EVENT_RETURN_FLAGS_DISABLE_AFTER_PROCESSING;
108       }
109     }
110
111     test_interface->current_trace_event_ =
112         TraceInfo{trace_ref, event_type, module, trace_id};
113     return ret;
114   }
115
116   // Only adds the event to buffer if the number of bytes inidcates is what is
117   // provided.
118   static void TraceSinkStartBlock(void* user_data, size_t size) {
119     TraceTestInterface* test_interface =
120         reinterpret_cast<TraceTestInterface*>(user_data);
121     test_interface->sink_block_size_ = size;
122     test_interface->sink_bytes_received_ = 0;
123   }
124
125   static void TraceSinkAddBytes(void* user_data,
126                                 const void* bytes,
127                                 size_t size) {
128     TraceTestInterface* test_interface =
129         reinterpret_cast<TraceTestInterface*>(user_data);
130     PW_UNUSED(bytes);
131     test_interface->sink_bytes_received_ += size;
132   }
133
134   static void TraceSinkEndBlock(void* user_data) {
135     TraceTestInterface* test_interface =
136         reinterpret_cast<TraceTestInterface*>(user_data);
137     if (test_interface->sink_block_size_ ==
138         test_interface->sink_bytes_received_) {
139       test_interface->buffer_.push_back(test_interface->current_trace_event_);
140     }
141   }
142
143   // Get the event buffer.
144   std::deque<TraceInfo>& GetEvents() { return buffer_; }
145
146   // Check that the next event in the buffer is equal to the expected (and pop
147   // that event).
148   bool CheckEvent(const TraceInfo& expected) {
149     if (buffer_.empty()) {
150       return false;
151     }
152     TraceInfo actual = buffer_.front();
153     buffer_.pop_front();
154     return actual == expected;
155   }
156
157  private:
158   ActionOnEvent action_ = ActionOnEvent::None;
159   TraceInfo event_match_;
160   TraceInfo current_trace_event_;
161   size_t sink_block_size_;
162   size_t sink_bytes_received_;
163   std::deque<TraceInfo> buffer_;
164   pw::trace::CallbacksImpl::SinkHandle sink_handle_;
165   pw::trace::CallbacksImpl::EventCallbackHandle event_callback_handle_;
166 };
167
168 }  // namespace
169
170 // Helper macro to pop the next trace out of test interface and check it against
171 // expecte values.
172 #define EXPECT_TRACE(...) PW_DELEGATE_BY_ARG_COUNT(_EXPECT_TRACE, __VA_ARGS__)
173 #define _EXPECT_TRACE3(interface, event_type, label) \
174   _EXPECT_TRACE7(interface,                          \
175                  event_type,                         \
176                  label,                              \
177                  PW_TRACE_GROUP_LABEL_DEFAULT,       \
178                  PW_TRACE_TRACE_ID_DEFAULT,          \
179                  PW_TRACE_MODULE_NAME,               \
180                  PW_TRACE_FLAGS_DEFAULT)
181 #define _EXPECT_TRACE4(interface, event_type, label, group) \
182   _EXPECT_TRACE7(interface,                                 \
183                  event_type,                                \
184                  label,                                     \
185                  group,                                     \
186                  PW_TRACE_TRACE_ID_DEFAULT,                 \
187                  PW_TRACE_MODULE_NAME,                      \
188                  PW_TRACE_FLAGS_DEFAULT)
189 #define _EXPECT_TRACE5(interface, event_type, label, group, trace_id) \
190   _EXPECT_TRACE7(interface,                                           \
191                  event_type,                                          \
192                  label,                                               \
193                  group,                                               \
194                  trace_id,                                            \
195                  PW_TRACE_MODULE_NAME,                                \
196                  PW_TRACE_FLAGS_DEFAULT)
197 #define _EXPECT_TRACE6(interface, event_type, label, group, trace_id, module) \
198   _EXPECT_TRACE7(interface,                                                   \
199                  event_type,                                                  \
200                  label,                                                       \
201                  group,                                                       \
202                  trace_id,                                                    \
203                  module,                                                      \
204                  PW_TRACE_FLAGS_DEFAULT)
205 #define _EXPECT_TRACE7(                                                      \
206     interface, event_type, label, group, trace_id, module, flags)            \
207   do {                                                                       \
208     static uint32_t _label_token =                                           \
209         PW_TRACE_REF(event_type, module, label, flags, group);               \
210     EXPECT_TRUE(                                                             \
211         interface.CheckEvent({_label_token, event_type, module, trace_id})); \
212   } while (0)
213
214 #define EXPECT_TRACE_DATA(...) \
215   PW_DELEGATE_BY_ARG_COUNT(_EXPECT_TRACE_DATA, __VA_ARGS__)
216 #define _EXPECT_TRACE_DATA4(interface, event_type, label, data_type) \
217   _EXPECT_TRACE_DATA8(interface,                                     \
218                       event_type,                                    \
219                       label,                                         \
220                       PW_TRACE_GROUP_LABEL_DEFAULT,                  \
221                       PW_TRACE_TRACE_ID_DEFAULT,                     \
222                       data_type,                                     \
223                       PW_TRACE_MODULE_NAME,                          \
224                       PW_TRACE_FLAGS_DEFAULT)
225 #define _EXPECT_TRACE_DATA5(interface, event_type, label, group, data_type) \
226   _EXPECT_TRACE_DATA8(interface,                                            \
227                       event_type,                                           \
228                       label,                                                \
229                       group,                                                \
230                       PW_TRACE_TRACE_ID_DEFAULT,                            \
231                       data_type,                                            \
232                       PW_TRACE_MODULE_NAME,                                 \
233                       PW_TRACE_FLAGS_DEFAULT)
234 #define _EXPECT_TRACE_DATA6(                                  \
235     interface, event_type, label, group, trace_id, data_type) \
236   _EXPECT_TRACE_DATA8(interface,                              \
237                       event_type,                             \
238                       label,                                  \
239                       group,                                  \
240                       trace_id,                               \
241                       data_type,                              \
242                       PW_TRACE_MODULE_NAME,                   \
243                       PW_TRACE_FLAGS_DEFAULT)
244 #define _EXPECT_TRACE_DATA7(                                          \
245     interface, event_type, label, group, trace_id, data_type, module) \
246   _EXPECT_TRACE_DATA8(interface,                                      \
247                       event_type,                                     \
248                       label,                                          \
249                       group,                                          \
250                       trace_id,                                       \
251                       data_type,                                      \
252                       module,                                         \
253                       PW_TRACE_FLAGS_DEFAULT)
254 #define _EXPECT_TRACE_DATA8(                                                   \
255     interface, event_type, label, group, trace_id, data_type, module, flags)   \
256   do {                                                                         \
257     static uint32_t _label_token =                                             \
258         PW_TRACE_REF_DATA(event_type, module, label, flags, group, data_type); \
259     EXPECT_TRUE(                                                               \
260         interface.CheckEvent({_label_token, event_type, module, trace_id}));   \
261   } while (0)
262
263 // Start of tests
264
265 TEST(TokenizedTrace, Instant) {
266   TraceTestInterface test_interface;
267
268   PW_TRACE_INSTANT("Test");
269   PW_TRACE_INSTANT("Test2", "g");
270   PW_TRACE_INSTANT("Test3", "g", 2);
271
272   // Check results
273   EXPECT_TRACE(test_interface, PW_TRACE_TYPE_INSTANT, "Test");
274   EXPECT_TRACE(test_interface, PW_TRACE_TYPE_INSTANT_GROUP, "Test2", "g");
275   EXPECT_TRACE(test_interface, PW_TRACE_TYPE_ASYNC_INSTANT, "Test3", "g", 2);
276   EXPECT_TRUE(test_interface.GetEvents().empty());
277 }
278
279 TEST(TokenizedTrace, Duration) {
280   TraceTestInterface test_interface;
281
282   PW_TRACE_START("Test");
283   PW_TRACE_END("Test");
284
285   // Check results
286   EXPECT_TRACE(test_interface, PW_TRACE_TYPE_DURATION_START, "Test");
287   EXPECT_TRACE(test_interface, PW_TRACE_TYPE_DURATION_END, "Test");
288   EXPECT_TRUE(test_interface.GetEvents().empty());
289 }
290
291 TEST(TokenizedTrace, DurationGroup) {
292   TraceTestInterface test_interface;
293
294   PW_TRACE_START("Parent", "group");
295   PW_TRACE_START("Child", "group");
296   PW_TRACE_END("Child", "group");
297   PW_TRACE_END("Parent", "group");
298
299   // Check results
300   EXPECT_TRACE(
301       test_interface, PW_TRACE_TYPE_DURATION_GROUP_START, "Parent", "group");
302   EXPECT_TRACE(
303       test_interface, PW_TRACE_TYPE_DURATION_GROUP_START, "Child", "group");
304   EXPECT_TRACE(
305       test_interface, PW_TRACE_TYPE_DURATION_GROUP_END, "Child", "group");
306   EXPECT_TRACE(
307       test_interface, PW_TRACE_TYPE_DURATION_GROUP_END, "Parent", "group");
308   EXPECT_TRUE(test_interface.GetEvents().empty());
309 }
310
311 TEST(TokenizedTrace, Async) {
312   TraceTestInterface test_interface;
313
314   uint32_t trace_id = 1;
315   PW_TRACE_START("label for async", "group", trace_id);
316   PW_TRACE_INSTANT("label for step", "group", trace_id);
317   PW_TRACE_END("label for async", "group", trace_id);
318
319   // Check results
320   EXPECT_TRACE(test_interface,
321                PW_TRACE_TYPE_ASYNC_START,
322                "label for async",
323                "group",
324                trace_id);
325   EXPECT_TRACE(test_interface,
326                PW_TRACE_TYPE_ASYNC_INSTANT,
327                "label for step",
328                "group",
329                trace_id);
330   EXPECT_TRACE(test_interface,
331                PW_TRACE_TYPE_ASYNC_END,
332                "label for async",
333                "group",
334                trace_id);
335   EXPECT_TRUE(test_interface.GetEvents().empty());
336 }
337
338 TEST(TokenizedTrace, SkipEvent) {
339   TraceTestInterface test_interface;
340
341   // Set trace interface to use skip flag in callback for a specific event.
342   TraceTestInterface::TraceInfo skip_event{
343       0, PW_TRACE_EVENT_TYPE_INVALID, "", PW_TRACE_TRACE_ID_DEFAULT};
344   skip_event.trace_ref = PW_TRACE_REF(PW_TRACE_TYPE_INSTANT,
345                                       "TST",
346                                       "Test2",
347                                       PW_TRACE_FLAGS_DEFAULT,
348                                       PW_TRACE_GROUP_LABEL_DEFAULT);
349   test_interface.SetCallbackEventAction(TraceTestInterface::ActionOnEvent::Skip,
350                                         skip_event);
351
352   PW_TRACE_INSTANT("Test");
353   PW_TRACE_INSTANT("Test2");
354
355   // Check results
356   EXPECT_TRACE(test_interface, PW_TRACE_TYPE_INSTANT, "Test");
357   EXPECT_TRUE(test_interface.GetEvents().empty());
358 }
359
360 TEST(TokenizedTrace, SkipModule) {
361   TraceTestInterface test_interface;
362   // Set trace interface to use skip flag in callback for a module.
363   TraceTestInterface::TraceInfo skip_event{
364       0, PW_TRACE_EVENT_TYPE_INVALID, "", PW_TRACE_TRACE_ID_DEFAULT};
365   skip_event.module = "SkipModule";
366   test_interface.SetCallbackEventAction(TraceTestInterface::ActionOnEvent::Skip,
367                                         skip_event);
368
369 #undef PW_TRACE_MODULE_NAME
370 #define PW_TRACE_MODULE_NAME "SkipModule"
371   PW_TRACE_INSTANT("Test");
372 #undef PW_TRACE_MODULE_NAME
373 #define PW_TRACE_MODULE_NAME "TST"
374   PW_TRACE_INSTANT("Test2");
375
376   // Check results
377   EXPECT_TRACE(test_interface, PW_TRACE_TYPE_INSTANT, "Test2");
378   EXPECT_TRUE(test_interface.GetEvents().empty());
379 }
380
381 TEST(TokenizedTrace, DisableBeforeTrace) {
382   TraceTestInterface test_interface;
383
384   // Set trace interface to disable when a specific event happens.
385   TraceTestInterface::TraceInfo trigger{
386       0, PW_TRACE_EVENT_TYPE_INVALID, "", PW_TRACE_TRACE_ID_DEFAULT};
387   // Stop capturing when Test2 event shows up.
388   trigger.trace_ref = PW_TRACE_REF(PW_TRACE_TYPE_INSTANT,
389                                    "TST",    // Module
390                                    "Test2",  // Label
391                                    PW_TRACE_FLAGS_DEFAULT,
392                                    PW_TRACE_GROUP_LABEL_DEFAULT);
393   test_interface.SetCallbackEventAction(
394       TraceTestInterface::ActionOnEvent::Disable, trigger);
395
396   PW_TRACE_INSTANT("Test1");
397   PW_TRACE_INSTANT("Test2");
398   PW_TRACE_INSTANT("Test3");
399
400   // Check results
401   EXPECT_TRACE(test_interface, PW_TRACE_TYPE_INSTANT, "Test1");
402   EXPECT_TRUE(test_interface.GetEvents().empty());
403 }
404
405 TEST(TokenizedTrace, DisableAfterTrace) {
406   TraceTestInterface test_interface;
407
408   // Set trace interface to use flag to disable after a specific event happens.
409   TraceTestInterface::TraceInfo trigger{
410       0, PW_TRACE_EVENT_TYPE_INVALID, "", PW_TRACE_TRACE_ID_DEFAULT};
411   // Stop capturing after Test2 event shows up.
412   trigger.trace_ref = PW_TRACE_REF(PW_TRACE_TYPE_INSTANT,
413                                    "TST",    // Module
414                                    "Test2",  // Label
415                                    PW_TRACE_FLAGS_DEFAULT,
416                                    PW_TRACE_GROUP_LABEL_DEFAULT);
417   test_interface.SetCallbackEventAction(
418       TraceTestInterface::ActionOnEvent::DisableAfter, trigger);
419
420   PW_TRACE_INSTANT("Test1");
421   PW_TRACE_INSTANT("Test2");
422   PW_TRACE_INSTANT("Test3");
423
424   // Check results
425   EXPECT_TRACE(test_interface, PW_TRACE_TYPE_INSTANT, "Test1");
426   EXPECT_TRACE(test_interface, PW_TRACE_TYPE_INSTANT, "Test2");
427   EXPECT_TRUE(test_interface.GetEvents().empty());
428 }
429
430 TEST(TokenizedTrace, Scope) {
431   TraceTestInterface test_interface;
432
433   { PW_TRACE_SCOPE("scoped trace"); }
434
435   // Check results
436   EXPECT_TRACE(test_interface, PW_TRACE_TYPE_DURATION_START, "scoped trace");
437   EXPECT_TRACE(test_interface, PW_TRACE_TYPE_DURATION_END, "scoped trace");
438   EXPECT_TRUE(test_interface.GetEvents().empty());
439 }
440
441 TEST(TokenizedTrace, ScopeGroup) {
442   TraceTestInterface test_interface;
443
444   { PW_TRACE_SCOPE("scoped group trace", "group"); }
445
446   // Check results
447   EXPECT_TRACE(test_interface,
448                PW_TRACE_TYPE_DURATION_GROUP_START,
449                "scoped group trace",
450                "group");
451   EXPECT_TRACE(test_interface,
452                PW_TRACE_TYPE_DURATION_GROUP_END,
453                "scoped group trace",
454                "group");
455   EXPECT_TRUE(test_interface.GetEvents().empty());
456 }
457
458 TEST(TokenizedTrace, ScopeLoop) {
459   TraceTestInterface test_interface;
460
461   for (uint32_t i = 0; i < 10; i++) {
462     PW_TRACE_SCOPE("scoped loop", "group", i);
463   }
464   // Check results
465   for (uint32_t i = 0; i < 10; i++) {
466     EXPECT_TRACE(
467         test_interface, PW_TRACE_TYPE_ASYNC_START, "scoped loop", "group", i);
468     EXPECT_TRACE(
469         test_interface, PW_TRACE_TYPE_ASYNC_END, "scoped loop", "group", i);
470   }
471   EXPECT_TRUE(test_interface.GetEvents().empty());
472 }
473
474 TEST(TokenizedTrace, Function) {
475   TraceTestInterface test_interface;
476
477   TraceFunction();
478
479   // Check results
480   EXPECT_TRACE(test_interface,
481                PW_TRACE_TYPE_DURATION_START,
482                PW_TRACE_FUNCTION_LABEL_FILE_LINE(__FILE__, kTraceFunctionLine));
483   EXPECT_TRACE(test_interface,
484                PW_TRACE_TYPE_DURATION_END,
485                PW_TRACE_FUNCTION_LABEL_FILE_LINE(__FILE__, kTraceFunctionLine));
486   EXPECT_TRUE(test_interface.GetEvents().empty());
487 }
488
489 TEST(TokenizedTrace, FunctionGroup) {
490   TraceTestInterface test_interface;
491
492   TraceFunctionGroup();
493
494   // Check results
495   EXPECT_TRACE(
496       test_interface,
497       PW_TRACE_TYPE_DURATION_GROUP_START,
498       PW_TRACE_FUNCTION_LABEL_FILE_LINE(__FILE__, kTraceFunctionGroupLine),
499       "FunctionGroup");
500   EXPECT_TRACE(
501       test_interface,
502       PW_TRACE_TYPE_DURATION_GROUP_END,
503       PW_TRACE_FUNCTION_LABEL_FILE_LINE(__FILE__, kTraceFunctionGroupLine),
504       "FunctionGroup");
505   EXPECT_TRUE(test_interface.GetEvents().empty());
506 }
507
508 TEST(TokenizedTrace, FunctionTraceId) {
509   TraceTestInterface test_interface;
510   static constexpr uint32_t kTraceId = 5;
511   TraceFunctionTraceId(kTraceId);
512
513   // Check results
514   EXPECT_TRACE(
515       test_interface,
516       PW_TRACE_TYPE_ASYNC_START,
517       PW_TRACE_FUNCTION_LABEL_FILE_LINE(__FILE__, kTraceFunctionIdLine),
518       "FunctionGroup",
519       kTraceId);
520   EXPECT_TRACE(
521       test_interface,
522       PW_TRACE_TYPE_ASYNC_END,
523       PW_TRACE_FUNCTION_LABEL_FILE_LINE(__FILE__, kTraceFunctionIdLine),
524       "FunctionGroup",
525       kTraceId);
526   EXPECT_TRUE(test_interface.GetEvents().empty());
527 }
528
529 TEST(TokenizedTrace, Data) {
530   TraceTestInterface test_interface;
531   int value = 5;
532   PW_TRACE_INSTANT_DATA("label", "i", &value, sizeof(value));
533   // Check results
534   EXPECT_TRACE_DATA(test_interface,
535                     PW_TRACE_TYPE_INSTANT,
536                     "label",
537                     "i");  // TODO(rgoliver): check data
538   EXPECT_TRUE(test_interface.GetEvents().empty());
539 }
540
541 // Create some helper macros that generated some test trace data based from a
542 // number, and can check that it is correct.
543 constexpr std::byte kTestData[] = {
544     std::byte{0}, std::byte{1}, std::byte{2}, std::byte{3}, std::byte{4}};
545 #define QUEUE_TESTS_ARGS(num)                               \
546   (num), static_cast<pw_trace_EventType>((num) % 10),       \
547       "module_" PW_STRINGIFY(num), (num), (num), kTestData, \
548       (num) % PW_ARRAY_SIZE(kTestData)
549 #define QUEUE_CHECK_RESULT(queue_size, result, num)                            \
550   result && ((result->trace_token) == (num)) &&                                \
551       ((result->event_type) == static_cast<pw_trace_EventType>((num) % 10)) && \
552       (strncmp(result->module,                                                 \
553                "module_" PW_STRINGIFY(num),                                    \
554                strlen("module_" PW_STRINGIFY(num))) == 0) &&                   \
555       ((result->trace_id) == (num)) && ((result->flags) == (num)) &&           \
556       (memcmp(const_cast<const pw::trace::internal::TraceQueue<                \
557                   queue_size>::QueueEventBlock*>(result)                       \
558                   ->data_buffer,                                               \
559               kTestData,                                                       \
560               result->data_size) == 0) &&                                      \
561       (result->data_size == (num) % PW_ARRAY_SIZE(kTestData))
562
563 TEST(TokenizedTrace, QueueSimple) {
564   constexpr size_t kQueueSize = 5;
565   pw::trace::internal::TraceQueue<kQueueSize> queue;
566   constexpr size_t kTestNum = 1;
567   queue.TryPushBack(QUEUE_TESTS_ARGS(kTestNum));
568   EXPECT_FALSE(queue.IsEmpty());
569   EXPECT_FALSE(queue.IsFull());
570   EXPECT_TRUE(QUEUE_CHECK_RESULT(kQueueSize, queue.PeekFront(), kTestNum));
571   queue.PopFront();
572   EXPECT_TRUE(queue.IsEmpty());
573   EXPECT_TRUE(queue.PeekFront() == nullptr);
574   EXPECT_FALSE(queue.IsFull());
575 }
576
577 TEST(TokenizedTrace, QueueFull) {
578   constexpr size_t kQueueSize = 5;
579   pw::trace::internal::TraceQueue<kQueueSize> queue;
580   for (size_t i = 0; i < kQueueSize; i++) {
581     EXPECT_EQ(queue.TryPushBack(QUEUE_TESTS_ARGS(i)), pw::OkStatus());
582   }
583   EXPECT_FALSE(queue.IsEmpty());
584   EXPECT_TRUE(queue.IsFull());
585   EXPECT_EQ(queue.TryPushBack(QUEUE_TESTS_ARGS(1)),
586             pw::Status::ResourceExhausted());
587
588   for (size_t i = 0; i < kQueueSize; i++) {
589     EXPECT_TRUE(QUEUE_CHECK_RESULT(kQueueSize, queue.PeekFront(), i));
590     queue.PopFront();
591   }
592   EXPECT_TRUE(queue.IsEmpty());
593   EXPECT_TRUE(queue.PeekFront() == nullptr);
594   EXPECT_FALSE(queue.IsFull());
595 }
596
597 TEST(TokenizedTrace, Clear) {
598   constexpr size_t kQueueSize = 5;
599   pw::trace::internal::TraceQueue<kQueueSize> queue;
600   for (size_t i = 0; i < kQueueSize; i++) {
601     EXPECT_EQ(queue.TryPushBack(QUEUE_TESTS_ARGS(i)), pw::OkStatus());
602   }
603   EXPECT_FALSE(queue.IsEmpty());
604   EXPECT_TRUE(queue.IsFull());
605   queue.Clear();
606   EXPECT_TRUE(queue.IsEmpty());
607   EXPECT_TRUE(queue.PeekFront() == nullptr);
608   EXPECT_FALSE(queue.IsFull());
609 }