Transpose
This commit is contained in:
@@ -34,6 +34,7 @@
|
||||
#include <vamp_pico/http_client.hpp>
|
||||
#include <vamp_zero/database.hpp>
|
||||
#include <vamp_zero/library.hpp>
|
||||
#include <vamp_zero/navigation.hpp>
|
||||
#include <vamp_zero/parse.hpp>
|
||||
#include <vamp_zero/page_control.hpp>
|
||||
#include <vamp_zero/score.hpp>
|
||||
@@ -321,6 +322,95 @@ BOOST_AUTO_TEST_CASE(score_parser_loads_the_generated_catalogue) {
|
||||
BOOST_TEST(count > 0U);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(chord_and_melody_practice_share_key_navigation_and_remote_display) {
|
||||
for (auto type : {"chord", "melody"}) {
|
||||
auto state = navigation_state();
|
||||
auto &exercise = state.practice.exercises.front();
|
||||
exercise.practice_type_id = type;
|
||||
auto variant = exercise.variants.front();
|
||||
variant.id = "exercise-d";
|
||||
variant.key_signature = "D";
|
||||
variant.source_path = "exercise-d.json";
|
||||
variant.source_json = score_asset_json("Exercise", "D");
|
||||
variant.total_pages = 3U;
|
||||
exercise.variants.push_back(variant);
|
||||
state.practice.types.front().id = type;
|
||||
state.practice.types.front().lesson_groups.front().exercises = {exercise};
|
||||
state.mode = vamp_zero::app_mode::PRACTICE_EXERCISE_MENU;
|
||||
state.selected_practice_type_index = 1U;
|
||||
state.selected_practice_lesson_index = 1U;
|
||||
state.selected_practice_exercise_index = 1U;
|
||||
state.audio.metronome_enabled = true;
|
||||
BOOST_TEST(vamp_zero::supports_key_selection(exercise));
|
||||
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) == 3U);
|
||||
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::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.practice.exercises.front());
|
||||
BOOST_REQUIRE(selected != nullptr);
|
||||
BOOST_TEST(selected->id == "exercise-d");
|
||||
BOOST_TEST(selected->source_path == "exercise-d.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(remote.pages == 3U);
|
||||
state = vamp_zero::apply_app_command(std::move(state), vamp_protocol::page_command::NEXT);
|
||||
BOOST_TEST(state.page_index == 1U);
|
||||
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 == 2U);
|
||||
BOOST_TEST(state.active_practice_id.empty());
|
||||
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::PREVIOUS);
|
||||
state = vamp_zero::apply_app_command(std::move(state), vamp_protocol::page_command::SELECT);
|
||||
BOOST_CHECK(state.mode == vamp_zero::app_mode::PRACTICE_EXERCISE_MENU);
|
||||
BOOST_REQUIRE(vamp_zero::validate_app_state(state));
|
||||
}
|
||||
}
|
||||
|
||||
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");
|
||||
BOOST_REQUIRE(run_ensure_database(config));
|
||||
for (auto iteration = std::uint32_t{}; iteration < 2U; ++iteration) {
|
||||
BOOST_REQUIRE(run_import(config, VAMP_TEST_ASSETS_DIR));
|
||||
auto io = boost::asio::io_context{};
|
||||
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);
|
||||
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]);
|
||||
BOOST_REQUIRE(vamp_zero::parse_score_document(exercise.variants[index].source_json, exercise.variants[index].source_path));
|
||||
}
|
||||
}
|
||||
}
|
||||
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_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_AUTO_TEST_CASE(integer_parsing_checks_range_sign_and_entire_input) {
|
||||
BOOST_TEST(vamp_zero::parse_integer<std::uint16_t>("65535", "port").value_or(0) == 65535U);
|
||||
BOOST_TEST(vamp_zero::parse_integer<std::int32_t>("-2147483648", "octave").value_or(0) == std::numeric_limits<std::int32_t>::min());
|
||||
|
||||
Reference in New Issue
Block a user