xref: /aosp_15_r20/external/pigweed/pw_trace_tokenized/trace_test.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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 
25 #include "pw_unit_test/framework.h"
26 
27 namespace {
28 
29 // These are line numbers for the functions below. Moving these functions to
30 // other lines will require updating these macros.
31 #define TRACE_FUNCTION_LINE 35
32 #define TRACE_FUNCTION_GROUP_LINE 36
33 #define TRACE_FUNCTION_ID_LINE 38
34 
TraceFunction()35 void TraceFunction() { PW_TRACE_FUNCTION(); }
TraceFunctionGroup()36 void TraceFunctionGroup() { PW_TRACE_FUNCTION("FunctionGroup"); }
TraceFunctionTraceId(uint32_t id)37 void TraceFunctionTraceId(uint32_t id) {
38   PW_TRACE_FUNCTION("FunctionGroup", id);
39 }
40 
41 // This trace test interface registers as a trace callback to capture trace
42 // events to verify extpected behaviour. It also supports testing common actions
43 // within the callback.
44 class TraceTestInterface {
45  public:
46   struct TraceInfo {
47     uint32_t trace_ref;
48     pw::trace::EventType event_type;
49     const char* module;
50     uint32_t trace_id;
operator ==__anon46320bad0111::TraceTestInterface::TraceInfo51     bool operator==(const TraceInfo& b) const {
52       return trace_ref == b.trace_ref && event_type == b.event_type &&
53              module == b.module && trace_id == b.trace_id;
54     }
55   };
56 
TraceTestInterface()57   TraceTestInterface() : callbacks_(pw::trace::GetCallbacks()) {
58     PW_TRACE_SET_ENABLED(true);
59     EXPECT_EQ(pw::OkStatus(),
60               callbacks_.RegisterSink(TraceSinkStartBlock,
61                                       TraceSinkAddBytes,
62                                       TraceSinkEndBlock,
63                                       this,
64                                       &sink_handle_));
65     EXPECT_EQ(pw::OkStatus(),
66               callbacks_.RegisterEventCallback(
67                   TraceEventCallback,
68                   pw::trace::Callbacks::kCallOnlyWhenEnabled,
69                   this,
70                   &event_callback_handle_));
71   }
~TraceTestInterface()72   ~TraceTestInterface() {
73     EXPECT_EQ(pw::OkStatus(), callbacks_.UnregisterSink(sink_handle_));
74     EXPECT_EQ(pw::OkStatus(),
75               callbacks_.UnregisterEventCallback(event_callback_handle_));
76   }
77   // ActionOnEvent will perform a specific action within the callback when an
78   // event matches one of the characteristics of event_match_.
79   enum class ActionOnEvent { None, Enable, Disable, DisableAfter, Skip };
SetCallbackEventAction(ActionOnEvent action,TraceInfo event)80   void SetCallbackEventAction(ActionOnEvent action, TraceInfo event) {
81     action_ = action;
82     event_match_ = event;
83   }
84 
85   // The trace event callback will save the trace event info and add it to
86   // buffer_ in the TraceSink callback, that way it only gets added to the
87   // buffer if tracing is enabled and the sample was not surpressed.
TraceEventCallback(void * user_data,pw_trace_tokenized_TraceEvent * event)88   static pw_trace_TraceEventReturnFlags TraceEventCallback(
89       void* user_data, pw_trace_tokenized_TraceEvent* event) {
90     TraceTestInterface* test_interface =
91         reinterpret_cast<TraceTestInterface*>(user_data);
92     pw_trace_TraceEventReturnFlags ret = 0;
93     if (test_interface->action_ != ActionOnEvent::None &&
94         (test_interface->event_match_.trace_ref == event->trace_token ||
95          test_interface->event_match_.event_type == event->event_type ||
96          test_interface->event_match_.module == event->module ||
97          (event->trace_id != PW_TRACE_TRACE_ID_DEFAULT &&
98           test_interface->event_match_.trace_id == event->trace_id))) {
99       if (test_interface->action_ == ActionOnEvent::Skip) {
100         ret |= PW_TRACE_EVENT_RETURN_FLAGS_SKIP_EVENT;
101       } else if (test_interface->action_ == ActionOnEvent::Enable) {
102         PW_TRACE_SET_ENABLED(true);
103       } else if (test_interface->action_ == ActionOnEvent::Disable) {
104         PW_TRACE_SET_ENABLED(false);
105       } else if (test_interface->action_ == ActionOnEvent::DisableAfter) {
106         ret |= PW_TRACE_EVENT_RETURN_FLAGS_DISABLE_AFTER_PROCESSING;
107       }
108     }
109 
110     test_interface->current_trace_event_ = TraceInfo{
111         event->trace_token, event->event_type, event->module, event->trace_id};
112     return ret;
113   }
114 
115   // Only adds the event to buffer if the number of bytes inidcates is what is
116   // provided.
TraceSinkStartBlock(void * user_data,size_t size)117   static void TraceSinkStartBlock(void* user_data, size_t size) {
118     TraceTestInterface* test_interface =
119         reinterpret_cast<TraceTestInterface*>(user_data);
120     test_interface->sink_block_size_ = size;
121     test_interface->sink_bytes_received_ = 0;
122   }
123 
TraceSinkAddBytes(void * user_data,const void * bytes,size_t size)124   static void TraceSinkAddBytes(void* user_data,
125                                 const void* bytes,
126                                 size_t size) {
127     TraceTestInterface* test_interface =
128         reinterpret_cast<TraceTestInterface*>(user_data);
129     static_cast<void>(bytes);
130     test_interface->sink_bytes_received_ += size;
131   }
132 
TraceSinkEndBlock(void * user_data)133   static void TraceSinkEndBlock(void* user_data) {
134     TraceTestInterface* test_interface =
135         reinterpret_cast<TraceTestInterface*>(user_data);
136     if (test_interface->sink_block_size_ ==
137         test_interface->sink_bytes_received_) {
138       test_interface->buffer_.push_back(test_interface->current_trace_event_);
139     }
140   }
141 
142   // Get the event buffer.
GetEvents()143   std::deque<TraceInfo>& GetEvents() { return buffer_; }
144 
145   // Check that the next event in the buffer is equal to the expected (and pop
146   // that event).
CheckEvent(const TraceInfo & expected)147   bool CheckEvent(const TraceInfo& expected) {
148     if (buffer_.empty()) {
149       return false;
150     }
151     TraceInfo actual = buffer_.front();
152     buffer_.pop_front();
153     return actual == expected;
154   }
155 
156  private:
157   ActionOnEvent action_ = ActionOnEvent::None;
158   TraceInfo event_match_;
159   TraceInfo current_trace_event_;
160   size_t sink_block_size_;
161   size_t sink_bytes_received_;
162   std::deque<TraceInfo> buffer_;
163   pw::trace::Callbacks& callbacks_;
164   pw::trace::Callbacks::SinkHandle sink_handle_;
165   pw::trace::Callbacks::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 
TEST(TokenizedTrace,Instant)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 
TEST(TokenizedTrace,Duration)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 
TEST(TokenizedTrace,DurationGroup)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 
TEST(TokenizedTrace,Async)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 
TEST(TokenizedTrace,SkipEvent)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 
TEST(TokenizedTrace,SkipModule)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 
TEST(TokenizedTrace,DisableBeforeTrace)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 
TEST(TokenizedTrace,DisableAfterTrace)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 
TEST(TokenizedTrace,Scope)430 TEST(TokenizedTrace, Scope) {
431   TraceTestInterface test_interface;
432 
433   {
434     PW_TRACE_SCOPE("scoped trace");
435   }
436 
437   // Check results
438   EXPECT_TRACE(test_interface, PW_TRACE_TYPE_DURATION_START, "scoped trace");
439   EXPECT_TRACE(test_interface, PW_TRACE_TYPE_DURATION_END, "scoped trace");
440   EXPECT_TRUE(test_interface.GetEvents().empty());
441 }
442 
TEST(TokenizedTrace,ScopeGroup)443 TEST(TokenizedTrace, ScopeGroup) {
444   TraceTestInterface test_interface;
445 
446   {
447     PW_TRACE_SCOPE("scoped group trace", "group");
448   }
449 
450   // Check results
451   EXPECT_TRACE(test_interface,
452                PW_TRACE_TYPE_DURATION_GROUP_START,
453                "scoped group trace",
454                "group");
455   EXPECT_TRACE(test_interface,
456                PW_TRACE_TYPE_DURATION_GROUP_END,
457                "scoped group trace",
458                "group");
459   EXPECT_TRUE(test_interface.GetEvents().empty());
460 }
461 
TEST(TokenizedTrace,ScopeLoop)462 TEST(TokenizedTrace, ScopeLoop) {
463   TraceTestInterface test_interface;
464 
465   for (uint32_t i = 0; i < 10; i++) {
466     PW_TRACE_SCOPE("scoped loop", "group", i);
467   }
468   // Check results
469   for (uint32_t i = 0; i < 10; i++) {
470     EXPECT_TRACE(
471         test_interface, PW_TRACE_TYPE_ASYNC_START, "scoped loop", "group", i);
472     EXPECT_TRACE(
473         test_interface, PW_TRACE_TYPE_ASYNC_END, "scoped loop", "group", i);
474   }
475   EXPECT_TRUE(test_interface.GetEvents().empty());
476 }
477 
TEST(TokenizedTrace,Function)478 TEST(TokenizedTrace, Function) {
479   TraceTestInterface test_interface;
480 
481   TraceFunction();
482 
483   // Check results
484   EXPECT_TRACE(
485       test_interface,
486       PW_TRACE_TYPE_DURATION_START,
487       PW_TRACE_FUNCTION_LABEL_FILE_LINE(__FILE__, TRACE_FUNCTION_LINE));
488   EXPECT_TRACE(
489       test_interface,
490       PW_TRACE_TYPE_DURATION_END,
491       PW_TRACE_FUNCTION_LABEL_FILE_LINE(__FILE__, TRACE_FUNCTION_LINE));
492   EXPECT_TRUE(test_interface.GetEvents().empty());
493 }
494 
TEST(TokenizedTrace,FunctionGroup)495 TEST(TokenizedTrace, FunctionGroup) {
496   TraceTestInterface test_interface;
497 
498   TraceFunctionGroup();
499 
500   // Check results
501   EXPECT_TRACE(
502       test_interface,
503       PW_TRACE_TYPE_DURATION_GROUP_START,
504       PW_TRACE_FUNCTION_LABEL_FILE_LINE(__FILE__, TRACE_FUNCTION_GROUP_LINE),
505       "FunctionGroup");
506   EXPECT_TRACE(
507       test_interface,
508       PW_TRACE_TYPE_DURATION_GROUP_END,
509       PW_TRACE_FUNCTION_LABEL_FILE_LINE(__FILE__, TRACE_FUNCTION_GROUP_LINE),
510       "FunctionGroup");
511   EXPECT_TRUE(test_interface.GetEvents().empty());
512 }
513 
TEST(TokenizedTrace,FunctionTraceId)514 TEST(TokenizedTrace, FunctionTraceId) {
515   TraceTestInterface test_interface;
516   static constexpr uint32_t kTraceId = 5;
517   TraceFunctionTraceId(kTraceId);
518 
519   // Check results
520   EXPECT_TRACE(
521       test_interface,
522       PW_TRACE_TYPE_ASYNC_START,
523       PW_TRACE_FUNCTION_LABEL_FILE_LINE(__FILE__, TRACE_FUNCTION_ID_LINE),
524       "FunctionGroup",
525       kTraceId);
526   EXPECT_TRACE(
527       test_interface,
528       PW_TRACE_TYPE_ASYNC_END,
529       PW_TRACE_FUNCTION_LABEL_FILE_LINE(__FILE__, TRACE_FUNCTION_ID_LINE),
530       "FunctionGroup",
531       kTraceId);
532   EXPECT_TRUE(test_interface.GetEvents().empty());
533 }
534 
TEST(TokenizedTrace,Data)535 TEST(TokenizedTrace, Data) {
536   TraceTestInterface test_interface;
537   int value = 5;
538   PW_TRACE_INSTANT_DATA("label", "i", &value, sizeof(value));
539   // Check results
540   EXPECT_TRACE_DATA(test_interface,
541                     PW_TRACE_TYPE_INSTANT,
542                     "label",
543                     "i");  // TODO(rgoliver): check data
544   EXPECT_TRUE(test_interface.GetEvents().empty());
545 }
546 
547 // Create some helper macros that generated some test trace data based from a
548 // number, and can check that it is correct.
549 constexpr std::byte kTestData[] = {
550     std::byte{0}, std::byte{1}, std::byte{2}, std::byte{3}, std::byte{4}};
551 #define QUEUE_TESTS_ARGS(num)                               \
552   (num), static_cast<pw_trace_EventType>((num) % 10),       \
553       "module_" PW_STRINGIFY(num), (num), (num), kTestData, \
554       (num) % PW_ARRAY_SIZE(kTestData)
555 #define QUEUE_CHECK_RESULT(queue_size, result, num)                            \
556   result && ((result->trace_token) == (num)) &&                                \
557       ((result->event_type) == static_cast<pw_trace_EventType>((num) % 10)) && \
558       (strncmp(result->module,                                                 \
559                "module_" PW_STRINGIFY(num),                                    \
560                strlen("module_" PW_STRINGIFY(num))) == 0) &&                   \
561       ((result->trace_id) == (num)) && ((result->flags) == (num)) &&           \
562       (memcmp(const_cast<const pw::trace::internal::TraceQueue<                \
563                   queue_size>::QueueEventBlock*>(result)                       \
564                   ->data_buffer,                                               \
565               kTestData,                                                       \
566               result->data_size) == 0) &&                                      \
567       (result->data_size == (num) % PW_ARRAY_SIZE(kTestData))
568 
TEST(TokenizedTrace,QueueSimple)569 TEST(TokenizedTrace, QueueSimple) {
570   constexpr size_t kQueueSize = 5;
571   pw::trace::internal::TraceQueue<kQueueSize> queue;
572   constexpr size_t kTestNum = 1;
573   ASSERT_EQ(pw::OkStatus(), queue.TryPushBack(QUEUE_TESTS_ARGS(kTestNum)));
574   EXPECT_FALSE(queue.IsEmpty());
575   EXPECT_FALSE(queue.IsFull());
576   EXPECT_TRUE(QUEUE_CHECK_RESULT(kQueueSize, queue.PeekFront(), kTestNum));
577   queue.PopFront();
578   EXPECT_TRUE(queue.IsEmpty());
579   EXPECT_TRUE(queue.PeekFront() == nullptr);
580   EXPECT_FALSE(queue.IsFull());
581 }
582 
TEST(TokenizedTrace,QueueFull)583 TEST(TokenizedTrace, QueueFull) {
584   constexpr size_t kQueueSize = 5;
585   pw::trace::internal::TraceQueue<kQueueSize> queue;
586   for (size_t i = 0; i < kQueueSize; i++) {
587     EXPECT_EQ(queue.TryPushBack(QUEUE_TESTS_ARGS(i)), pw::OkStatus());
588   }
589   EXPECT_FALSE(queue.IsEmpty());
590   EXPECT_TRUE(queue.IsFull());
591   EXPECT_EQ(queue.TryPushBack(QUEUE_TESTS_ARGS(1)),
592             pw::Status::ResourceExhausted());
593 
594   for (size_t i = 0; i < kQueueSize; i++) {
595     EXPECT_TRUE(QUEUE_CHECK_RESULT(kQueueSize, queue.PeekFront(), i));
596     queue.PopFront();
597   }
598   EXPECT_TRUE(queue.IsEmpty());
599   EXPECT_TRUE(queue.PeekFront() == nullptr);
600   EXPECT_FALSE(queue.IsFull());
601 }
602 
TEST(TokenizedTrace,Clear)603 TEST(TokenizedTrace, Clear) {
604   constexpr size_t kQueueSize = 5;
605   pw::trace::internal::TraceQueue<kQueueSize> queue;
606   for (size_t i = 0; i < kQueueSize; i++) {
607     EXPECT_EQ(queue.TryPushBack(QUEUE_TESTS_ARGS(i)), pw::OkStatus());
608   }
609   EXPECT_FALSE(queue.IsEmpty());
610   EXPECT_TRUE(queue.IsFull());
611   queue.Clear();
612   EXPECT_TRUE(queue.IsEmpty());
613   EXPECT_TRUE(queue.PeekFront() == nullptr);
614   EXPECT_FALSE(queue.IsFull());
615 }
616