156 lines
5.5 KiB
C++
156 lines
5.5 KiB
C++
#include "assets/brush_package.h"
|
|
#include "test_harness.h"
|
|
|
|
#include <array>
|
|
#include <cstddef>
|
|
#include <string>
|
|
#include <string_view>
|
|
|
|
namespace {
|
|
|
|
std::array<std::byte, pp::assets::ppbr_header_size> ppbr_header(std::uint16_t major, std::uint16_t minor)
|
|
{
|
|
return {
|
|
std::byte { 'P' },
|
|
std::byte { 'P' },
|
|
std::byte { 'B' },
|
|
std::byte { 'R' },
|
|
static_cast<std::byte>(major & 0xffU),
|
|
static_cast<std::byte>((major >> 8U) & 0xffU),
|
|
static_cast<std::byte>(minor & 0xffU),
|
|
static_cast<std::byte>((minor >> 8U) & 0xffU),
|
|
};
|
|
}
|
|
|
|
void parses_ppbr_header_and_legacy_version_tolerance(pp::tests::Harness& harness)
|
|
{
|
|
const auto canonical_bytes = ppbr_header(0, 1);
|
|
const auto canonical = pp::assets::parse_ppbr_header(canonical_bytes);
|
|
|
|
PP_EXPECT(harness, canonical);
|
|
PP_EXPECT(harness, canonical.value().major == 0U);
|
|
PP_EXPECT(harness, canonical.value().minor == 1U);
|
|
|
|
const auto minor_tolerated_bytes = ppbr_header(0, 2);
|
|
const auto major_tolerated_bytes = ppbr_header(1, 1);
|
|
const auto rejected_bytes = ppbr_header(1, 2);
|
|
const auto legacy_minor_tolerated = pp::assets::parse_ppbr_header(minor_tolerated_bytes);
|
|
const auto legacy_major_tolerated = pp::assets::parse_ppbr_header(major_tolerated_bytes);
|
|
const auto rejected = pp::assets::parse_ppbr_header(rejected_bytes);
|
|
PP_EXPECT(harness, legacy_minor_tolerated);
|
|
PP_EXPECT(harness, legacy_major_tolerated);
|
|
PP_EXPECT(harness, !rejected);
|
|
}
|
|
|
|
void rejects_truncated_and_bad_magic_headers(pp::tests::Harness& harness)
|
|
{
|
|
const std::array<std::byte, 4> truncated {
|
|
std::byte { 'P' },
|
|
std::byte { 'P' },
|
|
std::byte { 'B' },
|
|
std::byte { 'R' },
|
|
};
|
|
auto bad_magic = ppbr_header(0, 1);
|
|
bad_magic[2] = std::byte { 'X' };
|
|
|
|
const auto truncated_result = pp::assets::parse_ppbr_header(truncated);
|
|
const auto magic_result = pp::assets::parse_ppbr_header(bad_magic);
|
|
|
|
PP_EXPECT(harness, !truncated_result);
|
|
PP_EXPECT(harness, truncated_result.status().code == pp::foundation::StatusCode::out_of_range);
|
|
PP_EXPECT(harness, !magic_result);
|
|
PP_EXPECT(harness, magic_result.status().code == pp::foundation::StatusCode::invalid_argument);
|
|
}
|
|
|
|
void plans_export_package_and_data_paths(pp::tests::Harness& harness)
|
|
{
|
|
const auto regular = pp::assets::plan_ppbr_export_paths(
|
|
"D:/Paint/clouds",
|
|
"",
|
|
true,
|
|
pp::assets::PpbrDataDirectoryPolicy::next_to_package);
|
|
PP_EXPECT(harness, regular);
|
|
if (regular) {
|
|
PP_EXPECT(harness, regular.value().package_path == "D:/Paint/clouds.ppbr");
|
|
PP_EXPECT(harness, regular.value().directory == "D:/Paint");
|
|
PP_EXPECT(harness, regular.value().stem == "clouds");
|
|
PP_EXPECT(harness, regular.value().extension == "ppbr");
|
|
PP_EXPECT(harness, regular.value().data_directory == "D:/Paint/clouds_data");
|
|
PP_EXPECT(harness, regular.value().data_directory_enabled);
|
|
}
|
|
|
|
const auto override = pp::assets::plan_ppbr_export_paths(
|
|
"/brushes/clouds.ppbr",
|
|
"/Users/artist/Exports",
|
|
true,
|
|
pp::assets::PpbrDataDirectoryPolicy::override_directory);
|
|
PP_EXPECT(harness, override);
|
|
if (override) {
|
|
PP_EXPECT(harness, override.value().data_directory == "/Users/artist/Exports/clouds_data");
|
|
PP_EXPECT(harness, override.value().data_directory_enabled);
|
|
}
|
|
|
|
const auto no_data = pp::assets::plan_ppbr_export_paths(
|
|
"D:/Paint/clouds.ppbr",
|
|
"",
|
|
false,
|
|
pp::assets::PpbrDataDirectoryPolicy::next_to_package);
|
|
PP_EXPECT(harness, no_data);
|
|
if (no_data) {
|
|
PP_EXPECT(harness, !no_data.value().data_directory_enabled);
|
|
}
|
|
}
|
|
|
|
void preserves_legacy_extension_containment_rule(pp::tests::Harness& harness)
|
|
{
|
|
const auto path = pp::assets::normalize_ppbr_export_path("D:/Paint/clouds.ppbr.tmp");
|
|
|
|
PP_EXPECT(harness, path);
|
|
PP_EXPECT(harness, path.value() == "D:/Paint/clouds.ppbr.tmp");
|
|
}
|
|
|
|
void rejects_export_paths_that_legacy_regex_could_not_match(pp::tests::Harness& harness)
|
|
{
|
|
PP_EXPECT(
|
|
harness,
|
|
!pp::assets::plan_ppbr_export_paths(
|
|
"",
|
|
"",
|
|
true,
|
|
pp::assets::PpbrDataDirectoryPolicy::next_to_package));
|
|
PP_EXPECT(
|
|
harness,
|
|
!pp::assets::plan_ppbr_export_paths(
|
|
"clouds",
|
|
"",
|
|
true,
|
|
pp::assets::PpbrDataDirectoryPolicy::next_to_package));
|
|
PP_EXPECT(
|
|
harness,
|
|
!pp::assets::plan_ppbr_export_paths(
|
|
"D:/Paint/.ppbr",
|
|
"",
|
|
true,
|
|
pp::assets::PpbrDataDirectoryPolicy::next_to_package));
|
|
PP_EXPECT(
|
|
harness,
|
|
!pp::assets::plan_ppbr_export_paths(
|
|
"D:/Paint/clouds.ppbr!",
|
|
"",
|
|
true,
|
|
pp::assets::PpbrDataDirectoryPolicy::next_to_package));
|
|
}
|
|
|
|
} // namespace
|
|
|
|
int main()
|
|
{
|
|
pp::tests::Harness harness;
|
|
harness.run("parses PPBR header and legacy version tolerance", parses_ppbr_header_and_legacy_version_tolerance);
|
|
harness.run("rejects truncated and bad magic headers", rejects_truncated_and_bad_magic_headers);
|
|
harness.run("plans export package and data paths", plans_export_package_and_data_paths);
|
|
harness.run("preserves legacy extension containment rule", preserves_legacy_extension_containment_rule);
|
|
harness.run("rejects export paths that legacy regex could not match", rejects_export_paths_that_legacy_regex_could_not_match);
|
|
return harness.finish();
|
|
}
|