Data File Mappings
ci / checks (push) Successful in 2h3m59s

This commit is contained in:
khodowany
2026-09-16 23:55:09 -05:00
parent 079c024ca9
commit aa1273b07d
13 changed files with 291 additions and 271 deletions
+83 -3
View File
@@ -377,6 +377,13 @@ BOOST_AUTO_TEST_CASE(chord_and_melody_practice_share_key_navigation_and_remote_d
BOOST_AUTO_TEST_CASE(database_reload_preserves_all_generated_practice_keys) {
auto root = std::filesystem::temp_directory_path() / ("product-vamp-keys-test-" + std::to_string(std::chrono::steady_clock::now().time_since_epoch().count()));
auto config = test_database_config(root / "vamp.db");
auto expected_exercises = std::size_t{};
for (auto const &entry : std::filesystem::recursive_directory_iterator{std::filesystem::path{VAMP_TEST_SOURCE_DIR} / "data/practice"}) {
if (entry.is_regular_file() && entry.path().extension() == ".xml") {
++expected_exercises;
}
}
BOOST_REQUIRE(expected_exercises > 0U);
BOOST_REQUIRE(run_ensure_database(config));
for (auto iteration = std::uint32_t{}; iteration < 2U; ++iteration) {
BOOST_REQUIRE(run_import(config, VAMP_TEST_ASSETS_DIR));
@@ -384,14 +391,15 @@ BOOST_AUTO_TEST_CASE(database_reload_preserves_all_generated_practice_keys) {
auto future = boost::asio::co_spawn(io, vamp_zero::async_load_practice_library(io.get_executor(), config), boost::asio::use_future);
io.run();
auto library = future.get();
BOOST_REQUIRE(library);
BOOST_TEST(library->exercises.size() == 4U);
BOOST_REQUIRE_MESSAGE(library.has_value(), (library ? "" : library.error().describe()));
BOOST_TEST(library->exercises.size() == expected_exercises);
for (auto const &exercise : library->exercises) {
BOOST_TEST(vamp_zero::supports_key_selection(exercise));
BOOST_REQUIRE_EQUAL(exercise.variants.size(), 12U);
auto keys = vamp_zero::practice_key_names();
for (auto index = std::size_t{}; index < keys.size(); ++index) {
BOOST_TEST(exercise.variants[index].key_signature == keys[index]);
auto const &key = exercise.variants[index].key_signature;
BOOST_TEST(key.substr(0, key.find(' ')) == keys[index]);
BOOST_REQUIRE(vamp_zero::parse_score_document(exercise.variants[index].source_json, exercise.variants[index].source_path));
}
}
@@ -399,6 +407,78 @@ BOOST_AUTO_TEST_CASE(database_reload_preserves_all_generated_practice_keys) {
std::filesystem::remove_all(root);
}
BOOST_AUTO_TEST_CASE(numbered_practice_paths_keep_duplicate_titles_separate_and_refresh_after_rename) {
auto root = std::filesystem::temp_directory_path() / ("product-vamp-paths-test-" + std::to_string(std::chrono::steady_clock::now().time_since_epoch().count()));
auto assets = root / "assets";
auto config = test_database_config(root / "vamp.db");
std::filesystem::create_directories(assets / "songs");
for (auto name : {"chord/001_lesson/010-cycles", "chord/001_lesson/002-cycles", "chord/002_lesson/001-cycles", "melody/001_lesson/127-cycles"}) {
write_text(assets / "practice" / name / "c.json", score_asset_json("Shared Title"));
}
auto library = vamp_zero::load_practice_library(assets.string());
BOOST_REQUIRE(library);
BOOST_REQUIRE_EQUAL(library->exercises.size(), 4U);
BOOST_REQUIRE_EQUAL(library->types.size(), 2U);
BOOST_TEST(library->types.front().id == "chord");
BOOST_REQUIRE_EQUAL(library->types.front().lesson_groups.size(), 2U);
auto const &lesson = library->types.front().lesson_groups.front();
BOOST_TEST(lesson.id == "001_lesson");
BOOST_REQUIRE_EQUAL(lesson.exercises.size(), 2U);
BOOST_TEST(lesson.exercises[0].id == "chord-001_lesson-002-cycles");
BOOST_TEST(lesson.exercises[1].id == "chord-001_lesson-010-cycles");
for (auto const &exercise : library->exercises) {
BOOST_TEST(exercise.title == "Shared Title");
}
BOOST_REQUIRE(run_ensure_database(config));
BOOST_REQUIRE(run_import(config, assets));
std::filesystem::rename(assets / "practice/chord/001_lesson", assets / "practice/chord/003_renamed_lesson");
std::filesystem::rename(assets / "practice/chord/003_renamed_lesson/002-cycles", assets / "practice/chord/003_renamed_lesson/099-renamed");
BOOST_REQUIRE(run_import(config, assets));
auto rows = query_database(root / "vamp.db", "SELECT id FROM practice_exercises ORDER BY id");
BOOST_REQUIRE(rows);
BOOST_REQUIRE_EQUAL(rows->rows.size(), 4U);
BOOST_TEST(!has_value(*rows, 0U, "chord-001_lesson-002-cycles-c"));
BOOST_TEST(!has_value(*rows, 0U, "chord-001_lesson-010-cycles-c"));
BOOST_TEST(has_value(*rows, 0U, "chord-003_renamed_lesson-099-renamed-c"));
BOOST_TEST(has_value(*rows, 0U, "chord-003_renamed_lesson-010-cycles-c"));
BOOST_TEST(has_value(*rows, 0U, "chord-002_lesson-001-cycles-c"));
BOOST_TEST(has_value(*rows, 0U, "melody-001_lesson-127-cycles-c"));
std::filesystem::remove_all(root);
}
BOOST_AUTO_TEST_CASE(catalogue_queries_handle_empty_results_and_invalid_stored_scores) {
auto root = std::filesystem::temp_directory_path() / ("product-vamp-query-test-" + std::to_string(std::chrono::steady_clock::now().time_since_epoch().count()));
auto config = test_database_config(root / "vamp.db");
BOOST_REQUIRE(run_ensure_database(config));
for (auto invalid_rows : {false, true}) {
if (invalid_rows) {
for (auto table : {"songs", "practice_exercises"}) {
BOOST_REQUIRE(query_database(root / "vamp.db", std::string{"INSERT INTO "} + table + "(id, title, source_json, created_at_ms, updated_at_ms) VALUES('invalid', 'Invalid', '{}', 0, 0)"));
}
}
auto io = boost::asio::io_context{};
auto performance_future = boost::asio::co_spawn(io, vamp_zero::async_load_performance_library(io.get_executor(), config), boost::asio::use_future);
auto practice_future = boost::asio::co_spawn(io, vamp_zero::async_load_practice_library(io.get_executor(), config), boost::asio::use_future);
io.run();
auto performance = performance_future.get();
auto practice = practice_future.get();
if (invalid_rows) {
BOOST_REQUIRE(!performance);
BOOST_REQUIRE(!practice);
auto invalid_score = vamp_zero::parse_score_document("{}", "");
BOOST_REQUIRE(!invalid_score);
BOOST_TEST(performance.error().message() == invalid_score.error().message());
BOOST_TEST(practice.error().message() == invalid_score.error().message());
} else {
BOOST_REQUIRE(performance);
BOOST_REQUIRE(practice);
BOOST_TEST(performance->parts.empty());
BOOST_TEST(practice->exercises.empty());
}
}
std::filesystem::remove_all(root);
}
BOOST_AUTO_TEST_CASE(keyless_practice_variants_display_their_transposition_reference) {
auto source = boost::json::parse(score_asset_json("Keyless", "No key"));
auto &music = source.as_object()["music"].as_object();