From a78a870d6beb923206383dbcf35809d3065f1ebc Mon Sep 17 00:00:00 2001 From: Doug Evans <dje@google.com> Date: Tue, 14 May 2019 00:25:27 +0000 Subject: [PATCH] [ktrace_provider] Add test harness ... and context-switch tests PT-158 #done Change-Id: I5023f7cfbb073ae7999fcdcd59d2d9370be75963 --- garnet/bin/ktrace_provider/BUILD.gn | 61 ++++- garnet/bin/ktrace_provider/app.cc | 11 +- garnet/bin/ktrace_provider/device_reader.cc | 45 ++++ garnet/bin/ktrace_provider/device_reader.h | 33 +++ garnet/bin/ktrace_provider/importer.cc | 10 +- garnet/bin/ktrace_provider/importer.h | 19 +- .../bin/ktrace_provider/importer_unittest.cc | 228 ++++++++++++++++++ .../ktrace_provider/meta/importer_tests.cmx | 5 + garnet/bin/ktrace_provider/reader.cc | 60 ++--- garnet/bin/ktrace_provider/reader.h | 26 +- garnet/bin/ktrace_provider/tags.cc | 2 + garnet/bin/ktrace_provider/tags.h | 4 +- garnet/bin/ktrace_provider/test_reader.cc | 20 ++ garnet/bin/ktrace_provider/test_reader.h | 26 ++ garnet/packages/tests/BUILD.gn | 1 + 15 files changed, 474 insertions(+), 77 deletions(-) create mode 100644 garnet/bin/ktrace_provider/device_reader.cc create mode 100644 garnet/bin/ktrace_provider/device_reader.h create mode 100644 garnet/bin/ktrace_provider/importer_unittest.cc create mode 100644 garnet/bin/ktrace_provider/meta/importer_tests.cmx create mode 100644 garnet/bin/ktrace_provider/test_reader.cc create mode 100644 garnet/bin/ktrace_provider/test_reader.h diff --git a/garnet/bin/ktrace_provider/BUILD.gn b/garnet/bin/ktrace_provider/BUILD.gn index e96bfb70a0e..614fdab9786 100644 --- a/garnet/bin/ktrace_provider/BUILD.gn +++ b/garnet/bin/ktrace_provider/BUILD.gn @@ -3,6 +3,25 @@ # found in the LICENSE file. import("//build/package.gni") +import("//build/test/test_package.gni") + +source_set("importer") { + sources = [ + "importer.cc", + "importer.h", + "reader.cc", + "reader.h", + "tags.cc", + "tags.h", + ] + + public_deps = [ + "//src/lib/fxl", + "//zircon/public/lib/fbl", + "//zircon/public/lib/trace-engine", + "//zircon/public/lib/zircon-internal", + ] +} executable("bin") { output_name = "ktrace_provider" @@ -10,18 +29,15 @@ executable("bin") { sources = [ "app.cc", "app.h", - "importer.cc", - "importer.h", + "device_reader.cc", + "device_reader.h", "log_importer.cc", "log_importer.h", "main.cc", - "reader.cc", - "reader.h", - "tags.cc", - "tags.h", ] deps = [ + ":importer", "//sdk/lib/sys/cpp", "//src/lib/fxl", "//zircon/public/fidl/fuchsia-tracing-kernel:fuchsia-tracing-kernel_c", @@ -47,3 +63,36 @@ package("ktrace_provider") { }, ] } + +executable("importer_test_app") { + testonly = true + output_name = "importer_tests" + + sources = [ + "importer_unittest.cc", + "test_reader.cc", + "test_reader.h", + ] + + deps = [ + ":importer", + "//src/lib/fxl", + "//third_party/googletest:gtest", + "//zircon/public/lib/fbl", + "//zircon/public/lib/trace-engine", + "//zircon/public/lib/trace-test-utils", + ] +} + +test_package("ktrace_provider_tests") { + deps = [ + ":importer_test_app" + ] + + tests = [ + { + name = "importer_tests" + environments = basic_envs + }, + ] +} diff --git a/garnet/bin/ktrace_provider/app.cc b/garnet/bin/ktrace_provider/app.cc index 48bc821dc6c..d3e5d9ac213 100644 --- a/garnet/bin/ktrace_provider/app.cc +++ b/garnet/bin/ktrace_provider/app.cc @@ -5,21 +5,22 @@ #include "garnet/bin/ktrace_provider/app.h" #include <fcntl.h> +#include <unistd.h> + #include <fuchsia/tracing/kernel/c/fidl.h> #include <lib/async/default.h> #include <lib/fdio/fdio.h> #include <lib/zx/channel.h> +#include <src/lib/fxl/arraysize.h> +#include <src/lib/fxl/logging.h> #include <trace-engine/instrumentation.h> #include <trace-provider/provider.h> -#include <unistd.h> #include <zircon/device/ktrace.h> #include <zircon/status.h> #include <zircon/syscalls/log.h> +#include "garnet/bin/ktrace_provider/device_reader.h" #include "garnet/bin/ktrace_provider/importer.h" -#include "garnet/bin/ktrace_provider/reader.h" -#include "src/lib/fxl/arraysize.h" -#include "src/lib/fxl/logging.h" namespace ktrace_provider { namespace { @@ -191,7 +192,7 @@ void App::StopKTrace() { // Acquire a context for writing to the trace buffer. auto buffer_context = trace_acquire_context(); - Reader reader; + DeviceReader reader; Importer importer(buffer_context); if (!importer.Import(reader)) { FXL_LOG(ERROR) << "Errors encountered while importing ktrace data"; diff --git a/garnet/bin/ktrace_provider/device_reader.cc b/garnet/bin/ktrace_provider/device_reader.cc new file mode 100644 index 00000000000..6d4ded832bb --- /dev/null +++ b/garnet/bin/ktrace_provider/device_reader.cc @@ -0,0 +1,45 @@ +// Copyright 2019 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 "garnet/bin/ktrace_provider/device_reader.h" + +#include <fcntl.h> +#include <limits.h> +#include <sys/stat.h> +#include <unistd.h> + +#include "src/lib/files/eintr_wrapper.h" + +namespace ktrace_provider { + +namespace { +constexpr char kTraceDev[] = "/dev/misc/ktrace"; +} // namespace + +DeviceReader::DeviceReader() + : Reader(buffer_, kChunkSize), + fd_(open(kTraceDev, O_RDONLY)) { +} + +void DeviceReader::ReadMoreData() { + memcpy(buffer_, current_, AvailableBytes()); + char* new_marker = buffer_ + AvailableBytes(); + + while (new_marker < end_) { + int bytes_read = + HANDLE_EINTR(read(fd_.get(), new_marker, + std::distance(const_cast<const char*>(new_marker), + end_))); + + if (bytes_read <= 0) + break; + + new_marker += bytes_read; + } + + marker_ = new_marker; + current_ = buffer_; +} + +} // namespace ktrace_provider diff --git a/garnet/bin/ktrace_provider/device_reader.h b/garnet/bin/ktrace_provider/device_reader.h new file mode 100644 index 00000000000..eb1aed68841 --- /dev/null +++ b/garnet/bin/ktrace_provider/device_reader.h @@ -0,0 +1,33 @@ +// Copyright 2019 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. + +#ifndef GARNET_BIN_KTRACE_PROVIDER_DEVICE_READER_H_ +#define GARNET_BIN_KTRACE_PROVIDER_DEVICE_READER_H_ + +#include <src/lib/files/unique_fd.h> +#include <src/lib/fxl/macros.h> + +#include "garnet/bin/ktrace_provider/reader.h" + +namespace ktrace_provider { + +class DeviceReader : public Reader { + public: + DeviceReader(); + + private: + static constexpr size_t kChunkSize{16 * 4 * 1024}; + + void ReadMoreData() override; + + fxl::UniqueFD fd_; + + char buffer_[kChunkSize]; + + FXL_DISALLOW_COPY_AND_ASSIGN(DeviceReader); +}; + +} // namespace ktrace_provider + +#endif // GARNET_BIN_KTRACE_PROVIDER_DEVICE_READER_H_ diff --git a/garnet/bin/ktrace_provider/importer.cc b/garnet/bin/ktrace_provider/importer.cc index b728ec769c1..0d22312890a 100644 --- a/garnet/bin/ktrace_provider/importer.cc +++ b/garnet/bin/ktrace_provider/importer.cc @@ -15,13 +15,6 @@ namespace ktrace_provider { namespace { -constexpr zx_koid_t kNoProcess = 0u; -constexpr zx_koid_t kKernelThreadFlag = 0x100000000; - -constexpr zx_koid_t kKernelPseudoKoidBase = 0x00000000'70000000u; -constexpr zx_koid_t kKernelPseudoCpuBase = - kKernelPseudoKoidBase + 0x00000000'01000000u; - constexpr uint64_t ToUInt64(uint32_t lo, uint32_t hi) { return (static_cast<uint64_t>(hi) << 32) | lo; } @@ -96,7 +89,8 @@ bool Importer::Import(Reader& reader) { while (true) { if (auto record = reader.ReadNextRecord()) { if (!ImportRecord(record, KTRACE_LEN(record->tag))) { - FXL_VLOG(2) << "Skipped ktrace record, tag=" << record->tag; + FXL_VLOG(2) << "Skipped ktrace record, tag=0x" << std::hex + << record->tag; } } else { break; diff --git a/garnet/bin/ktrace_provider/importer.h b/garnet/bin/ktrace_provider/importer.h index a4db5343498..be0d61df3f8 100644 --- a/garnet/bin/ktrace_provider/importer.h +++ b/garnet/bin/ktrace_provider/importer.h @@ -5,19 +5,21 @@ #ifndef GARNET_BIN_KTRACE_PROVIDER_IMPORTER_H_ #define GARNET_BIN_KTRACE_PROVIDER_IMPORTER_H_ -#include <fbl/string.h> -#include <fbl/string_piece.h> -#include <trace-engine/context.h> +#include <stddef.h> +#include <stdint.h> #include <array> #include <tuple> #include <unordered_map> #include <vector> +#include <fbl/string.h> +#include <fbl/string_piece.h> +#include <trace-engine/context.h> + +#include "garnet/bin/ktrace_provider/reader.h" #include "garnet/bin/ktrace_provider/tags.h" #include "src/lib/fxl/macros.h" -#include "stddef.h" -#include "stdint.h" namespace ktrace_provider { @@ -25,6 +27,13 @@ class Reader; class Importer { public: + static constexpr zx_koid_t kNoProcess = 0u; + static constexpr zx_koid_t kKernelThreadFlag = 0x100000000; + + static constexpr zx_koid_t kKernelPseudoKoidBase = 0x00000000'70000000u; + static constexpr zx_koid_t kKernelPseudoCpuBase = + kKernelPseudoKoidBase + 0x00000000'01000000u; + Importer(trace_context* context); ~Importer(); diff --git a/garnet/bin/ktrace_provider/importer_unittest.cc b/garnet/bin/ktrace_provider/importer_unittest.cc new file mode 100644 index 00000000000..326f792098a --- /dev/null +++ b/garnet/bin/ktrace_provider/importer_unittest.cc @@ -0,0 +1,228 @@ +// Copyright 2019 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 <fbl/algorithm.h> +#include <gtest/gtest.h> +#include <src/lib/fxl/command_line.h> +#include <src/lib/fxl/log_settings_command_line.h> +#include <trace-engine/instrumentation.h> +#include <trace-test-utils/fixture.h> + +#include "garnet/bin/ktrace_provider/importer.h" +#include "garnet/bin/ktrace_provider/test_reader.h" + +namespace ktrace_provider { +namespace { + +class TestImporter : public ::testing::Test { + public: + // A copy of kernel/thread.h:thread_state values we use. + enum class KernelThreadState : uint8_t { + // The naming style chosen here is to be consistent with thread.h. + // If its values change, just re-cut-n-paste. + THREAD_INITIAL = 0, + THREAD_READY, + THREAD_RUNNING, + THREAD_BLOCKED, + THREAD_BLOCKED_READ_LOCK, + THREAD_SLEEPING, + THREAD_SUSPENDED, + THREAD_DEATH, + }; + + void SetUp() { + fixture_set_up(kNoAttachToThread, TRACE_BUFFERING_MODE_ONESHOT, + kFxtBufferSize); + fixture_start_tracing(); + context_ = trace_acquire_context(); + ASSERT_NE(context_, nullptr); + } + + void StopTracing() { + if (context_) { + trace_release_context(context_); + context_ = nullptr; + } + fixture_stop_tracing(); + } + + void TearDown() { + // Stop tracing maybe again just in case. + StopTracing(); + fixture_tear_down(); + } + + // Extract the records in the buffer, discarding administrative records + // that the importer creates. + // TODO(dje): Use std::vector when fixture is ready. + bool ExtractRecords(fbl::Vector<trace::Record>* out_records) { + fbl::Vector<trace::Record> records; + + if (!fixture_read_records(&records)) { + return false; + } + + // The kernel process record is the last administrative record. + // Drop every record up to and including that one. + bool skipping = true; + for (auto& rec : records) { + if (skipping) { + if (rec.type() == trace::RecordType::kKernelObject) { + const trace::Record::KernelObject& kobj = rec.GetKernelObject(); + if (kobj.object_type == ZX_OBJ_TYPE_PROCESS && + kobj.koid == 0u && + kobj.name == "kernel") { + skipping = false; + } + } + } else { + out_records->push_back(std::move(rec)); + } + } + + // We should have found the kernel process record. + if (skipping) { + FXL_VLOG(1) << "Kernel process record not found"; + return false; + } + + return true; + } + + void CompareRecord(const trace::Record& rec, const char* expected) { + EXPECT_STREQ(rec.ToString().c_str(), expected); + } + + void EmitKtraceRecord(const void* record, size_t record_size) { + ASSERT_LE(record_size, KtraceAvailableBytes()); + memcpy(ktrace_buffer_next_, record, record_size); + ktrace_buffer_next_ += record_size; + } + + void EmitKtrace32Record(uint32_t tag, uint32_t tid, uint64_t ts, + uint32_t a, uint32_t b, uint32_t c, uint32_t d) { + const ktrace_rec_32b record { + .tag = tag, + .tid = tid, + .ts = ts, + .a = a, + .b = b, + .c = c, + .d = d, + }; + EmitKtraceRecord(&record, sizeof(record)); + } + + void EmitContextSwitchRecord(uint64_t ts, uint32_t old_thread_tid, + uint32_t new_thread_tid, uint8_t cpu, + KernelThreadState old_thread_state, + uint8_t old_thread_prio, + uint8_t new_thread_prio, + uint32_t new_kernel_thread) { + uint32_t old_kernel_thread = 0; // importer ignores this + EmitKtrace32Record(TAG_CONTEXT_SWITCH, old_thread_tid, ts, + new_thread_tid, + (cpu | + (static_cast<uint8_t>(old_thread_state) << 8) | + (old_thread_prio << 16) | (new_thread_prio << 24)), + old_kernel_thread, new_kernel_thread); + } + + bool StopTracingAndImportRecords(fbl::Vector<trace::Record>* out_records) { + TestReader reader{ktrace_buffer(), ktrace_buffer_written()}; + Importer importer{context()}; + + if (!importer.Import(reader)) { + return false; + } + + // Do this after importing as the importer needs tracing to be running in + // order to acquire a "context" with which to write records. + StopTracing(); + + return ExtractRecords(out_records); + } + + trace_context_t* context() const { return context_; } + + const char* ktrace_buffer() const { return ktrace_buffer_; } + + size_t ktrace_buffer_written() const { + return ktrace_buffer_next_ - ktrace_buffer_; + } + + private: + static constexpr size_t kKtraceBufferSize = 65536; + static constexpr size_t kFxtBufferSize = 65536; + + size_t KtraceAvailableBytes() { + return std::distance(ktrace_buffer_next_, ktrace_buffer_end_); + } + + char ktrace_buffer_[kKtraceBufferSize]; + char* ktrace_buffer_next_ = ktrace_buffer_; + char* ktrace_buffer_end_ = ktrace_buffer_ + kKtraceBufferSize; + trace_context_t* context_ = nullptr; +}; + +TEST_F(TestImporter, ContextSwitch) { + // Establish initial running thread. + EmitContextSwitchRecord( + 99, // ts + 0, // old_thread_tid + 42, // new_thread_tid + 1, // cpu + KernelThreadState::THREAD_RUNNING, // old_thread_state + 3, // old_thread_prio + 4, // new_thread_prio + 0); + // Test switching to user thread. + EmitContextSwitchRecord( + 100, // ts + 42, // old_thread_tid + 43, // new_thread_tid + 1, // cpu + KernelThreadState::THREAD_RUNNING, // old_thread_state + 5, // old_thread_prio + 6, // new_thread_prio + 0); + // Test switching to kernel thread. + EmitContextSwitchRecord( + 101, // ts + 43, // old_thread_tid + 0, // 0 --> kernel thread + 1, // cpu + KernelThreadState::THREAD_RUNNING, // old_thread_state + 7, // old_thread_prio + 8, // new_thread_prio + 12345678); + static const char* const expected[] = { + "ContextSwitch(ts: 99, cpu: 1, os: running, opt: 0/0, ipt: 0/42, oprio: 3, iprio: 4)", + "ContextSwitch(ts: 100, cpu: 1, os: running, opt: 0/42, ipt: 0/43, oprio: 5, iprio: 6)", + // 4307312974 = 12345678 | kKernelThreadFlag + "ContextSwitch(ts: 101, cpu: 1, os: running, opt: 0/43, ipt: 0/4307312974, oprio: 7, iprio: 8)", + }; + + fbl::Vector<trace::Record> records; + ASSERT_TRUE(StopTracingAndImportRecords(&records)); + ASSERT_EQ(records.size(), fbl::count_of(expected)); + for (size_t i = 0; i < records.size(); ++i) { + CompareRecord(records[i], expected[i]); + } +} + +} // namespace +} // namespace ktrace_provider + +// Provide our own main so that --verbose,etc. are recognized. +int main(int argc, char** argv) { + auto cl = fxl::CommandLineFromArgcArgv(argc, argv); + if (!fxl::SetLogSettingsFromCommandLine(cl)) { + return EXIT_FAILURE; + } + + testing::InitGoogleTest(&argc, argv); + + return RUN_ALL_TESTS(); +} diff --git a/garnet/bin/ktrace_provider/meta/importer_tests.cmx b/garnet/bin/ktrace_provider/meta/importer_tests.cmx new file mode 100644 index 00000000000..fd7604d7207 --- /dev/null +++ b/garnet/bin/ktrace_provider/meta/importer_tests.cmx @@ -0,0 +1,5 @@ +{ + "program": { + "binary": "test/importer_tests" + } +} diff --git a/garnet/bin/ktrace_provider/reader.cc b/garnet/bin/ktrace_provider/reader.cc index 7d71e61f596..9a6a68964da 100644 --- a/garnet/bin/ktrace_provider/reader.cc +++ b/garnet/bin/ktrace_provider/reader.cc @@ -2,62 +2,50 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "garnet/bin/ktrace_provider/reader.h" - -#include <fcntl.h> -#include <limits.h> -#include <sys/stat.h> -#include <unistd.h> +#include <lib/zircon-internal/ktrace.h> -#include "src/lib/files/eintr_wrapper.h" +#include "garnet/bin/ktrace_provider/reader.h" namespace ktrace_provider { -namespace { - -constexpr char kTraceDev[] = "/dev/misc/ktrace"; - -} // namespace -Reader::Reader() : fd_(open(kTraceDev, O_RDONLY)) {} +Reader::Reader(const char* buffer, size_t buffer_size) + : current_(buffer), + marker_(buffer), + end_(buffer + buffer_size) { +} -ktrace_header_t* Reader::ReadNextRecord() { - if (AvailableBytes() < sizeof(ktrace_header_t)) +const ktrace_header_t* Reader::ReadNextRecord() { + if (AvailableBytes() < sizeof(ktrace_header_t)) { ReadMoreData(); + } - if (AvailableBytes() < sizeof(ktrace_header_t)) + if (AvailableBytes() < sizeof(ktrace_header_t)) { + FXL_VLOG(10) << "No more records"; return nullptr; + } - auto record = reinterpret_cast<ktrace_header_t*>(current_); + auto record = reinterpret_cast<const ktrace_header_t*>(current_); - if (AvailableBytes() < KTRACE_LEN(record->tag)) + if (AvailableBytes() < KTRACE_LEN(record->tag)) { ReadMoreData(); + } - if (AvailableBytes() < KTRACE_LEN(record->tag)) + if (AvailableBytes() < KTRACE_LEN(record->tag)) { + FXL_VLOG(10) << "No more records, incomplete last record"; return nullptr; + } - record = reinterpret_cast<ktrace_header_t*>(current_); + record = reinterpret_cast<const ktrace_header_t*>(current_); current_ += KTRACE_LEN(record->tag); number_bytes_read_ += KTRACE_LEN(record->tag); number_records_read_ += 1; - return record; -} - -void Reader::ReadMoreData() { - memcpy(buffer_, current_, AvailableBytes()); - marker_ = buffer_ + AvailableBytes(); - while (marker_ < end_) { - int bytes_read = - HANDLE_EINTR(read(fd_.get(), marker_, std::distance(marker_, end_))); + FXL_VLOG(10) << "Importing ktrace event 0x" << std::hex + << KTRACE_EVENT(record->tag) << ", size " << std::dec + << KTRACE_LEN(record->tag); - if (bytes_read <= 0) - break; - - marker_ += bytes_read; - } - - current_ = buffer_; + return record; } } // namespace ktrace_provider diff --git a/garnet/bin/ktrace_provider/reader.h b/garnet/bin/ktrace_provider/reader.h index 275945e1cc4..5de6731cd1e 100644 --- a/garnet/bin/ktrace_provider/reader.h +++ b/garnet/bin/ktrace_provider/reader.h @@ -5,36 +5,34 @@ #ifndef GARNET_BIN_KTRACE_PROVIDER_READER_H_ #define GARNET_BIN_KTRACE_PROVIDER_READER_H_ -#include <lib/zircon-internal/ktrace.h> +#include <iterator> -#include "src/lib/files/unique_fd.h" -#include "src/lib/fxl/macros.h" +#include <src/lib/files/unique_fd.h> +#include <src/lib/fxl/macros.h> +#include <lib/zircon-internal/ktrace.h> namespace ktrace_provider { class Reader { public: - Reader(); + Reader(const char* buffer, size_t buffer_size); + virtual ~Reader() = default; - ktrace_header_t* ReadNextRecord(); + const ktrace_header_t* ReadNextRecord(); size_t number_bytes_read() const { return number_bytes_read_; } size_t number_records_read() const { return number_records_read_; } - private: - static constexpr size_t kChunkSize{16 * 4 * 1024}; - + protected: inline size_t AvailableBytes() const { return std::distance(current_, marker_); } - void ReadMoreData(); + virtual void ReadMoreData() = 0; - fxl::UniqueFD fd_; - char buffer_[kChunkSize]; - char* current_ = buffer_; - char* marker_ = buffer_; - char* end_ = buffer_ + kChunkSize; + const char* current_; + const char* marker_; + const char* end_; size_t number_bytes_read_ = 0; size_t number_records_read_ = 0; diff --git a/garnet/bin/ktrace_provider/tags.cc b/garnet/bin/ktrace_provider/tags.cc index 795b4439382..83462d1ac67 100644 --- a/garnet/bin/ktrace_provider/tags.cc +++ b/garnet/bin/ktrace_provider/tags.cc @@ -6,6 +6,8 @@ #include <mutex> +#include <lib/zircon-internal/ktrace.h> + namespace ktrace_provider { namespace { diff --git a/garnet/bin/ktrace_provider/tags.h b/garnet/bin/ktrace_provider/tags.h index db93d18905c..b2b48b594d3 100644 --- a/garnet/bin/ktrace_provider/tags.h +++ b/garnet/bin/ktrace_provider/tags.h @@ -5,9 +5,7 @@ #ifndef GARNET_BIN_KTRACE_PROVIDER_TAGS_H_ #define GARNET_BIN_KTRACE_PROVIDER_TAGS_H_ -#include <lib/zircon-internal/ktrace.h> - -#include "stdint.h" +#include <stdint.h> #include <unordered_map> diff --git a/garnet/bin/ktrace_provider/test_reader.cc b/garnet/bin/ktrace_provider/test_reader.cc new file mode 100644 index 00000000000..10f37b57a2f --- /dev/null +++ b/garnet/bin/ktrace_provider/test_reader.cc @@ -0,0 +1,20 @@ +// Copyright 2019 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 "garnet/bin/ktrace_provider/test_reader.h" + +namespace ktrace_provider { + +TestReader::TestReader(const void* trace_data, size_t trace_data_size) + : Reader(reinterpret_cast<const char*>(trace_data), trace_data_size) { + // Mark the end of "read" data. + marker_ = end_; +} + +void TestReader::ReadMoreData() { + // There is no more. + current_ = marker_; +} + +} // namespace ktrace_provider diff --git a/garnet/bin/ktrace_provider/test_reader.h b/garnet/bin/ktrace_provider/test_reader.h new file mode 100644 index 00000000000..fa29ed754b1 --- /dev/null +++ b/garnet/bin/ktrace_provider/test_reader.h @@ -0,0 +1,26 @@ +// Copyright 2019 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. + +#ifndef GARNET_BIN_KTRACE_PROVIDER_TEST_READER_H_ +#define GARNET_BIN_KTRACE_PROVIDER_TEST_READER_H_ + +#include <src/lib/fxl/macros.h> + +#include "garnet/bin/ktrace_provider/reader.h" + +namespace ktrace_provider { + +class TestReader : public Reader { + public: + TestReader(const void* trace_data, size_t trace_data_size); + + private: + void ReadMoreData() override; + + FXL_DISALLOW_COPY_AND_ASSIGN(TestReader); +}; + +} // namespace ktrace_provider + +#endif // GARNET_BIN_KTRACE_PROVIDER_TEST_READER_H_ diff --git a/garnet/packages/tests/BUILD.gn b/garnet/packages/tests/BUILD.gn index bc83c3a2c1d..e5a51acd05a 100644 --- a/garnet/packages/tests/BUILD.gn +++ b/garnet/packages/tests/BUILD.gn @@ -60,6 +60,7 @@ group("tracing") { testonly = true public_deps = [ "//garnet/bin/cpuperf_provider:cpuperf_provider_tests", + "//garnet/bin/ktrace_provider:ktrace_provider_tests", "//garnet/bin/trace/tests:trace_tests", "//garnet/bin/trace2json:trace2json_tests($host_toolchain)", "//garnet/bin/trace_stress", -- GitLab