blob: 3a2138cd8215b85ff60e8ff036473fe143fd75e6 [file] [log] [blame]
//===-- fdr_log_writer_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 <time.h>
#include "xray/xray_records.h"
#include "xray_fdr_log_writer.h"
#include "llvm/Support/DataExtractor.h"
#include "llvm/Testing/Support/Error.h"
#include "llvm/XRay/Trace.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
namespace __xray {
namespace {
static constexpr size_t kSize = 4096;
using ::llvm::HasValue;
using ::testing::Eq;
using ::testing::SizeIs;
// Exercise the common code path where we initialize a buffer and are able to
// write some records successfully.
TEST(FdrLogWriterTest, WriteSomeRecords) {
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));
ASSERT_EQ(Buffers.releaseBuffer(B), BufferQueue::ErrorCode::Ok);
ASSERT_EQ(B.Data, nullptr);
ASSERT_EQ(Buffers.finalize(), BufferQueue::ErrorCode::Ok);
// 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);
llvm::DataExtractor DE(Serialized, true, 8);
auto TraceOrErr = llvm::xray::loadTrace(DE);
EXPECT_THAT_EXPECTED(TraceOrErr, HasValue(SizeIs(2)));
}
} // namespace
} // namespace __xray