19ab99eecSDuncan P. N. Exon Smith //===- unittests/Lex/HeaderMapTest.cpp - HeaderMap tests ----------===//
29ab99eecSDuncan P. N. Exon Smith //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
69ab99eecSDuncan P. N. Exon Smith //
79ab99eecSDuncan P. N. Exon Smith //===--------------------------------------------------------------===//
89ab99eecSDuncan P. N. Exon Smith 
9*37b530a2SDmitry Polukhin #include "HeaderMapTestUtils.h"
1008fd70faSDuncan P. N. Exon Smith #include "llvm/ADT/SmallString.h"
119ab99eecSDuncan P. N. Exon Smith #include "gtest/gtest.h"
1296a01fa0SDuncan P. N. Exon Smith #include <type_traits>
139ab99eecSDuncan P. N. Exon Smith 
149ab99eecSDuncan P. N. Exon Smith using namespace clang;
159ab99eecSDuncan P. N. Exon Smith using namespace llvm;
16*37b530a2SDmitry Polukhin using namespace clang::test;
179ab99eecSDuncan P. N. Exon Smith 
189ab99eecSDuncan P. N. Exon Smith namespace {
199ab99eecSDuncan P. N. Exon Smith 
TEST(HeaderMapTest,checkHeaderEmpty)209ab99eecSDuncan P. N. Exon Smith TEST(HeaderMapTest, checkHeaderEmpty) {
219ab99eecSDuncan P. N. Exon Smith   bool NeedsSwap;
229ab99eecSDuncan P. N. Exon Smith   ASSERT_FALSE(HeaderMapImpl::checkHeader(
239ab99eecSDuncan P. N. Exon Smith       *MemoryBuffer::getMemBufferCopy("", "empty"), NeedsSwap));
249ab99eecSDuncan P. N. Exon Smith   ASSERT_FALSE(HeaderMapImpl::checkHeader(
259ab99eecSDuncan P. N. Exon Smith       *MemoryBuffer::getMemBufferCopy("", "empty"), NeedsSwap));
269ab99eecSDuncan P. N. Exon Smith }
279ab99eecSDuncan P. N. Exon Smith 
TEST(HeaderMapTest,checkHeaderMagic)289ab99eecSDuncan P. N. Exon Smith TEST(HeaderMapTest, checkHeaderMagic) {
29*37b530a2SDmitry Polukhin   HMapFileMock<1, 1> File;
309ab99eecSDuncan P. N. Exon Smith   File.init();
319ab99eecSDuncan P. N. Exon Smith   File.Header.Magic = 0;
329ab99eecSDuncan P. N. Exon Smith   bool NeedsSwap;
339ab99eecSDuncan P. N. Exon Smith   ASSERT_FALSE(HeaderMapImpl::checkHeader(*File.getBuffer(), NeedsSwap));
349ab99eecSDuncan P. N. Exon Smith }
359ab99eecSDuncan P. N. Exon Smith 
TEST(HeaderMapTest,checkHeaderReserved)369ab99eecSDuncan P. N. Exon Smith TEST(HeaderMapTest, checkHeaderReserved) {
37*37b530a2SDmitry Polukhin   HMapFileMock<1, 1> File;
389ab99eecSDuncan P. N. Exon Smith   File.init();
399ab99eecSDuncan P. N. Exon Smith   File.Header.Reserved = 1;
409ab99eecSDuncan P. N. Exon Smith   bool NeedsSwap;
419ab99eecSDuncan P. N. Exon Smith   ASSERT_FALSE(HeaderMapImpl::checkHeader(*File.getBuffer(), NeedsSwap));
429ab99eecSDuncan P. N. Exon Smith }
439ab99eecSDuncan P. N. Exon Smith 
TEST(HeaderMapTest,checkHeaderVersion)449ab99eecSDuncan P. N. Exon Smith TEST(HeaderMapTest, checkHeaderVersion) {
45*37b530a2SDmitry Polukhin   HMapFileMock<1, 1> File;
469ab99eecSDuncan P. N. Exon Smith   File.init();
479ab99eecSDuncan P. N. Exon Smith   ++File.Header.Version;
489ab99eecSDuncan P. N. Exon Smith   bool NeedsSwap;
499ab99eecSDuncan P. N. Exon Smith   ASSERT_FALSE(HeaderMapImpl::checkHeader(*File.getBuffer(), NeedsSwap));
509ab99eecSDuncan P. N. Exon Smith }
519ab99eecSDuncan P. N. Exon Smith 
TEST(HeaderMapTest,checkHeaderValidButEmpty)529ab99eecSDuncan P. N. Exon Smith TEST(HeaderMapTest, checkHeaderValidButEmpty) {
53*37b530a2SDmitry Polukhin   HMapFileMock<1, 1> File;
549ab99eecSDuncan P. N. Exon Smith   File.init();
559ab99eecSDuncan P. N. Exon Smith   bool NeedsSwap;
569ab99eecSDuncan P. N. Exon Smith   ASSERT_TRUE(HeaderMapImpl::checkHeader(*File.getBuffer(), NeedsSwap));
579ab99eecSDuncan P. N. Exon Smith   ASSERT_FALSE(NeedsSwap);
589ab99eecSDuncan P. N. Exon Smith 
599ab99eecSDuncan P. N. Exon Smith   File.swapBytes();
609ab99eecSDuncan P. N. Exon Smith   ASSERT_TRUE(HeaderMapImpl::checkHeader(*File.getBuffer(), NeedsSwap));
619ab99eecSDuncan P. N. Exon Smith   ASSERT_TRUE(NeedsSwap);
629ab99eecSDuncan P. N. Exon Smith }
639ab99eecSDuncan P. N. Exon Smith 
TEST(HeaderMapTest,checkHeader3Buckets)64dfe85305SDuncan P. N. Exon Smith TEST(HeaderMapTest, checkHeader3Buckets) {
65*37b530a2SDmitry Polukhin   HMapFileMock<3, 1> File;
66dfe85305SDuncan P. N. Exon Smith   ASSERT_EQ(3 * sizeof(HMapBucket), sizeof(File.Buckets));
67dfe85305SDuncan P. N. Exon Smith 
68dfe85305SDuncan P. N. Exon Smith   File.init();
69dfe85305SDuncan P. N. Exon Smith   bool NeedsSwap;
70dfe85305SDuncan P. N. Exon Smith   ASSERT_FALSE(HeaderMapImpl::checkHeader(*File.getBuffer(), NeedsSwap));
71dfe85305SDuncan P. N. Exon Smith }
72dfe85305SDuncan P. N. Exon Smith 
TEST(HeaderMapTest,checkHeader0Buckets)733a7def09SDuncan P. N. Exon Smith TEST(HeaderMapTest, checkHeader0Buckets) {
743a7def09SDuncan P. N. Exon Smith   // Create with 1 bucket to avoid 0-sized arrays.
75*37b530a2SDmitry Polukhin   HMapFileMock<1, 1> File;
763a7def09SDuncan P. N. Exon Smith   File.init();
773a7def09SDuncan P. N. Exon Smith   File.Header.NumBuckets = 0;
783a7def09SDuncan P. N. Exon Smith   bool NeedsSwap;
793a7def09SDuncan P. N. Exon Smith   ASSERT_FALSE(HeaderMapImpl::checkHeader(*File.getBuffer(), NeedsSwap));
803a7def09SDuncan P. N. Exon Smith }
813a7def09SDuncan P. N. Exon Smith 
TEST(HeaderMapTest,checkHeaderNotEnoughBuckets)828d6a31c0SDuncan P. N. Exon Smith TEST(HeaderMapTest, checkHeaderNotEnoughBuckets) {
83*37b530a2SDmitry Polukhin   HMapFileMock<1, 1> File;
848d6a31c0SDuncan P. N. Exon Smith   File.init();
858d6a31c0SDuncan P. N. Exon Smith   File.Header.NumBuckets = 8;
868d6a31c0SDuncan P. N. Exon Smith   bool NeedsSwap;
878d6a31c0SDuncan P. N. Exon Smith   ASSERT_FALSE(HeaderMapImpl::checkHeader(*File.getBuffer(), NeedsSwap));
888d6a31c0SDuncan P. N. Exon Smith }
898d6a31c0SDuncan P. N. Exon Smith 
TEST(HeaderMapTest,lookupFilename)9008fd70faSDuncan P. N. Exon Smith TEST(HeaderMapTest, lookupFilename) {
91*37b530a2SDmitry Polukhin   typedef HMapFileMock<2, 7> FileTy;
9208fd70faSDuncan P. N. Exon Smith   FileTy File;
9308fd70faSDuncan P. N. Exon Smith   File.init();
9408fd70faSDuncan P. N. Exon Smith 
95*37b530a2SDmitry Polukhin   HMapFileMockMaker<FileTy> Maker(File);
9608fd70faSDuncan P. N. Exon Smith   auto a = Maker.addString("a");
9708fd70faSDuncan P. N. Exon Smith   auto b = Maker.addString("b");
9808fd70faSDuncan P. N. Exon Smith   auto c = Maker.addString("c");
99*37b530a2SDmitry Polukhin   Maker.addBucket("a", a, b, c);
10008fd70faSDuncan P. N. Exon Smith 
10108fd70faSDuncan P. N. Exon Smith   bool NeedsSwap;
10208fd70faSDuncan P. N. Exon Smith   ASSERT_TRUE(HeaderMapImpl::checkHeader(*File.getBuffer(), NeedsSwap));
10308fd70faSDuncan P. N. Exon Smith   ASSERT_FALSE(NeedsSwap);
10408fd70faSDuncan P. N. Exon Smith   HeaderMapImpl Map(File.getBuffer(), NeedsSwap);
10508fd70faSDuncan P. N. Exon Smith 
10608fd70faSDuncan P. N. Exon Smith   SmallString<8> DestPath;
10708fd70faSDuncan P. N. Exon Smith   ASSERT_EQ("bc", Map.lookupFilename("a", DestPath));
10808fd70faSDuncan P. N. Exon Smith }
10908fd70faSDuncan P. N. Exon Smith 
11096a01fa0SDuncan P. N. Exon Smith template <class FileTy, class PaddingTy> struct PaddedFile {
11196a01fa0SDuncan P. N. Exon Smith   FileTy File;
11296a01fa0SDuncan P. N. Exon Smith   PaddingTy Padding;
11396a01fa0SDuncan P. N. Exon Smith };
11496a01fa0SDuncan P. N. Exon Smith 
TEST(HeaderMapTest,lookupFilenameTruncatedSuffix)115b5ce11fcSDuncan P. N. Exon Smith TEST(HeaderMapTest, lookupFilenameTruncatedSuffix) {
116*37b530a2SDmitry Polukhin   typedef HMapFileMock<2, 64 - sizeof(HMapHeader) - 2 * sizeof(HMapBucket)>
117*37b530a2SDmitry Polukhin       FileTy;
11896a01fa0SDuncan P. N. Exon Smith   static_assert(std::is_standard_layout<FileTy>::value,
11996a01fa0SDuncan P. N. Exon Smith                 "Expected standard layout");
12096a01fa0SDuncan P. N. Exon Smith   static_assert(sizeof(FileTy) == 64, "check the math");
12196a01fa0SDuncan P. N. Exon Smith   PaddedFile<FileTy, uint64_t> P;
12296a01fa0SDuncan P. N. Exon Smith   auto &File = P.File;
12396a01fa0SDuncan P. N. Exon Smith   auto &Padding = P.Padding;
12496a01fa0SDuncan P. N. Exon Smith   File.init();
12596a01fa0SDuncan P. N. Exon Smith 
126*37b530a2SDmitry Polukhin   HMapFileMockMaker<FileTy> Maker(File);
12796a01fa0SDuncan P. N. Exon Smith   auto a = Maker.addString("a");
12896a01fa0SDuncan P. N. Exon Smith   auto b = Maker.addString("b");
12996a01fa0SDuncan P. N. Exon Smith   auto c = Maker.addString("c");
130*37b530a2SDmitry Polukhin   Maker.addBucket("a", a, b, c);
13196a01fa0SDuncan P. N. Exon Smith 
13296a01fa0SDuncan P. N. Exon Smith   // Add 'x' characters to cause an overflow into Padding.
13396a01fa0SDuncan P. N. Exon Smith   ASSERT_EQ('c', File.Bytes[5]);
13496a01fa0SDuncan P. N. Exon Smith   for (unsigned I = 6; I < sizeof(File.Bytes); ++I) {
13596a01fa0SDuncan P. N. Exon Smith     ASSERT_EQ(0, File.Bytes[I]);
13696a01fa0SDuncan P. N. Exon Smith     File.Bytes[I] = 'x';
13796a01fa0SDuncan P. N. Exon Smith   }
13896a01fa0SDuncan P. N. Exon Smith   Padding = 0xffffffff; // Padding won't stop it either.
13996a01fa0SDuncan P. N. Exon Smith 
14096a01fa0SDuncan P. N. Exon Smith   bool NeedsSwap;
14196a01fa0SDuncan P. N. Exon Smith   ASSERT_TRUE(HeaderMapImpl::checkHeader(*File.getBuffer(), NeedsSwap));
14296a01fa0SDuncan P. N. Exon Smith   ASSERT_FALSE(NeedsSwap);
14396a01fa0SDuncan P. N. Exon Smith   HeaderMapImpl Map(File.getBuffer(), NeedsSwap);
14496a01fa0SDuncan P. N. Exon Smith 
14596a01fa0SDuncan P. N. Exon Smith   // The string for "c" runs to the end of File.  Check that the suffix
146b5ce11fcSDuncan P. N. Exon Smith   // ("cxxxx...") is detected as truncated, and an empty string is returned.
14796a01fa0SDuncan P. N. Exon Smith   SmallString<24> DestPath;
148b5ce11fcSDuncan P. N. Exon Smith   ASSERT_EQ("", Map.lookupFilename("a", DestPath));
149b5ce11fcSDuncan P. N. Exon Smith }
150b5ce11fcSDuncan P. N. Exon Smith 
TEST(HeaderMapTest,lookupFilenameTruncatedPrefix)151b5ce11fcSDuncan P. N. Exon Smith TEST(HeaderMapTest, lookupFilenameTruncatedPrefix) {
152*37b530a2SDmitry Polukhin   typedef HMapFileMock<2, 64 - sizeof(HMapHeader) - 2 * sizeof(HMapBucket)>
153*37b530a2SDmitry Polukhin       FileTy;
154b5ce11fcSDuncan P. N. Exon Smith   static_assert(std::is_standard_layout<FileTy>::value,
155b5ce11fcSDuncan P. N. Exon Smith                 "Expected standard layout");
156b5ce11fcSDuncan P. N. Exon Smith   static_assert(sizeof(FileTy) == 64, "check the math");
157b5ce11fcSDuncan P. N. Exon Smith   PaddedFile<FileTy, uint64_t> P;
158b5ce11fcSDuncan P. N. Exon Smith   auto &File = P.File;
159b5ce11fcSDuncan P. N. Exon Smith   auto &Padding = P.Padding;
160b5ce11fcSDuncan P. N. Exon Smith   File.init();
161b5ce11fcSDuncan P. N. Exon Smith 
162*37b530a2SDmitry Polukhin   HMapFileMockMaker<FileTy> Maker(File);
163b5ce11fcSDuncan P. N. Exon Smith   auto a = Maker.addString("a");
164b5ce11fcSDuncan P. N. Exon Smith   auto c = Maker.addString("c");
165b5ce11fcSDuncan P. N. Exon Smith   auto b = Maker.addString("b"); // Store the prefix last.
166*37b530a2SDmitry Polukhin   Maker.addBucket("a", a, b, c);
167b5ce11fcSDuncan P. N. Exon Smith 
168b5ce11fcSDuncan P. N. Exon Smith   // Add 'x' characters to cause an overflow into Padding.
169b5ce11fcSDuncan P. N. Exon Smith   ASSERT_EQ('b', File.Bytes[5]);
170b5ce11fcSDuncan P. N. Exon Smith   for (unsigned I = 6; I < sizeof(File.Bytes); ++I) {
171b5ce11fcSDuncan P. N. Exon Smith     ASSERT_EQ(0, File.Bytes[I]);
172b5ce11fcSDuncan P. N. Exon Smith     File.Bytes[I] = 'x';
173b5ce11fcSDuncan P. N. Exon Smith   }
174b5ce11fcSDuncan P. N. Exon Smith   Padding = 0xffffffff; // Padding won't stop it either.
175b5ce11fcSDuncan P. N. Exon Smith 
176b5ce11fcSDuncan P. N. Exon Smith   bool NeedsSwap;
177b5ce11fcSDuncan P. N. Exon Smith   ASSERT_TRUE(HeaderMapImpl::checkHeader(*File.getBuffer(), NeedsSwap));
178b5ce11fcSDuncan P. N. Exon Smith   ASSERT_FALSE(NeedsSwap);
179b5ce11fcSDuncan P. N. Exon Smith   HeaderMapImpl Map(File.getBuffer(), NeedsSwap);
180b5ce11fcSDuncan P. N. Exon Smith 
181b5ce11fcSDuncan P. N. Exon Smith   // The string for "b" runs to the end of File.  Check that the prefix
182b5ce11fcSDuncan P. N. Exon Smith   // ("bxxxx...") is detected as truncated, and an empty string is returned.
183b5ce11fcSDuncan P. N. Exon Smith   SmallString<24> DestPath;
184b5ce11fcSDuncan P. N. Exon Smith   ASSERT_EQ("", Map.lookupFilename("a", DestPath));
18596a01fa0SDuncan P. N. Exon Smith }
18696a01fa0SDuncan P. N. Exon Smith 
1879ab99eecSDuncan P. N. Exon Smith } // end namespace
188