diff options
Diffstat (limited to 'src/zen-test/utility-cmd-tests.cpp')
| -rw-r--r-- | src/zen-test/utility-cmd-tests.cpp | 179 |
1 files changed, 179 insertions, 0 deletions
diff --git a/src/zen-test/utility-cmd-tests.cpp b/src/zen-test/utility-cmd-tests.cpp new file mode 100644 index 000000000..aa49d7299 --- /dev/null +++ b/src/zen-test/utility-cmd-tests.cpp @@ -0,0 +1,179 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#include <zencore/zencore.h> + +#if ZEN_WITH_TESTS + +# include "zen-test.h" + +# include <zencore/compactbinarybuilder.h> +# include <zencore/filesystem.h> +# include <zencore/iobuffer.h> +# include <zencore/testing.h> +# include <zencore/testutils.h> + +namespace zen::tests { + +TEST_SUITE_BEGIN("zen.utility-cmd"); + +TEST_CASE("print.cbo_to_json") +{ + ScopedTemporaryDirectory TempDir; + + // Build a small compact binary object covering a few primitive field types. + CbObjectWriter Writer; + Writer << "Name" + << "ZenPrintTest"; + Writer << "Count" << int32_t(42); + Writer << "Enabled" << true; + + IoBuffer Payload = Writer.Save().GetBuffer().AsIoBuffer(); + REQUIRE(Payload.GetSize() > 0); + + const std::filesystem::path CboPath = TempDir.Path() / "object.cbo"; + WriteFile(CboPath, Payload); + + const ZenCommandResult Result = RunZen(fmt::format(R"(print --source "{}")", CboPath.string())); + + REQUIRE_MESSAGE(Result.ExitCode == 0, fmt::format("zen print exited with code {}", Result.ExitCode)); + + // CompactBinaryToJson emits a JSON object; field names are quoted and values appear verbatim. + CHECK(Result.Output.find("\"Name\"") != std::string::npos); + CHECK(Result.Output.find("\"ZenPrintTest\"") != std::string::npos); + CHECK(Result.Output.find("\"Count\"") != std::string::npos); + CHECK(Result.Output.find("42") != std::string::npos); + CHECK(Result.Output.find("\"Enabled\"") != std::string::npos); + CHECK(Result.Output.find("true") != std::string::npos); +} + +TEST_CASE("print.show_type_info_annotates_output") +{ + ScopedTemporaryDirectory TempDir; + + CbObjectWriter Writer; + Writer << "Count" << int32_t(7); + + IoBuffer Payload = Writer.Save().GetBuffer().AsIoBuffer(); + const std::filesystem::path CboPath = TempDir.Path() / "object.cbo"; + WriteFile(CboPath, Payload); + + const ZenCommandResult Plain = RunZen(fmt::format(R"(print --source "{}")", CboPath.string())); + const ZenCommandResult Typed = RunZen(fmt::format(R"(print --show-type-info --source "{}")", CboPath.string())); + + REQUIRE(Plain.ExitCode == 0); + REQUIRE(Typed.ExitCode == 0); + + // --show-type-info prefixes values with type annotations like [IntegerPositive] that the plain variant omits. + CHECK(Typed.Output.size() > Plain.Output.size()); + CHECK(Typed.Output.find("[IntegerPositive]") != std::string::npos); + CHECK(Plain.Output.find("[IntegerPositive]") == std::string::npos); +} + +TEST_CASE("print.missing_source_fails") +{ + const ZenCommandResult Result = RunZen(R"(print)"); + + CHECK(Result.ExitCode != 0); +} + +TEST_CASE("print.non_cbo_file_fails") +{ + ScopedTemporaryDirectory TempDir; + + const std::filesystem::path GarbagePath = TempDir.Path() / "garbage.cbo"; + const std::string_view Garbage = "this is not compact binary data"; + WriteFile(GarbagePath, IoBuffer(IoBuffer::Wrap, Garbage.data(), Garbage.size())); + + const ZenCommandResult Result = RunZen(fmt::format(R"(print --source "{}")", GarbagePath.string())); + + CHECK(Result.ExitCode != 0); +} + +//////////////////////////////////////////////////////////////////////////////// +// wipe + +namespace { + + // Drop a small fixture tree of files and nested directories inside Root so wipe has + // something non-trivial to recurse over. + void PopulateWipeFixture(const std::filesystem::path& Root) + { + std::filesystem::create_directories(Root / "nested" / "deep"); + const std::string_view Contents = "hello"; + const IoBuffer Payload(IoBuffer::Wrap, Contents.data(), Contents.size()); + WriteFile(Root / "top.txt", Payload); + WriteFile(Root / "nested" / "mid.txt", Payload); + WriteFile(Root / "nested" / "deep" / "leaf.txt", Payload); + } + + bool DirectoryIsEmpty(const std::filesystem::path& Path) + { + std::error_code Ec; + return std::filesystem::is_empty(Path, Ec) && !Ec; + } + +} // namespace + +TEST_CASE("wipe.removes_directory_contents") +{ + ScopedTemporaryDirectory TempDir; + const std::filesystem::path Target = TempDir.Path() / "to-wipe"; + PopulateWipeFixture(Target); + + REQUIRE(std::filesystem::exists(Target / "top.txt")); + REQUIRE(std::filesystem::exists(Target / "nested" / "deep" / "leaf.txt")); + + const ZenCommandResult Result = RunZen(fmt::format(R"(wipe --yes --quiet --directory "{}")", Target.string())); + + REQUIRE_MESSAGE(Result.ExitCode == 0, fmt::format("zen wipe exited with code {}", Result.ExitCode)); + + CHECK_FALSE(std::filesystem::exists(Target / "top.txt")); + CHECK_FALSE(std::filesystem::exists(Target / "nested")); +} + +TEST_CASE("wipe.dryrun_keeps_files") +{ + ScopedTemporaryDirectory TempDir; + const std::filesystem::path Target = TempDir.Path() / "to-wipe"; + PopulateWipeFixture(Target); + + const ZenCommandResult Result = RunZen(fmt::format(R"(wipe --yes --quiet --dryrun --directory "{}")", Target.string())); + + REQUIRE_MESSAGE(Result.ExitCode == 0, fmt::format("zen wipe --dryrun exited with code {}", Result.ExitCode)); + + // --dryrun must leave the tree untouched. + CHECK(std::filesystem::exists(Target / "top.txt")); + CHECK(std::filesystem::exists(Target / "nested" / "mid.txt")); + CHECK(std::filesystem::exists(Target / "nested" / "deep" / "leaf.txt")); +} + +TEST_CASE("wipe.nonexistent_directory_is_noop") +{ + ScopedTemporaryDirectory TempDir; + const std::filesystem::path Missing = TempDir.Path() / "does-not-exist"; + REQUIRE_FALSE(std::filesystem::exists(Missing)); + + const ZenCommandResult Result = RunZen(fmt::format(R"(wipe --yes --quiet --directory "{}")", Missing.string())); + + // A missing directory should be silently skipped without failing. + CHECK(Result.ExitCode == 0); + CHECK_FALSE(std::filesystem::exists(Missing)); +} + +TEST_CASE("wipe.empty_directory") +{ + ScopedTemporaryDirectory TempDir; + const std::filesystem::path Target = TempDir.Path() / "empty"; + std::filesystem::create_directories(Target); + REQUIRE(DirectoryIsEmpty(Target)); + + const ZenCommandResult Result = RunZen(fmt::format(R"(wipe --yes --quiet --directory "{}")", Target.string())); + + CHECK(Result.ExitCode == 0); +} + +TEST_SUITE_END(); + +} // namespace zen::tests + +#endif |