+51
-59
@@ -92,7 +92,7 @@ auto has_value(noto::query_result const &result, std::size_t column, std::string
|
||||
});
|
||||
}
|
||||
|
||||
auto score_asset_json(std::string title, std::string key = "C") -> std::string {
|
||||
auto score_asset_json(std::string title, std::string key = "C", std::string part = "Lead") -> std::string {
|
||||
auto value = boost::json::parse(R"json({
|
||||
"schema_version":3,
|
||||
"music":{"metadata":{"title":"Fixture","composer":"Composer","key_signature":"C","time_signature":"4/4"},
|
||||
@@ -103,6 +103,7 @@ auto score_asset_json(std::string title, std::string key = "C") -> std::string {
|
||||
auto &metadata = value.as_object()["music"].as_object()["metadata"].as_object();
|
||||
metadata["title"] = std::move(title);
|
||||
metadata["key_signature"] = std::move(key);
|
||||
value.at("music").at("staves").as_array().front().as_object()["name"] = std::move(part);
|
||||
return boost::json::serialize(value);
|
||||
}
|
||||
|
||||
@@ -117,8 +118,7 @@ auto navigation_state() -> vamp_zero::app_state {
|
||||
.measure_count = 1,
|
||||
.total_pages = 2,
|
||||
};
|
||||
auto variant = vamp_zero::practice_exercise::score_variant{
|
||||
.id = "exercise-c",
|
||||
auto practice_part = vamp_zero::library_part{
|
||||
.key_signature = "C",
|
||||
.source_path = "exercise.json",
|
||||
.measure_count = 1,
|
||||
@@ -128,14 +128,11 @@ auto navigation_state() -> vamp_zero::app_state {
|
||||
.id = "exercise-1",
|
||||
.title = "C Major",
|
||||
.composer = "Composer",
|
||||
.authored_key_signature = "C",
|
||||
.variants = {variant},
|
||||
};
|
||||
exercise.variants.clear();
|
||||
for (auto key : vamp_zero::practice_key_names()) {
|
||||
variant.id = "exercise-" + std::string{key};
|
||||
variant.key_signature = key;
|
||||
exercise.variants.push_back(variant);
|
||||
for (auto part_name : vamp_zero::practice_part_names()) {
|
||||
practice_part.id = "exercise-" + std::string{part_name};
|
||||
practice_part.part = part_name;
|
||||
exercise.parts.push_back(practice_part);
|
||||
}
|
||||
auto practice = vamp_zero::group_practice_exercises({exercise});
|
||||
BOOST_REQUIRE(practice);
|
||||
@@ -286,12 +283,12 @@ BOOST_AUTO_TEST_CASE(score_parser_loads_the_generated_catalogue) {
|
||||
BOOST_TEST(count > 0U);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(practice_key_navigation_and_remote_display) {
|
||||
BOOST_AUTO_TEST_CASE(practice_part_navigation_and_remote_display) {
|
||||
auto state = navigation_state();
|
||||
auto catalog = std::make_shared<vamp_zero::catalogue>(*state.catalog);
|
||||
auto &variant = catalog->practice.exercises.front().variants[2];
|
||||
variant.source_path = "exercise-d.json";
|
||||
variant.total_pages = 3U;
|
||||
auto &practice_part = catalog->practice.exercises.front().parts[2];
|
||||
practice_part.source_path = "exercise-vocal.json";
|
||||
practice_part.total_pages = 3U;
|
||||
state.catalog = catalog;
|
||||
state.selected_main_menu_index = 1U;
|
||||
state = vamp_zero::apply_app_command(std::move(state), vamp_protocol::page_command::SELECT);
|
||||
@@ -299,23 +296,23 @@ BOOST_AUTO_TEST_CASE(practice_key_navigation_and_remote_display) {
|
||||
state = vamp_zero::apply_app_command(std::move(state), vamp_protocol::page_command::NEXT);
|
||||
state.audio.metronome_enabled = true;
|
||||
state = vamp_zero::apply_app_command(std::move(state), vamp_protocol::page_command::SELECT);
|
||||
BOOST_CHECK(state.mode == vamp_zero::app_mode::PRACTICE_KEY_MENU);
|
||||
BOOST_TEST(vamp_zero::practice_key_row_count(state) == 13U);
|
||||
BOOST_CHECK(state.mode == vamp_zero::app_mode::PRACTICE_PART_MENU);
|
||||
BOOST_TEST(vamp_zero::practice_part_row_count(state) == 4U);
|
||||
for (auto index = std::uint32_t{}; index < 3U; ++index) {
|
||||
state = vamp_zero::apply_app_command(std::move(state), vamp_protocol::page_command::NEXT);
|
||||
}
|
||||
state = vamp_zero::apply_app_command(std::move(state), vamp_protocol::page_command::SELECT);
|
||||
BOOST_CHECK(state.mode == vamp_zero::app_mode::PRACTICE_SCORE);
|
||||
BOOST_TEST(state.audio.metronome_enabled);
|
||||
auto selected = vamp_zero::selected_practice_variant(state, state.catalog->practice.exercises.front());
|
||||
auto selected = vamp_zero::selected_practice_part(state, state.catalog->practice.exercises.front());
|
||||
BOOST_REQUIRE(selected != nullptr);
|
||||
BOOST_TEST(selected->id == "exercise-D");
|
||||
BOOST_TEST(selected->source_path == "exercise-d.json");
|
||||
BOOST_TEST(selected->id == "exercise-Vocal");
|
||||
BOOST_TEST(selected->source_path == "exercise-vocal.json");
|
||||
BOOST_TEST(vamp_zero::active_pages(state) == 3U);
|
||||
auto remote = vamp_pico::remote_display_state{};
|
||||
BOOST_REQUIRE(vamp_pico::parse_remote_display_body(vamp_zero::remote_display_text(state), remote));
|
||||
BOOST_TEST(remote.active);
|
||||
BOOST_TEST(std::string{remote.part} == "Key: D");
|
||||
BOOST_TEST(std::string{remote.part} == "Vocal");
|
||||
BOOST_TEST(remote.pages == 3U);
|
||||
state = vamp_zero::apply_app_command(std::move(state), vamp_protocol::page_command::NEXT);
|
||||
BOOST_TEST(state.page_index == 1U);
|
||||
@@ -323,11 +320,11 @@ BOOST_AUTO_TEST_CASE(practice_key_navigation_and_remote_display) {
|
||||
playing.audio.playback_enabled = true;
|
||||
auto control = vamp_zero::control_state{{}, playing};
|
||||
control.finish_playback(playing.score_session);
|
||||
BOOST_CHECK(control.snapshot().mode == vamp_zero::app_mode::PRACTICE_KEY_MENU);
|
||||
BOOST_TEST(control.snapshot().selected_practice_key_index == 3U);
|
||||
BOOST_CHECK(control.snapshot().mode == vamp_zero::app_mode::PRACTICE_PART_MENU);
|
||||
BOOST_TEST(control.snapshot().selected_practice_part_index == 3U);
|
||||
state = vamp_zero::apply_app_command(std::move(state), vamp_protocol::page_command::SELECT);
|
||||
BOOST_CHECK(state.mode == vamp_zero::app_mode::PRACTICE_KEY_MENU);
|
||||
BOOST_TEST(state.selected_practice_key_index == 3U);
|
||||
BOOST_CHECK(state.mode == vamp_zero::app_mode::PRACTICE_PART_MENU);
|
||||
BOOST_TEST(state.selected_practice_part_index == 3U);
|
||||
BOOST_TEST(state.active_practice_id.empty());
|
||||
for (auto index = std::uint32_t{}; index < 3U; ++index) {
|
||||
state = vamp_zero::apply_app_command(std::move(state), vamp_protocol::page_command::PREVIOUS);
|
||||
@@ -362,7 +359,7 @@ BOOST_AUTO_TEST_CASE(flat_practice_wraps_and_empty_catalogue_returns_to_main) {
|
||||
BOOST_TEST(state.selected_practice_exercise_index == 0U);
|
||||
state = vamp_zero::apply_app_command(std::move(state), vamp_protocol::page_command::PREVIOUS);
|
||||
state = vamp_zero::apply_app_command(std::move(state), vamp_protocol::page_command::SELECT);
|
||||
BOOST_CHECK(state.mode == vamp_zero::app_mode::PRACTICE_KEY_MENU);
|
||||
BOOST_CHECK(state.mode == vamp_zero::app_mode::PRACTICE_PART_MENU);
|
||||
state.catalog = vamp_zero::empty_catalogue();
|
||||
state = vamp_zero::apply_app_command(std::move(state), vamp_protocol::page_command::NEXT);
|
||||
BOOST_CHECK(state.mode == vamp_zero::app_mode::PRACTICE_EXERCISE_MENU);
|
||||
@@ -372,11 +369,11 @@ BOOST_AUTO_TEST_CASE(flat_practice_wraps_and_empty_catalogue_returns_to_main) {
|
||||
BOOST_CHECK(state.mode == vamp_zero::app_mode::MAIN_MENU);
|
||||
}
|
||||
|
||||
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()));
|
||||
BOOST_AUTO_TEST_CASE(database_reload_preserves_all_generated_practice_parts) {
|
||||
auto root = std::filesystem::temp_directory_path() / ("product-vamp-parts-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::directory_iterator{std::filesystem::path{VAMP_TEST_SOURCE_DIR} / "data"}) {
|
||||
for (auto const &entry : std::filesystem::directory_iterator{std::filesystem::path{VAMP_TEST_SOURCE_DIR} / "data" / "practice"}) {
|
||||
if (entry.is_regular_file() && entry.path().extension() == ".xml") {
|
||||
++expected_exercises;
|
||||
}
|
||||
@@ -391,27 +388,26 @@ BOOST_AUTO_TEST_CASE(database_reload_preserves_all_generated_practice_keys) {
|
||||
BOOST_REQUIRE_MESSAGE(library.has_value(), (library ? "" : library.error().describe()));
|
||||
BOOST_TEST(library->exercises.size() == expected_exercises);
|
||||
for (auto const &exercise : library->exercises) {
|
||||
BOOST_REQUIRE_EQUAL(exercise.variants.size(), 12U);
|
||||
auto keys = vamp_zero::practice_key_names();
|
||||
for (auto index = std::size_t{}; index < keys.size(); ++index) {
|
||||
auto const &key = exercise.variants[index].key_signature;
|
||||
BOOST_TEST(key.substr(0, key.find(' ')) == keys[index]);
|
||||
BOOST_TEST(exercise.variants[index].total_pages > 0U);
|
||||
BOOST_TEST(exercise.variants[index].measure_count > 0U);
|
||||
BOOST_REQUIRE_EQUAL(exercise.parts.size(), 3U);
|
||||
auto parts = vamp_zero::practice_part_names();
|
||||
for (auto index = std::size_t{}; index < parts.size(); ++index) {
|
||||
BOOST_TEST(exercise.parts[index].part == parts[index]);
|
||||
BOOST_TEST(exercise.parts[index].total_pages > 0U);
|
||||
BOOST_TEST(exercise.parts[index].measure_count > 0U);
|
||||
if (iteration == 0U) {
|
||||
auto const &variant = exercise.variants[index];
|
||||
auto const &practice_part = exercise.parts[index];
|
||||
io.restart();
|
||||
auto loaded = boost::asio::co_spawn(io, vamp_zero::async_load_score(io.get_executor(), config, {vamp_zero::score_category::PRACTICE, variant.id}, VAMP_TEST_ASSETS_DIR), boost::asio::use_future);
|
||||
auto loaded = boost::asio::co_spawn(io, vamp_zero::async_load_score(io.get_executor(), config, {vamp_zero::score_category::PRACTICE, practice_part.id}, VAMP_TEST_ASSETS_DIR), boost::asio::use_future);
|
||||
io.run();
|
||||
auto score = loaded.get();
|
||||
BOOST_REQUIRE_MESSAGE(score, (score ? "" : score.error().describe()));
|
||||
BOOST_TEST(score->title == exercise.title);
|
||||
BOOST_TEST(score->composer == exercise.composer);
|
||||
BOOST_TEST(score->key_signature == variant.key_signature);
|
||||
BOOST_TEST(score->authored_key_signature == exercise.authored_key_signature);
|
||||
BOOST_TEST(score->measure_count == variant.measure_count);
|
||||
BOOST_TEST(score->pages.size() == variant.total_pages);
|
||||
BOOST_TEST(score->source_path == variant.source_path);
|
||||
BOOST_TEST(score->key_signature == practice_part.key_signature);
|
||||
BOOST_TEST(score->part == practice_part.part);
|
||||
BOOST_TEST(score->measure_count == practice_part.measure_count);
|
||||
BOOST_TEST(score->pages.size() == practice_part.total_pages);
|
||||
BOOST_TEST(score->source_path == practice_part.source_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -425,8 +421,8 @@ BOOST_AUTO_TEST_CASE(numbered_practice_paths_keep_duplicate_titles_separate_and_
|
||||
auto config = test_database_config(root / "vamp.db");
|
||||
std::filesystem::create_directories(assets / "songs");
|
||||
for (auto name : {"010", "002", "001", "127"}) {
|
||||
for (auto key : vamp_zero::practice_key_names()) {
|
||||
write_text(assets / "practice" / name / (std::string{key} + ".json"), score_asset_json("Shared Title", std::string{key}));
|
||||
for (auto part_name : vamp_zero::practice_part_names()) {
|
||||
write_text(assets / "practice" / name / vamp_test::part_filename(part_name), score_asset_json("Shared Title", "C", std::string{part_name}));
|
||||
}
|
||||
}
|
||||
BOOST_REQUIRE(vamp_test::build_catalogue(assets, config.path));
|
||||
@@ -448,25 +444,21 @@ BOOST_AUTO_TEST_CASE(numbered_practice_paths_keep_duplicate_titles_separate_and_
|
||||
BOOST_REQUIRE(vamp_test::build_catalogue(assets, config.path));
|
||||
auto rows = query_database(root / "vamp.db", "SELECT id FROM practice_exercises ORDER BY id");
|
||||
BOOST_REQUIRE(rows);
|
||||
BOOST_REQUIRE_EQUAL(rows->rows.size(), 48U);
|
||||
BOOST_TEST(!has_value(*rows, 0U, "002-C"));
|
||||
BOOST_TEST(has_value(*rows, 0U, "099-C"));
|
||||
BOOST_TEST(has_value(*rows, 0U, "010-C"));
|
||||
BOOST_TEST(has_value(*rows, 0U, "001-C"));
|
||||
BOOST_TEST(has_value(*rows, 0U, "127-C"));
|
||||
BOOST_REQUIRE_EQUAL(rows->rows.size(), 12U);
|
||||
BOOST_TEST(!has_value(*rows, 0U, "002-acoustic"));
|
||||
BOOST_TEST(has_value(*rows, 0U, "099-acoustic"));
|
||||
BOOST_TEST(has_value(*rows, 0U, "010-acoustic"));
|
||||
BOOST_TEST(has_value(*rows, 0U, "001-acoustic"));
|
||||
BOOST_TEST(has_value(*rows, 0U, "127-acoustic"));
|
||||
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();
|
||||
music["metadata"].as_object()["variant_tonic"] = "D";
|
||||
music["staves"].as_array().front().as_object()["arrangement_part_type"] = "practice";
|
||||
auto document = vamp_zero::parse_score_document(boost::json::serialize(source), "d.json");
|
||||
BOOST_AUTO_TEST_CASE(keyless_scores_keep_their_authored_key) {
|
||||
auto source = score_asset_json("Keyless", "No key", "Vocal");
|
||||
auto document = vamp_zero::parse_score_document(source, "vocal.json");
|
||||
BOOST_REQUIRE(document);
|
||||
BOOST_TEST(document->key_signature == "D (no key)");
|
||||
auto retained = boost::json::parse(document->source_json);
|
||||
BOOST_TEST(retained.as_object()["music"].as_object()["metadata"].as_object()["key_signature"].as_string() == "No key");
|
||||
BOOST_TEST(document->key_signature == "No key");
|
||||
BOOST_TEST(document->part == "Vocal");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(integer_parsing_checks_range_sign_and_entire_input) {
|
||||
|
||||
Reference in New Issue
Block a user