summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/engineprime/database.hpp10
-rw-r--r--src/engineprime/track.hpp34
-rw-r--r--src/track.cpp33
-rw-r--r--src/track_test.cpp53
-rw-r--r--testdata/el2/m.dbbin0 -> 557056 bytes
-rw-r--r--testdata/el2/p.dbbin0 -> 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
new file mode 100644
index 0000000..d07bd1d
--- /dev/null
+++ b/testdata/el2/m.db
Binary files differ
diff --git a/testdata/el2/p.db b/testdata/el2/p.db
new file mode 100644
index 0000000..0f1c49b
--- /dev/null
+++ b/testdata/el2/p.db
Binary files differ