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