186 lines · cpp
1//===- unittests/Lex/HeaderMapTest.cpp - HeaderMap tests ----------===//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-exception6//7//===--------------------------------------------------------------===//8 9#include "HeaderMapTestUtils.h"10#include "llvm/ADT/SmallString.h"11#include "gtest/gtest.h"12#include <type_traits>13 14using namespace clang;15using namespace llvm;16using namespace clang::test;17 18namespace {19 20TEST(HeaderMapTest, checkHeaderEmpty) {21 bool NeedsSwap;22 ASSERT_FALSE(HeaderMapImpl::checkHeader(23 *MemoryBuffer::getMemBufferCopy("", "empty"), NeedsSwap));24 ASSERT_FALSE(HeaderMapImpl::checkHeader(25 *MemoryBuffer::getMemBufferCopy("", "empty"), NeedsSwap));26}27 28TEST(HeaderMapTest, checkHeaderMagic) {29 HMapFileMock<1, 1> File;30 File.init();31 File.Header.Magic = 0;32 bool NeedsSwap;33 ASSERT_FALSE(HeaderMapImpl::checkHeader(*File.getBuffer(), NeedsSwap));34}35 36TEST(HeaderMapTest, checkHeaderReserved) {37 HMapFileMock<1, 1> File;38 File.init();39 File.Header.Reserved = 1;40 bool NeedsSwap;41 ASSERT_FALSE(HeaderMapImpl::checkHeader(*File.getBuffer(), NeedsSwap));42}43 44TEST(HeaderMapTest, checkHeaderVersion) {45 HMapFileMock<1, 1> File;46 File.init();47 ++File.Header.Version;48 bool NeedsSwap;49 ASSERT_FALSE(HeaderMapImpl::checkHeader(*File.getBuffer(), NeedsSwap));50}51 52TEST(HeaderMapTest, checkHeaderValidButEmpty) {53 HMapFileMock<1, 1> File;54 File.init();55 bool NeedsSwap;56 ASSERT_TRUE(HeaderMapImpl::checkHeader(*File.getBuffer(), NeedsSwap));57 ASSERT_FALSE(NeedsSwap);58 59 File.swapBytes();60 ASSERT_TRUE(HeaderMapImpl::checkHeader(*File.getBuffer(), NeedsSwap));61 ASSERT_TRUE(NeedsSwap);62}63 64TEST(HeaderMapTest, checkHeader3Buckets) {65 HMapFileMock<3, 1> File;66 ASSERT_EQ(3 * sizeof(HMapBucket), sizeof(File.Buckets));67 68 File.init();69 bool NeedsSwap;70 ASSERT_FALSE(HeaderMapImpl::checkHeader(*File.getBuffer(), NeedsSwap));71}72 73TEST(HeaderMapTest, checkHeader0Buckets) {74 // Create with 1 bucket to avoid 0-sized arrays.75 HMapFileMock<1, 1> File;76 File.init();77 File.Header.NumBuckets = 0;78 bool NeedsSwap;79 ASSERT_FALSE(HeaderMapImpl::checkHeader(*File.getBuffer(), NeedsSwap));80}81 82TEST(HeaderMapTest, checkHeaderNotEnoughBuckets) {83 HMapFileMock<1, 1> File;84 File.init();85 File.Header.NumBuckets = 8;86 bool NeedsSwap;87 ASSERT_FALSE(HeaderMapImpl::checkHeader(*File.getBuffer(), NeedsSwap));88}89 90TEST(HeaderMapTest, lookupFilename) {91 typedef HMapFileMock<2, 7> FileTy;92 FileTy File;93 File.init();94 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);100 101 bool NeedsSwap;102 ASSERT_TRUE(HeaderMapImpl::checkHeader(*File.getBuffer(), NeedsSwap));103 ASSERT_FALSE(NeedsSwap);104 HeaderMapImpl Map(File.getBuffer(), NeedsSwap);105 106 SmallString<8> DestPath;107 ASSERT_EQ("bc", Map.lookupFilename("a", DestPath));108}109 110template <class FileTy, class PaddingTy> struct PaddedFile {111 FileTy File;112 PaddingTy Padding;113};114 115TEST(HeaderMapTest, lookupFilenameTruncatedSuffix) {116 typedef HMapFileMock<2, 64 - sizeof(HMapHeader) - 2 * sizeof(HMapBucket)>117 FileTy;118 static_assert(std::is_standard_layout_v<FileTy>, "Expected standard layout");119 static_assert(sizeof(FileTy) == 64, "check the math");120 PaddedFile<FileTy, uint64_t> P;121 auto &File = P.File;122 auto &Padding = P.Padding;123 File.init();124 125 HMapFileMockMaker<FileTy> Maker(File);126 auto a = Maker.addString("a");127 auto b = Maker.addString("b");128 auto c = Maker.addString("c");129 Maker.addBucket("a", a, b, c);130 131 // Add 'x' characters to cause an overflow into Padding.132 ASSERT_EQ('c', File.Bytes[5]);133 for (unsigned I = 6; I < sizeof(File.Bytes); ++I) {134 ASSERT_EQ(0, File.Bytes[I]);135 File.Bytes[I] = 'x';136 }137 Padding = 0xffffffff; // Padding won't stop it either.138 139 bool NeedsSwap;140 ASSERT_TRUE(HeaderMapImpl::checkHeader(*File.getBuffer(), NeedsSwap));141 ASSERT_FALSE(NeedsSwap);142 HeaderMapImpl Map(File.getBuffer(), NeedsSwap);143 144 // The string for "c" runs to the end of File. Check that the suffix145 // ("cxxxx...") is detected as truncated, and an empty string is returned.146 SmallString<24> DestPath;147 ASSERT_EQ("", Map.lookupFilename("a", DestPath));148}149 150TEST(HeaderMapTest, lookupFilenameTruncatedPrefix) {151 typedef HMapFileMock<2, 64 - sizeof(HMapHeader) - 2 * sizeof(HMapBucket)>152 FileTy;153 static_assert(std::is_standard_layout_v<FileTy>, "Expected standard layout");154 static_assert(sizeof(FileTy) == 64, "check the math");155 PaddedFile<FileTy, uint64_t> P;156 auto &File = P.File;157 auto &Padding = P.Padding;158 File.init();159 160 HMapFileMockMaker<FileTy> Maker(File);161 auto a = Maker.addString("a");162 auto c = Maker.addString("c");163 auto b = Maker.addString("b"); // Store the prefix last.164 Maker.addBucket("a", a, b, c);165 166 // Add 'x' characters to cause an overflow into Padding.167 ASSERT_EQ('b', File.Bytes[5]);168 for (unsigned I = 6; I < sizeof(File.Bytes); ++I) {169 ASSERT_EQ(0, File.Bytes[I]);170 File.Bytes[I] = 'x';171 }172 Padding = 0xffffffff; // Padding won't stop it either.173 174 bool NeedsSwap;175 ASSERT_TRUE(HeaderMapImpl::checkHeader(*File.getBuffer(), NeedsSwap));176 ASSERT_FALSE(NeedsSwap);177 HeaderMapImpl Map(File.getBuffer(), NeedsSwap);178 179 // The string for "b" runs to the end of File. Check that the prefix180 // ("bxxxx...") is detected as truncated, and an empty string is returned.181 SmallString<24> DestPath;182 ASSERT_EQ("", Map.lookupFilename("a", DestPath));183}184 185} // end namespace186