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