1 //===- llvm/unittest/Support/TarWriterTest.cpp ----------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "llvm/Support/TarWriter.h" 11 #include "llvm/Support/FileSystem.h" 12 #include "llvm/Support/MemoryBuffer.h" 13 #include "gtest/gtest.h" 14 #include <vector> 15 16 using namespace llvm; 17 namespace { 18 19 struct UstarHeader { 20 char Name[100]; 21 char Mode[8]; 22 char Uid[8]; 23 char Gid[8]; 24 char Size[12]; 25 char Mtime[12]; 26 char Checksum[8]; 27 char TypeFlag; 28 char Linkname[100]; 29 char Magic[6]; 30 char Version[2]; 31 char Uname[32]; 32 char Gname[32]; 33 char DevMajor[8]; 34 char DevMinor[8]; 35 char Prefix[155]; 36 char Pad[12]; 37 }; 38 39 class TarWriterTest : public ::testing::Test {}; 40 41 static std::vector<uint8_t> createTar(StringRef Base, StringRef Filename) { 42 // Create a temporary file. 43 SmallString<128> Path; 44 std::error_code EC = 45 sys::fs::createTemporaryFile("TarWriterTest", "tar", Path); 46 EXPECT_FALSE((bool)EC); 47 48 // Create a tar file. 49 Expected<std::unique_ptr<TarWriter>> TarOrErr = TarWriter::create(Path, Base); 50 EXPECT_TRUE((bool)TarOrErr); 51 std::unique_ptr<TarWriter> Tar = std::move(*TarOrErr); 52 Tar->append(Filename, "contents"); 53 Tar.reset(); 54 55 // Read the tar file. 56 ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr = MemoryBuffer::getFile(Path); 57 EXPECT_TRUE((bool)MBOrErr); 58 std::unique_ptr<MemoryBuffer> MB = std::move(*MBOrErr); 59 std::vector<uint8_t> Buf((const uint8_t *)MB->getBufferStart(), 60 (const uint8_t *)MB->getBufferEnd()); 61 62 // Windows does not allow us to remove a mmap'ed files, so 63 // unmap first and then remove the temporary file. 64 MB = nullptr; 65 sys::fs::remove(Path); 66 67 return Buf; 68 } 69 70 static UstarHeader createUstar(StringRef Base, StringRef Filename) { 71 std::vector<uint8_t> Buf = createTar(Base, Filename); 72 EXPECT_TRUE(Buf.size() >= sizeof(UstarHeader)); 73 return *reinterpret_cast<const UstarHeader *>(Buf.data()); 74 } 75 76 TEST_F(TarWriterTest, Basics) { 77 UstarHeader Hdr = createUstar("base", "file"); 78 EXPECT_EQ("ustar", StringRef(Hdr.Magic)); 79 EXPECT_EQ("00", StringRef(Hdr.Version, 2)); 80 EXPECT_EQ("base/file", StringRef(Hdr.Name)); 81 EXPECT_EQ("00000000010", StringRef(Hdr.Size)); 82 } 83 84 TEST_F(TarWriterTest, LongFilename) { 85 std::string x154(154, 'x'); 86 std::string x155(155, 'x'); 87 std::string y99(99, 'y'); 88 std::string y100(100, 'y'); 89 90 UstarHeader Hdr1 = createUstar("", x154 + "/" + y99); 91 EXPECT_EQ("/" + x154, StringRef(Hdr1.Prefix)); 92 EXPECT_EQ(y99, StringRef(Hdr1.Name)); 93 94 UstarHeader Hdr2 = createUstar("", x155 + "/" + y99); 95 EXPECT_EQ("", StringRef(Hdr2.Prefix)); 96 EXPECT_EQ("", StringRef(Hdr2.Name)); 97 98 UstarHeader Hdr3 = createUstar("", x154 + "/" + y100); 99 EXPECT_EQ("", StringRef(Hdr3.Prefix)); 100 EXPECT_EQ("", StringRef(Hdr3.Name)); 101 102 UstarHeader Hdr4 = createUstar("", x155 + "/" + y100); 103 EXPECT_EQ("", StringRef(Hdr4.Prefix)); 104 EXPECT_EQ("", StringRef(Hdr4.Name)); 105 106 std::string yz = "yyyyyyyyyyyyyyyyyyyy/zzzzzzzzzzzzzzzzzzzz"; 107 UstarHeader Hdr5 = createUstar("", x154 + "/" + yz); 108 EXPECT_EQ("/" + x154, StringRef(Hdr5.Prefix)); 109 EXPECT_EQ(yz, StringRef(Hdr5.Name)); 110 } 111 112 TEST_F(TarWriterTest, Pax) { 113 std::vector<uint8_t> Buf = createTar("", std::string(200, 'x')); 114 EXPECT_TRUE(Buf.size() >= 1024); 115 116 auto *Hdr = reinterpret_cast<const UstarHeader *>(Buf.data()); 117 EXPECT_EQ("", StringRef(Hdr->Prefix)); 118 EXPECT_EQ("", StringRef(Hdr->Name)); 119 120 StringRef Pax = StringRef((char *)(Buf.data() + 512), 512); 121 EXPECT_TRUE(Pax.startswith("211 path=/" + std::string(200, 'x'))); 122 } 123 124 TEST_F(TarWriterTest, SingleFile) { 125 SmallString<128> Path; 126 std::error_code EC = 127 sys::fs::createTemporaryFile("TarWriterTest", "tar", Path); 128 EXPECT_FALSE((bool)EC); 129 130 Expected<std::unique_ptr<TarWriter>> TarOrErr = TarWriter::create(Path, ""); 131 EXPECT_TRUE((bool)TarOrErr); 132 std::unique_ptr<TarWriter> Tar = std::move(*TarOrErr); 133 Tar->append("FooPath", "foo"); 134 Tar.reset(); 135 136 uint64_t TarSize; 137 EC = sys::fs::file_size(Path, TarSize); 138 EXPECT_FALSE((bool)EC); 139 EXPECT_EQ(TarSize, 2048ULL); 140 } 141 142 TEST_F(TarWriterTest, NoDuplicate) { 143 SmallString<128> Path; 144 std::error_code EC = 145 sys::fs::createTemporaryFile("TarWriterTest", "tar", Path); 146 EXPECT_FALSE((bool)EC); 147 148 Expected<std::unique_ptr<TarWriter>> TarOrErr = TarWriter::create(Path, ""); 149 EXPECT_TRUE((bool)TarOrErr); 150 std::unique_ptr<TarWriter> Tar = std::move(*TarOrErr); 151 Tar->append("FooPath", "foo"); 152 Tar->append("BarPath", "bar"); 153 Tar.reset(); 154 155 uint64_t TarSize; 156 EC = sys::fs::file_size(Path, TarSize); 157 EXPECT_FALSE((bool)EC); 158 EXPECT_EQ(TarSize, 3072ULL); 159 } 160 161 TEST_F(TarWriterTest, Duplicate) { 162 SmallString<128> Path; 163 std::error_code EC = 164 sys::fs::createTemporaryFile("TarWriterTest", "tar", Path); 165 EXPECT_FALSE((bool)EC); 166 167 Expected<std::unique_ptr<TarWriter>> TarOrErr = TarWriter::create(Path, ""); 168 EXPECT_TRUE((bool)TarOrErr); 169 std::unique_ptr<TarWriter> Tar = std::move(*TarOrErr); 170 Tar->append("FooPath", "foo"); 171 Tar->append("FooPath", "bar"); 172 Tar.reset(); 173 174 uint64_t TarSize; 175 EC = sys::fs::file_size(Path, TarSize); 176 EXPECT_FALSE((bool)EC); 177 EXPECT_EQ(TarSize, 2048ULL); 178 } 179 } // namespace 180