xref: /llvm-project/llvm/unittests/Bitstream/BitstreamWriterTest.cpp (revision 7cfffe74eeb68fbb3fb9706ac7071f8caeeb6520)
1 //===- BitstreamWriterTest.cpp - Tests for BitstreamWriter ----------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/Bitstream/BitstreamWriter.h"
10 #include "llvm/ADT/STLExtras.h"
11 #include "llvm/ADT/SmallString.h"
12 #include "llvm/Bitstream/BitCodeEnums.h"
13 #include "llvm/Bitstream/BitstreamReader.h"
14 #include "llvm/Support/Error.h"
15 #include "llvm/Support/MemoryBuffer.h"
16 #include "llvm/Testing/Support/SupportHelpers.h"
17 #include "gmock/gmock.h"
18 #include "gtest/gtest.h"
19 
20 using namespace llvm;
21 
22 namespace {
23 
TEST(BitstreamWriterTest,emitBlob)24 TEST(BitstreamWriterTest, emitBlob) {
25   SmallString<64> Buffer;
26   BitstreamWriter W(Buffer);
27   W.emitBlob("str", /* ShouldEmitSize */ false);
28   EXPECT_EQ(StringRef("str\0", 4), Buffer);
29 }
30 
TEST(BitstreamWriterTest,emitBlobWithSize)31 TEST(BitstreamWriterTest, emitBlobWithSize) {
32   SmallString<64> Buffer;
33   {
34     BitstreamWriter W(Buffer);
35     W.emitBlob("str");
36   }
37   SmallString<64> Expected;
38   {
39     BitstreamWriter W(Expected);
40     W.EmitVBR(3, 6);
41     W.FlushToWord();
42     W.Emit('s', 8);
43     W.Emit('t', 8);
44     W.Emit('r', 8);
45     W.Emit(0, 8);
46   }
47   EXPECT_EQ(Expected.str(), Buffer);
48 }
49 
TEST(BitstreamWriterTest,emitBlobEmpty)50 TEST(BitstreamWriterTest, emitBlobEmpty) {
51   SmallString<64> Buffer;
52   BitstreamWriter W(Buffer);
53   W.emitBlob("", /* ShouldEmitSize */ false);
54   EXPECT_EQ(StringRef(""), Buffer);
55 }
56 
TEST(BitstreamWriterTest,emitBlob4ByteAligned)57 TEST(BitstreamWriterTest, emitBlob4ByteAligned) {
58   SmallString<64> Buffer;
59   BitstreamWriter W(Buffer);
60   W.emitBlob("str0", /* ShouldEmitSize */ false);
61   EXPECT_EQ(StringRef("str0"), Buffer);
62 }
63 
64 class BitstreamWriterFlushTest : public ::testing::TestWithParam<int> {
65 protected:
66   // Any value after bitc::FIRST_APPLICATION_BLOCKID is good, but let's pick a
67   // distinctive one.
68   const unsigned BlkID = bitc::FIRST_APPLICATION_BLOCKID + 17;
69 
write(StringRef TestFilePath,int FlushThreshold,llvm::function_ref<void (BitstreamWriter &)> Action)70   void write(StringRef TestFilePath, int FlushThreshold,
71              llvm::function_ref<void(BitstreamWriter &)> Action) {
72     std::error_code EC;
73     raw_fd_stream Out(TestFilePath, EC);
74     ASSERT_FALSE(EC);
75     BitstreamWriter W(Out, FlushThreshold);
76     Action(W);
77   }
78 };
79 
TEST_P(BitstreamWriterFlushTest,simpleExample)80 TEST_P(BitstreamWriterFlushTest, simpleExample) {
81   llvm::unittest::TempFile TestFile("bitstream", "", "",
82                                     /*Unique*/ true);
83   write(TestFile.path(), GetParam(),
84         [&](BitstreamWriter &W) { W.EmitVBR(42, 2); });
85 
86   ErrorOr<std::unique_ptr<MemoryBuffer>> MB =
87       MemoryBuffer::getFile(TestFile.path());
88   ASSERT_TRUE(!!MB);
89   ASSERT_NE(*MB, nullptr);
90   BitstreamCursor Cursor((*MB)->getBuffer());
91   auto V = Cursor.ReadVBR(2);
92   EXPECT_TRUE(!!V);
93   EXPECT_EQ(*V, 42U);
94 }
95 
TEST_P(BitstreamWriterFlushTest,subBlock)96 TEST_P(BitstreamWriterFlushTest, subBlock) {
97   llvm::unittest::TempFile TestFile("bitstream", "", "",
98                                     /*Unique*/ true);
99   write(TestFile.path(), GetParam(), [&](BitstreamWriter &W) {
100     W.EnterSubblock(BlkID, 2);
101     W.EmitVBR(42, 2);
102     W.ExitBlock();
103   });
104   ErrorOr<std::unique_ptr<MemoryBuffer>> MB =
105       MemoryBuffer::getFile(TestFile.path());
106   ASSERT_TRUE(!!MB);
107   ASSERT_NE(*MB, nullptr);
108   BitstreamCursor Cursor((*MB)->getBuffer());
109   auto Blk = Cursor.advance(BitstreamCursor::AF_DontAutoprocessAbbrevs);
110   ASSERT_TRUE(!!Blk);
111   EXPECT_EQ(Blk->Kind, BitstreamEntry::SubBlock);
112   EXPECT_EQ(Blk->ID, BlkID);
113   EXPECT_FALSE(Cursor.EnterSubBlock(BlkID));
114   auto V = Cursor.ReadVBR(2);
115   EXPECT_TRUE(!!V);
116   EXPECT_EQ(*V, 42U);
117   // ReadBlockEnd() returns false if it actually read the block end.
118   EXPECT_FALSE(Cursor.ReadBlockEnd());
119   EXPECT_TRUE(Cursor.AtEndOfStream());
120 }
121 
TEST_P(BitstreamWriterFlushTest,blobRawRead)122 TEST_P(BitstreamWriterFlushTest, blobRawRead) {
123   llvm::unittest::TempFile TestFile("bitstream", "", "",
124                                     /*Unique*/ true);
125   write(TestFile.path(), GetParam(), [&](BitstreamWriter &W) {
126     W.emitBlob("str", /* ShouldEmitSize */ false);
127   });
128 
129   ErrorOr<std::unique_ptr<MemoryBuffer>> MB =
130       MemoryBuffer::getFile(TestFile.path());
131   ASSERT_TRUE(!!MB);
132   ASSERT_NE(*MB, nullptr);
133   EXPECT_EQ(StringRef("str\0", 4), (*MB)->getBuffer());
134 }
135 
136 INSTANTIATE_TEST_SUITE_P(BitstreamWriterFlushCases, BitstreamWriterFlushTest,
137                          ::testing::Values(0, 1 /*MB*/));
138 } // end namespace
139