Add ArchiveReaderIterator
This commit is contained in:
253
tests/IO/Archive/ArchiveReaderIterator.cpp
Normal file
253
tests/IO/Archive/ArchiveReaderIterator.cpp
Normal file
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include <catch2/catch_all.hpp>
|
||||
|
||||
#include "IO/Archive/ArchiveReader.hpp"
|
||||
#include "IO/Archive/ArchiveReaderIterator.hpp"
|
||||
#include "IO/Archive/ArchiveWriter.hpp"
|
||||
#include "IO/AppFolders.hpp"
|
||||
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace OpenVulkano;
|
||||
|
||||
namespace
|
||||
{
|
||||
std::filesystem::path iteratorTestArchiveDir()
|
||||
{
|
||||
return AppFolders::GetAppTempDir();
|
||||
}
|
||||
|
||||
std::filesystem::path iteratorTestArchivePath()
|
||||
{
|
||||
return iteratorTestArchiveDir() / "test_iterator_archive.zip";
|
||||
}
|
||||
|
||||
void makeIteratorTestArchive()
|
||||
{
|
||||
ArchiveWriter writer(iteratorTestArchivePath());
|
||||
|
||||
// Add multiple files for iteration testing
|
||||
std::vector<std::pair<std::string, std::string>> files = {
|
||||
{"file1.txt", "Content of file 1"},
|
||||
{"file2.txt", "Content of file 2"},
|
||||
{"subdir/file3.txt", "Content of file 3"},
|
||||
{"subdir/file4.txt", "Content of file 4"},
|
||||
{"readme.md", "# Test Archive"}
|
||||
};
|
||||
|
||||
for (const auto& [path, content]: files)
|
||||
{
|
||||
FileDescription desc = FileDescription::MkFile(path, content.size());
|
||||
writer.AddFile(desc, content.data());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Iterator Basic Operations", "[ArchiveReaderIterator]")
|
||||
{
|
||||
makeIteratorTestArchive();
|
||||
|
||||
SECTION("Begin and End")
|
||||
{
|
||||
ArchiveReader reader(iteratorTestArchivePath());
|
||||
auto begin_it = reader.begin();
|
||||
auto end_it = reader.end();
|
||||
|
||||
REQUIRE(begin_it != end_it);
|
||||
REQUIRE(end_it == reader.end());
|
||||
}
|
||||
|
||||
SECTION("Dereference Operations")
|
||||
{
|
||||
ArchiveReader reader(iteratorTestArchivePath());
|
||||
auto it = reader.begin();
|
||||
REQUIRE(it != reader.end());
|
||||
|
||||
// Test operator*
|
||||
const auto& desc = *it;
|
||||
REQUIRE(!desc.first.path.empty());
|
||||
REQUIRE(desc.first.size > 0);
|
||||
REQUIRE(desc.first.type == std::filesystem::file_type::regular);
|
||||
|
||||
// Test operator->
|
||||
REQUIRE(it->first.path == desc.first.path);
|
||||
REQUIRE(it->first.size == desc.first.size);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Iterator Traversal", "[ArchiveReaderIterator]")
|
||||
{
|
||||
makeIteratorTestArchive();
|
||||
|
||||
SECTION("Pre-increment")
|
||||
{
|
||||
ArchiveReader reader(iteratorTestArchivePath());
|
||||
auto it = reader.begin();
|
||||
auto first_path = it->first.path;
|
||||
|
||||
++it;
|
||||
REQUIRE(it != reader.end());
|
||||
REQUIRE(it->first.path != first_path);
|
||||
}
|
||||
|
||||
SECTION("Post-increment")
|
||||
{
|
||||
ArchiveReader reader(iteratorTestArchivePath());
|
||||
auto it = reader.begin();
|
||||
auto first_path = it->first.path;
|
||||
|
||||
auto old_it = it++;
|
||||
REQUIRE(old_it->first.path == first_path);
|
||||
REQUIRE(it->first.path != first_path);
|
||||
}
|
||||
|
||||
SECTION("Complete Traversal")
|
||||
{
|
||||
ArchiveReader reader(iteratorTestArchivePath());
|
||||
int count = 0;
|
||||
for (auto it = reader.begin(); it != reader.end(); ++it)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
REQUIRE(count == 5); // We added 5 files in makeIteratorTestArchive
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Range-based For Loop", "[ArchiveReaderIterator]")
|
||||
{
|
||||
makeIteratorTestArchive();
|
||||
|
||||
SECTION("Basic Range Loop")
|
||||
{
|
||||
ArchiveReader reader(iteratorTestArchivePath());
|
||||
std::vector<std::string> paths;
|
||||
for (const auto& entry: reader)
|
||||
{
|
||||
paths.push_back(entry.first.path);
|
||||
}
|
||||
|
||||
REQUIRE(paths.size() == 5);
|
||||
REQUIRE(std::find(paths.begin(), paths.end(), "file1.txt") != paths.end());
|
||||
REQUIRE(std::find(paths.begin(), paths.end(), "readme.md") != paths.end());
|
||||
}
|
||||
|
||||
SECTION("Const Iterator")
|
||||
{
|
||||
ArchiveReader reader(iteratorTestArchivePath());
|
||||
const ArchiveReader& const_reader = reader;
|
||||
int count = 0;
|
||||
|
||||
for (const auto& entry: const_reader)
|
||||
{
|
||||
REQUIRE(!entry.first.path.empty());
|
||||
count++;
|
||||
}
|
||||
|
||||
REQUIRE(count == 5);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Iterator Edge Cases", "[ArchiveReaderIterator]")
|
||||
{
|
||||
SECTION("Empty Archive")
|
||||
{
|
||||
// Create empty archive
|
||||
std::filesystem::path emptyPath = iteratorTestArchiveDir() / "empty.zip";
|
||||
{
|
||||
ArchiveWriter writer(emptyPath);
|
||||
}
|
||||
|
||||
ArchiveReader reader(emptyPath);
|
||||
REQUIRE(reader.begin() == reader.end());
|
||||
|
||||
int count = 0;
|
||||
for (const auto& entry : reader)
|
||||
{
|
||||
(void)entry;
|
||||
count++;
|
||||
}
|
||||
REQUIRE(count == 0);
|
||||
}
|
||||
|
||||
SECTION("Iterator Invalidation")
|
||||
{
|
||||
makeIteratorTestArchive();
|
||||
|
||||
ArchiveReader reader(iteratorTestArchivePath());
|
||||
|
||||
auto it = reader.begin();
|
||||
REQUIRE(it != reader.end());
|
||||
|
||||
// Advance to end
|
||||
while (it != reader.end())
|
||||
{
|
||||
++it;
|
||||
}
|
||||
|
||||
// Further increment should not crash
|
||||
++it;
|
||||
REQUIRE(it == reader.end());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Iterator with STL Algorithms", "[ArchiveReaderIterator]")
|
||||
{
|
||||
makeIteratorTestArchive();
|
||||
|
||||
SECTION("std::distance")
|
||||
{
|
||||
ArchiveReader reader(iteratorTestArchivePath());
|
||||
auto distance = std::distance(reader.begin(), reader.end());
|
||||
REQUIRE(distance == 5);
|
||||
}
|
||||
|
||||
SECTION("std::count_if")
|
||||
{
|
||||
ArchiveReader reader(iteratorTestArchivePath());
|
||||
auto txt_count = std::count_if(reader.begin(), reader.end(),
|
||||
[](const auto& desc)
|
||||
{ return desc.first.path.find(".txt") != std::string::npos; });
|
||||
REQUIRE(txt_count == 4);
|
||||
}
|
||||
|
||||
SECTION("std::find_if")
|
||||
{
|
||||
ArchiveReader reader(iteratorTestArchivePath());
|
||||
auto it = std::find_if(reader.begin(), reader.end(),
|
||||
[](const auto& desc)
|
||||
{ return desc.first.path == "readme.md"; });
|
||||
|
||||
REQUIRE(it != reader.end());
|
||||
REQUIRE(it->first.path == "readme.md");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Iterator Copy and Assignment", "[ArchiveReaderIterator]")
|
||||
{
|
||||
makeIteratorTestArchive();
|
||||
|
||||
SECTION("Copy Constructor")
|
||||
{
|
||||
ArchiveReader reader(iteratorTestArchivePath());
|
||||
auto it1 = reader.begin(), it2 = it1;
|
||||
REQUIRE(it1 == it2);
|
||||
REQUIRE(it1->first.path == it2->first.path);
|
||||
}
|
||||
|
||||
SECTION("Assignment Operator")
|
||||
{
|
||||
ArchiveReader reader(iteratorTestArchivePath());
|
||||
auto it1 = reader.begin(), it2 = reader.end();
|
||||
it2 = it1;
|
||||
REQUIRE(it1 == it2);
|
||||
REQUIRE(it2 != reader.end());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user