TarWriterTest.cpp 5.3 KB

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