1 //===- unittests/Lex/HeaderMapTest.cpp - HeaderMap tests ----------===//
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
7 //===--------------------------------------------------------------===//
9 #include "HeaderMapTestUtils.h"
10 #include "llvm/ADT/SmallString.h"
11 #include "gtest/gtest.h"
12 #include <type_traits>
14 using namespace clang
;
16 using namespace clang::test
;
20 TEST(HeaderMapTest
, checkHeaderEmpty
) {
22 ASSERT_FALSE(HeaderMapImpl::checkHeader(
23 *MemoryBuffer::getMemBufferCopy("", "empty"), NeedsSwap
));
24 ASSERT_FALSE(HeaderMapImpl::checkHeader(
25 *MemoryBuffer::getMemBufferCopy("", "empty"), NeedsSwap
));
28 TEST(HeaderMapTest
, checkHeaderMagic
) {
29 HMapFileMock
<1, 1> File
;
31 File
.Header
.Magic
= 0;
33 ASSERT_FALSE(HeaderMapImpl::checkHeader(*File
.getBuffer(), NeedsSwap
));
36 TEST(HeaderMapTest
, checkHeaderReserved
) {
37 HMapFileMock
<1, 1> File
;
39 File
.Header
.Reserved
= 1;
41 ASSERT_FALSE(HeaderMapImpl::checkHeader(*File
.getBuffer(), NeedsSwap
));
44 TEST(HeaderMapTest
, checkHeaderVersion
) {
45 HMapFileMock
<1, 1> File
;
47 ++File
.Header
.Version
;
49 ASSERT_FALSE(HeaderMapImpl::checkHeader(*File
.getBuffer(), NeedsSwap
));
52 TEST(HeaderMapTest
, checkHeaderValidButEmpty
) {
53 HMapFileMock
<1, 1> File
;
56 ASSERT_TRUE(HeaderMapImpl::checkHeader(*File
.getBuffer(), NeedsSwap
));
57 ASSERT_FALSE(NeedsSwap
);
60 ASSERT_TRUE(HeaderMapImpl::checkHeader(*File
.getBuffer(), NeedsSwap
));
61 ASSERT_TRUE(NeedsSwap
);
64 TEST(HeaderMapTest
, checkHeader3Buckets
) {
65 HMapFileMock
<3, 1> File
;
66 ASSERT_EQ(3 * sizeof(HMapBucket
), sizeof(File
.Buckets
));
70 ASSERT_FALSE(HeaderMapImpl::checkHeader(*File
.getBuffer(), NeedsSwap
));
73 TEST(HeaderMapTest
, checkHeader0Buckets
) {
74 // Create with 1 bucket to avoid 0-sized arrays.
75 HMapFileMock
<1, 1> File
;
77 File
.Header
.NumBuckets
= 0;
79 ASSERT_FALSE(HeaderMapImpl::checkHeader(*File
.getBuffer(), NeedsSwap
));
82 TEST(HeaderMapTest
, checkHeaderNotEnoughBuckets
) {
83 HMapFileMock
<1, 1> File
;
85 File
.Header
.NumBuckets
= 8;
87 ASSERT_FALSE(HeaderMapImpl::checkHeader(*File
.getBuffer(), NeedsSwap
));
90 TEST(HeaderMapTest
, lookupFilename
) {
91 typedef HMapFileMock
<2, 7> FileTy
;
95 HMapFileMockMaker
<FileTy
> Maker(File
);
96 auto a
= Maker
.addString("a");
97 auto b
= Maker
.addString("b");
98 auto c
= Maker
.addString("c");
99 Maker
.addBucket("a", a
, b
, c
);
102 ASSERT_TRUE(HeaderMapImpl::checkHeader(*File
.getBuffer(), NeedsSwap
));
103 ASSERT_FALSE(NeedsSwap
);
104 HeaderMapImpl
Map(File
.getBuffer(), NeedsSwap
);
106 SmallString
<8> DestPath
;
107 ASSERT_EQ("bc", Map
.lookupFilename("a", DestPath
));
110 template <class FileTy
, class PaddingTy
> struct PaddedFile
{
115 TEST(HeaderMapTest
, lookupFilenameTruncatedSuffix
) {
116 typedef HMapFileMock
<2, 64 - sizeof(HMapHeader
) - 2 * sizeof(HMapBucket
)>
118 static_assert(std::is_standard_layout
<FileTy
>::value
,
119 "Expected standard layout");
120 static_assert(sizeof(FileTy
) == 64, "check the math");
121 PaddedFile
<FileTy
, uint64_t> P
;
123 auto &Padding
= P
.Padding
;
126 HMapFileMockMaker
<FileTy
> Maker(File
);
127 auto a
= Maker
.addString("a");
128 auto b
= Maker
.addString("b");
129 auto c
= Maker
.addString("c");
130 Maker
.addBucket("a", a
, b
, c
);
132 // Add 'x' characters to cause an overflow into Padding.
133 ASSERT_EQ('c', File
.Bytes
[5]);
134 for (unsigned I
= 6; I
< sizeof(File
.Bytes
); ++I
) {
135 ASSERT_EQ(0, File
.Bytes
[I
]);
138 Padding
= 0xffffffff; // Padding won't stop it either.
141 ASSERT_TRUE(HeaderMapImpl::checkHeader(*File
.getBuffer(), NeedsSwap
));
142 ASSERT_FALSE(NeedsSwap
);
143 HeaderMapImpl
Map(File
.getBuffer(), NeedsSwap
);
145 // The string for "c" runs to the end of File. Check that the suffix
146 // ("cxxxx...") is detected as truncated, and an empty string is returned.
147 SmallString
<24> DestPath
;
148 ASSERT_EQ("", Map
.lookupFilename("a", DestPath
));
151 TEST(HeaderMapTest
, lookupFilenameTruncatedPrefix
) {
152 typedef HMapFileMock
<2, 64 - sizeof(HMapHeader
) - 2 * sizeof(HMapBucket
)>
154 static_assert(std::is_standard_layout
<FileTy
>::value
,
155 "Expected standard layout");
156 static_assert(sizeof(FileTy
) == 64, "check the math");
157 PaddedFile
<FileTy
, uint64_t> P
;
159 auto &Padding
= P
.Padding
;
162 HMapFileMockMaker
<FileTy
> Maker(File
);
163 auto a
= Maker
.addString("a");
164 auto c
= Maker
.addString("c");
165 auto b
= Maker
.addString("b"); // Store the prefix last.
166 Maker
.addBucket("a", a
, b
, c
);
168 // Add 'x' characters to cause an overflow into Padding.
169 ASSERT_EQ('b', File
.Bytes
[5]);
170 for (unsigned I
= 6; I
< sizeof(File
.Bytes
); ++I
) {
171 ASSERT_EQ(0, File
.Bytes
[I
]);
174 Padding
= 0xffffffff; // Padding won't stop it either.
177 ASSERT_TRUE(HeaderMapImpl::checkHeader(*File
.getBuffer(), NeedsSwap
));
178 ASSERT_FALSE(NeedsSwap
);
179 HeaderMapImpl
Map(File
.getBuffer(), NeedsSwap
);
181 // The string for "b" runs to the end of File. Check that the prefix
182 // ("bxxxx...") is detected as truncated, and an empty string is returned.
183 SmallString
<24> DestPath
;
184 ASSERT_EQ("", Map
.lookupFilename("a", DestPath
));