diff --git a/include/llvm/XRay/BlockIndexer.h b/include/llvm/XRay/BlockIndexer.h index 46a7243685f..b42fa17f3fb 100644 --- a/include/llvm/XRay/BlockIndexer.h +++ b/include/llvm/XRay/BlockIndexer.h @@ -54,6 +54,8 @@ public: Error visit(NewBufferRecord &) override; Error visit(EndBufferRecord &) override; Error visit(FunctionRecord &) override; + Error visit(CustomEventRecordV5 &) override; + Error visit(TypedEventRecord &) override; /// The flush() function will clear out the current state of the visitor, to /// allow for explicitly flushing a block's records to the currently diff --git a/include/llvm/XRay/BlockPrinter.h b/include/llvm/XRay/BlockPrinter.h index 3a8f6e0d35e..bfb21e23951 100644 --- a/include/llvm/XRay/BlockPrinter.h +++ b/include/llvm/XRay/BlockPrinter.h @@ -50,6 +50,8 @@ public: Error visit(NewBufferRecord &) override; Error visit(EndBufferRecord &) override; Error visit(FunctionRecord &) override; + Error visit(CustomEventRecordV5 &) override; + Error visit(TypedEventRecord &) override; void reset() { CurrentState = State::Start; } }; diff --git a/include/llvm/XRay/BlockVerifier.h b/include/llvm/XRay/BlockVerifier.h index b43a435e93b..46371c13891 100644 --- a/include/llvm/XRay/BlockVerifier.h +++ b/include/llvm/XRay/BlockVerifier.h @@ -33,6 +33,7 @@ public: NewCPUId, TSCWrap, CustomEvent, + TypedEvent, Function, CallArg, EndOfBuffer, @@ -58,6 +59,8 @@ public: Error visit(NewBufferRecord &) override; Error visit(EndBufferRecord &) override; Error visit(FunctionRecord &) override; + Error visit(CustomEventRecordV5 &) override; + Error visit(TypedEventRecord &) override; Error verify(); void reset(); diff --git a/include/llvm/XRay/FDRRecords.h b/include/llvm/XRay/FDRRecords.h index 2d47ab3cfe5..9d48332d508 100644 --- a/include/llvm/XRay/FDRRecords.h +++ b/include/llvm/XRay/FDRRecords.h @@ -66,6 +66,7 @@ public: PIDEntry, NewBuffer, EndOfBuffer, + TypedEvent, }; Type type() const override { return Type::Metadata; } @@ -174,6 +175,52 @@ public: Error apply(RecordVisitor &V) override; }; +class CustomEventRecordV5 : public MetadataRecord { + int32_t Size = 0; + int32_t Delta = 0; + std::string Data{}; + friend class RecordInitializer; + +public: + CustomEventRecordV5() = default; + explicit CustomEventRecordV5(int32_t S, int32_t D, std::string P) + : MetadataRecord(), Size(S), Delta(D), Data(std::move(P)) {} + + MetadataType metadataType() const override { + return MetadataType::CustomEvent; + } + + int32_t size() const { return Size; } + int32_t delta() const { return Delta; } + StringRef data() const { return Data; } + + Error apply(RecordVisitor &V) override; +}; + +class TypedEventRecord : public MetadataRecord { + int32_t Size = 0; + int32_t Delta = 0; + uint16_t EventType = 0; + std::string Data{}; + friend class RecordInitializer; + +public: + TypedEventRecord() = default; + explicit TypedEventRecord(int32_t S, int32_t D, uint16_t E, std::string P) + : MetadataRecord(), Size(S), Delta(D), Data(std::move(P)) {} + + MetadataType metadataType() const override { + return MetadataType::TypedEvent; + } + + int32_t size() const { return Size; } + int32_t delta() const { return Delta; } + uint16_t eventType() const { return EventType; } + StringRef data() const { return Data; } + + Error apply(RecordVisitor &V) override; +}; + class CallArgRecord : public MetadataRecord { uint64_t Arg; friend class RecordInitializer; @@ -269,6 +316,8 @@ public: virtual Error visit(NewBufferRecord &) = 0; virtual Error visit(EndBufferRecord &) = 0; virtual Error visit(FunctionRecord &) = 0; + virtual Error visit(CustomEventRecordV5 &) = 0; + virtual Error visit(TypedEventRecord &) = 0; }; class RecordInitializer : public RecordVisitor { @@ -277,7 +326,7 @@ class RecordInitializer : public RecordVisitor { uint16_t Version; public: - static constexpr uint16_t DefaultVersion = 4u; + static constexpr uint16_t DefaultVersion = 5u; explicit RecordInitializer(DataExtractor &DE, uint32_t &OP, uint16_t V) : RecordVisitor(), E(DE), OffsetPtr(OP), Version(V) {} @@ -295,6 +344,8 @@ public: Error visit(NewBufferRecord &) override; Error visit(EndBufferRecord &) override; Error visit(FunctionRecord &) override; + Error visit(CustomEventRecordV5 &) override; + Error visit(TypedEventRecord &) override; }; } // namespace xray diff --git a/include/llvm/XRay/FDRTraceExpander.h b/include/llvm/XRay/FDRTraceExpander.h index 64c459930b2..02a21bed5ce 100644 --- a/include/llvm/XRay/FDRTraceExpander.h +++ b/include/llvm/XRay/FDRTraceExpander.h @@ -49,6 +49,8 @@ public: Error visit(NewBufferRecord &) override; Error visit(EndBufferRecord &) override; Error visit(FunctionRecord &) override; + Error visit(CustomEventRecordV5 &) override; + Error visit(TypedEventRecord &) override; // Must be called after all the records have been processed, to handle the // most recent record generated. diff --git a/include/llvm/XRay/FDRTraceWriter.h b/include/llvm/XRay/FDRTraceWriter.h index 91488f89ecc..7b3b5fa25ef 100644 --- a/include/llvm/XRay/FDRTraceWriter.h +++ b/include/llvm/XRay/FDRTraceWriter.h @@ -43,6 +43,8 @@ public: Error visit(NewBufferRecord &) override; Error visit(EndBufferRecord &) override; Error visit(FunctionRecord &) override; + Error visit(CustomEventRecordV5 &) override; + Error visit(TypedEventRecord &) override; private: support::endian::Writer OS; diff --git a/include/llvm/XRay/RecordPrinter.h b/include/llvm/XRay/RecordPrinter.h index bad1a5742b4..649c64ab6f5 100644 --- a/include/llvm/XRay/RecordPrinter.h +++ b/include/llvm/XRay/RecordPrinter.h @@ -40,6 +40,8 @@ public: Error visit(NewBufferRecord &) override; Error visit(EndBufferRecord &) override; Error visit(FunctionRecord &) override; + Error visit(CustomEventRecordV5 &) override; + Error visit(TypedEventRecord &) override; }; } // namespace xray diff --git a/lib/XRay/BlockIndexer.cpp b/lib/XRay/BlockIndexer.cpp index 98e91f7de54..4dbe2d2717a 100644 --- a/lib/XRay/BlockIndexer.cpp +++ b/lib/XRay/BlockIndexer.cpp @@ -39,6 +39,16 @@ Error BlockIndexer::visit(CustomEventRecord &R) { return Error::success(); } +Error BlockIndexer::visit(CustomEventRecordV5 &R) { + CurrentBlock.Records.push_back(&R); + return Error::success(); +} + +Error BlockIndexer::visit(TypedEventRecord &R) { + CurrentBlock.Records.push_back(&R); + return Error::success(); +} + Error BlockIndexer::visit(CallArgRecord &R) { CurrentBlock.Records.push_back(&R); return Error::success(); diff --git a/lib/XRay/BlockPrinter.cpp b/lib/XRay/BlockPrinter.cpp index c8b65fc12d7..0acebee0cbd 100644 --- a/lib/XRay/BlockPrinter.cpp +++ b/lib/XRay/BlockPrinter.cpp @@ -68,6 +68,24 @@ Error BlockPrinter::visit(CustomEventRecord &R) { return E; } +Error BlockPrinter::visit(CustomEventRecordV5 &R) { + if (CurrentState == State::Metadata) + OS << "\n"; + CurrentState = State::CustomEvent; + OS << "* "; + auto E = RP.visit(R); + return E; +} + +Error BlockPrinter::visit(TypedEventRecord &R) { + if (CurrentState == State::Metadata) + OS << "\n"; + CurrentState = State::CustomEvent; + OS << "* "; + auto E = RP.visit(R); + return E; +} + // Function call printing. Error BlockPrinter::visit(FunctionRecord &R) { if (CurrentState == State::Metadata) diff --git a/lib/XRay/BlockVerifier.cpp b/lib/XRay/BlockVerifier.cpp index 62be1a87ab5..5e949ec4e46 100644 --- a/lib/XRay/BlockVerifier.cpp +++ b/lib/XRay/BlockVerifier.cpp @@ -43,6 +43,8 @@ StringRef recordToString(BlockVerifier::State R) { return "CallArg"; case BlockVerifier::State::EndOfBuffer: return "EndOfBuffer"; + case BlockVerifier::State::TypedEvent: + return "TypedEvent"; case BlockVerifier::State::StateMax: case BlockVerifier::State::Unknown: return "Unknown"; @@ -75,27 +77,34 @@ Error BlockVerifier::transition(State To) { {State::NewCPUId, {mask(State::NewCPUId) | mask(State::TSCWrap) | mask(State::CustomEvent) | mask(State::Function) | - mask(State::EndOfBuffer)}}, + mask(State::EndOfBuffer) | mask(State::TypedEvent)}}, {State::TSCWrap, {mask(State::TSCWrap) | mask(State::NewCPUId) | mask(State::CustomEvent) | mask(State::Function) | - mask(State::EndOfBuffer)}}, + mask(State::EndOfBuffer) | mask(State::TypedEvent)}}, {State::CustomEvent, {mask(State::CustomEvent) | mask(State::TSCWrap) | mask(State::NewCPUId) | mask(State::Function) | - mask(State::EndOfBuffer)}}, + mask(State::EndOfBuffer) | mask(State::TypedEvent)}}, + + {State::TypedEvent, + {mask(State::TypedEvent) | mask(State::TSCWrap) | + mask(State::NewCPUId) | mask(State::Function) | + mask(State::EndOfBuffer) | mask(State::CustomEvent)}}, {State::Function, {mask(State::Function) | mask(State::TSCWrap) | mask(State::NewCPUId) | mask(State::CustomEvent) | - mask(State::CallArg) | mask(State::EndOfBuffer)}}, + mask(State::CallArg) | mask(State::EndOfBuffer) | + mask(State::TypedEvent)}}, {State::CallArg, {mask(State::CallArg) | mask(State::Function) | mask(State::TSCWrap) | mask(State::NewCPUId) | - mask(State::CustomEvent) | mask(State::EndOfBuffer)}}, + mask(State::CustomEvent) | mask(State::EndOfBuffer) | + mask(State::TypedEvent)}}, {State::EndOfBuffer, {}}}}; @@ -145,6 +154,14 @@ Error BlockVerifier::visit(CustomEventRecord &) { return transition(State::CustomEvent); } +Error BlockVerifier::visit(CustomEventRecordV5 &) { + return transition(State::CustomEvent); +} + +Error BlockVerifier::visit(TypedEventRecord &) { + return transition(State::TypedEvent); +} + Error BlockVerifier::visit(CallArgRecord &) { return transition(State::CallArg); } @@ -169,6 +186,7 @@ Error BlockVerifier::verify() { case State::EndOfBuffer: case State::NewCPUId: case State::CustomEvent: + case State::TypedEvent: case State::Function: case State::CallArg: case State::TSCWrap: diff --git a/lib/XRay/FDRRecordProducer.cpp b/lib/XRay/FDRRecordProducer.cpp index 59b5697cd64..122578010c4 100644 --- a/lib/XRay/FDRRecordProducer.cpp +++ b/lib/XRay/FDRRecordProducer.cpp @@ -53,14 +53,15 @@ metadataRecordType(const XRayFileHeader &Header, uint8_t T) { case MetadataRecordKinds::WalltimeMarkerKind: return make_unique(); case MetadataRecordKinds::CustomEventMarkerKind: + if (Header.Version >= 5) + return make_unique(); return make_unique(); case MetadataRecordKinds::CallArgumentKind: return make_unique(); case MetadataRecordKinds::BufferExtentsKind: return make_unique(); case MetadataRecordKinds::TypedEventMarkerKind: - return createStringError(std::make_error_code(std::errc::invalid_argument), - "Encountered an unsupported TypedEventMarker."); + return make_unique(); case MetadataRecordKinds::PidKind: return make_unique(); case MetadataRecordKinds::EnumEndMarker: diff --git a/lib/XRay/FDRRecords.cpp b/lib/XRay/FDRRecords.cpp index 66d17ffcb53..2b68a73686f 100644 --- a/lib/XRay/FDRRecords.cpp +++ b/lib/XRay/FDRRecords.cpp @@ -26,6 +26,8 @@ Error PIDRecord::apply(RecordVisitor &V) { return V.visit(*this); } Error NewBufferRecord::apply(RecordVisitor &V) { return V.visit(*this); } Error EndBufferRecord::apply(RecordVisitor &V) { return V.visit(*this); } Error FunctionRecord::apply(RecordVisitor &V) { return V.visit(*this); } +Error CustomEventRecordV5::apply(RecordVisitor &V) { return V.visit(*this); } +Error TypedEventRecord::apply(RecordVisitor &V) { return V.visit(*this); } } // namespace xray } // namespace llvm diff --git a/lib/XRay/FDRTraceExpander.cpp b/lib/XRay/FDRTraceExpander.cpp index adddb550ecd..e67f4b5d89f 100644 --- a/lib/XRay/FDRTraceExpander.cpp +++ b/lib/XRay/FDRTraceExpander.cpp @@ -52,6 +52,39 @@ Error TraceExpander::visit(CustomEventRecord &R) { return Error::success(); } +Error TraceExpander::visit(CustomEventRecordV5 &R) { + resetCurrentRecord(); + if (!IgnoringRecords) { + BaseTSC += R.delta(); + CurrentRecord.TSC = BaseTSC; + CurrentRecord.CPU = CPUId; + CurrentRecord.PId = PID; + CurrentRecord.TId = TID; + CurrentRecord.Type = RecordTypes::CUSTOM_EVENT; + std::copy(R.data().begin(), R.data().end(), + std::back_inserter(CurrentRecord.Data)); + BuildingRecord = true; + } + return Error::success(); +} + +Error TraceExpander::visit(TypedEventRecord &R) { + resetCurrentRecord(); + if (!IgnoringRecords) { + BaseTSC += R.delta(); + CurrentRecord.TSC = BaseTSC; + CurrentRecord.CPU = CPUId; + CurrentRecord.PId = PID; + CurrentRecord.TId = TID; + CurrentRecord.RecordType = R.eventType(); + CurrentRecord.Type = RecordTypes::TYPED_EVENT; + std::copy(R.data().begin(), R.data().end(), + std::back_inserter(CurrentRecord.Data)); + BuildingRecord = true; + } + return Error::success(); +} + Error TraceExpander::visit(CallArgRecord &R) { CurrentRecord.CallArgs.push_back(R.arg()); CurrentRecord.Type = RecordTypes::ENTER_ARG; diff --git a/lib/XRay/FDRTraceWriter.cpp b/lib/XRay/FDRTraceWriter.cpp index 4f40593cba0..d5f96979986 100644 --- a/lib/XRay/FDRTraceWriter.cpp +++ b/lib/XRay/FDRTraceWriter.cpp @@ -102,6 +102,24 @@ Error FDRTraceWriter::visit(CustomEventRecord &R) { return Error::success(); } +Error FDRTraceWriter::visit(CustomEventRecordV5 &R) { + if (auto E = writeMetadata<5u>(OS, R.size(), R.delta())) + return E; + auto D = R.data(); + ArrayRef Bytes(D.data(), D.size()); + OS.write(Bytes); + return Error::success(); +} + +Error FDRTraceWriter::visit(TypedEventRecord &R) { + if (auto E = writeMetadata<7u>(OS, R.size(), R.delta(), R.eventType())) + return E; + auto D = R.data(); + ArrayRef Bytes(D.data(), D.size()); + OS.write(Bytes); + return Error::success(); +} + Error FDRTraceWriter::visit(CallArgRecord &R) { return writeMetadata<6u>(OS, R.arg()); } diff --git a/lib/XRay/FileHeaderReader.cpp b/lib/XRay/FileHeaderReader.cpp index 9dea217840b..0b3fb8b6f69 100644 --- a/lib/XRay/FileHeaderReader.cpp +++ b/lib/XRay/FileHeaderReader.cpp @@ -63,10 +63,6 @@ Expected readBinaryFormatHeader(DataExtractor &HeaderExtractor, // Manually advance the offset pointer 16 bytes, after getting a raw memcpy // from the underlying data. OffsetPtr += 16; - if (FileHeader.Version < 1 || FileHeader.Version > 4) - return createStringError(std::make_error_code(std::errc::invalid_argument), - "Unsupported XRay file version: %d at offset %d", - FileHeader.Version, OffsetPtr); return std::move(FileHeader); } diff --git a/lib/XRay/RecordInitializer.cpp b/lib/XRay/RecordInitializer.cpp index 2ebaa1cec26..cc9dd460949 100644 --- a/lib/XRay/RecordInitializer.cpp +++ b/lib/XRay/RecordInitializer.cpp @@ -151,6 +151,105 @@ Error RecordInitializer::visit(CustomEventRecord &R) { return Error::success(); } +Error RecordInitializer::visit(CustomEventRecordV5 &R) { + if (!E.isValidOffsetForDataOfSize(OffsetPtr, + MetadataRecord::kMetadataBodySize)) + return createStringError(std::make_error_code(std::errc::bad_address), + "Invalid offset for a custom event record (%d).", + OffsetPtr); + + auto BeginOffset = OffsetPtr; + auto PreReadOffset = OffsetPtr; + + R.Size = E.getSigned(&OffsetPtr, sizeof(int32_t)); + if (PreReadOffset == OffsetPtr) + return createStringError( + std::make_error_code(std::errc::invalid_argument), + "Cannot read a custom event record size field offset %d.", OffsetPtr); + + PreReadOffset = OffsetPtr; + R.Delta = E.getSigned(&OffsetPtr, sizeof(int32_t)); + if (PreReadOffset == OffsetPtr) + return createStringError( + std::make_error_code(std::errc::invalid_argument), + "Cannot read a custom event record TSC delta field at offset %d.", + OffsetPtr); + + assert(OffsetPtr > BeginOffset && + OffsetPtr - BeginOffset <= MetadataRecord::kMetadataBodySize); + OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - BeginOffset); + + // Next we read in a fixed chunk of data from the given offset. + if (!E.isValidOffsetForDataOfSize(OffsetPtr, R.Size)) + return createStringError( + std::make_error_code(std::errc::bad_address), + "Cannot read %d bytes of custom event data from offset %d.", R.Size, + OffsetPtr); + + std::vector Buffer; + Buffer.resize(R.Size); + if (E.getU8(&OffsetPtr, Buffer.data(), R.Size) != Buffer.data()) + return createStringError( + std::make_error_code(std::errc::invalid_argument), + "Failed reading data into buffer of size %d at offset %d.", R.Size, + OffsetPtr); + R.Data.assign(Buffer.begin(), Buffer.end()); + return Error::success(); +} + +Error RecordInitializer::visit(TypedEventRecord &R) { + if (!E.isValidOffsetForDataOfSize(OffsetPtr, + MetadataRecord::kMetadataBodySize)) + return createStringError(std::make_error_code(std::errc::bad_address), + "Invalid offset for a typed event record (%d).", + OffsetPtr); + + auto BeginOffset = OffsetPtr; + auto PreReadOffset = OffsetPtr; + + R.Size = E.getSigned(&OffsetPtr, sizeof(int32_t)); + if (PreReadOffset == OffsetPtr) + return createStringError( + std::make_error_code(std::errc::invalid_argument), + "Cannot read a typed event record size field offset %d.", OffsetPtr); + + PreReadOffset = OffsetPtr; + R.Delta = E.getSigned(&OffsetPtr, sizeof(int32_t)); + if (PreReadOffset == OffsetPtr) + return createStringError( + std::make_error_code(std::errc::invalid_argument), + "Cannot read a typed event record TSC delta field at offset %d.", + OffsetPtr); + + PreReadOffset = OffsetPtr; + R.EventType = E.getU16(&OffsetPtr); + if (PreReadOffset == OffsetPtr) + return createStringError( + std::make_error_code(std::errc::invalid_argument), + "Cannot read a typed event record type field at offset %d.", OffsetPtr); + + assert(OffsetPtr > BeginOffset && + OffsetPtr - BeginOffset <= MetadataRecord::kMetadataBodySize); + OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - BeginOffset); + + // Next we read in a fixed chunk of data from the given offset. + if (!E.isValidOffsetForDataOfSize(OffsetPtr, R.Size)) + return createStringError( + std::make_error_code(std::errc::bad_address), + "Cannot read %d bytes of custom event data from offset %d.", R.Size, + OffsetPtr); + + std::vector Buffer; + Buffer.resize(R.Size); + if (E.getU8(&OffsetPtr, Buffer.data(), R.Size) != Buffer.data()) + return createStringError( + std::make_error_code(std::errc::invalid_argument), + "Failed reading data into buffer of size %d at offset %d.", R.Size, + OffsetPtr); + R.Data.assign(Buffer.begin(), Buffer.end()); + return Error::success(); +} + Error RecordInitializer::visit(CallArgRecord &R) { if (!E.isValidOffsetForDataOfSize(OffsetPtr, MetadataRecord::kMetadataBodySize)) diff --git a/lib/XRay/RecordPrinter.cpp b/lib/XRay/RecordPrinter.cpp index 61a292cef85..71ea7d0e969 100644 --- a/lib/XRay/RecordPrinter.cpp +++ b/lib/XRay/RecordPrinter.cpp @@ -42,6 +42,21 @@ Error RecordPrinter::visit(CustomEventRecord &R) { return Error::success(); } +Error RecordPrinter::visit(CustomEventRecordV5 &R) { + OS << formatv("", + R.delta(), R.size(), R.data()) + << Delim; + return Error::success(); +} + +Error RecordPrinter::visit(TypedEventRecord &R) { + OS << formatv( + "", R.arg()) << Delim; return Error::success(); diff --git a/lib/XRay/Trace.cpp b/lib/XRay/Trace.cpp index 37cd147078e..4f28f3f754c 100644 --- a/lib/XRay/Trace.cpp +++ b/lib/XRay/Trace.cpp @@ -247,6 +247,17 @@ Error loadNaiveFormatLog(StringRef Data, bool IsLittleEndian, /// ThreadBuffer: BufferExtents NewBuffer WallClockTime Pid NewCPUId /// FunctionSequence /// EOB: *deprecated* +/// +/// In Version 4, we make the following changes: +/// +/// CustomEventRecord now includes the CPU data. +/// +/// In Version 5, we make the following changes: +/// +/// CustomEventRecord and TypedEventRecord now use TSC delta encoding similar to +/// what FunctionRecord instances use, and we no longer need to include the CPU +/// id in the CustomEventRecord. +/// Error loadFDRLog(StringRef Data, bool IsLittleEndian, XRayFileHeader &FileHeader, std::vector &Records) { @@ -435,7 +446,7 @@ Expected llvm::xray::loadTrace(const DataExtractor &DE, bool Sort) { } break; case FLIGHT_DATA_RECORDER_FORMAT: - if (Version >= 1 && Version <= 4) { + if (Version >= 1 && Version <= 5) { if (auto E = loadFDRLog(DE.getData(), DE.isLittleEndian(), T.FileHeader, T.Records)) return std::move(E); diff --git a/unittests/XRay/FDRRecordsTest.cpp b/unittests/XRay/FDRRecordsTest.cpp index 1cce1c2b2c1..86b478a5a45 100644 --- a/unittests/XRay/FDRRecordsTest.cpp +++ b/unittests/XRay/FDRRecordsTest.cpp @@ -34,6 +34,8 @@ TEST(XRayFDRTest, BuilderAndBlockIndexer) { .add(1) .add(RecordTypes::ENTER, 1, 1) .add(RecordTypes::EXIT, 1, 100) + .add(1, 4, "XRAY") + .add(1, 4, 2, "XRAY") .consume(); auto Block1 = LogBuilder() .add(100) @@ -42,6 +44,8 @@ TEST(XRayFDRTest, BuilderAndBlockIndexer) { .add(1) .add(RecordTypes::ENTER, 1, 1) .add(RecordTypes::EXIT, 1, 100) + .add(1, 4, "XRAY") + .add(1, 4, 2, "XRAY") .consume(); auto Block2 = LogBuilder() .add(100) @@ -50,6 +54,8 @@ TEST(XRayFDRTest, BuilderAndBlockIndexer) { .add(1) .add(RecordTypes::ENTER, 1, 1) .add(RecordTypes::EXIT, 1, 100) + .add(1, 4, "XRAY") + .add(1, 4, 2, "XRAY") .consume(); BlockIndexer::Index Index; BlockIndexer Indexer(Index); @@ -92,6 +98,8 @@ TEST(XRayFDRTest, IndexAndVerifyBlocks) { .add(1, 2) .add(RecordTypes::ENTER, 1, 1) .add(RecordTypes::EXIT, 1, 100) + .add(1, 4, "XRAY") + .add(1, 4, 2, "XRAY") .consume(); auto Block1 = LogBuilder() .add(64) @@ -101,6 +109,8 @@ TEST(XRayFDRTest, IndexAndVerifyBlocks) { .add(1, 2) .add(RecordTypes::ENTER, 1, 1) .add(RecordTypes::EXIT, 1, 100) + .add(1, 4, "XRAY") + .add(1, 4, 2, "XRAY") .consume(); auto Block2 = LogBuilder() .add(64) @@ -110,6 +120,8 @@ TEST(XRayFDRTest, IndexAndVerifyBlocks) { .add(1, 2) .add(RecordTypes::ENTER, 1, 1) .add(RecordTypes::EXIT, 1, 100) + .add(1, 4, "XRAY") + .add(1, 4, 2, "XRAY") .consume(); // First, index the records in different blocks.