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