+62
-158
@@ -37,8 +37,7 @@ template <typename T>
|
||||
concept retains_score_json = requires(T value) { value.source_json; };
|
||||
|
||||
static_assert(!retains_score_json<vamp_zero::library_part>);
|
||||
static_assert(!retains_score_json<vamp_zero::practice_exercise>);
|
||||
static_assert(!retains_score_json<vamp_zero::library_part>);
|
||||
static_assert(!retains_score_json<vamp_zero::catalog>);
|
||||
|
||||
struct catalog_directory {
|
||||
std::filesystem::path path;
|
||||
@@ -127,60 +126,41 @@ struct catalog_database {
|
||||
auto build() const -> std::bool_t {
|
||||
return vamp_test::build_catalog(assets, config.path);
|
||||
}
|
||||
auto performance() const -> std::expected<vamp_zero::library_state, modulus::error> {
|
||||
return run_catalog_operation(vamp_zero::async_load_performance_library, config, assets.string());
|
||||
auto performance() const -> std::expected<vamp_zero::catalog, modulus::error> {
|
||||
return run_catalog_operation(vamp_zero::async_load_catalog, config, assets.string());
|
||||
}
|
||||
auto practice() const -> std::expected<vamp_zero::practice_library, modulus::error> {
|
||||
return run_catalog_operation(vamp_zero::async_load_practice_library, config, assets.string());
|
||||
}
|
||||
auto score(vamp_zero::score_category category, std::string id) const -> std::expected<vamp_zero::score_document, modulus::error> {
|
||||
return run_catalog_operation(vamp_zero::async_load_score, config, vamp_zero::score_reference{category, std::move(id)}, assets.string());
|
||||
auto score(std::string id) const -> std::expected<vamp_zero::score_document, modulus::error> {
|
||||
return run_catalog_operation(vamp_zero::async_load_score, config, vamp_zero::score_reference{std::move(id)}, assets.string());
|
||||
}
|
||||
};
|
||||
|
||||
auto catalog_exercise(std::string authored = "Eb", std::string id = "0001") -> vamp_zero::practice_exercise {
|
||||
auto result = vamp_zero::practice_exercise{
|
||||
.id = std::move(id),
|
||||
.title = "Exercise",
|
||||
.composer = "Composer",
|
||||
};
|
||||
for (auto part_name : vamp_zero::practice_part_names()) {
|
||||
result.parts.push_back({.id = result.id + "-" + std::string{part_name}, .key_signature = authored, .part = std::string{part_name}, .measure_count = 3, .total_pages = 2});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(catalog_snapshots_heartbeat_and_navigation_share_immutable_metadata) {
|
||||
auto performance = vamp_zero::group_library_parts({
|
||||
auto performance = vamp_zero::group_ordered_parts({
|
||||
{.id = "other", .title = "A Tune", .composer = "Composer", .part = "Lead", .total_pages = 1},
|
||||
{.id = "chosen", .title = "B Tune", .composer = "Composer", .part = "Lead", .total_pages = 2},
|
||||
});
|
||||
auto practice = vamp_zero::group_practice_exercises({catalog_exercise("Eb", "0002"), catalog_exercise("Eb", "0001")});
|
||||
BOOST_REQUIRE(practice);
|
||||
auto catalog = std::make_shared<vamp_zero::catalog const>(vamp_zero::catalog{std::move(performance), std::move(*practice)});
|
||||
auto catalog = std::make_shared<vamp_zero::catalog const>(std::move(performance));
|
||||
auto original = vamp_zero::app_state{
|
||||
.catalog = catalog,
|
||||
.mode = vamp_zero::app_mode::PERFORMANCE_PART_MENU,
|
||||
.selected_song_index = 2,
|
||||
.selected_part_index = 1,
|
||||
.selected_practice_exercise_index = 2,
|
||||
};
|
||||
auto control = vamp_zero::control_state{{}, original};
|
||||
auto observed = std::vector<vamp_zero::app_state>{};
|
||||
control.set_observer([&](vamp_zero::app_state state) { observed.push_back(std::move(state)); });
|
||||
auto before = control.snapshot();
|
||||
BOOST_TEST(before.catalog.get() == catalog.get());
|
||||
BOOST_TEST(vamp_zero::selected_part(before) == &catalog->performance.parts[1]);
|
||||
BOOST_TEST(vamp_zero::selected_practice_exercise(before) == &catalog->practice.exercises[1]);
|
||||
BOOST_TEST(vamp_zero::selected_part(before) == &catalog->parts[1]);
|
||||
auto heartbeat = control.heartbeat();
|
||||
BOOST_TEST(heartbeat.catalog.get() == catalog.get());
|
||||
BOOST_TEST(heartbeat.heartbeat_count == 1U);
|
||||
BOOST_TEST(heartbeat.pico_connected);
|
||||
auto playing = control.apply(vamp_protocol::page_command::SELECT);
|
||||
BOOST_TEST(vamp_zero::to_string(playing.mode) == "performance_score");
|
||||
BOOST_TEST(vamp_zero::active_part(playing) == &catalog->performance.parts[1]);
|
||||
BOOST_TEST(vamp_zero::active_part(playing) == &catalog->parts[1]);
|
||||
BOOST_TEST(control.apply(vamp_protocol::page_command::NEXT).page_index == 1U);
|
||||
BOOST_TEST(control.apply(vamp_protocol::page_command::PREVIOUS).page_index == 0U);
|
||||
control.apply(vamp_protocol::page_command::SELECT);
|
||||
@@ -193,29 +173,14 @@ BOOST_AUTO_TEST_CASE(catalog_snapshots_heartbeat_and_navigation_share_immutable_
|
||||
for (auto const &snapshot : observed) {
|
||||
BOOST_TEST(snapshot.catalog.get() == catalog.get());
|
||||
}
|
||||
original.mode = vamp_zero::app_mode::PRACTICE_EXERCISE_MENU;
|
||||
auto practice_control = vamp_zero::control_state{{}, original};
|
||||
auto parts = practice_control.apply(vamp_protocol::page_command::SELECT);
|
||||
BOOST_TEST(vamp_zero::to_string(parts.mode) == "practice_part_menu");
|
||||
auto selected = practice_control.apply(vamp_protocol::page_command::NEXT);
|
||||
BOOST_TEST(selected.catalog.get() == catalog.get());
|
||||
BOOST_TEST(vamp_zero::selected_practice_part(selected, catalog->practice.exercises[1]) == &catalog->practice.exercises[1].parts[0]);
|
||||
auto exercise = practice_control.apply(vamp_protocol::page_command::SELECT);
|
||||
BOOST_TEST(vamp_zero::to_string(exercise.mode) == "practice_score");
|
||||
BOOST_TEST(exercise.catalog.get() == catalog.get());
|
||||
BOOST_TEST(vamp_zero::active_practice(exercise) == &catalog->practice.exercises[1]);
|
||||
BOOST_TEST(practice_control.apply(vamp_protocol::page_command::NEXT).page_index == 1U);
|
||||
BOOST_TEST(practice_control.heartbeat().catalog.get() == catalog.get());
|
||||
BOOST_TEST(parts.active_practice_id.empty());
|
||||
BOOST_TEST(parts.selected_practice_part_index == 0U);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(catalog_performance_groups_use_title_and_composer_with_part_indices) {
|
||||
auto library = vamp_zero::group_library_parts({
|
||||
{.id = "other-composer", .title = "Shared Title", .composer = "Bea", .part = "Lead"},
|
||||
{.id = "vocal", .title = "Shared Title", .composer = "Ada", .part = "Vocal"},
|
||||
auto library = vamp_zero::group_ordered_parts({
|
||||
{.id = "other-title", .title = "Other Title", .composer = "Ada", .part = "Lead"},
|
||||
{.id = "guitar", .title = "Shared Title", .composer = "Ada", .part = "Guitar"},
|
||||
{.id = "vocal", .title = "Shared Title", .composer = "Ada", .part = "Vocal"},
|
||||
{.id = "other-composer", .title = "Shared Title", .composer = "Bea", .part = "Lead"},
|
||||
});
|
||||
BOOST_REQUIRE_EQUAL(library.parts.size(), 4U);
|
||||
BOOST_REQUIRE_EQUAL(library.groups.size(), 3U);
|
||||
@@ -241,79 +206,56 @@ BOOST_AUTO_TEST_CASE(catalog_performance_groups_use_title_and_composer_with_part
|
||||
BOOST_TEST(library.parts[library.groups[1].parts[1]].id == "vocal");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(catalog_practice_requires_complete_ordered_parts_and_key_agreement) {
|
||||
for (auto authored : {"Eb", "C dorian", "No key", ""}) {
|
||||
auto first = catalog_exercise(authored);
|
||||
std::reverse(first.parts.begin(), first.parts.end());
|
||||
auto last = first.parts.back();
|
||||
first.parts.pop_back();
|
||||
auto fragment = catalog_exercise(authored);
|
||||
fragment.parts = {last};
|
||||
auto grouped = vamp_zero::group_practice_exercises({catalog_exercise("F", "0002"), first, fragment});
|
||||
BOOST_REQUIRE(grouped);
|
||||
BOOST_REQUIRE_EQUAL(grouped->exercises.size(), 2U);
|
||||
auto const &exercise = grouped->exercises[0];
|
||||
BOOST_TEST(exercise.id == "0001");
|
||||
BOOST_TEST(exercise.parts.front().key_signature == authored);
|
||||
BOOST_REQUIRE_EQUAL(exercise.parts.size(), 3U);
|
||||
for (auto index = std::size_t{}; index < exercise.parts.size(); ++index) {
|
||||
BOOST_TEST(exercise.parts[index].part == vamp_zero::practice_part_names()[index]);
|
||||
}
|
||||
}
|
||||
for (auto conflict : {"F", ""}) {
|
||||
auto first = catalog_exercise();
|
||||
auto second = catalog_exercise(conflict);
|
||||
second.parts = {second.parts.back()};
|
||||
first.parts.pop_back();
|
||||
auto grouped = vamp_zero::group_practice_exercises({first, second});
|
||||
BOOST_REQUIRE(!grouped);
|
||||
BOOST_TEST(grouped.error().code() == static_cast<std::int32_t>(vamp_zero::error_code::INVALID_ARGUMENT));
|
||||
BOOST_TEST(grouped.error().message().find("disagree on key") != std::string_view::npos);
|
||||
}
|
||||
auto missing = catalog_exercise();
|
||||
missing.parts.pop_back();
|
||||
BOOST_TEST(!vamp_zero::group_practice_exercises({missing}));
|
||||
auto duplicate = catalog_exercise();
|
||||
duplicate.parts.back().part = "Acoustic";
|
||||
BOOST_TEST(!vamp_zero::group_practice_exercises({duplicate}));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(catalog_individual_score_lookup_uses_category_and_reports_missing_or_invalid) {
|
||||
BOOST_AUTO_TEST_CASE(catalog_individual_score_lookup_is_parameterized_and_reports_missing_or_invalid) {
|
||||
auto db = catalog_database{};
|
||||
auto song = catalog_bundle("Song", "F");
|
||||
auto exercise = catalog_bundle("Exercise", "D", "Electric");
|
||||
db.write("songs/shared.json", song);
|
||||
for (auto part : vamp_zero::practice_part_names()) {
|
||||
db.write(std::filesystem::path{"practice/0001"} / vamp_test::part_filename(part), catalog_bundle("Exercise", "D", part));
|
||||
BOOST_REQUIRE(db.build());
|
||||
std::filesystem::remove_all(db.assets);
|
||||
auto document = db.score("shared");
|
||||
BOOST_REQUIRE(document);
|
||||
BOOST_TEST(document->id == "shared");
|
||||
BOOST_TEST(document->title == "Song");
|
||||
BOOST_TEST(document->key_signature == "F");
|
||||
BOOST_TEST(document->source_json == song);
|
||||
BOOST_TEST(document->source_path == (db.assets / "songs/shared.json").string());
|
||||
BOOST_TEST(document->measure_count == 3U);
|
||||
BOOST_REQUIRE_EQUAL(document->pages.size(), 2U);
|
||||
BOOST_TEST(document->pages[1].path == "fixture.pages/2.png");
|
||||
for (auto id : {"missing", "shared' OR 1=1 --"}) {
|
||||
auto missing = db.score(id);
|
||||
BOOST_REQUIRE(!missing);
|
||||
BOOST_TEST(missing.error().code() == static_cast<std::int32_t>(vamp_zero::error_code::NOT_FOUND));
|
||||
}
|
||||
db.query("UPDATE songs SET source_json = '{}' WHERE id = 'shared'");
|
||||
auto invalid = db.score("shared");
|
||||
BOOST_REQUIRE(!invalid);
|
||||
BOOST_TEST(invalid.error().code() == static_cast<std::int32_t>(vamp_zero::error_code::INVALID_ARGUMENT));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(catalog_query_orders_and_groups_by_exact_song_identity) {
|
||||
auto db = catalog_database{};
|
||||
for (auto const &id : {"upper-bea", "upper-vocal", "upper-acoustic", "lower", "upper-acoustic-second"}) {
|
||||
db.write(std::filesystem::path{"songs"} / (std::string{id} + ".json"), catalog_bundle("Same"));
|
||||
}
|
||||
BOOST_REQUIRE(db.build());
|
||||
db.query("UPDATE practice_exercises SET id = 'shared' WHERE part = 'Electric'");
|
||||
std::filesystem::remove_all(db.assets);
|
||||
for (auto category : {vamp_zero::score_category::PERFORMANCE, vamp_zero::score_category::PRACTICE}) {
|
||||
auto is_song = category == vamp_zero::score_category::PERFORMANCE;
|
||||
auto document = db.score(category, "shared");
|
||||
BOOST_REQUIRE(document);
|
||||
BOOST_TEST(document->id == "shared");
|
||||
BOOST_TEST(document->title == (is_song ? "Song" : "Exercise"));
|
||||
BOOST_TEST(document->key_signature == (is_song ? "F" : "D"));
|
||||
BOOST_TEST(document->source_json == (is_song ? song : exercise));
|
||||
BOOST_TEST(document->source_path == (db.assets / (is_song ? "songs/shared.json" : "practice/0001/electric.json")).string());
|
||||
BOOST_TEST(document->measure_count == 3U);
|
||||
BOOST_REQUIRE_EQUAL(document->pages.size(), 2U);
|
||||
BOOST_TEST(document->pages[1].path == "fixture.pages/2.png");
|
||||
for (auto id : {"missing", "shared' OR 1=1 --"}) {
|
||||
auto missing = db.score(category, id);
|
||||
BOOST_REQUIRE(!missing);
|
||||
BOOST_TEST(missing.error().code() == static_cast<std::int32_t>(vamp_zero::error_code::NOT_FOUND));
|
||||
}
|
||||
auto table = std::string{is_song ? "songs" : "practice_exercises"};
|
||||
db.query("UPDATE " + table + " SET source_json = '{}' WHERE id = 'shared'");
|
||||
auto invalid = db.score(category, "shared");
|
||||
BOOST_REQUIRE(!invalid);
|
||||
BOOST_TEST(invalid.error().code() == static_cast<std::int32_t>(vamp_zero::error_code::INVALID_ARGUMENT));
|
||||
BOOST_REQUIRE(db.score(is_song ? vamp_zero::score_category::PRACTICE : vamp_zero::score_category::PERFORMANCE, "shared"));
|
||||
db.query("UPDATE " + table + " SET source_json = ?1 WHERE id = 'shared'", {noto::sqlite_value{is_song ? song : exercise}});
|
||||
db.query("UPDATE songs SET composer = 'Ada', part = 'Acoustic'");
|
||||
db.query("UPDATE songs SET composer = 'Bea' WHERE id = 'upper-bea'");
|
||||
db.query("UPDATE songs SET part = 'Vocal' WHERE id = 'upper-vocal'");
|
||||
db.query("UPDATE songs SET title = 'same' WHERE id = 'lower'");
|
||||
auto result = db.performance();
|
||||
BOOST_REQUIRE(result);
|
||||
BOOST_REQUIRE_EQUAL(result->groups.size(), 3U);
|
||||
auto ids = std::vector<std::string>{};
|
||||
for (auto const &part : result->parts) {
|
||||
ids.push_back(part.id);
|
||||
}
|
||||
auto expected = std::vector<std::string>{"upper-acoustic", "upper-acoustic-second", "upper-vocal", "upper-bea", "lower"};
|
||||
BOOST_TEST(ids == expected, boost::test_tools::per_element());
|
||||
BOOST_TEST(result->groups[0].composer == "Ada");
|
||||
BOOST_TEST(result->groups[0].parts.size() == 3U);
|
||||
BOOST_TEST(result->groups[1].composer == "Bea");
|
||||
BOOST_TEST(result->groups[2].title == "same");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(catalog_sequential_score_loads_keep_executor_stack_bounded) {
|
||||
@@ -322,7 +264,7 @@ BOOST_AUTO_TEST_CASE(catalog_sequential_score_loads_keep_executor_stack_bounded)
|
||||
BOOST_REQUIRE(db.build());
|
||||
auto repeated_loads = [](boost::asio::any_io_executor executor, vamp_zero::database_config config, std::string assets)
|
||||
-> boost::asio::awaitable<std::expected<std::uint32_t, modulus::error>> {
|
||||
auto reference = vamp_zero::score_reference{.category = vamp_zero::score_category::PERFORMANCE, .id = "repeated"};
|
||||
auto reference = vamp_zero::score_reference{.id = "repeated"};
|
||||
for (auto count = std::uint32_t{}; count < 4096U; ++count) {
|
||||
auto score = co_await vamp_zero::async_load_score(executor, config, reference, assets);
|
||||
if (!score) {
|
||||
@@ -343,48 +285,20 @@ BOOST_AUTO_TEST_CASE(catalog_reload_uses_cached_metadata_without_parsing_score_j
|
||||
db.query("INSERT INTO songs(id, title, composer, source_json, part, source_path, "
|
||||
"key_signature, measure_count, total_pages, title_image) "
|
||||
"VALUES('tune', 'Metadata Song', 'Composer', '{}', 'Lead', 'songs/tune.json', 'F', 3, 2, '0000000000000000000000000000000000000000000000000000000000000000')");
|
||||
for (auto part_name : vamp_zero::practice_part_names()) {
|
||||
db.query("INSERT INTO practice_exercises(id, exercise_id, "
|
||||
"title, composer, key_signature, source_json, source_path, measure_count, total_pages, part, title_image) "
|
||||
"VALUES(?1, '0001', 'Metadata Exercise', 'Composer', 'Eb', '{}', ?3, 3, 2, ?2, '0000000000000000000000000000000000000000000000000000000000000000')",
|
||||
{noto::sqlite_value{std::string{"practice_part-"} + std::string{part_name}}, noto::sqlite_value{std::string{part_name}},
|
||||
noto::sqlite_value{std::string{"practice/0001/"} + std::string{part_name} + ".json"}});
|
||||
}
|
||||
auto songs = db.rows("songs");
|
||||
auto exercises = db.rows("practice_exercises");
|
||||
for (auto attempt = std::uint32_t{}; attempt < 2U; ++attempt) {
|
||||
auto performance = db.performance();
|
||||
auto practice = db.practice();
|
||||
BOOST_REQUIRE(performance);
|
||||
BOOST_REQUIRE(practice);
|
||||
BOOST_REQUIRE_EQUAL(performance->parts.size(), 1U);
|
||||
BOOST_TEST(performance->parts[0].title == "Metadata Song");
|
||||
BOOST_TEST(performance->parts[0].key_signature == "F");
|
||||
BOOST_TEST(performance->parts[0].measure_count == 3U);
|
||||
BOOST_TEST(performance->parts[0].total_pages == 2U);
|
||||
BOOST_REQUIRE_EQUAL(practice->exercises.size(), 1U);
|
||||
BOOST_TEST(practice->exercises[0].title == "Metadata Exercise");
|
||||
BOOST_TEST(practice->exercises[0].parts.front().key_signature == "Eb");
|
||||
BOOST_REQUIRE_EQUAL(practice->exercises[0].parts.size(), 3U);
|
||||
BOOST_TEST(practice->exercises[0].parts[0].part == "Acoustic");
|
||||
BOOST_TEST(practice->exercises[0].parts[2].part == "Vocal");
|
||||
for (auto const &practice_part : practice->exercises[0].parts) {
|
||||
BOOST_TEST(practice_part.measure_count == 3U);
|
||||
BOOST_TEST(practice_part.total_pages == 2U);
|
||||
}
|
||||
}
|
||||
BOOST_TEST(db.rows("songs") == songs, boost::test_tools::per_element());
|
||||
BOOST_TEST(db.rows("practice_exercises") == exercises, boost::test_tools::per_element());
|
||||
auto song = db.score(vamp_zero::score_category::PERFORMANCE, "tune");
|
||||
auto exercise = db.score(vamp_zero::score_category::PRACTICE, "practice_part-Vocal");
|
||||
auto song = db.score("tune");
|
||||
BOOST_REQUIRE(!song);
|
||||
BOOST_REQUIRE(!exercise);
|
||||
BOOST_TEST(song.error().code() == static_cast<std::int32_t>(vamp_zero::error_code::INVALID_ARGUMENT));
|
||||
BOOST_TEST(exercise.error().code() == static_cast<std::int32_t>(vamp_zero::error_code::INVALID_ARGUMENT));
|
||||
db.query("UPDATE practice_exercises SET key_signature = 'F' WHERE id = 'practice_part-Vocal'");
|
||||
auto disagreement = db.practice();
|
||||
BOOST_REQUIRE(!disagreement);
|
||||
BOOST_TEST(disagreement.error().message().find("disagree on key") != std::string_view::npos);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(catalog_validation_rejects_missing_incompatible_and_corrupt_files_without_repair) {
|
||||
@@ -395,12 +309,9 @@ BOOST_AUTO_TEST_CASE(catalog_validation_rejects_missing_incompatible_and_corrupt
|
||||
BOOST_REQUIRE(db.build());
|
||||
BOOST_REQUIRE(validate());
|
||||
auto songs = db.performance();
|
||||
auto practice = db.practice();
|
||||
BOOST_REQUIRE(songs);
|
||||
BOOST_REQUIRE(practice);
|
||||
BOOST_TEST(songs->parts.empty());
|
||||
BOOST_TEST(practice->exercises.empty());
|
||||
for (auto sql : {"ALTER TABLE songs RENAME COLUMN part TO obsolete_part", "ALTER TABLE practice_exercises RENAME COLUMN exercise_id TO obsolete_id", "DROP TABLE songs", "DROP TABLE practice_exercises"}) {
|
||||
for (auto sql : {"ALTER TABLE songs RENAME COLUMN part TO obsolete_part", "DROP TABLE songs"}) {
|
||||
db.query(sql);
|
||||
auto snapshot_sql = "SELECT json_group_array(sql) FROM (SELECT sql FROM sqlite_schema ORDER BY name)";
|
||||
auto before = std::get<std::string>(db.query(snapshot_sql).rows[0][0].value);
|
||||
@@ -444,12 +355,8 @@ BOOST_AUTO_TEST_CASE(catalog_validation_checks_column_types_constraints_and_tabl
|
||||
BOOST_AUTO_TEST_CASE(catalog_reads_readonly_database_without_json_and_resolves_relocated_assets) {
|
||||
auto db = catalog_database{};
|
||||
db.write("songs/tune.json", catalog_bundle("Relocated"));
|
||||
for (auto part_name : vamp_zero::practice_part_names()) {
|
||||
db.write(std::filesystem::path{"practice/0001"} / vamp_test::part_filename(part_name), catalog_bundle("Exercise", "Eb", part_name));
|
||||
}
|
||||
BOOST_REQUIRE(db.build());
|
||||
std::filesystem::remove(db.assets / "songs/tune.json");
|
||||
std::filesystem::remove_all(db.assets / "practice");
|
||||
auto moved = db.directory.path / "relocated";
|
||||
std::filesystem::rename(db.assets, moved);
|
||||
db.assets = moved;
|
||||
@@ -457,14 +364,11 @@ BOOST_AUTO_TEST_CASE(catalog_reads_readonly_database_without_json_and_resolves_r
|
||||
std::filesystem::permissions(db.config.path, std::filesystem::perms::owner_read);
|
||||
BOOST_REQUIRE(run_catalog_operation(vamp_zero::async_validate_database, db.config, true));
|
||||
auto songs = db.performance();
|
||||
auto practice = db.practice();
|
||||
auto score = db.score(vamp_zero::score_category::PERFORMANCE, "tune");
|
||||
auto score = db.score("tune");
|
||||
BOOST_REQUIRE(songs);
|
||||
BOOST_REQUIRE(practice);
|
||||
BOOST_REQUIRE(score);
|
||||
BOOST_TEST(score->source_path == (moved / "songs/tune.json").string());
|
||||
BOOST_TEST(songs->parts[0].source_path == score->source_path);
|
||||
BOOST_TEST(practice->exercises[0].parts.front().key_signature == "Eb");
|
||||
BOOST_TEST((std::filesystem::last_write_time(db.config.path) == timestamp));
|
||||
BOOST_TEST(!std::filesystem::exists(db.config.path + "-wal"));
|
||||
BOOST_TEST(!std::filesystem::exists(db.config.path + "-shm"));
|
||||
@@ -481,10 +385,10 @@ BOOST_AUTO_TEST_CASE(catalog_rejects_paths_outside_the_asset_root) {
|
||||
}
|
||||
db.query("UPDATE songs SET source_path = ?1", {noto::sqlite_value{std::string{path}}});
|
||||
BOOST_TEST(!db.performance());
|
||||
BOOST_TEST(!db.score(vamp_zero::score_category::PERFORMANCE, "tune"));
|
||||
BOOST_TEST(!db.score("tune"));
|
||||
}
|
||||
std::filesystem::create_directory_symlink(db.directory.path, db.assets / "escape");
|
||||
db.query("UPDATE songs SET source_path = 'escape/tune.json'");
|
||||
BOOST_TEST(!db.performance());
|
||||
BOOST_TEST(!db.score(vamp_zero::score_category::PERFORMANCE, "tune"));
|
||||
BOOST_TEST(!db.score("tune"));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user