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
937b530a2SDmitry 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;
1637b530a2SDmitry 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) {
2937b530a2SDmitry 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) {
3737b530a2SDmitry 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) {
4537b530a2SDmitry 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) {
5337b530a2SDmitry 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) {
6537b530a2SDmitry 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.
7537b530a2SDmitry 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) {
8337b530a2SDmitry 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) {
9137b530a2SDmitry 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
9537b530a2SDmitry 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");
9937b530a2SDmitry 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) {
11637b530a2SDmitry Polukhin typedef HMapFileMock<2, 64 - sizeof(HMapHeader) - 2 * sizeof(HMapBucket)>
11737b530a2SDmitry Polukhin FileTy;
118*108e41d9SNathan James static_assert(std::is_standard_layout_v<FileTy>, "Expected standard layout");
11996a01fa0SDuncan P. N. Exon Smith static_assert(sizeof(FileTy) == 64, "check the math");
12096a01fa0SDuncan P. N. Exon Smith PaddedFile<FileTy, uint64_t> P;
12196a01fa0SDuncan P. N. Exon Smith auto &File = P.File;
12296a01fa0SDuncan P. N. Exon Smith auto &Padding = P.Padding;
12396a01fa0SDuncan P. N. Exon Smith File.init();
12496a01fa0SDuncan P. N. Exon Smith
12537b530a2SDmitry Polukhin HMapFileMockMaker<FileTy> Maker(File);
12696a01fa0SDuncan P. N. Exon Smith auto a = Maker.addString("a");
12796a01fa0SDuncan P. N. Exon Smith auto b = Maker.addString("b");
12896a01fa0SDuncan P. N. Exon Smith auto c = Maker.addString("c");
12937b530a2SDmitry Polukhin Maker.addBucket("a", a, b, c);
13096a01fa0SDuncan P. N. Exon Smith
13196a01fa0SDuncan P. N. Exon Smith // Add 'x' characters to cause an overflow into Padding.
13296a01fa0SDuncan P. N. Exon Smith ASSERT_EQ('c', File.Bytes[5]);
13396a01fa0SDuncan P. N. Exon Smith for (unsigned I = 6; I < sizeof(File.Bytes); ++I) {
13496a01fa0SDuncan P. N. Exon Smith ASSERT_EQ(0, File.Bytes[I]);
13596a01fa0SDuncan P. N. Exon Smith File.Bytes[I] = 'x';
13696a01fa0SDuncan P. N. Exon Smith }
13796a01fa0SDuncan P. N. Exon Smith Padding = 0xffffffff; // Padding won't stop it either.
13896a01fa0SDuncan P. N. Exon Smith
13996a01fa0SDuncan P. N. Exon Smith bool NeedsSwap;
14096a01fa0SDuncan P. N. Exon Smith ASSERT_TRUE(HeaderMapImpl::checkHeader(*File.getBuffer(), NeedsSwap));
14196a01fa0SDuncan P. N. Exon Smith ASSERT_FALSE(NeedsSwap);
14296a01fa0SDuncan P. N. Exon Smith HeaderMapImpl Map(File.getBuffer(), NeedsSwap);
14396a01fa0SDuncan P. N. Exon Smith
14496a01fa0SDuncan P. N. Exon Smith // The string for "c" runs to the end of File. Check that the suffix
145b5ce11fcSDuncan P. N. Exon Smith // ("cxxxx...") is detected as truncated, and an empty string is returned.
14696a01fa0SDuncan P. N. Exon Smith SmallString<24> DestPath;
147b5ce11fcSDuncan P. N. Exon Smith ASSERT_EQ("", Map.lookupFilename("a", DestPath));
148b5ce11fcSDuncan P. N. Exon Smith }
149b5ce11fcSDuncan P. N. Exon Smith
TEST(HeaderMapTest,lookupFilenameTruncatedPrefix)150b5ce11fcSDuncan P. N. Exon Smith TEST(HeaderMapTest, lookupFilenameTruncatedPrefix) {
15137b530a2SDmitry Polukhin typedef HMapFileMock<2, 64 - sizeof(HMapHeader) - 2 * sizeof(HMapBucket)>
15237b530a2SDmitry Polukhin FileTy;
153*108e41d9SNathan James static_assert(std::is_standard_layout_v<FileTy>, "Expected standard layout");
154b5ce11fcSDuncan P. N. Exon Smith static_assert(sizeof(FileTy) == 64, "check the math");
155b5ce11fcSDuncan P. N. Exon Smith PaddedFile<FileTy, uint64_t> P;
156b5ce11fcSDuncan P. N. Exon Smith auto &File = P.File;
157b5ce11fcSDuncan P. N. Exon Smith auto &Padding = P.Padding;
158b5ce11fcSDuncan P. N. Exon Smith File.init();
159b5ce11fcSDuncan P. N. Exon Smith
16037b530a2SDmitry Polukhin HMapFileMockMaker<FileTy> Maker(File);
161b5ce11fcSDuncan P. N. Exon Smith auto a = Maker.addString("a");
162b5ce11fcSDuncan P. N. Exon Smith auto c = Maker.addString("c");
163b5ce11fcSDuncan P. N. Exon Smith auto b = Maker.addString("b"); // Store the prefix last.
16437b530a2SDmitry Polukhin Maker.addBucket("a", a, b, c);
165b5ce11fcSDuncan P. N. Exon Smith
166b5ce11fcSDuncan P. N. Exon Smith // Add 'x' characters to cause an overflow into Padding.
167b5ce11fcSDuncan P. N. Exon Smith ASSERT_EQ('b', File.Bytes[5]);
168b5ce11fcSDuncan P. N. Exon Smith for (unsigned I = 6; I < sizeof(File.Bytes); ++I) {
169b5ce11fcSDuncan P. N. Exon Smith ASSERT_EQ(0, File.Bytes[I]);
170b5ce11fcSDuncan P. N. Exon Smith File.Bytes[I] = 'x';
171b5ce11fcSDuncan P. N. Exon Smith }
172b5ce11fcSDuncan P. N. Exon Smith Padding = 0xffffffff; // Padding won't stop it either.
173b5ce11fcSDuncan P. N. Exon Smith
174b5ce11fcSDuncan P. N. Exon Smith bool NeedsSwap;
175b5ce11fcSDuncan P. N. Exon Smith ASSERT_TRUE(HeaderMapImpl::checkHeader(*File.getBuffer(), NeedsSwap));
176b5ce11fcSDuncan P. N. Exon Smith ASSERT_FALSE(NeedsSwap);
177b5ce11fcSDuncan P. N. Exon Smith HeaderMapImpl Map(File.getBuffer(), NeedsSwap);
178b5ce11fcSDuncan P. N. Exon Smith
179b5ce11fcSDuncan P. N. Exon Smith // The string for "b" runs to the end of File. Check that the prefix
180b5ce11fcSDuncan P. N. Exon Smith // ("bxxxx...") is detected as truncated, and an empty string is returned.
181b5ce11fcSDuncan P. N. Exon Smith SmallString<24> DestPath;
182b5ce11fcSDuncan P. N. Exon Smith ASSERT_EQ("", Map.lookupFilename("a", DestPath));
18396a01fa0SDuncan P. N. Exon Smith }
18496a01fa0SDuncan P. N. Exon Smith
1859ab99eecSDuncan P. N. Exon Smith } // end namespace
186