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