blob: 9210072269bf2a04cbabd5585f0de2ae335a7aba [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 <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/trace-engine/context.h>
#include <lib/trace-engine/handler.h>
#include <lib/trace-engine/types.h>
#include <lib/trace-provider/handler.h>
#include <stddef.h>
#include <array>
#include <memory>
#include <trace-test-utils/compare_records.h>
#include <trace-test-utils/read_records.h>
#include <zxtest/zxtest.h>
#include "trace-vthread/event_vthread.h"
// Helper macros for writing tests.
#define I32_ARGS1 "k1", TA_INT32(1)
#define I32_ARGS4 "k1", TA_INT32(1), "k2", TA_INT32(2), "k3", TA_INT32(3), "k4", TA_INT32(4)
#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 init_status = trace_engine_initialize(loop_.dispatcher(), this, kBufferingMode,
buffer_->data(), buffer_->size());
zx_status_t start_status = trace_engine_start(TRACE_START_CLEAR_ENTIRE_BUFFER);
return init_status == ZX_OK && start_status == ZX_OK;
}
bool StopTracing() {
trace_engine_terminate();
loop_.RunUntilIdle();
return true;
}
void CompareBuffer(const char* expected) {
fbl::Vector<trace::Record> records;
ASSERT_TRUE(trace_testing::ReadRecords(buffer_->data(), buffer_->size(), &records));
ASSERT_TRUE(trace_testing::CompareBuffer(records, expected));
}
private:
async::Loop loop_{&kAsyncLoopConfigAttachToCurrentThread};
std::unique_ptr<std::array<uint8_t, kBufferSize>> buffer_;
};
TEST(EventThreadTests, TestVthreadDurationBegin) {
TraceFixture fixture;
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_NO_FATAL_FAILURES(
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\
"));
}
TEST(EventThreadTests, TestVthreadDurationEnd) {
TraceFixture fixture;
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_NO_FATAL_FAILURES(
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\
"));
}
TEST(EventThreadTests, TestVthreadFlowBegin) {
TraceFixture fixture;
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_NO_FATAL_FAILURES(
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\
"));
}
TEST(EventThreadTests, TestVthreadFlowStep) {
TraceFixture fixture;
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_NO_FATAL_FAILURES(
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\
"));
}
TEST(EventThreadTests, TestVthreadFlowEnd) {
TraceFixture fixture;
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_NO_FATAL_FAILURES(
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\
"));
}
TEST(EventThreadTests, TestVthreadCounter) {
TraceFixture fixture;
ASSERT_TRUE(fixture.StartTracing());
TRACE_VTHREAD_COUNTER("+enabled", "name", "virtual-thread", 1u, 2u, zx_ticks_get());
TRACE_VTHREAD_COUNTER("+enabled", "name", "virtual-thread", 1u, 2u, zx_ticks_get(), I32_ARGS1);
TRACE_VTHREAD_COUNTER("+enabled", "name", "virtual-thread", 1u, 2u, zx_ticks_get(), I32_ARGS4);
ASSERT_TRUE(fixture.StopTracing());
ASSERT_NO_FATAL_FAILURES(
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\", Counter(id: 2), {})\n\
String(index: 4, \"k1\")\n\
Event(ts: <>, pt: <>, category: \"+enabled\", name: \"name\", Counter(id: 2), {k1: int32(1)})\n\
String(index: 5, \"k2\")\n\
String(index: 6, \"k3\")\n\
String(index: 7, \"k4\")\n\
Event(ts: <>, pt: <>, category: \"+enabled\", name: \"name\", Counter(id: 2), {k1: int32(1), k2: int32(2), k3: int32(3), k4: int32(4)})\n\
"));
}