mirror of
https://github.com/logos-co/logos-package.git
synced 2026-08-30 19:51:11 +00:00
276 lines
8.1 KiB
C++
276 lines
8.1 KiB
C++
#include <gtest/gtest.h>
|
|
#include "core/tar_writer.h"
|
|
#include "core/tar_reader.h"
|
|
|
|
using namespace lgx;
|
|
|
|
// =============================================================================
|
|
// Basic Entry Tests
|
|
// =============================================================================
|
|
|
|
TEST(TarWriterTest, AddFile_Simple) {
|
|
DeterministicTarWriter writer;
|
|
|
|
std::vector<uint8_t> content = {'H', 'e', 'l', 'l', 'o'};
|
|
writer.addFile("test.txt", content);
|
|
|
|
EXPECT_EQ(writer.entryCount(), 1);
|
|
|
|
auto tarData = writer.finalize();
|
|
EXPECT_FALSE(tarData.empty());
|
|
EXPECT_TRUE(TarReader::isValidTar(tarData));
|
|
}
|
|
|
|
TEST(TarWriterTest, AddFile_FromString) {
|
|
DeterministicTarWriter writer;
|
|
|
|
writer.addFile("readme.txt", "Hello World");
|
|
|
|
auto tarData = writer.finalize();
|
|
|
|
// Read back and verify content
|
|
auto fileData = TarReader::readFile(tarData, "readme.txt");
|
|
ASSERT_TRUE(fileData.has_value());
|
|
|
|
std::string content(fileData->begin(), fileData->end());
|
|
EXPECT_EQ(content, "Hello World");
|
|
}
|
|
|
|
TEST(TarWriterTest, AddDirectory) {
|
|
DeterministicTarWriter writer;
|
|
|
|
writer.addDirectory("variants");
|
|
writer.addDirectory("variants/linux");
|
|
writer.addFile("variants/linux/lib.so", "binary content");
|
|
|
|
auto tarData = writer.finalize();
|
|
|
|
auto result = TarReader::read(tarData);
|
|
ASSERT_TRUE(result.success);
|
|
EXPECT_EQ(result.entries.size(), 3);
|
|
}
|
|
|
|
TEST(TarWriterTest, AddEntry) {
|
|
DeterministicTarWriter writer;
|
|
|
|
TarEntry entry;
|
|
entry.path = "custom/path/file.bin";
|
|
entry.data = {0x00, 0x01, 0x02, 0x03};
|
|
entry.isDirectory = false;
|
|
|
|
writer.addEntry(entry);
|
|
|
|
auto tarData = writer.finalize();
|
|
|
|
auto fileData = TarReader::readFile(tarData, "custom/path/file.bin");
|
|
ASSERT_TRUE(fileData.has_value());
|
|
EXPECT_EQ(*fileData, entry.data);
|
|
}
|
|
|
|
// =============================================================================
|
|
// Determinism Tests
|
|
// =============================================================================
|
|
|
|
TEST(TarWriterTest, Determinism_SameEntries) {
|
|
auto createTar = []() {
|
|
DeterministicTarWriter writer;
|
|
writer.addFile("file1.txt", "content1");
|
|
writer.addFile("file2.txt", "content2");
|
|
writer.addDirectory("dir");
|
|
return writer.finalize();
|
|
};
|
|
|
|
auto tar1 = createTar();
|
|
auto tar2 = createTar();
|
|
|
|
EXPECT_EQ(tar1, tar2);
|
|
}
|
|
|
|
TEST(TarWriterTest, Determinism_DifferentOrder) {
|
|
// Entries added in different order should produce same output (sorted)
|
|
DeterministicTarWriter writer1;
|
|
writer1.addFile("zzz.txt", "last");
|
|
writer1.addFile("aaa.txt", "first");
|
|
writer1.addFile("mmm.txt", "middle");
|
|
auto tar1 = writer1.finalize();
|
|
|
|
DeterministicTarWriter writer2;
|
|
writer2.addFile("aaa.txt", "first");
|
|
writer2.addFile("mmm.txt", "middle");
|
|
writer2.addFile("zzz.txt", "last");
|
|
auto tar2 = writer2.finalize();
|
|
|
|
EXPECT_EQ(tar1, tar2);
|
|
}
|
|
|
|
TEST(TarWriterTest, Determinism_SortedEntries) {
|
|
DeterministicTarWriter writer;
|
|
writer.addFile("c.txt", "c");
|
|
writer.addFile("a.txt", "a");
|
|
writer.addFile("b.txt", "b");
|
|
|
|
auto tarData = writer.finalize();
|
|
|
|
// Read entries and verify order
|
|
auto entries = TarReader::readInfo(tarData);
|
|
ASSERT_GE(entries.size(), 3);
|
|
|
|
// Should be sorted: a.txt, b.txt, c.txt
|
|
EXPECT_EQ(entries[0].path, "a.txt");
|
|
EXPECT_EQ(entries[1].path, "b.txt");
|
|
EXPECT_EQ(entries[2].path, "c.txt");
|
|
}
|
|
|
|
// =============================================================================
|
|
// Fixed Metadata Tests
|
|
// =============================================================================
|
|
|
|
TEST(TarWriterTest, FixedMetadata) {
|
|
DeterministicTarWriter writer;
|
|
writer.addFile("test.txt", "content");
|
|
writer.addDirectory("testdir");
|
|
|
|
auto tarData = writer.finalize();
|
|
auto entries = TarReader::readInfo(tarData);
|
|
|
|
for (const auto& entry : entries) {
|
|
// UID and GID should be 0
|
|
EXPECT_EQ(entry.uid, 0);
|
|
EXPECT_EQ(entry.gid, 0);
|
|
|
|
// Mtime should be 0
|
|
EXPECT_EQ(entry.mtime, 0);
|
|
|
|
// Mode should be 0644 for files, 0755 for directories
|
|
if (entry.isDirectory) {
|
|
EXPECT_EQ(entry.mode, 0755);
|
|
} else {
|
|
EXPECT_EQ(entry.mode, 0644);
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST(TarWriterTest, CustomMode) {
|
|
DeterministicTarWriter writer;
|
|
|
|
// Add file with custom mode
|
|
TarEntry entry1("script.sh", std::string("echo hello"), 0700);
|
|
writer.addEntry(entry1);
|
|
|
|
// Add directory with custom mode
|
|
TarEntry entry2("tools", true, 0777);
|
|
writer.addEntry(entry2);
|
|
|
|
auto tarData = writer.finalize();
|
|
auto result = TarReader::read(tarData);
|
|
ASSERT_TRUE(result.success);
|
|
ASSERT_EQ(result.entries.size(), 2);
|
|
|
|
// Entries are sorted lexicographically: script.sh, tools
|
|
EXPECT_EQ(result.entries[0].path, "script.sh");
|
|
EXPECT_EQ(result.entries[0].mode, 0700);
|
|
|
|
EXPECT_EQ(result.entries[1].path, "tools/");
|
|
EXPECT_EQ(result.entries[1].mode, 0755); // Directories now always DIR_MODE (0755)
|
|
}
|
|
|
|
// =============================================================================
|
|
// Roundtrip Tests
|
|
// =============================================================================
|
|
|
|
TEST(TarWriterTest, Roundtrip_MultipleFiles) {
|
|
DeterministicTarWriter writer;
|
|
|
|
std::map<std::string, std::vector<uint8_t>> files = {
|
|
{"file1.txt", {'a', 'b', 'c'}},
|
|
{"dir/file2.bin", {0x00, 0x01, 0x02, 0xFF}},
|
|
{"dir/subdir/file3.dat", {'x', 'y', 'z'}}
|
|
};
|
|
|
|
for (const auto& [path, data] : files) {
|
|
writer.addFile(path, data);
|
|
}
|
|
|
|
auto tarData = writer.finalize();
|
|
auto result = TarReader::read(tarData);
|
|
|
|
ASSERT_TRUE(result.success);
|
|
|
|
// Verify each file
|
|
for (const auto& [path, expectedData] : files) {
|
|
auto fileData = TarReader::readFile(tarData, path);
|
|
ASSERT_TRUE(fileData.has_value()) << "File not found: " << path;
|
|
EXPECT_EQ(*fileData, expectedData) << "Content mismatch for: " << path;
|
|
}
|
|
}
|
|
|
|
TEST(TarWriterTest, Roundtrip_LargeFile) {
|
|
DeterministicTarWriter writer;
|
|
|
|
// 100KB file
|
|
std::vector<uint8_t> largeData(100 * 1024);
|
|
for (size_t i = 0; i < largeData.size(); ++i) {
|
|
largeData[i] = static_cast<uint8_t>(i % 256);
|
|
}
|
|
|
|
writer.addFile("large.bin", largeData);
|
|
|
|
auto tarData = writer.finalize();
|
|
auto result = TarReader::readFile(tarData, "large.bin");
|
|
|
|
ASSERT_TRUE(result.has_value());
|
|
EXPECT_EQ(*result, largeData);
|
|
}
|
|
|
|
// =============================================================================
|
|
// Clear Tests
|
|
// =============================================================================
|
|
|
|
TEST(TarWriterTest, Clear) {
|
|
DeterministicTarWriter writer;
|
|
|
|
writer.addFile("file1.txt", "content1");
|
|
writer.addFile("file2.txt", "content2");
|
|
EXPECT_EQ(writer.entryCount(), 2);
|
|
|
|
writer.clear();
|
|
EXPECT_EQ(writer.entryCount(), 0);
|
|
|
|
writer.addFile("file3.txt", "content3");
|
|
EXPECT_EQ(writer.entryCount(), 1);
|
|
|
|
auto tarData = writer.finalize();
|
|
auto result = TarReader::read(tarData);
|
|
|
|
ASSERT_TRUE(result.success);
|
|
EXPECT_EQ(result.entries.size(), 1);
|
|
EXPECT_EQ(result.entries[0].path, "file3.txt");
|
|
}
|
|
|
|
// =============================================================================
|
|
// Edge Cases
|
|
// =============================================================================
|
|
|
|
TEST(TarWriterTest, EmptyFile) {
|
|
DeterministicTarWriter writer;
|
|
writer.addFile("empty.txt", std::vector<uint8_t>{});
|
|
|
|
auto tarData = writer.finalize();
|
|
auto result = TarReader::readFile(tarData, "empty.txt");
|
|
|
|
ASSERT_TRUE(result.has_value());
|
|
EXPECT_TRUE(result->empty());
|
|
}
|
|
|
|
TEST(TarWriterTest, DeepDirectory) {
|
|
DeterministicTarWriter writer;
|
|
writer.addFile("a/b/c/d/e/f/g/deep.txt", "deep content");
|
|
|
|
auto tarData = writer.finalize();
|
|
auto result = TarReader::readFile(tarData, "a/b/c/d/e/f/g/deep.txt");
|
|
|
|
ASSERT_TRUE(result.has_value());
|
|
std::string content(result->begin(), result->end());
|
|
EXPECT_EQ(content, "deep content");
|
|
}
|