#include "assets/settings_document.h" #include "test_harness.h" #include #include #include #include using pp::assets::SettingsDocument; using pp::assets::SettingsValue; using pp::assets::max_settings_entries; using pp::assets::settings_value_type_name; using pp::assets::validate_settings_key; using pp::assets::validate_settings_value; using pp::foundation::StatusCode; namespace { void stores_updates_and_reads_typed_values(pp::tests::Harness& h) { SettingsDocument document; PP_EXPECT(h, document.empty()); PP_EXPECT(h, document.set("ui.theme", std::string("dark")).ok()); PP_EXPECT(h, document.set("brush.size", std::int64_t { 42 }).ok()); PP_EXPECT(h, document.set("brush.opacity", 0.75).ok()); PP_EXPECT(h, document.set("tablet.enabled", true).ok()); PP_EXPECT(h, document.size() == 4U); PP_EXPECT(h, document.has("brush.size")); const auto theme = document.get("ui.theme"); const auto size = document.get("brush.size"); const auto opacity = document.get("brush.opacity"); const auto tablet = document.get("tablet.enabled"); PP_EXPECT(h, theme.ok()); PP_EXPECT(h, std::get(theme.value()) == std::string_view("dark")); PP_EXPECT(h, settings_value_type_name(theme.value()) == std::string_view("string")); PP_EXPECT(h, size.ok()); PP_EXPECT(h, std::get(size.value()) == 42); PP_EXPECT(h, opacity.ok()); PP_EXPECT(h, std::fabs(std::get(opacity.value()) - 0.75) < 0.0001); PP_EXPECT(h, tablet.ok()); PP_EXPECT(h, std::get(tablet.value())); PP_EXPECT(h, document.set("brush.size", std::int64_t { 64 }).ok()); PP_EXPECT(h, document.size() == 4U); PP_EXPECT(h, std::get(document.get("brush.size").value()) == 64); } void unsets_and_clears_entries(pp::tests::Harness& h) { SettingsDocument document; PP_EXPECT(h, document.set("a", true).ok()); PP_EXPECT(h, document.set("b", std::int64_t { 2 }).ok()); PP_EXPECT(h, document.unset("a").ok()); PP_EXPECT(h, !document.has("a")); PP_EXPECT(h, document.size() == 1U); const auto missing = document.unset("a"); PP_EXPECT(h, !missing.ok()); PP_EXPECT(h, missing.code == StatusCode::out_of_range); document.clear(); PP_EXPECT(h, document.empty()); } void rejects_bad_keys_and_values(pp::tests::Harness& h) { const auto empty = validate_settings_key(""); const auto dotted_start = validate_settings_key(".bad"); const auto dotted_end = validate_settings_key("bad."); const auto invalid_char = validate_settings_key("bad/key"); const auto long_key = validate_settings_key(std::string(129, 'a')); const auto non_finite = validate_settings_value(SettingsValue { std::nan("") }); const auto huge_string = validate_settings_value(SettingsValue { std::string(4097, 'x') }); PP_EXPECT(h, !empty.ok()); PP_EXPECT(h, empty.code == StatusCode::invalid_argument); PP_EXPECT(h, !dotted_start.ok()); PP_EXPECT(h, dotted_start.code == StatusCode::invalid_argument); PP_EXPECT(h, !dotted_end.ok()); PP_EXPECT(h, dotted_end.code == StatusCode::invalid_argument); PP_EXPECT(h, !invalid_char.ok()); PP_EXPECT(h, invalid_char.code == StatusCode::invalid_argument); PP_EXPECT(h, !long_key.ok()); PP_EXPECT(h, long_key.code == StatusCode::out_of_range); PP_EXPECT(h, !non_finite.ok()); PP_EXPECT(h, non_finite.code == StatusCode::invalid_argument); PP_EXPECT(h, !huge_string.ok()); PP_EXPECT(h, huge_string.code == StatusCode::out_of_range); } void rejects_missing_and_excessive_entries(pp::tests::Harness& h) { SettingsDocument document; const auto missing = document.get("missing"); PP_EXPECT(h, !missing.ok()); PP_EXPECT(h, missing.status().code == StatusCode::out_of_range); for (std::size_t i = 0; i < max_settings_entries; ++i) { const auto key = std::string("k") + std::to_string(i); PP_EXPECT(h, document.set(key, std::int64_t { 1 }).ok()); } const auto excessive = document.set("one-more", std::int64_t { 1 }); PP_EXPECT(h, !excessive.ok()); PP_EXPECT(h, excessive.code == StatusCode::out_of_range); } } int main() { pp::tests::Harness harness; harness.run("stores_updates_and_reads_typed_values", stores_updates_and_reads_typed_values); harness.run("unsets_and_clears_entries", unsets_and_clears_entries); harness.run("rejects_bad_keys_and_values", rejects_bad_keys_and_values); harness.run("rejects_missing_and_excessive_entries", rejects_missing_and_excessive_entries); return harness.finish(); }