blob: bc83903a364f4fba9f1fdccc800bc6eaacd9fc0e [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <stddef.h>
#include <array>
#include <memory>
#include <lib/async-loop/cpp/loop.h>
#include <trace-engine/context.h>
#include <trace-engine/handler.h>
#include <trace-engine/types.h>
#include <trace-provider/handler.h>
#include <trace-test-utils/compare_records.h>
#include <trace-test-utils/read_records.h>
#include <unittest/unittest.h>
#include "trace-vthread/event_vthread.h"
// Helper macros for writing tests.
#define STR_ARGS1 "k1", TA_STRING("v1")
#define STR_ARGS4 "k1", TA_STRING("v1"), "k2", TA_STRING("v2"), \
"k3", TA_STRING("v3"), "k4", TA_STRING("v4")
class TraceFixture : private trace::TraceHandler {
public:
static constexpr trace_buffering_mode_t kBufferingMode =
TRACE_BUFFERING_MODE_ONESHOT;
static constexpr size_t kBufferSize = 1024 * 1024;
TraceFixture() {
buffer_.reset(new std::array<uint8_t, kBufferSize>);
}
bool StartTracing() {
zx_status_t status = trace_start_engine(loop_.dispatcher(), this,
kBufferingMode,
buffer_->data(), buffer_->size());
return status == ZX_OK;
}
bool StopTracing() {
zx_status_t status = trace_stop_engine(ZX_OK);
loop_.RunUntilIdle();
return status == ZX_OK;
}
bool CompareBuffer(const char* expected) {
BEGIN_HELPER;
fbl::Vector<trace::Record> records;
ASSERT_TRUE(trace_testing::ReadRecords(buffer_->data(), buffer_->size(),
&records));
ASSERT_TRUE(trace_testing::CompareBuffer(records, expected));
END_HELPER;
}
private:
async::Loop loop_{&kAsyncLoopConfigAttachToThread};
std::unique_ptr<std::array<uint8_t, kBufferSize>> buffer_;
};
bool TestVthreadDurationBegin() {
TraceFixture fixture;
BEGIN_TEST;
ASSERT_TRUE(fixture.StartTracing());
TRACE_VTHREAD_DURATION_BEGIN("+enabled", "name", "virtual-thread", 1u, zx_ticks_get());
TRACE_VTHREAD_DURATION_BEGIN("+enabled", "name", "virtual-thread", 1u, zx_ticks_get(), STR_ARGS1);
TRACE_VTHREAD_DURATION_BEGIN("+enabled", "name", "virtual-thread", 1u, zx_ticks_get(), STR_ARGS4);
ASSERT_TRUE(fixture.StopTracing());
ASSERT_TRUE(fixture.CompareBuffer("\
String(index: 1, \"+enabled\")\n\
String(index: 2, \"process\")\n\
KernelObject(koid: <>, type: thread, name: \"virtual-thread\", {process: koid(<>)})\n\
Thread(index: 1, <>)\n\
String(index: 3, \"name\")\n\
Event(ts: <>, pt: <>, category: \"+enabled\", name: \"name\", DurationBegin, {})\n\
String(index: 4, \"k1\")\n\
Event(ts: <>, pt: <>, category: \"+enabled\", name: \"name\", DurationBegin, {k1: string(\"v1\")})\n\
String(index: 5, \"k2\")\n\
String(index: 6, \"k3\")\n\
String(index: 7, \"k4\")\n\
Event(ts: <>, pt: <>, category: \"+enabled\", name: \"name\", DurationBegin, {k1: string(\"v1\"), k2: string(\"v2\"), k3: string(\"v3\"), k4: string(\"v4\")})\n\
"));
END_TEST;
}
bool TestVthreadDurationEnd() {
TraceFixture fixture;
BEGIN_TEST;
ASSERT_TRUE(fixture.StartTracing());
TRACE_VTHREAD_DURATION_END("+enabled", "name", "virtual-thread", 1u, zx_ticks_get());
TRACE_VTHREAD_DURATION_END("+enabled", "name", "virtual-thread", 1u, zx_ticks_get(), STR_ARGS1);
TRACE_VTHREAD_DURATION_END("+enabled", "name", "virtual-thread", 1u, zx_ticks_get(), STR_ARGS4);
ASSERT_TRUE(fixture.StopTracing());
ASSERT_TRUE(fixture.CompareBuffer("\
String(index: 1, \"+enabled\")\n\
String(index: 2, \"process\")\n\
KernelObject(koid: <>, type: thread, name: \"virtual-thread\", {process: koid(<>)})\n\
Thread(index: 1, <>)\n\
String(index: 3, \"name\")\n\
Event(ts: <>, pt: <>, category: \"+enabled\", name: \"name\", DurationEnd, {})\n\
String(index: 4, \"k1\")\n\
Event(ts: <>, pt: <>, category: \"+enabled\", name: \"name\", DurationEnd, {k1: string(\"v1\")})\n\
String(index: 5, \"k2\")\n\
String(index: 6, \"k3\")\n\
String(index: 7, \"k4\")\n\
Event(ts: <>, pt: <>, category: \"+enabled\", name: \"name\", DurationEnd, {k1: string(\"v1\"), k2: string(\"v2\"), k3: string(\"v3\"), k4: string(\"v4\")})\n\
"));
END_TEST;
}
bool TestVthreadFlowBegin() {
TraceFixture fixture;
BEGIN_TEST;
ASSERT_TRUE(fixture.StartTracing());
TRACE_VTHREAD_FLOW_BEGIN("+enabled", "name", "virtual-thread", 1u, 2u, zx_ticks_get());
TRACE_VTHREAD_FLOW_BEGIN("+enabled", "name", "virtual-thread", 1u, 2u, zx_ticks_get(), STR_ARGS1);
TRACE_VTHREAD_FLOW_BEGIN("+enabled", "name", "virtual-thread", 1u, 2u, zx_ticks_get(), STR_ARGS4);
ASSERT_TRUE(fixture.StopTracing());
ASSERT_TRUE(fixture.CompareBuffer("\
String(index: 1, \"+enabled\")\n\
String(index: 2, \"process\")\n\
KernelObject(koid: <>, type: thread, name: \"virtual-thread\", {process: koid(<>)})\n\
Thread(index: 1, <>)\n\
String(index: 3, \"name\")\n\
Event(ts: <>, pt: <>, category: \"+enabled\", name: \"name\", FlowBegin(id: 2), {})\n\
String(index: 4, \"k1\")\n\
Event(ts: <>, pt: <>, category: \"+enabled\", name: \"name\", FlowBegin(id: 2), {k1: string(\"v1\")})\n\
String(index: 5, \"k2\")\n\
String(index: 6, \"k3\")\n\
String(index: 7, \"k4\")\n\
Event(ts: <>, pt: <>, category: \"+enabled\", name: \"name\", FlowBegin(id: 2), {k1: string(\"v1\"), k2: string(\"v2\"), k3: string(\"v3\"), k4: string(\"v4\")})\n\
"));
END_TEST;
}
bool TestVthreadFlowStep() {
TraceFixture fixture;
BEGIN_TEST;
ASSERT_TRUE(fixture.StartTracing());
TRACE_VTHREAD_FLOW_STEP("+enabled", "name", "virtual-thread", 1u, 2u, zx_ticks_get());
TRACE_VTHREAD_FLOW_STEP("+enabled", "name", "virtual-thread", 1u, 2u, zx_ticks_get(), STR_ARGS1);
TRACE_VTHREAD_FLOW_STEP("+enabled", "name", "virtual-thread", 1u, 2u, zx_ticks_get(), STR_ARGS4);
ASSERT_TRUE(fixture.StopTracing());
ASSERT_TRUE(fixture.CompareBuffer("\
String(index: 1, \"+enabled\")\n\
String(index: 2, \"process\")\n\
KernelObject(koid: <>, type: thread, name: \"virtual-thread\", {process: koid(<>)})\n\
Thread(index: 1, <>)\n\
String(index: 3, \"name\")\n\
Event(ts: <>, pt: <>, category: \"+enabled\", name: \"name\", FlowStep(id: 2), {})\n\
String(index: 4, \"k1\")\n\
Event(ts: <>, pt: <>, category: \"+enabled\", name: \"name\", FlowStep(id: 2), {k1: string(\"v1\")})\n\
String(index: 5, \"k2\")\n\
String(index: 6, \"k3\")\n\
String(index: 7, \"k4\")\n\
Event(ts: <>, pt: <>, category: \"+enabled\", name: \"name\", FlowStep(id: 2), {k1: string(\"v1\"), k2: string(\"v2\"), k3: string(\"v3\"), k4: string(\"v4\")})\n\
"));
END_TEST;
}
bool TestVthreadFlowEnd() {
TraceFixture fixture;
BEGIN_TEST;
ASSERT_TRUE(fixture.StartTracing());
TRACE_VTHREAD_FLOW_END("+enabled", "name", "virtual-thread", 1u, 2u, zx_ticks_get());
TRACE_VTHREAD_FLOW_END("+enabled", "name", "virtual-thread", 1u, 2u, zx_ticks_get(), STR_ARGS1);
TRACE_VTHREAD_FLOW_END("+enabled", "name", "virtual-thread", 1u, 2u, zx_ticks_get(), STR_ARGS4);
ASSERT_TRUE(fixture.StopTracing());
ASSERT_TRUE(fixture.CompareBuffer("\
String(index: 1, \"+enabled\")\n\
String(index: 2, \"process\")\n\
KernelObject(koid: <>, type: thread, name: \"virtual-thread\", {process: koid(<>)})\n\
Thread(index: 1, <>)\n\
String(index: 3, \"name\")\n\
Event(ts: <>, pt: <>, category: \"+enabled\", name: \"name\", FlowEnd(id: 2), {})\n\
String(index: 4, \"k1\")\n\
Event(ts: <>, pt: <>, category: \"+enabled\", name: \"name\", FlowEnd(id: 2), {k1: string(\"v1\")})\n\
String(index: 5, \"k2\")\n\
String(index: 6, \"k3\")\n\
String(index: 7, \"k4\")\n\
Event(ts: <>, pt: <>, category: \"+enabled\", name: \"name\", FlowEnd(id: 2), {k1: string(\"v1\"), k2: string(\"v2\"), k3: string(\"v3\"), k4: string(\"v4\")})\n\
"));
END_TEST;
}
BEGIN_TEST_CASE(event_thread_tests)
RUN_TEST(TestVthreadDurationBegin)
RUN_TEST(TestVthreadDurationEnd)
RUN_TEST(TestVthreadFlowBegin)
RUN_TEST(TestVthreadFlowStep)
RUN_TEST(TestVthreadFlowEnd)
END_TEST_CASE(event_thread_tests)