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