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