#include "foundation/trace.h" #include "test_harness.h" using pp::foundation::StatusCode; using pp::foundation::TraceRecorder; using pp::foundation::TraceSpanDesc; namespace { void records_completed_spans_with_context(pp::tests::Harness& h) { TraceRecorder recorder; const auto id = recorder.begin_span( TraceSpanDesc { .component = "paint", .name = "stroke_commit", .thread_id = 7, .frame_id = 11, .stroke_id = 13, }, 100); PP_EXPECT(h, id.ok()); PP_EXPECT(h, recorder.active_span_count() == 1U); PP_EXPECT(h, recorder.end_span(id.value(), 145).ok()); PP_EXPECT(h, recorder.active_span_count() == 0U); PP_EXPECT(h, recorder.events().size() == 1U); const auto& event = recorder.events()[0]; PP_EXPECT(h, event.component == "paint"); PP_EXPECT(h, event.name == "stroke_commit"); PP_EXPECT(h, event.thread_id == 7U); PP_EXPECT(h, event.frame_id == 11U); PP_EXPECT(h, event.stroke_id == 13U); PP_EXPECT(h, event.start_us == 100U); PP_EXPECT(h, event.duration_us == 45U); } void rejects_invalid_span_descriptions(pp::tests::Harness& h) { TraceRecorder recorder; const auto no_component = recorder.begin_span( TraceSpanDesc { .component = "", .name = "load" }, 1); const auto no_name = recorder.begin_span( TraceSpanDesc { .component = "assets", .name = "" }, 1); PP_EXPECT(h, !no_component.ok()); PP_EXPECT(h, no_component.status().code == StatusCode::invalid_argument); PP_EXPECT(h, !no_name.ok()); PP_EXPECT(h, no_name.status().code == StatusCode::invalid_argument); PP_EXPECT(h, recorder.events().empty()); } void rejects_bad_end_calls_without_recording_events(pp::tests::Harness& h) { TraceRecorder recorder; const auto id = recorder.begin_span( TraceSpanDesc { .component = "renderer", .name = "readback" }, 50); PP_EXPECT(h, id.ok()); const auto backwards = recorder.end_span(id.value(), 49); PP_EXPECT(h, !backwards.ok()); PP_EXPECT(h, backwards.code == StatusCode::invalid_argument); PP_EXPECT(h, recorder.active_span_count() == 1U); PP_EXPECT(h, recorder.events().empty()); PP_EXPECT(h, recorder.end_span(id.value(), 51).ok()); const auto duplicate = recorder.end_span(id.value(), 52); PP_EXPECT(h, !duplicate.ok()); PP_EXPECT(h, duplicate.code == StatusCode::out_of_range); PP_EXPECT(h, recorder.events().size() == 1U); } void clear_resets_events_and_span_ids(pp::tests::Harness& h) { TraceRecorder recorder; const auto first = recorder.begin_span( TraceSpanDesc { .component = "ui", .name = "layout" }, 10); PP_EXPECT(h, first.ok()); PP_EXPECT(h, recorder.end_span(first.value(), 20).ok()); recorder.clear(); const auto second = recorder.begin_span( TraceSpanDesc { .component = "ui", .name = "layout" }, 30); PP_EXPECT(h, second.ok()); PP_EXPECT(h, second.value() == first.value()); PP_EXPECT(h, recorder.events().empty()); PP_EXPECT(h, recorder.active_span_count() == 1U); } } int main() { pp::tests::Harness harness; harness.run("records_completed_spans_with_context", records_completed_spans_with_context); harness.run("rejects_invalid_span_descriptions", rejects_invalid_span_descriptions); harness.run("rejects_bad_end_calls_without_recording_events", rejects_bad_end_calls_without_recording_events); harness.run("clear_resets_events_and_span_ids", clear_resets_events_and_span_ids); return harness.finish(); }