#include <time.h>
#include "test_helpers.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 ::llvm::xray::testing::FuncId;
using ::llvm::xray::testing::RecordType;
using ::testing::AllOf;
using ::testing::ElementsAre;
using ::testing::Eq;
using ::testing::IsEmpty;
using ::testing::IsNull;
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);
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, ReuseBuffers) {
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>(
uint16_t{1}, uint64_t{1}));
uint64_t TSC = 1;
ASSERT_TRUE(
Writer.writeFunction(FDRLogWriter::FunctionRecordKind::Enter, 1, TSC++));
ASSERT_TRUE(
Writer.writeFunction(FDRLogWriter::FunctionRecordKind::Exit, 1, TSC++));
ASSERT_EQ(Buffers.releaseBuffer(B), BufferQueue::ErrorCode::Ok);
ASSERT_THAT(B.Data, IsNull());
ASSERT_EQ(Buffers.getBuffer(B), BufferQueue::ErrorCode::Ok);
Writer.resetRecord();
ASSERT_THAT(Writer.writeMetadataRecords(Preamble),
Eq(sizeof(MetadataRecord) * 3));
ASSERT_TRUE(Writer.writeMetadata<MetadataRecord::RecordKinds::NewCPUId>(
uint16_t{1}, uint64_t{1}));
ASSERT_TRUE(
Writer.writeFunction(FDRLogWriter::FunctionRecordKind::Enter, 1, TSC++));
ASSERT_EQ(Buffers.releaseBuffer(B), BufferQueue::ErrorCode::Ok);
ASSERT_THAT(B.Data, IsNull());
ASSERT_EQ(Buffers.finalize(), BufferQueue::ErrorCode::Ok);
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)))));
}
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);
std::string Serialized = serialize(Buffers, 3);
llvm::DataExtractor DE(Serialized, true, 8);
auto TraceOrErr = llvm::xray::loadTrace(DE);
EXPECT_THAT_EXPECTED(TraceOrErr, HasValue(IsEmpty()));
}
}
}