1 //===- BitstreamReaderTest.cpp - Tests for BitstreamReader ----------------===// 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/BitstreamReader.h" 10 #include "llvm/ADT/STLExtras.h" 11 #include "llvm/Bitstream/BitstreamWriter.h" 12 #include "gtest/gtest.h" 13 14 using namespace llvm; 15 16 namespace { 17 18 TEST(BitstreamReaderTest, AtEndOfStream) { 19 uint8_t Bytes[4] = { 20 0x00, 0x01, 0x02, 0x03 21 }; 22 BitstreamCursor Cursor(Bytes); 23 24 EXPECT_FALSE(Cursor.AtEndOfStream()); 25 Expected<SimpleBitstreamCursor::word_t> MaybeRead = Cursor.Read(8); 26 EXPECT_TRUE((bool)MaybeRead); 27 EXPECT_FALSE(Cursor.AtEndOfStream()); 28 MaybeRead = Cursor.Read(24); 29 EXPECT_TRUE((bool)MaybeRead); 30 EXPECT_TRUE(Cursor.AtEndOfStream()); 31 32 EXPECT_FALSE(Cursor.JumpToBit(0)); 33 EXPECT_FALSE(Cursor.AtEndOfStream()); 34 35 EXPECT_FALSE(Cursor.JumpToBit(32)); 36 EXPECT_TRUE(Cursor.AtEndOfStream()); 37 } 38 39 TEST(BitstreamReaderTest, AtEndOfStreamJump) { 40 uint8_t Bytes[4] = { 41 0x00, 0x01, 0x02, 0x03 42 }; 43 BitstreamCursor Cursor(Bytes); 44 45 EXPECT_FALSE(Cursor.JumpToBit(32)); 46 EXPECT_TRUE(Cursor.AtEndOfStream()); 47 } 48 49 TEST(BitstreamReaderTest, AtEndOfStreamEmpty) { 50 BitstreamCursor Cursor(ArrayRef<uint8_t>{}); 51 52 EXPECT_TRUE(Cursor.AtEndOfStream()); 53 } 54 55 TEST(BitstreamReaderTest, getCurrentByteNo) { 56 uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03}; 57 SimpleBitstreamCursor Cursor(Bytes); 58 59 for (unsigned I = 0, E = 32; I != E; ++I) { 60 EXPECT_EQ(I / 8, Cursor.getCurrentByteNo()); 61 Expected<SimpleBitstreamCursor::word_t> MaybeRead = Cursor.Read(1); 62 EXPECT_TRUE((bool)MaybeRead); 63 } 64 EXPECT_EQ(4u, Cursor.getCurrentByteNo()); 65 } 66 67 TEST(BitstreamReaderTest, getPointerToByte) { 68 uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; 69 SimpleBitstreamCursor Cursor(Bytes); 70 71 for (unsigned I = 0, E = 8; I != E; ++I) { 72 EXPECT_EQ(Bytes + I, Cursor.getPointerToByte(I, 1)); 73 } 74 } 75 76 TEST(BitstreamReaderTest, getPointerToBit) { 77 uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; 78 SimpleBitstreamCursor Cursor(Bytes); 79 80 for (unsigned I = 0, E = 8; I != E; ++I) { 81 EXPECT_EQ(Bytes + I, Cursor.getPointerToBit(I * 8, 1)); 82 } 83 } 84 85 TEST(BitstreamReaderTest, readRecordWithBlobWhileStreaming) { 86 SmallVector<uint8_t, 1> BlobData; 87 for (unsigned I = 0, E = 1024; I != E; ++I) 88 BlobData.push_back(I); 89 90 // Try a bunch of different sizes. 91 const unsigned Magic = 0x12345678; 92 const unsigned BlockID = bitc::FIRST_APPLICATION_BLOCKID; 93 const unsigned RecordID = 1; 94 for (unsigned I = 0, BlobSize = 0, E = BlobData.size(); BlobSize < E; 95 BlobSize += ++I) { 96 StringRef BlobIn((const char *)BlobData.begin(), BlobSize); 97 98 // Write the bitcode. 99 SmallVector<char, 1> Buffer; 100 unsigned AbbrevID; 101 { 102 BitstreamWriter Stream(Buffer); 103 Stream.Emit(Magic, 32); 104 Stream.EnterSubblock(BlockID, 3); 105 106 auto Abbrev = std::make_shared<BitCodeAbbrev>(); 107 Abbrev->Add(BitCodeAbbrevOp(RecordID)); 108 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); 109 AbbrevID = Stream.EmitAbbrev(std::move(Abbrev)); 110 unsigned Record[] = {RecordID}; 111 Stream.EmitRecordWithBlob(AbbrevID, makeArrayRef(Record), BlobIn); 112 113 Stream.ExitBlock(); 114 } 115 116 // Stream the buffer into the reader. 117 BitstreamCursor Stream( 118 ArrayRef<uint8_t>((const uint8_t *)Buffer.begin(), Buffer.size())); 119 120 // Header. Included in test so that we can run llvm-bcanalyzer to debug 121 // when there are problems. 122 Expected<SimpleBitstreamCursor::word_t> MaybeRead = Stream.Read(32); 123 ASSERT_TRUE((bool)MaybeRead); 124 ASSERT_EQ(Magic, MaybeRead.get()); 125 126 // Block. 127 Expected<BitstreamEntry> MaybeEntry = 128 Stream.advance(BitstreamCursor::AF_DontAutoprocessAbbrevs); 129 ASSERT_TRUE((bool)MaybeEntry); 130 BitstreamEntry Entry = MaybeEntry.get(); 131 ASSERT_EQ(BitstreamEntry::SubBlock, Entry.Kind); 132 ASSERT_EQ(BlockID, Entry.ID); 133 ASSERT_FALSE(Stream.EnterSubBlock(BlockID)); 134 135 // Abbreviation. 136 MaybeEntry = Stream.advance(); 137 ASSERT_TRUE((bool)MaybeEntry); 138 Entry = MaybeEntry.get(); 139 ASSERT_EQ(BitstreamEntry::Record, Entry.Kind); 140 ASSERT_EQ(AbbrevID, Entry.ID); 141 142 // Record. 143 StringRef BlobOut; 144 SmallVector<uint64_t, 1> Record; 145 Expected<unsigned> MaybeRecord = 146 Stream.readRecord(Entry.ID, Record, &BlobOut); 147 ASSERT_TRUE((bool)MaybeRecord); 148 ASSERT_EQ(RecordID, MaybeRecord.get()); 149 EXPECT_TRUE(Record.empty()); 150 EXPECT_EQ(BlobIn, BlobOut); 151 } 152 } 153 154 TEST(BitstreamReaderTest, shortRead) { 155 uint8_t Bytes[] = {8, 7, 6, 5, 4, 3, 2, 1}; 156 for (unsigned I = 1; I != 8; ++I) { 157 SimpleBitstreamCursor Cursor(ArrayRef<uint8_t>(Bytes, I)); 158 Expected<SimpleBitstreamCursor::word_t> MaybeRead = Cursor.Read(8); 159 ASSERT_TRUE((bool)MaybeRead); 160 EXPECT_EQ(8ull, MaybeRead.get()); 161 } 162 } 163 164 static_assert(std::is_trivially_copyable<BitCodeAbbrevOp>::value, 165 "trivially copyable"); 166 167 } // end anonymous namespace 168