diff options
-rw-r--r-- | src/engineprime/database.hpp | 10 | ||||
-rw-r--r-- | src/engineprime/track.hpp | 34 | ||||
-rw-r--r-- | src/track.cpp | 33 | ||||
-rw-r--r-- | src/track_test.cpp | 53 | ||||
-rw-r--r-- | testdata/el2/m.db | bin | 0 -> 557056 bytes | |||
-rw-r--r-- | testdata/el2/p.db | bin | 0 -> 409600 bytes |
6 files changed, 109 insertions, 21 deletions
diff --git a/src/engineprime/database.hpp b/src/engineprime/database.hpp index b23eae9..38f7f27 100644 --- a/src/engineprime/database.hpp +++ b/src/engineprime/database.hpp @@ -23,10 +23,20 @@ #define ENGINEPRIME_DATABASE_HPP #include <memory> +#include <stdexcept> #include <string> namespace engineprime { +class database_inconsistency : public std::logic_error +{ +public: + explicit database_inconsistency(const std::string &what_arg) noexcept : + logic_error{what_arg} + {} + virtual ~database_inconsistency() = default; +}; + class database { public: diff --git a/src/engineprime/track.hpp b/src/engineprime/track.hpp index 3d62d4b..f8fe596 100644 --- a/src/engineprime/track.hpp +++ b/src/engineprime/track.hpp @@ -25,6 +25,7 @@ #include <chrono> #include <cstdint> #include <memory> +#include <stdexcept> #include <string> #include <vector> @@ -42,6 +43,7 @@ struct album_art std::vector<image_data_type> image_data; }; +// TODO - Move to dedicated analysis file enum class musical_key { a_minor = 1, @@ -141,6 +143,38 @@ struct track_analysis } }; + +class nonexistent_track : public std::invalid_argument +{ +public: + explicit nonexistent_track(int id) noexcept : + invalid_argument{"Track does not exist in database"}, + id_{id} + {} + virtual ~nonexistent_track() = default; + int id() const noexcept { return id_; } +private: + int id_; +}; + +class track_database_inconsistency : public database_inconsistency +{ +public: + explicit track_database_inconsistency(const std::string &what_arg) + noexcept : + database_inconsistency{what_arg} + {} + explicit track_database_inconsistency(const std::string &what_arg, int id) + noexcept : + database_inconsistency{what_arg}, + id_{id} + {} + virtual ~track_database_inconsistency() = default; + int id() const noexcept { return id_; } +private: + int id_; +}; + class track { public: diff --git a/src/track.cpp b/src/track.cpp index 5ad99e5..7273923 100644 --- a/src/track.cpp +++ b/src/track.cpp @@ -115,7 +115,12 @@ track_row select_track_row(const std::string &music_db_path, int id) throw std::runtime_error{err_msg_str}; } sqlite3_bind_int(stmt, 1, id); - if (sqlite3_step(stmt) != SQLITE_ROW) + auto rc = sqlite3_step(stmt); + if (rc == SQLITE_DONE) + { + throw nonexistent_track(id); + } + else if (rc != SQLITE_ROW) { std::string err_msg_str{sqlite3_errmsg(m.db)}; throw std::runtime_error{err_msg_str}; @@ -158,9 +163,16 @@ str_metadata_vec select_metadata_rows(const std::string &music_db_path, int id) } sqlite3_bind_int(stmt, 1, id); + auto rc = sqlite3_step(stmt); + if (rc == SQLITE_DONE) + { + throw track_database_inconsistency{ + "No entry in Metadata table for track", id}; + } + // Iterate through rows (we only know about types 1-16 so far though) str_metadata_vec results{17}; - for (auto rc = sqlite3_step(stmt); rc != SQLITE_DONE; rc = sqlite3_step(stmt)) + for (; rc != SQLITE_DONE; rc = sqlite3_step(stmt)) { if (rc != SQLITE_ROW) { @@ -198,9 +210,16 @@ int_metadata_vec select_int_metadata_rows( } sqlite3_bind_int(stmt, 1, id); + auto rc = sqlite3_step(stmt); + if (rc == SQLITE_DONE) + { + throw track_database_inconsistency{ + "No entry in MetadataInteger table for track", id}; + } + // Iterate through rows (we only know about types 1-11 so far though) int_metadata_vec results{12}; - for (auto rc = sqlite3_step(stmt); rc != SQLITE_DONE; rc = sqlite3_step(stmt)) + for (; rc != SQLITE_DONE; rc = sqlite3_step(stmt)) { if (rc != SQLITE_ROW) { @@ -295,13 +314,9 @@ std::vector<int> all_track_ids(const database &database) } std::vector<int> results; - int rc; - while (true) + for (auto rc = sqlite3_step(stmt); rc != SQLITE_DONE; + rc = sqlite3_step(stmt)) { - rc = sqlite3_step(stmt); - if (rc == SQLITE_DONE) - break; - if (rc != SQLITE_ROW) { std::string err_msg_str{sqlite3_errmsg(m.db)}; diff --git a/src/track_test.cpp b/src/track_test.cpp index eb2d423..e776cb7 100644 --- a/src/track_test.cpp +++ b/src/track_test.cpp @@ -28,7 +28,7 @@ namespace ep = engineprime; using namespace std; -const std::string sample_path{STRINGIFY(TESTDATA_DIR) "/el1"}; +const std::string sample_path{STRINGIFY(TESTDATA_DIR) "/el2"}; BOOST_AUTO_TEST_CASE (all_track_ids__sample_db__expected_ids) @@ -40,14 +40,8 @@ BOOST_AUTO_TEST_CASE (all_track_ids__sample_db__expected_ids) auto results = ep::all_track_ids(db); // Assert - BOOST_CHECK_EQUAL(results.size(), 7); + BOOST_CHECK_EQUAL(results.size(), 1); BOOST_CHECK_EQUAL(results[0], 1); - BOOST_CHECK_EQUAL(results[1], 2); - BOOST_CHECK_EQUAL(results[2], 3); - BOOST_CHECK_EQUAL(results[3], 4); - BOOST_CHECK_EQUAL(results[4], 5); - BOOST_CHECK_EQUAL(results[5], 6); - BOOST_CHECK_EQUAL(results[6], 7); } BOOST_AUTO_TEST_CASE (ctor__track1__correct_fields) @@ -60,9 +54,44 @@ BOOST_AUTO_TEST_CASE (ctor__track1__correct_fields) // Assert BOOST_CHECK_EQUAL(t.id(), 1); - BOOST_CHECK_EQUAL(t.path(), "../01-track-wav-format.wav"); - BOOST_CHECK_EQUAL(t.filename(), "01-track-wav-format.wav"); - // etc. - BOOST_CHECK_EQUAL(t.file_extension(), "wav"); + BOOST_CHECK_EQUAL(t.track_number(), 1); + BOOST_CHECK_EQUAL(t.duration().count(), 396); + BOOST_CHECK_EQUAL(t.bpm(), 123); + BOOST_CHECK_EQUAL(t.year(), 2017); + BOOST_CHECK_EQUAL(t.title(), "Mad (Original Mix)"); + BOOST_CHECK_EQUAL(t.artist(), "Dennis Cruz"); + BOOST_CHECK_EQUAL(t.album(), "Mad EP"); + BOOST_CHECK_EQUAL(t.genre(), "Tech House"); + BOOST_CHECK_EQUAL(t.comment(), "Purchased at Beatport.com"); + BOOST_CHECK_EQUAL(t.publisher(), "Stereo Productions"); + BOOST_CHECK_EQUAL(t.composer(), ""); + BOOST_CHECK_EQUAL(t.path(), "../01 - Dennis Cruz - Mad (Original Mix).mp3"); + BOOST_CHECK_EQUAL(t.filename(), "01 - Dennis Cruz - Mad (Original Mix).mp3"); + BOOST_CHECK_EQUAL(t.file_extension(), "mp3"); + BOOST_CHECK_EQUAL(t.last_modified_at().time_since_epoch().count() * + std::chrono::system_clock::period::num / + std::chrono::system_clock::period::den, 1509371790); + BOOST_CHECK_EQUAL(t.bitrate(), 320); + BOOST_CHECK_EQUAL(t.ever_played(), false); + BOOST_CHECK_EQUAL(t.last_played_at().time_since_epoch().count(), 0); + BOOST_CHECK_EQUAL(t.last_loaded_at().time_since_epoch().count() * + std::chrono::system_clock::period::num / + std::chrono::system_clock::period::den, 1509321600); + BOOST_CHECK_EQUAL(t.is_imported(), false); + BOOST_CHECK_EQUAL(t.external_database_id(), ""); + BOOST_CHECK_EQUAL(t.track_id_in_external_database(), 0); + BOOST_CHECK_EQUAL(t.album_art_id(), 2); + BOOST_CHECK_EQUAL(t.has_album_art(), true); } +BOOST_AUTO_TEST_CASE (ctor_nonexistent_track__throws) +{ + // Arrange + ep::database db{sample_path}; + + // Act / Assert + // Note the extra brackets around the invocation, because the preprocessor + // doesn't understand curly braces! + BOOST_CHECK_EXCEPTION((ep::track{db, 123}), ep::nonexistent_track, + [](const ep::nonexistent_track &e) { return e.id() == 123; }); +} diff --git a/testdata/el2/m.db b/testdata/el2/m.db Binary files differnew file mode 100644 index 0000000..d07bd1d --- /dev/null +++ b/testdata/el2/m.db diff --git a/testdata/el2/p.db b/testdata/el2/p.db Binary files differnew file mode 100644 index 0000000..0f1c49b --- /dev/null +++ b/testdata/el2/p.db |