//===- BitstreamWriterTest.cpp - Tests for BitstreamWriter ----------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "llvm/Bitstream/BitstreamWriter.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/Bitstream/BitCodeEnums.h" #include "llvm/Bitstream/BitstreamReader.h" #include "llvm/Support/Error.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Testing/Support/SupportHelpers.h" #include "gmock/gmock.h" #include "gtest/gtest.h" using namespace llvm; namespace { TEST(BitstreamWriterTest, emitBlob) { SmallString<64> Buffer; BitstreamWriter W(Buffer); W.emitBlob("str", /* ShouldEmitSize */ false); EXPECT_EQ(StringRef("str\0", 4), Buffer); } TEST(BitstreamWriterTest, emitBlobWithSize) { SmallString<64> Buffer; { BitstreamWriter W(Buffer); W.emitBlob("str"); } SmallString<64> Expected; { BitstreamWriter W(Expected); W.EmitVBR(3, 6); W.FlushToWord(); W.Emit('s', 8); W.Emit('t', 8); W.Emit('r', 8); W.Emit(0, 8); } EXPECT_EQ(Expected.str(), Buffer); } TEST(BitstreamWriterTest, emitBlobEmpty) { SmallString<64> Buffer; BitstreamWriter W(Buffer); W.emitBlob("", /* ShouldEmitSize */ false); EXPECT_EQ(StringRef(""), Buffer); } TEST(BitstreamWriterTest, emitBlob4ByteAligned) { SmallString<64> Buffer; BitstreamWriter W(Buffer); W.emitBlob("str0", /* ShouldEmitSize */ false); EXPECT_EQ(StringRef("str0"), Buffer); } class BitstreamWriterFlushTest : public ::testing::TestWithParam { protected: // Any value after bitc::FIRST_APPLICATION_BLOCKID is good, but let's pick a // distinctive one. const unsigned BlkID = bitc::FIRST_APPLICATION_BLOCKID + 17; void write(StringRef TestFilePath, int FlushThreshold, llvm::function_ref Action) { std::error_code EC; raw_fd_stream Out(TestFilePath, EC); ASSERT_FALSE(EC); BitstreamWriter W(Out, FlushThreshold); Action(W); } }; TEST_P(BitstreamWriterFlushTest, simpleExample) { llvm::unittest::TempFile TestFile("bitstream", "", "", /*Unique*/ true); write(TestFile.path(), GetParam(), [&](BitstreamWriter &W) { W.EmitVBR(42, 2); }); ErrorOr> MB = MemoryBuffer::getFile(TestFile.path()); ASSERT_TRUE(!!MB); ASSERT_NE(*MB, nullptr); BitstreamCursor Cursor((*MB)->getBuffer()); auto V = Cursor.ReadVBR(2); EXPECT_TRUE(!!V); EXPECT_EQ(*V, 42U); } TEST_P(BitstreamWriterFlushTest, subBlock) { llvm::unittest::TempFile TestFile("bitstream", "", "", /*Unique*/ true); write(TestFile.path(), GetParam(), [&](BitstreamWriter &W) { W.EnterSubblock(BlkID, 2); W.EmitVBR(42, 2); W.ExitBlock(); }); ErrorOr> MB = MemoryBuffer::getFile(TestFile.path()); ASSERT_TRUE(!!MB); ASSERT_NE(*MB, nullptr); BitstreamCursor Cursor((*MB)->getBuffer()); auto Blk = Cursor.advance(BitstreamCursor::AF_DontAutoprocessAbbrevs); ASSERT_TRUE(!!Blk); EXPECT_EQ(Blk->Kind, BitstreamEntry::SubBlock); EXPECT_EQ(Blk->ID, BlkID); EXPECT_FALSE(Cursor.EnterSubBlock(BlkID)); auto V = Cursor.ReadVBR(2); EXPECT_TRUE(!!V); EXPECT_EQ(*V, 42U); // ReadBlockEnd() returns false if it actually read the block end. EXPECT_FALSE(Cursor.ReadBlockEnd()); EXPECT_TRUE(Cursor.AtEndOfStream()); } TEST_P(BitstreamWriterFlushTest, blobRawRead) { llvm::unittest::TempFile TestFile("bitstream", "", "", /*Unique*/ true); write(TestFile.path(), GetParam(), [&](BitstreamWriter &W) { W.emitBlob("str", /* ShouldEmitSize */ false); }); ErrorOr> MB = MemoryBuffer::getFile(TestFile.path()); ASSERT_TRUE(!!MB); ASSERT_NE(*MB, nullptr); EXPECT_EQ(StringRef("str\0", 4), (*MB)->getBuffer()); } INSTANTIATE_TEST_SUITE_P(BitstreamWriterFlushCases, BitstreamWriterFlushTest, ::testing::Values(0, 1 /*MB*/)); } // end namespace