1// Copyright 2017 The Fuchsia Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5// 6// Helper functions for setting up and tearing down a test fixture which 7// manages the trace engine on behalf of a test. 8// 9 10#pragma once 11 12#include <stddef.h> 13 14#ifdef __cplusplus 15#include <fbl/string.h> 16#include <fbl/vector.h> 17#include <trace-engine/buffer_internal.h> 18#include <trace-reader/records.h> 19#endif 20 21#include <lib/async-loop/loop.h> 22#include <trace-engine/types.h> 23#include <unittest/unittest.h> 24#include <zircon/compiler.h> 25 26// Specifies whether the trace engine async loop uses the same thread as the 27// app or a different thread. 28typedef enum { 29 // Use different thread from app. 30 kNoAttachToThread, 31 // Use same thread as app. 32 kAttachToThread, 33} attach_to_thread_t; 34 35#ifdef __cplusplus 36 37// FixtureSquelch is used to filter out elements of a trace record that may 38// vary run to run or even within a run and are not germaine to determining 39// correctness. The canonical example is record timestamps. 40// The term "squelch" derives from radio circuitry used to remove noise. 41struct FixtureSquelch; 42 43// |regex_str| is a regular expression consistenting of one or more 44// subexpressions, the text in the parenthesis of each matching expressions 45// is replaced with '<>'. 46// Best illustration is an example. This example removes decimal numbers, 47// koids, timestamps ("ts"), and lowercase hex numbers. 48// const char regex[] = "([0-9]+/[0-9]+)" 49// "|koid\\(([0-9]+)\\)" 50// "|koid: ([0-9]+)" 51// "|ts: ([0-9]+)" 52// "|(0x[0-9a-f]+)"; 53// So "ts: 123 42 mumble koid(456) foo koid: 789, bar 0xabcd" 54// becomes "ts: <> <> mumble koid(<>) foo koid: <>, bar <>". 55bool fixture_create_squelch(const char* regex_str, FixtureSquelch** out_squelch); 56void fixture_destroy_squelch(FixtureSquelch* squelch); 57fbl::String fixture_squelch(FixtureSquelch* squelch, const char* str); 58 59bool fixture_compare_raw_records(const fbl::Vector<trace::Record>& records, 60 size_t start_record, size_t max_num_records, 61 const char* expected); 62bool fixture_compare_n_records(size_t max_num_records, const char* expected, 63 fbl::Vector<trace::Record>* records); 64 65using trace::internal::trace_buffer_header; 66void fixture_snapshot_buffer_header(trace_buffer_header* header); 67 68#endif 69 70__BEGIN_CDECLS 71 72void fixture_set_up(attach_to_thread_t attach_to_thread, 73 trace_buffering_mode_t mode, size_t buffer_size); 74void fixture_tear_down(void); 75void fixture_start_tracing(void); 76 77// There are two ways of stopping tracing. 78// 1) |fixture_stop_tracing()|: 79// a) stops the engine, 80// b) waits for everything to quiesce, 81// c) shuts down the dispatcher loop. 82// A variant of this is |fixture_stop_tracing_hard()| which is for 83// specialized cases where the async loop exits forcing the engine to 84// quit on its own. 85// 2) |fixture_stop_engine(),fixture_shutdown()|: This variant splits out 86// steps (a) and (c) above, leaving the test free to manage step (b): the 87// quiescence. 88void fixture_stop_tracing(void); 89void fixture_stop_tracing_hard(void); 90void fixture_stop_engine(void); 91void fixture_shutdown(void); 92 93async_loop_t* fixture_async_loop(void); 94zx_status_t fixture_get_disposition(void); 95bool fixture_wait_buffer_full_notification(void); 96uint32_t fixture_get_buffer_full_wrapped_count(void); 97void fixture_reset_buffer_full_notification(void); 98bool fixture_compare_records(const char* expected); 99 100static inline void fixture_scope_cleanup(bool* scope) { 101 fixture_tear_down(); 102} 103 104#define DEFAULT_BUFFER_SIZE_BYTES (1024u * 1024u) 105 106// This isn't a do-while because of the cleanup. 107#define BEGIN_TRACE_TEST_ETC(attach_to_thread, mode, buffer_size) \ 108 BEGIN_TEST; \ 109 __attribute__((cleanup(fixture_scope_cleanup))) bool __scope; \ 110 (void)__scope; \ 111 fixture_set_up((attach_to_thread), (mode), (buffer_size)) 112 113#define BEGIN_TRACE_TEST \ 114 BEGIN_TRACE_TEST_ETC(kNoAttachToThread, TRACE_BUFFERING_MODE_ONESHOT, \ 115 DEFAULT_BUFFER_SIZE_BYTES) 116 117#define END_TRACE_TEST \ 118 END_TEST; 119 120#ifndef NTRACE 121#ifdef __cplusplus 122#define ASSERT_RECORDS(expected_c, expected_cpp) \ 123 ASSERT_TRUE(fixture_compare_records(expected_c expected_cpp), "record mismatch") 124#define ASSERT_N_RECORDS(max_num_recs, expected_c, expected_cpp, records) \ 125 ASSERT_TRUE(fixture_compare_n_records((max_num_recs), expected_c expected_cpp, (records)), "record mismatch") 126#else 127#define ASSERT_RECORDS(expected_c, expected_cpp) \ 128 ASSERT_TRUE(fixture_compare_records(expected_c), "record mismatch") 129#endif // __cplusplus 130#else 131#define ASSERT_RECORDS(expected_c, expected_cpp) \ 132 ASSERT_TRUE(fixture_compare_records(""), "record mismatch") 133#ifdef __cplusplus 134#define ASSERT_N_RECORDS(max_num_recs, expected_c, expected_cpp, records) \ 135 ASSERT_TRUE(fixture_compare_records((max_num_recs), "", (records)), "record mismatch") 136#endif 137#endif // NTRACE 138 139__END_CDECLS 140