summaryrefslogtreecommitdiffstats
path: root/compiler-rt/lib/xray/tests
diff options
context:
space:
mode:
authorDean Michael Berris <dberris@google.com>2018-10-15 02:57:06 +0000
committerDean Michael Berris <dberris@google.com>2018-10-15 02:57:06 +0000
commit3c01508409d3e9a7e43950318b626e2bd1bf7e78 (patch)
treef68110bd424d7adb2a28b98baaa234ca667c6270 /compiler-rt/lib/xray/tests
parent06aea1720a632634cd4bd0a718042e8507579f1d (diff)
downloadbcm5719-llvm-3c01508409d3e9a7e43950318b626e2bd1bf7e78.tar.gz
bcm5719-llvm-3c01508409d3e9a7e43950318b626e2bd1bf7e78.zip
[XRay][compiler-rt] FDR Mode Controller
Summary: This change implements a controller for abstracting away the details of what happens when tracing with FDR mode. This controller type allows us to test in isolation the various cases where we're encountering function entry, exit, and other kinds of events we are handling when FDR mode is enabled. This change introduces a number of testing facilities we've needed to better support expressing the conditions we need for the unit tests. We leave some TODOs for moving those utilities into the LLVM project, sitting in the `Testing` library, to make matching conditions on XRay `Trace` instances through googlemock more manageable and declarative. We don't wire in the controller right away, to allow us to incrementally update the implementation(s) as we increase testing coverage of the controller type. There's a need to re-think the way we're managing buffers in a multi-threaded environment, which is more invasive than this implementation. This step in the process allows us to encode our assumptions in the implementation of the controller, and then evolve the buffer queue implementation to support generational buffer management to ensure we can continue to support the cases we're already supporting with the controller. Reviewers: mboerger, eizan Subscribers: mgorny, llvm-commits, jfb Differential Revision: https://reviews.llvm.org/D52588 llvm-svn: 344488
Diffstat (limited to 'compiler-rt/lib/xray/tests')
-rw-r--r--compiler-rt/lib/xray/tests/unit/CMakeLists.txt8
-rw-r--r--compiler-rt/lib/xray/tests/unit/fdr_controller_test.cc242
-rw-r--r--compiler-rt/lib/xray/tests/unit/fdr_log_writer_test.cc70
-rw-r--r--compiler-rt/lib/xray/tests/unit/test_helpers.cc91
-rw-r--r--compiler-rt/lib/xray/tests/unit/test_helpers.h59
5 files changed, 441 insertions, 29 deletions
diff --git a/compiler-rt/lib/xray/tests/unit/CMakeLists.txt b/compiler-rt/lib/xray/tests/unit/CMakeLists.txt
index d0ead947df2..42ea43750e3 100644
--- a/compiler-rt/lib/xray/tests/unit/CMakeLists.txt
+++ b/compiler-rt/lib/xray/tests/unit/CMakeLists.txt
@@ -1,8 +1,10 @@
add_xray_unittest(XRayTest SOURCES
- buffer_queue_test.cc
allocator_test.cc
- segmented_array_test.cc
+ buffer_queue_test.cc
+ fdr_controller_test.cc
+ fdr_log_writer_test.cc
function_call_trie_test.cc
profile_collector_test.cc
- fdr_log_writer_test.cc
+ segmented_array_test.cc
+ test_helpers.cc
xray_unit_test_main.cc)
diff --git a/compiler-rt/lib/xray/tests/unit/fdr_controller_test.cc b/compiler-rt/lib/xray/tests/unit/fdr_controller_test.cc
new file mode 100644
index 00000000000..73666a76b3f
--- /dev/null
+++ b/compiler-rt/lib/xray/tests/unit/fdr_controller_test.cc
@@ -0,0 +1,242 @@
+//===-- fdr_controller_test.cc --------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of XRay, a function call tracing system.
+//
+//===----------------------------------------------------------------------===//
+#include <algorithm>
+#include <memory>
+#include <time.h>
+
+#include "test_helpers.h"
+#include "xray/xray_records.h"
+#include "xray_buffer_queue.h"
+#include "xray_fdr_controller.h"
+#include "xray_fdr_log_writer.h"
+#include "llvm/Support/DataExtractor.h"
+#include "llvm/Testing/Support/Error.h"
+#include "llvm/XRay/Trace.h"
+#include "llvm/XRay/XRayRecord.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace __xray {
+namespace {
+
+using ::llvm::HasValue;
+using ::llvm::xray::testing::FuncId;
+using ::llvm::xray::testing::HasArg;
+using ::llvm::xray::testing::RecordType;
+using ::testing::AllOf;
+using ::testing::ElementsAre;
+using ::testing::Eq;
+using ::testing::Field;
+using ::testing::IsEmpty;
+using ::testing::SizeIs;
+
+class FunctionSequenceTest : public ::testing::Test {
+protected:
+ BufferQueue::Buffer B{};
+ std::unique_ptr<BufferQueue> BQ;
+ std::unique_ptr<FDRLogWriter> W;
+ std::unique_ptr<FDRController<>> C;
+
+public:
+ void SetUp() override {
+ bool Success;
+ BQ = llvm::make_unique<BufferQueue>(4096, 1, Success);
+ ASSERT_TRUE(Success);
+ ASSERT_EQ(BQ->getBuffer(B), BufferQueue::ErrorCode::Ok);
+ W = llvm::make_unique<FDRLogWriter>(B);
+ C = llvm::make_unique<FDRController<>>(BQ.get(), B, *W, clock_gettime, 0);
+ }
+};
+
+TEST_F(FunctionSequenceTest, DefaultInitFinalizeFlush) {
+ ASSERT_TRUE(C->functionEnter(1, 2, 3));
+ ASSERT_TRUE(C->functionExit(1, 2, 3));
+ ASSERT_TRUE(C->flush());
+ ASSERT_EQ(BQ->finalize(), BufferQueue::ErrorCode::Ok);
+
+ // Serialize the buffers then test to see we find the expected records.
+ std::string Serialized = serialize(*BQ, 3);
+ llvm::DataExtractor DE(Serialized, true, 8);
+ auto TraceOrErr = llvm::xray::loadTrace(DE);
+ EXPECT_THAT_EXPECTED(
+ TraceOrErr,
+ HasValue(ElementsAre(
+ AllOf(FuncId(1), RecordType(llvm::xray::RecordTypes::ENTER)),
+ AllOf(FuncId(1), RecordType(llvm::xray::RecordTypes::EXIT)))));
+}
+
+TEST_F(FunctionSequenceTest, ThresholdsAreEnforced) {
+ C = llvm::make_unique<FDRController<>>(BQ.get(), B, *W, clock_gettime, 1000);
+ ASSERT_TRUE(C->functionEnter(1, 2, 3));
+ ASSERT_TRUE(C->functionExit(1, 2, 3));
+ ASSERT_TRUE(C->flush());
+ ASSERT_EQ(BQ->finalize(), BufferQueue::ErrorCode::Ok);
+
+ // Serialize the buffers then test to see we find the *no* records, because
+ // the function entry-exit comes under the cycle threshold.
+ std::string Serialized = serialize(*BQ, 3);
+ llvm::DataExtractor DE(Serialized, true, 8);
+ auto TraceOrErr = llvm::xray::loadTrace(DE);
+ EXPECT_THAT_EXPECTED(TraceOrErr, HasValue(IsEmpty()));
+}
+
+TEST_F(FunctionSequenceTest, ArgsAreHandledAndKept) {
+ C = llvm::make_unique<FDRController<>>(BQ.get(), B, *W, clock_gettime, 1000);
+ ASSERT_TRUE(C->functionEnterArg(1, 2, 3, 4));
+ ASSERT_TRUE(C->functionExit(1, 2, 3));
+ ASSERT_TRUE(C->flush());
+ ASSERT_EQ(BQ->finalize(), BufferQueue::ErrorCode::Ok);
+
+ // Serialize the buffers then test to see we find the function enter arg
+ // record with the specified argument.
+ std::string Serialized = serialize(*BQ, 3);
+ llvm::DataExtractor DE(Serialized, true, 8);
+ auto TraceOrErr = llvm::xray::loadTrace(DE);
+ EXPECT_THAT_EXPECTED(
+ TraceOrErr,
+ HasValue(ElementsAre(
+ AllOf(FuncId(1), RecordType(llvm::xray::RecordTypes::ENTER_ARG),
+ HasArg(4)),
+ AllOf(FuncId(1), RecordType(llvm::xray::RecordTypes::EXIT)))));
+}
+
+TEST_F(FunctionSequenceTest, RewindingMultipleCalls) {
+ C = llvm::make_unique<FDRController<>>(BQ.get(), B, *W, clock_gettime, 1000);
+
+ // First we construct an arbitrarily deep function enter/call stack.
+ // We also ensure that we are in the same CPU.
+ uint64_t TSC = 1;
+ uint16_t CPU = 1;
+ ASSERT_TRUE(C->functionEnter(1, TSC++, CPU));
+ ASSERT_TRUE(C->functionEnter(2, TSC++, CPU));
+ ASSERT_TRUE(C->functionEnter(3, TSC++, CPU));
+
+ // Then we exit them one at a time, in reverse order of entry.
+ ASSERT_TRUE(C->functionExit(3, TSC++, CPU));
+ ASSERT_TRUE(C->functionExit(2, TSC++, CPU));
+ ASSERT_TRUE(C->functionExit(1, TSC++, CPU));
+
+ ASSERT_TRUE(C->flush());
+ ASSERT_EQ(BQ->finalize(), BufferQueue::ErrorCode::Ok);
+
+ // Serialize the buffers then test to see we find that all the calls have been
+ // unwound because all of them are under the cycle counter threshold.
+ std::string Serialized = serialize(*BQ, 3);
+ llvm::DataExtractor DE(Serialized, true, 8);
+ auto TraceOrErr = llvm::xray::loadTrace(DE);
+ EXPECT_THAT_EXPECTED(TraceOrErr, HasValue(IsEmpty()));
+}
+
+TEST_F(FunctionSequenceTest, RewindingIntermediaryTailExits) {
+ C = llvm::make_unique<FDRController<>>(BQ.get(), B, *W, clock_gettime, 1000);
+
+ // First we construct an arbitrarily deep function enter/call stack.
+ // We also ensure that we are in the same CPU.
+ uint64_t TSC = 1;
+ uint16_t CPU = 1;
+ ASSERT_TRUE(C->functionEnter(1, TSC++, CPU));
+ ASSERT_TRUE(C->functionEnter(2, TSC++, CPU));
+ ASSERT_TRUE(C->functionEnter(3, TSC++, CPU));
+
+ // Next we tail-exit into a new function multiple times.
+ ASSERT_TRUE(C->functionTailExit(3, TSC++, CPU));
+ ASSERT_TRUE(C->functionEnter(4, TSC++, CPU));
+ ASSERT_TRUE(C->functionTailExit(4, TSC++, CPU));
+ ASSERT_TRUE(C->functionEnter(5, TSC++, CPU));
+ ASSERT_TRUE(C->functionTailExit(5, TSC++, CPU));
+ ASSERT_TRUE(C->functionEnter(6, TSC++, CPU));
+
+ // Then we exit them one at a time, in reverse order of entry.
+ ASSERT_TRUE(C->functionExit(6, TSC++, CPU));
+ ASSERT_TRUE(C->functionExit(2, TSC++, CPU));
+ ASSERT_TRUE(C->functionExit(1, TSC++, CPU));
+ ASSERT_TRUE(C->flush());
+ ASSERT_EQ(BQ->finalize(), BufferQueue::ErrorCode::Ok);
+
+ // Serialize the buffers then test to see we find that all the calls have been
+ // unwound because all of them are under the cycle counter threshold.
+ std::string Serialized = serialize(*BQ, 3);
+ llvm::DataExtractor DE(Serialized, true, 8);
+ auto TraceOrErr = llvm::xray::loadTrace(DE);
+ EXPECT_THAT_EXPECTED(TraceOrErr, HasValue(IsEmpty()));
+}
+
+class BufferManagementTest : public ::testing::Test {
+protected:
+ BufferQueue::Buffer B{};
+ std::unique_ptr<BufferQueue> BQ;
+ std::unique_ptr<FDRLogWriter> W;
+ std::unique_ptr<FDRController<>> C;
+
+ static constexpr size_t kBuffers = 10;
+
+public:
+ void SetUp() override {
+ bool Success;
+ BQ = llvm::make_unique<BufferQueue>(sizeof(MetadataRecord) * 4 +
+ sizeof(FunctionRecord) * 2,
+ kBuffers, Success);
+ ASSERT_TRUE(Success);
+ ASSERT_EQ(BQ->getBuffer(B), BufferQueue::ErrorCode::Ok);
+ W = llvm::make_unique<FDRLogWriter>(B);
+ C = llvm::make_unique<FDRController<>>(BQ.get(), B, *W, clock_gettime, 0);
+ }
+};
+
+constexpr size_t BufferManagementTest::kBuffers;
+
+TEST_F(BufferManagementTest, HandlesOverflow) {
+ uint64_t TSC = 1;
+ uint16_t CPU = 1;
+ for (size_t I = 0; I < kBuffers; ++I) {
+ ASSERT_TRUE(C->functionEnter(1, TSC++, CPU));
+ ASSERT_TRUE(C->functionExit(1, TSC++, CPU));
+ }
+ C->flush();
+ ASSERT_EQ(BQ->finalize(), BufferQueue::ErrorCode::Ok);
+
+ std::string Serialized = serialize(*BQ, 3);
+ llvm::DataExtractor DE(Serialized, true, 8);
+ auto TraceOrErr = llvm::xray::loadTrace(DE);
+ EXPECT_THAT_EXPECTED(TraceOrErr, HasValue(SizeIs(kBuffers * 2)));
+}
+
+TEST_F(BufferManagementTest, HandlesFinalizedBufferQueue) {
+ uint64_t TSC = 1;
+ uint16_t CPU = 1;
+
+ // First write one function entry.
+ ASSERT_TRUE(C->functionEnter(1, TSC++, CPU));
+
+ // Then we finalize the buffer queue, simulating the case where the logging
+ // has been finalized.
+ ASSERT_EQ(BQ->finalize(), BufferQueue::ErrorCode::Ok);
+
+ // At this point further calls to the controller must fail.
+ ASSERT_FALSE(C->functionExit(1, TSC++, CPU));
+
+ // But flushing should succeed.
+ ASSERT_TRUE(C->flush());
+
+ // We expect that we'll only be able to find the function enter event, but not
+ // the function exit event.
+ std::string Serialized = serialize(*BQ, 3);
+ llvm::DataExtractor DE(Serialized, true, 8);
+ auto TraceOrErr = llvm::xray::loadTrace(DE);
+ EXPECT_THAT_EXPECTED(
+ TraceOrErr, HasValue(ElementsAre(AllOf(
+ FuncId(1), RecordType(llvm::xray::RecordTypes::ENTER)))));
+}
+
+} // namespace
+} // namespace __xray
diff --git a/compiler-rt/lib/xray/tests/unit/fdr_log_writer_test.cc b/compiler-rt/lib/xray/tests/unit/fdr_log_writer_test.cc
index 3a2138cd821..1aeaf099d32 100644
--- a/compiler-rt/lib/xray/tests/unit/fdr_log_writer_test.cc
+++ b/compiler-rt/lib/xray/tests/unit/fdr_log_writer_test.cc
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include <time.h>
+#include "test_helpers.h"
#include "xray/xray_records.h"
#include "xray_fdr_log_writer.h"
#include "llvm/Support/DataExtractor.h"
@@ -26,8 +27,12 @@ namespace {
static constexpr size_t kSize = 4096;
using ::llvm::HasValue;
+using ::llvm::xray::testing::FuncId;
+using ::llvm::xray::testing::RecordType;
using ::testing::Eq;
-using ::testing::SizeIs;
+using ::testing::AllOf;
+using ::testing::IsEmpty;
+using ::testing::ElementsAre;
// Exercise the common code path where we initialize a buffer and are able to
// write some records successfully.
@@ -58,34 +63,47 @@ TEST(FdrLogWriterTest, WriteSomeRecords) {
// We then need to go through each element of the Buffers, and re-create a
// flat buffer that we would see if they were laid out in a file. This also
// means we need to write out the header manually.
- // TODO: Isolate the file header writing.
- std::string Serialized;
- std::aligned_storage<sizeof(XRayFileHeader), alignof(XRayFileHeader)>::type
- HeaderStorage;
- auto *Header = reinterpret_cast<XRayFileHeader *>(&HeaderStorage);
- new (Header) XRayFileHeader();
- Header->Version = 3;
- Header->Type = FileTypes::FDR_LOG;
- Header->CycleFrequency = 3e9;
- Header->ConstantTSC = 1;
- Header->NonstopTSC = 1;
- Serialized.append(reinterpret_cast<const char *>(&HeaderStorage),
- sizeof(XRayFileHeader));
- size_t BufferCount = 0;
- Buffers.apply([&](const BufferQueue::Buffer &B) {
- ++BufferCount;
- auto Size = atomic_load_relaxed(&B.Extents);
- auto Extents =
- createMetadataRecord<MetadataRecord::RecordKinds::BufferExtents>(Size);
- Serialized.append(reinterpret_cast<const char *>(&Extents),
- sizeof(Extents));
- Serialized.append(reinterpret_cast<const char *>(B.Data), Size);
- });
- ASSERT_EQ(BufferCount, 1u);
+ std::string Serialized = serialize(Buffers, 3);
+ llvm::DataExtractor DE(Serialized, true, 8);
+ auto TraceOrErr = llvm::xray::loadTrace(DE);
+ EXPECT_THAT_EXPECTED(
+ TraceOrErr,
+ HasValue(ElementsAre(
+ AllOf(FuncId(1), RecordType(llvm::xray::RecordTypes::ENTER)),
+ AllOf(FuncId(1), RecordType(llvm::xray::RecordTypes::EXIT)))));
+}
+
+TEST(FdrLogWriterTest, UnwriteRecords) {
+ bool Success = false;
+ BufferQueue Buffers(kSize, 1, Success);
+ BufferQueue::Buffer B;
+ ASSERT_EQ(Buffers.getBuffer(B), BufferQueue::ErrorCode::Ok);
+
+ FDRLogWriter Writer(B);
+ MetadataRecord Preamble[] = {
+ createMetadataRecord<MetadataRecord::RecordKinds::NewBuffer>(int32_t{1}),
+ createMetadataRecord<MetadataRecord::RecordKinds::WalltimeMarker>(
+ int64_t{1}, int32_t{2}),
+ createMetadataRecord<MetadataRecord::RecordKinds::Pid>(int32_t{1}),
+ };
+ ASSERT_THAT(Writer.writeMetadataRecords(Preamble),
+ Eq(sizeof(MetadataRecord) * 3));
+ ASSERT_TRUE(Writer.writeMetadata<MetadataRecord::RecordKinds::NewCPUId>(1));
+ ASSERT_TRUE(
+ Writer.writeFunction(FDRLogWriter::FunctionRecordKind::Enter, 1, 1));
+ ASSERT_TRUE(
+ Writer.writeFunction(FDRLogWriter::FunctionRecordKind::Exit, 1, 1));
+ Writer.undoWrites(sizeof(FunctionRecord) * 2);
+ ASSERT_EQ(Buffers.releaseBuffer(B), BufferQueue::ErrorCode::Ok);
+ ASSERT_EQ(B.Data, nullptr);
+ ASSERT_EQ(Buffers.finalize(), BufferQueue::ErrorCode::Ok);
+ // We've un-done the two function records we've written, and now we expect
+ // that we don't have any function records in the trace.
+ std::string Serialized = serialize(Buffers, 3);
llvm::DataExtractor DE(Serialized, true, 8);
auto TraceOrErr = llvm::xray::loadTrace(DE);
- EXPECT_THAT_EXPECTED(TraceOrErr, HasValue(SizeIs(2)));
+ EXPECT_THAT_EXPECTED(TraceOrErr, HasValue(IsEmpty()));
}
} // namespace
diff --git a/compiler-rt/lib/xray/tests/unit/test_helpers.cc b/compiler-rt/lib/xray/tests/unit/test_helpers.cc
new file mode 100644
index 00000000000..ebc40f88cde
--- /dev/null
+++ b/compiler-rt/lib/xray/tests/unit/test_helpers.cc
@@ -0,0 +1,91 @@
+//===-- test_helpers.cc ---------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of XRay, a function call tracing system.
+//
+//===----------------------------------------------------------------------===//
+#include "test_helpers.h"
+#include "xray/xray_records.h"
+#include "xray_buffer_queue.h"
+#include "xray_fdr_log_writer.h"
+#include <type_traits>
+
+// TODO: Move these to llvm/include/Testing/XRay/...
+namespace llvm {
+namespace xray {
+
+std::string RecordTypeAsString(RecordTypes T) {
+ switch (T) {
+ case RecordTypes::ENTER:
+ return "llvm::xray::RecordTypes::ENTER";
+ case RecordTypes::EXIT:
+ return "llvm::xray::RecordTypes::EXIT";
+ case RecordTypes::TAIL_EXIT:
+ return "llvm::xray::RecordTypes::TAIL_EXIT";
+ case RecordTypes::ENTER_ARG:
+ return "llvm::xray::RecordTypes::ENTER_ARG";
+ }
+ return "<UNKNOWN>";
+}
+
+void PrintTo(RecordTypes T, std::ostream *OS) {
+ *OS << RecordTypeAsString(T);
+}
+
+void PrintTo(const XRayRecord &R, std::ostream *OS) {
+ *OS << "XRayRecord { CPU = " << R.CPU
+ << "; Type = " << RecordTypeAsString(R.Type) << "; FuncId = " << R.FuncId
+ << "; TSC = " << R.TSC << "; TId = " << R.TId << "; PId = " << R.PId
+ << " Args = " << ::testing::PrintToString(R.CallArgs) << " }";
+}
+
+void PrintTo(const Trace &T, std::ostream *OS) {
+ const auto &H = T.getFileHeader();
+ *OS << "XRay Trace:\nHeader: { Version = " << H.Version
+ << "; Type = " << H.Type
+ << "; ConstantTSC = " << ::testing::PrintToString(H.ConstantTSC)
+ << "; NonstopTSC = " << ::testing::PrintToString(H.NonstopTSC)
+ << "; CycleFrequency = " << H.CycleFrequency << "; FreeFormData = '"
+ << ::testing::PrintToString(H.FreeFormData) << "' }\n";
+ for (const auto &R : T) {
+ PrintTo(R, OS);
+ *OS << "\n";
+ }
+}
+
+} // namespace xray
+} // namespace llvm
+
+namespace __xray {
+
+std::string serialize(BufferQueue &Buffers, int32_t Version) {
+ std::string Serialized;
+ std::aligned_storage<sizeof(XRayFileHeader), alignof(XRayFileHeader)>::type
+ HeaderStorage;
+ auto *Header = reinterpret_cast<XRayFileHeader *>(&HeaderStorage);
+ new (Header) XRayFileHeader();
+ Header->Version = Version;
+ Header->Type = FileTypes::FDR_LOG;
+ Header->CycleFrequency = 3e9;
+ Header->ConstantTSC = 1;
+ Header->NonstopTSC = 1;
+ Serialized.append(reinterpret_cast<const char *>(&HeaderStorage),
+ sizeof(XRayFileHeader));
+ Buffers.apply([&](const BufferQueue::Buffer &B) {
+ auto Size = atomic_load_relaxed(&B.Extents);
+ auto Extents =
+ createMetadataRecord<MetadataRecord::RecordKinds::BufferExtents>(Size);
+ Serialized.append(reinterpret_cast<const char *>(&Extents),
+ sizeof(Extents));
+ Serialized.append(reinterpret_cast<const char *>(B.Data), Size);
+ });
+ return Serialized;
+}
+
+} // namespace __xray
diff --git a/compiler-rt/lib/xray/tests/unit/test_helpers.h b/compiler-rt/lib/xray/tests/unit/test_helpers.h
new file mode 100644
index 00000000000..6eca7795e31
--- /dev/null
+++ b/compiler-rt/lib/xray/tests/unit/test_helpers.h
@@ -0,0 +1,59 @@
+//===-- test_helpers.h ----------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of XRay, a function call tracing system.
+//
+//===----------------------------------------------------------------------===//
+#ifndef COMPILER_RT_LIB_XRAY_TESTS_TEST_HELPERS_H_
+#define COMPILER_RT_LIB_XRAY_TESTS_TEST_HELPERS_H_
+
+#include "xray_buffer_queue.h"
+#include "llvm/XRay/XRayRecord.h"
+#include "llvm/XRay/Trace.h"
+#include "gmock/gmock.h"
+
+// TODO: Move these to llvm/include/Testing/XRay/...
+namespace llvm {
+namespace xray {
+
+std::string RecordTypeAsString(RecordTypes T);
+void PrintTo(RecordTypes T, std::ostream *OS);
+void PrintTo(const XRayRecord &R, std::ostream *OS);
+void PrintTo(const Trace &T, std::ostream *OS);
+
+namespace testing {
+
+MATCHER_P(FuncId, F, "") {
+ *result_listener << "where the function id is " << F;
+ return arg.FuncId == F;
+}
+
+MATCHER_P(RecordType, T, "") {
+ *result_listener << "where the record type is " << RecordTypeAsString(T);
+ return arg.Type == T;
+}
+
+MATCHER_P(HasArg, A, "") {
+ *result_listener << "where args contains " << A;
+ return !arg.CallArgs.empty() &&
+ std::any_of(arg.CallArgs.begin(), arg.CallArgs.end(),
+ [this](decltype(A) V) { return V == A; });
+}
+
+} // namespace testing
+} // namespace xray
+} // namespace llvm
+
+namespace __xray {
+
+std::string serialize(BufferQueue &Buffers, int32_t Version);
+
+} // namespace __xray
+
+#endif // COMPILER_RT_LIB_XRAY_TESTS_TEST_HELPERS_H_
OpenPOWER on IntegriCloud