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