Merge lp:~xavi-garcia-mena/mediascanner2/ms-dbus-wal into lp:mediascanner2
- ms-dbus-wal
- Merge into trunk
Status: | Needs review |
---|---|
Proposed branch: | lp:~xavi-garcia-mena/mediascanner2/ms-dbus-wal |
Merge into: | lp:mediascanner2 |
Diff against target: |
2214 lines (+945/-453) 18 files modified
debian/control (+1/-0) src/daemon/CMakeLists.txt (+1/-0) src/mediascanner/CMakeLists.txt (+20/-2) src/mediascanner/MediaStore.cc (+94/-19) src/mediascanner/MediaStore.hh (+9/-1) src/mediascanner/d-bus/service-stub.cc (+6/-0) src/mediascanner/d-bus/service-stub.hh (+1/-0) src/mediascanner/mediascanner-2.0.map (+35/-5) src/ms-dbus/CMakeLists.txt (+1/-2) src/ms-dbus/main.cc (+2/-2) src/ms-dbus/service-skeleton.cc (+2/-2) src/ms-dbus/service-skeleton.hh (+1/-1) src/qml/Ubuntu/MediaScanner/MediaStoreWrapper.cc (+1/-1) test/CMakeLists.txt (+15/-5) test/test_dbus.cc (+1/-1) test/test_mediastore.cc (+658/-412) test/utils/DBusTest.cpp (+50/-0) test/utils/DBusTest.h (+47/-0) |
To merge this branch: | bzr merge lp:~xavi-garcia-mena/mediascanner2/ms-dbus-wal |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
unity-api-1-bot | continuous-integration | Needs Fixing | |
PS Jenkins bot (community) | continuous-integration | Needs Fixing | |
Jussi Pakkanen (community) | Needs Fixing | ||
Jamie Strandboge | Pending | ||
James Henstridge | Pending | ||
Review via email: mp+249346@code.launchpad.net |
Commit message
Modified to use the d-bus interface when MediaStore is created in Read Only mode.
Description of the change
Modified to use the d-bus interface when MediaStore is created in Read Only mode.
- 300. By Xavi Garcia
-
Modifed media store tests to avoid duplicating code
- 301. By Xavi Garcia
-
Removed Unity-api dependency, as it was not needed
- 302. By Xavi Garcia
-
Added libqtdbustest to test the d-bus connection
Jussi Pakkanen (jpakkane) wrote : | # |
Looks fine. Just a few niggles:
- the new variables have an underscore after their names, whereas the naming convention elsewere is not to have underscores
- when printing the text about error messages, please also print the URL of the bug in question
- in brokenfiles you wrap everything in a try/catch that just prints a generic error, why is this, AFAICR gtest will automatically fail any test that throws and prints the exception's error messag
I think we need to start talking to Jamie about the dbus/apparmor bits that this thing needs (also in music-app).
- 303. By Xavi Garcia
-
Erased final _ for member variables
Xavi Garcia (xavi-garcia-mena) wrote : | # |
Hey Jussi,
what file do you mean when you say?
*when printing the text about error messages, please also print the URL of
the bug in question*
What do you mean to print the URL of the bug? When an exception is thrown?
I've erased the try... catch, as it was part of a test I did and changed
(but obviously forgot to erase the try..catch)
Thanks,
Xavi
On Mon, Feb 16, 2015 at 2:40 PM, Jussi Pakkanen <
<email address hidden>> wrote:
> Review: Needs Fixing
>
> Looks fine. Just a few niggles:
>
> - the new variables have an underscore after their names, whereas the
> naming convention elsewere is not to have underscores
> - when printing the text about error messages, please also print the URL
> of the bug in question
> - in brokenfiles you wrap everything in a try/catch that just prints a
> generic error, why is this, AFAICR gtest will automatically fail any test
> that throws and prints the exception's error messag
>
> I think we need to start talking to Jamie about the dbus/apparmor bits
> that this thing needs (also in music-app).
> --
>
> https:/
> You are the owner of lp:~xavi-garcia-mena/mediascanner2/ms-dbus-wal.
>
- 304. By Xavi Garcia
-
Added bug link in error message and remove unnecessary try...catch in unit test
Jussi Pakkanen (jpakkane) wrote : | # |
Now we need to do the AppArmor bits and for that we need Jamie's help, so I subscribed him.
What we are trying to do here is the following:
Currently users of Mediascanner (media scopes and music-app) have read-only access to Mediascanner's media storage dir ~/.cache/
This means that we need the following Apparmor changes:
- remove read access from existing users
- grant them access to the dbus server instead
- create new daemon that is allowed to own the service name and has r/w access to the media directory
Does this seem like a suitable approach, security-wise?
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:304
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https:/
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:304
https:/
Executed test runs:
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:304
https:/
Executed test runs:
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Unmerged revisions
- 304. By Xavi Garcia
-
Added bug link in error message and remove unnecessary try...catch in unit test
- 303. By Xavi Garcia
-
Erased final _ for member variables
- 302. By Xavi Garcia
-
Added libqtdbustest to test the d-bus connection
- 301. By Xavi Garcia
-
Removed Unity-api dependency, as it was not needed
- 300. By Xavi Garcia
-
Modifed media store tests to avoid duplicating code
- 299. By Xavi Garcia
-
Using DBus for read only mode
Preview Diff
1 | === modified file 'debian/control' | |||
2 | --- debian/control 2014-10-09 08:48:05 +0000 | |||
3 | +++ debian/control 2015-02-16 14:24:40 +0000 | |||
4 | @@ -18,6 +18,7 @@ | |||
5 | 18 | libgdk-pixbuf2.0-dev, | 18 | libgdk-pixbuf2.0-dev, |
6 | 19 | libgtest-dev, | 19 | libgtest-dev, |
7 | 20 | libproperties-cpp-dev, | 20 | libproperties-cpp-dev, |
8 | 21 | libqtdbustest1-dev, | ||
9 | 21 | libsqlite3-dev (>= 3.8.5), | 22 | libsqlite3-dev (>= 3.8.5), |
10 | 22 | libudisks2-dev, | 23 | libudisks2-dev, |
11 | 23 | qt5-default, | 24 | qt5-default, |
12 | 24 | 25 | ||
13 | === modified file 'src/daemon/CMakeLists.txt' | |||
14 | --- src/daemon/CMakeLists.txt 2014-10-09 08:48:05 +0000 | |||
15 | +++ src/daemon/CMakeLists.txt 2015-02-16 14:24:40 +0000 | |||
16 | @@ -9,6 +9,7 @@ | |||
17 | 9 | SubtreeWatcher.cc | 9 | SubtreeWatcher.cc |
18 | 10 | Scanner.cc | 10 | Scanner.cc |
19 | 11 | ../mediascanner/utils.cc | 11 | ../mediascanner/utils.cc |
20 | 12 | $<TARGET_OBJECTS:mediascanner-dbus-static> | ||
21 | 12 | ) | 13 | ) |
22 | 13 | 14 | ||
23 | 14 | target_link_libraries(scannerstuff ${GST_LIBRARIES} ${EXIF_LDFLAGS} ${UDISKS_LDFLAGS} | 15 | target_link_libraries(scannerstuff ${GST_LIBRARIES} ${EXIF_LDFLAGS} ${UDISKS_LDFLAGS} |
24 | 15 | 16 | ||
25 | === modified file 'src/mediascanner/CMakeLists.txt' | |||
26 | --- src/mediascanner/CMakeLists.txt 2014-08-22 14:33:27 +0000 | |||
27 | +++ src/mediascanner/CMakeLists.txt 2015-02-16 14:24:40 +0000 | |||
28 | @@ -1,3 +1,18 @@ | |||
29 | 1 | pkg_check_modules(DBUSCPP dbus-cpp REQUIRED) | ||
30 | 2 | |||
31 | 3 | add_library( | ||
32 | 4 | mediascanner-dbus-static OBJECT | ||
33 | 5 | d-bus/dbus-codec.cc | ||
34 | 6 | d-bus/service-stub.cc | ||
35 | 7 | ) | ||
36 | 8 | |||
37 | 9 | set_target_properties( | ||
38 | 10 | mediascanner-dbus-static | ||
39 | 11 | PROPERTIES | ||
40 | 12 | LINK_FLAGS "-Wl,--export-all-symbols" | ||
41 | 13 | COMPILE_FLAGS -fPIC | ||
42 | 14 | ) | ||
43 | 15 | |||
44 | 1 | add_library(mediascanner SHARED | 16 | add_library(mediascanner SHARED |
45 | 2 | MediaFile.cc | 17 | MediaFile.cc |
46 | 3 | MediaFileBuilder.cc | 18 | MediaFileBuilder.cc |
47 | @@ -9,6 +24,7 @@ | |||
48 | 9 | utils.cc | 24 | utils.cc |
49 | 10 | mozilla/fts3_porter.c | 25 | mozilla/fts3_porter.c |
50 | 11 | mozilla/Normalize.c | 26 | mozilla/Normalize.c |
51 | 27 | $<TARGET_OBJECTS:mediascanner-dbus-static> | ||
52 | 12 | ) | 28 | ) |
53 | 13 | 29 | ||
54 | 14 | set(symbol_map "${CMAKE_CURRENT_SOURCE_DIR}/mediascanner-2.0.map") | 30 | set(symbol_map "${CMAKE_CURRENT_SOURCE_DIR}/mediascanner-2.0.map") |
55 | @@ -16,8 +32,10 @@ | |||
56 | 16 | LINK_FLAGS "${ldflags} -Wl,--version-script,${symbol_map}") | 32 | LINK_FLAGS "${ldflags} -Wl,--version-script,${symbol_map}") |
57 | 17 | set_target_properties(mediascanner PROPERTIES LINK_DEPENDS ${symbol_map}) | 33 | set_target_properties(mediascanner PROPERTIES LINK_DEPENDS ${symbol_map}) |
58 | 18 | 34 | ||
61 | 19 | add_definitions(${MEDIASCANNER_CFLAGS}) | 35 | add_definitions(${DBUSCPP_CFLAGS} ${MEDIASCANNER_CFLAGS}) |
62 | 20 | target_link_libraries(mediascanner ${MEDIASCANNER_LIBRARIES}) | 36 | |
63 | 37 | include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/src) | ||
64 | 38 | target_link_libraries(mediascanner ${MEDIASCANNER_LIBRARIES} ${DBUSCPP_LDFLAGS}) | ||
65 | 21 | 39 | ||
66 | 22 | set_target_properties(mediascanner PROPERTIES | 40 | set_target_properties(mediascanner PROPERTIES |
67 | 23 | OUTPUT_NAME "mediascanner-2.0" | 41 | OUTPUT_NAME "mediascanner-2.0" |
68 | 24 | 42 | ||
69 | === modified file 'src/mediascanner/MediaStore.cc' | |||
70 | --- src/mediascanner/MediaStore.cc 2015-01-28 09:41:26 +0000 | |||
71 | +++ src/mediascanner/MediaStore.cc 2015-02-16 14:24:40 +0000 | |||
72 | @@ -39,6 +39,7 @@ | |||
73 | 39 | #include "Filter.hh" | 39 | #include "Filter.hh" |
74 | 40 | #include "internal/sqliteutils.hh" | 40 | #include "internal/sqliteutils.hh" |
75 | 41 | #include "internal/utils.hh" | 41 | #include "internal/utils.hh" |
76 | 42 | #include "d-bus/service-stub.hh" | ||
77 | 42 | 43 | ||
78 | 43 | using namespace std; | 44 | using namespace std; |
79 | 44 | 45 | ||
80 | @@ -54,6 +55,11 @@ | |||
81 | 54 | // http://sqlite.com/faq.html#q6 | 55 | // http://sqlite.com/faq.html#q6 |
82 | 55 | std::mutex dbMutex; | 56 | std::mutex dbMutex; |
83 | 56 | 57 | ||
84 | 58 | OpenType access_mode; | ||
85 | 59 | |||
86 | 60 | std::unique_ptr<mediascanner::dbus::ServiceStub> media_store_dbus; | ||
87 | 61 | |||
88 | 62 | MediaStorePrivate(OpenType access); | ||
89 | 57 | void insert(const MediaFile &m) const; | 63 | void insert(const MediaFile &m) const; |
90 | 58 | void remove(const std::string &fname) const; | 64 | void remove(const std::string &fname) const; |
91 | 59 | void insert_broken_file(const std::string &fname, const std::string &etag) const; | 65 | void insert_broken_file(const std::string &fname, const std::string &etag) const; |
92 | @@ -121,7 +127,7 @@ | |||
93 | 121 | ** (<hit count> / <global hit count>) * <column weight> | 127 | ** (<hit count> / <global hit count>) * <column weight> |
94 | 122 | ** | 128 | ** |
95 | 123 | ** aPhraseinfo[] points to the start of the data for phrase iPhrase. So | 129 | ** aPhraseinfo[] points to the start of the data for phrase iPhrase. So |
97 | 124 | ** the hit count and global hit counts for each column are found in | 130 | ** the hit count and global hit counts for each column are found in |
98 | 125 | ** aPhraseinfo[iCol*3] and aPhraseinfo[iCol*3+1], respectively. | 131 | ** aPhraseinfo[iCol*3] and aPhraseinfo[iCol*3+1], respectively. |
99 | 126 | */ | 132 | */ |
100 | 127 | const int32_t *aPhraseinfo = &aMatchinfo[2 + iPhrase*nCol*3]; | 133 | const int32_t *aPhraseinfo = &aMatchinfo[2 + iPhrase*nCol*3]; |
101 | @@ -287,6 +293,13 @@ | |||
102 | 287 | execute_sql(db, deleteCmd); | 293 | execute_sql(db, deleteCmd); |
103 | 288 | } | 294 | } |
104 | 289 | 295 | ||
105 | 296 | void activateWalMode(sqlite3 *db) { | ||
106 | 297 | string activateWalCmd(R"( | ||
107 | 298 | PRAGMA journal_mode = WAL; | ||
108 | 299 | )"); | ||
109 | 300 | execute_sql(db, activateWalCmd); | ||
110 | 301 | } | ||
111 | 302 | |||
112 | 290 | void createTables(sqlite3 *db) { | 303 | void createTables(sqlite3 *db) { |
113 | 291 | string schema(R"( | 304 | string schema(R"( |
114 | 292 | CREATE TABLE schemaVersion (version INTEGER); | 305 | CREATE TABLE schemaVersion (version INTEGER); |
115 | @@ -338,7 +351,7 @@ | |||
116 | 338 | type INTEGER -- 0=Audio, 1=Video | 351 | type INTEGER -- 0=Audio, 1=Video |
117 | 339 | ); | 352 | ); |
118 | 340 | 353 | ||
120 | 341 | CREATE VIRTUAL TABLE media_fts | 354 | CREATE VIRTUAL TABLE media_fts |
121 | 342 | USING fts4(content='media', title, artist, album, tokenize=mozporter); | 355 | USING fts4(content='media', title, artist, album, tokenize=mozporter); |
122 | 343 | 356 | ||
123 | 344 | CREATE TRIGGER media_bu BEFORE UPDATE ON media BEGIN | 357 | CREATE TRIGGER media_bu BEFORE UPDATE ON media BEGIN |
124 | @@ -394,43 +407,51 @@ | |||
125 | 394 | 407 | ||
126 | 395 | MediaStore::MediaStore(const std::string &filename, OpenType access, const std::string &retireprefix) { | 408 | MediaStore::MediaStore(const std::string &filename, OpenType access, const std::string &retireprefix) { |
127 | 396 | int sqliteFlags = access == MS_READ_WRITE ? SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE : SQLITE_OPEN_READONLY; | 409 | int sqliteFlags = access == MS_READ_WRITE ? SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE : SQLITE_OPEN_READONLY; |
129 | 397 | p = new MediaStorePrivate(); | 410 | p = new MediaStorePrivate(access); |
130 | 411 | if(access != MS_READ_WRITE) { | ||
131 | 412 | return; | ||
132 | 413 | } | ||
133 | 398 | if(sqlite3_open_v2(filename.c_str(), &p->db, sqliteFlags, nullptr) != SQLITE_OK) { | 414 | if(sqlite3_open_v2(filename.c_str(), &p->db, sqliteFlags, nullptr) != SQLITE_OK) { |
134 | 399 | throw runtime_error(sqlite3_errmsg(p->db)); | 415 | throw runtime_error(sqlite3_errmsg(p->db)); |
135 | 400 | } | 416 | } |
136 | 401 | register_tokenizer(p->db); | 417 | register_tokenizer(p->db); |
137 | 402 | register_functions(p->db); | 418 | register_functions(p->db); |
138 | 403 | int detectedSchemaVersion = getSchemaVersion(p->db); | 419 | int detectedSchemaVersion = getSchemaVersion(p->db); |
154 | 404 | if(access == MS_READ_WRITE) { | 420 | activateWalMode(p->db); |
155 | 405 | if(detectedSchemaVersion != schemaVersion) { | 421 | if(detectedSchemaVersion != schemaVersion) { |
156 | 406 | deleteTables(p->db); | 422 | deleteTables(p->db); |
157 | 407 | createTables(p->db); | 423 | createTables(p->db); |
143 | 408 | } | ||
144 | 409 | if(!retireprefix.empty()) | ||
145 | 410 | archiveItems(retireprefix); | ||
146 | 411 | } else { | ||
147 | 412 | if(detectedSchemaVersion != schemaVersion) { | ||
148 | 413 | std::string msg("Tried to open a db with schema version "); | ||
149 | 414 | msg += std::to_string(detectedSchemaVersion); | ||
150 | 415 | msg += ", while supported version is "; | ||
151 | 416 | msg += std::to_string(schemaVersion) + "."; | ||
152 | 417 | throw runtime_error(msg); | ||
153 | 418 | } | ||
158 | 419 | } | 424 | } |
159 | 425 | if(!retireprefix.empty()) | ||
160 | 426 | archiveItems(retireprefix); | ||
161 | 420 | } | 427 | } |
162 | 421 | 428 | ||
163 | 422 | MediaStore::~MediaStore() { | 429 | MediaStore::~MediaStore() { |
165 | 423 | sqlite3_close(p->db); | 430 | if(p->db) { |
166 | 431 | sqlite3_close(p->db); | ||
167 | 432 | } | ||
168 | 424 | delete p; | 433 | delete p; |
169 | 425 | } | 434 | } |
170 | 426 | 435 | ||
171 | 436 | MediaStorePrivate::MediaStorePrivate(OpenType access) : db(nullptr), access_mode(access), media_store_dbus(nullptr) { | ||
172 | 437 | if(access_mode != MS_READ_WRITE) { | ||
173 | 438 | media_store_dbus.reset(new dbus::ServiceStub()); | ||
174 | 439 | } | ||
175 | 440 | } | ||
176 | 441 | |||
177 | 427 | size_t MediaStorePrivate::size() const { | 442 | size_t MediaStorePrivate::size() const { |
178 | 443 | if(access_mode != MS_READ_WRITE) { | ||
179 | 444 | throw runtime_error("MediaStorePrivate::size() is not available in read only mode"); | ||
180 | 445 | } | ||
181 | 428 | Statement count(db, "SELECT COUNT(*) FROM media"); | 446 | Statement count(db, "SELECT COUNT(*) FROM media"); |
182 | 429 | count.step(); | 447 | count.step(); |
183 | 430 | return count.getInt(0); | 448 | return count.getInt(0); |
184 | 431 | } | 449 | } |
185 | 432 | 450 | ||
186 | 433 | void MediaStorePrivate::insert(const MediaFile &m) const { | 451 | void MediaStorePrivate::insert(const MediaFile &m) const { |
187 | 452 | if(access_mode != MS_READ_WRITE) { | ||
188 | 453 | throw runtime_error("MediaStorePrivate::insert() is not available in read only mode"); | ||
189 | 454 | } | ||
190 | 434 | Statement query(db, "INSERT OR REPLACE INTO media (filename, content_type, etag, title, date, artist, album, album_artist, genre, disc_number, track_number, duration, width, height, latitude, longitude, has_thumbnail, type) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); | 455 | Statement query(db, "INSERT OR REPLACE INTO media (filename, content_type, etag, title, date, artist, album, album_artist, genre, disc_number, track_number, duration, width, height, latitude, longitude, has_thumbnail, type) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); |
191 | 435 | query.bind(1, m.getFileName()); | 456 | query.bind(1, m.getFileName()); |
192 | 436 | query.bind(2, m.getContentType()); | 457 | query.bind(2, m.getContentType()); |
193 | @@ -466,12 +487,18 @@ | |||
194 | 466 | } | 487 | } |
195 | 467 | 488 | ||
196 | 468 | void MediaStorePrivate::remove(const string &fname) const { | 489 | void MediaStorePrivate::remove(const string &fname) const { |
197 | 490 | if(access_mode != MS_READ_WRITE) { | ||
198 | 491 | throw runtime_error("MediaStorePrivate::remove() is not available in read only mode"); | ||
199 | 492 | } | ||
200 | 469 | Statement del(db, "DELETE FROM media WHERE filename = ?"); | 493 | Statement del(db, "DELETE FROM media WHERE filename = ?"); |
201 | 470 | del.bind(1, fname); | 494 | del.bind(1, fname); |
202 | 471 | del.step(); | 495 | del.step(); |
203 | 472 | } | 496 | } |
204 | 473 | 497 | ||
205 | 474 | void MediaStorePrivate::insert_broken_file(const std::string &fname, const std::string &etag) const { | 498 | void MediaStorePrivate::insert_broken_file(const std::string &fname, const std::string &etag) const { |
206 | 499 | if(access_mode != MS_READ_WRITE) { | ||
207 | 500 | throw runtime_error("MediaStorePrivate::insert_broken_file() is not available in read only mode"); | ||
208 | 501 | } | ||
209 | 475 | Statement del(db, "INSERT OR REPLACE INTO broken_files (filename, etag) VALUES (?, ?)"); | 502 | Statement del(db, "INSERT OR REPLACE INTO broken_files (filename, etag) VALUES (?, ?)"); |
210 | 476 | del.bind(1, fname); | 503 | del.bind(1, fname); |
211 | 477 | del.bind(2, etag); | 504 | del.bind(2, etag); |
212 | @@ -479,12 +506,18 @@ | |||
213 | 479 | } | 506 | } |
214 | 480 | 507 | ||
215 | 481 | void MediaStorePrivate::remove_broken_file(const std::string &fname) const { | 508 | void MediaStorePrivate::remove_broken_file(const std::string &fname) const { |
216 | 509 | if(access_mode != MS_READ_WRITE) { | ||
217 | 510 | throw runtime_error("MediaStorePrivate::remove_broken_file() is not available in read only mode"); | ||
218 | 511 | } | ||
219 | 482 | Statement del(db, "DELETE FROM broken_files WHERE filename = ?"); | 512 | Statement del(db, "DELETE FROM broken_files WHERE filename = ?"); |
220 | 483 | del.bind(1, fname); | 513 | del.bind(1, fname); |
221 | 484 | del.step(); | 514 | del.step(); |
222 | 485 | } | 515 | } |
223 | 486 | 516 | ||
224 | 487 | bool MediaStorePrivate::is_broken_file(const std::string &fname, const std::string &etag) const { | 517 | bool MediaStorePrivate::is_broken_file(const std::string &fname, const std::string &etag) const { |
225 | 518 | if(access_mode != MS_READ_WRITE) { | ||
226 | 519 | throw runtime_error("MediaStorePrivate::is_broken_file() is not available in read only mode"); | ||
227 | 520 | } | ||
228 | 488 | Statement query(db, "SELECT * FROM broken_files WHERE filename = ? AND etag = ?"); | 521 | Statement query(db, "SELECT * FROM broken_files WHERE filename = ? AND etag = ?"); |
229 | 489 | query.bind(1, fname); | 522 | query.bind(1, fname); |
230 | 490 | query.bind(2, etag); | 523 | query.bind(2, etag); |
231 | @@ -521,6 +554,9 @@ | |||
232 | 521 | } | 554 | } |
233 | 522 | 555 | ||
234 | 523 | MediaFile MediaStorePrivate::lookup(const std::string &filename) const { | 556 | MediaFile MediaStorePrivate::lookup(const std::string &filename) const { |
235 | 557 | if(access_mode != MS_READ_WRITE) { | ||
236 | 558 | return media_store_dbus->lookup(filename); | ||
237 | 559 | } | ||
238 | 524 | Statement query(db, R"( | 560 | Statement query(db, R"( |
239 | 525 | SELECT filename, content_type, etag, title, date, artist, album, album_artist, genre, disc_number, track_number, duration, width, height, latitude, longitude, has_thumbnail, type | 561 | SELECT filename, content_type, etag, title, date, artist, album, album_artist, genre, disc_number, track_number, duration, width, height, latitude, longitude, has_thumbnail, type |
240 | 526 | FROM media | 562 | FROM media |
241 | @@ -534,6 +570,9 @@ | |||
242 | 534 | } | 570 | } |
243 | 535 | 571 | ||
244 | 536 | vector<MediaFile> MediaStorePrivate::query(const std::string &core_term, MediaType type, const Filter &filter) const { | 572 | vector<MediaFile> MediaStorePrivate::query(const std::string &core_term, MediaType type, const Filter &filter) const { |
245 | 573 | if(access_mode != MS_READ_WRITE) { | ||
246 | 574 | return media_store_dbus->query(core_term, type, filter); | ||
247 | 575 | } | ||
248 | 537 | string qs(R"( | 576 | string qs(R"( |
249 | 538 | SELECT filename, content_type, etag, title, date, artist, album, album_artist, genre, disc_number, track_number, duration, width, height, latitude, longitude, has_thumbnail, type | 577 | SELECT filename, content_type, etag, title, date, artist, album, album_artist, genre, disc_number, track_number, duration, width, height, latitude, longitude, has_thumbnail, type |
250 | 539 | FROM media | 578 | FROM media |
251 | @@ -603,6 +642,9 @@ | |||
252 | 603 | } | 642 | } |
253 | 604 | 643 | ||
254 | 605 | vector<Album> MediaStorePrivate::queryAlbums(const std::string &core_term, const Filter &filter) const { | 644 | vector<Album> MediaStorePrivate::queryAlbums(const std::string &core_term, const Filter &filter) const { |
255 | 645 | if(access_mode != MS_READ_WRITE) { | ||
256 | 646 | return media_store_dbus->queryAlbums(core_term, filter); | ||
257 | 647 | } | ||
258 | 606 | string qs(R"( | 648 | string qs(R"( |
259 | 607 | SELECT album, album_artist, first(date) as date, first(genre) as genre, first(filename) as filename, first(has_thumbnail) as has_thumbnail FROM media | 649 | SELECT album, album_artist, first(date) as date, first(genre) as genre, first(filename) as filename, first(has_thumbnail) as has_thumbnail FROM media |
260 | 608 | WHERE type = ? AND album <> '' | 650 | WHERE type = ? AND album <> '' |
261 | @@ -638,6 +680,9 @@ | |||
262 | 638 | } | 680 | } |
263 | 639 | 681 | ||
264 | 640 | vector<string> MediaStorePrivate::queryArtists(const string &q, const Filter &filter) const { | 682 | vector<string> MediaStorePrivate::queryArtists(const string &q, const Filter &filter) const { |
265 | 683 | if(access_mode != MS_READ_WRITE) { | ||
266 | 684 | return media_store_dbus->queryArtists(q, filter); | ||
267 | 685 | } | ||
268 | 641 | string qs(R"( | 686 | string qs(R"( |
269 | 642 | SELECT artist FROM media | 687 | SELECT artist FROM media |
270 | 643 | WHERE type = ? AND artist <> '' | 688 | WHERE type = ? AND artist <> '' |
271 | @@ -677,6 +722,9 @@ | |||
272 | 677 | } | 722 | } |
273 | 678 | 723 | ||
274 | 679 | vector<MediaFile> MediaStorePrivate::getAlbumSongs(const Album& album) const { | 724 | vector<MediaFile> MediaStorePrivate::getAlbumSongs(const Album& album) const { |
275 | 725 | if(access_mode != MS_READ_WRITE) { | ||
276 | 726 | return media_store_dbus->getAlbumSongs(album); | ||
277 | 727 | } | ||
278 | 680 | Statement query(db, R"( | 728 | Statement query(db, R"( |
279 | 681 | SELECT filename, content_type, etag, title, date, artist, album, album_artist, genre, disc_number, track_number, duration, width, height, latitude, longitude, type FROM media | 729 | SELECT filename, content_type, etag, title, date, artist, album, album_artist, genre, disc_number, track_number, duration, width, height, latitude, longitude, type FROM media |
280 | 682 | WHERE album = ? AND album_artist = ? AND type = ? | 730 | WHERE album = ? AND album_artist = ? AND type = ? |
281 | @@ -689,6 +737,9 @@ | |||
282 | 689 | } | 737 | } |
283 | 690 | 738 | ||
284 | 691 | std::string MediaStorePrivate::getETag(const std::string &filename) const { | 739 | std::string MediaStorePrivate::getETag(const std::string &filename) const { |
285 | 740 | if(access_mode != MS_READ_WRITE) { | ||
286 | 741 | return media_store_dbus->getETag(filename); | ||
287 | 742 | } | ||
288 | 692 | Statement query(db, R"( | 743 | Statement query(db, R"( |
289 | 693 | SELECT etag FROM media WHERE filename = ? | 744 | SELECT etag FROM media WHERE filename = ? |
290 | 694 | )"); | 745 | )"); |
291 | @@ -701,6 +752,9 @@ | |||
292 | 701 | } | 752 | } |
293 | 702 | 753 | ||
294 | 703 | std::vector<MediaFile> MediaStorePrivate::listSongs(const Filter &filter) const { | 754 | std::vector<MediaFile> MediaStorePrivate::listSongs(const Filter &filter) const { |
295 | 755 | if(access_mode != MS_READ_WRITE) { | ||
296 | 756 | return media_store_dbus->listSongs(filter); | ||
297 | 757 | } | ||
298 | 704 | std::string qs(R"( | 758 | std::string qs(R"( |
299 | 705 | SELECT filename, content_type, etag, title, date, artist, album, album_artist, genre, disc_number, track_number, duration, width, height, latitude, longitude, has_thumbnail, type | 759 | SELECT filename, content_type, etag, title, date, artist, album, album_artist, genre, disc_number, track_number, duration, width, height, latitude, longitude, has_thumbnail, type |
300 | 706 | FROM media | 760 | FROM media |
301 | @@ -744,6 +798,9 @@ | |||
302 | 744 | } | 798 | } |
303 | 745 | 799 | ||
304 | 746 | std::vector<Album> MediaStorePrivate::listAlbums(const Filter &filter) const { | 800 | std::vector<Album> MediaStorePrivate::listAlbums(const Filter &filter) const { |
305 | 801 | if(access_mode != MS_READ_WRITE) { | ||
306 | 802 | return media_store_dbus->listAlbums(filter); | ||
307 | 803 | } | ||
308 | 747 | std::string qs(R"( | 804 | std::string qs(R"( |
309 | 748 | SELECT album, album_artist, first(date) as date, first(genre) as genre, first(filename) as filename, first(has_thumbnail) as has_thumbnail FROM media | 805 | SELECT album, album_artist, first(date) as date, first(genre) as genre, first(filename) as filename, first(has_thumbnail) as has_thumbnail FROM media |
310 | 749 | WHERE type = ? | 806 | WHERE type = ? |
311 | @@ -781,6 +838,9 @@ | |||
312 | 781 | } | 838 | } |
313 | 782 | 839 | ||
314 | 783 | vector<std::string> MediaStorePrivate::listArtists(const Filter &filter) const { | 840 | vector<std::string> MediaStorePrivate::listArtists(const Filter &filter) const { |
315 | 841 | if(access_mode != MS_READ_WRITE) { | ||
316 | 842 | return media_store_dbus->listArtists(filter); | ||
317 | 843 | } | ||
318 | 784 | string qs(R"( | 844 | string qs(R"( |
319 | 785 | SELECT artist FROM media | 845 | SELECT artist FROM media |
320 | 786 | WHERE type = ? | 846 | WHERE type = ? |
321 | @@ -810,6 +870,9 @@ | |||
322 | 810 | } | 870 | } |
323 | 811 | 871 | ||
324 | 812 | vector<std::string> MediaStorePrivate::listAlbumArtists(const Filter &filter) const { | 872 | vector<std::string> MediaStorePrivate::listAlbumArtists(const Filter &filter) const { |
325 | 873 | if(access_mode != MS_READ_WRITE) { | ||
326 | 874 | return media_store_dbus->listAlbumArtists(filter); | ||
327 | 875 | } | ||
328 | 813 | string qs(R"( | 876 | string qs(R"( |
329 | 814 | SELECT album_artist FROM media | 877 | SELECT album_artist FROM media |
330 | 815 | WHERE type = ? | 878 | WHERE type = ? |
331 | @@ -839,6 +902,9 @@ | |||
332 | 839 | } | 902 | } |
333 | 840 | 903 | ||
334 | 841 | vector<std::string> MediaStorePrivate::listGenres(const Filter &filter) const { | 904 | vector<std::string> MediaStorePrivate::listGenres(const Filter &filter) const { |
335 | 905 | if(access_mode != MS_READ_WRITE) { | ||
336 | 906 | return media_store_dbus->listGenres(filter); | ||
337 | 907 | } | ||
338 | 842 | Statement query(db, R"( | 908 | Statement query(db, R"( |
339 | 843 | SELECT genre FROM media | 909 | SELECT genre FROM media |
340 | 844 | WHERE type = ? | 910 | WHERE type = ? |
341 | @@ -858,6 +924,9 @@ | |||
342 | 858 | } | 924 | } |
343 | 859 | 925 | ||
344 | 860 | void MediaStorePrivate::pruneDeleted() { | 926 | void MediaStorePrivate::pruneDeleted() { |
345 | 927 | if(access_mode != MS_READ_WRITE) { | ||
346 | 928 | throw runtime_error("MediaStorePrivate::pruneDeleted() is not available in read only mode"); | ||
347 | 929 | } | ||
348 | 861 | std::map<std::string, bool> path_cache; | 930 | std::map<std::string, bool> path_cache; |
349 | 862 | vector<string> deleted; | 931 | vector<string> deleted; |
350 | 863 | Statement query(db, "SELECT filename FROM media"); | 932 | Statement query(db, "SELECT filename FROM media"); |
351 | @@ -877,6 +946,9 @@ | |||
352 | 877 | } | 946 | } |
353 | 878 | 947 | ||
354 | 879 | void MediaStorePrivate::archiveItems(const std::string &prefix) { | 948 | void MediaStorePrivate::archiveItems(const std::string &prefix) { |
355 | 949 | if(access_mode != MS_READ_WRITE) { | ||
356 | 950 | throw runtime_error("MediaStorePrivate::archiveItems() is not available in read only mode"); | ||
357 | 951 | } | ||
358 | 880 | const char *templ = R"(BEGIN TRANSACTION; | 952 | const char *templ = R"(BEGIN TRANSACTION; |
359 | 881 | INSERT INTO media_attic SELECT * FROM media WHERE filename LIKE %s; | 953 | INSERT INTO media_attic SELECT * FROM media WHERE filename LIKE %s; |
360 | 882 | DELETE FROM media WHERE filename LIKE %s; | 954 | DELETE FROM media WHERE filename LIKE %s; |
361 | @@ -894,6 +966,9 @@ | |||
362 | 894 | } | 966 | } |
363 | 895 | 967 | ||
364 | 896 | void MediaStorePrivate::restoreItems(const std::string &prefix) { | 968 | void MediaStorePrivate::restoreItems(const std::string &prefix) { |
365 | 969 | if(access_mode != MS_READ_WRITE) { | ||
366 | 970 | throw runtime_error("MediaStorePrivate::restoreItems() is not available in read only mode"); | ||
367 | 971 | } | ||
368 | 897 | const char *templ = R"(BEGIN TRANSACTION; | 972 | const char *templ = R"(BEGIN TRANSACTION; |
369 | 898 | INSERT INTO media SELECT * FROM media_attic WHERE filename LIKE %s; | 973 | INSERT INTO media SELECT * FROM media_attic WHERE filename LIKE %s; |
370 | 899 | DELETE FROM media_attic WHERE filename LIKE %s; | 974 | DELETE FROM media_attic WHERE filename LIKE %s; |
371 | 900 | 975 | ||
372 | === modified file 'src/mediascanner/MediaStore.hh' | |||
373 | --- src/mediascanner/MediaStore.hh 2014-08-25 12:51:22 +0000 | |||
374 | +++ src/mediascanner/MediaStore.hh 2015-02-16 14:24:40 +0000 | |||
375 | @@ -23,6 +23,13 @@ | |||
376 | 23 | #include "MediaStoreBase.hh" | 23 | #include "MediaStoreBase.hh" |
377 | 24 | #include<vector> | 24 | #include<vector> |
378 | 25 | #include<string> | 25 | #include<string> |
379 | 26 | #include<memory> | ||
380 | 27 | |||
381 | 28 | namespace core { | ||
382 | 29 | namespace dbus { | ||
383 | 30 | class Bus; | ||
384 | 31 | } | ||
385 | 32 | } | ||
386 | 26 | 33 | ||
387 | 27 | namespace mediascanner { | 34 | namespace mediascanner { |
388 | 28 | 35 | ||
389 | @@ -34,7 +41,8 @@ | |||
390 | 34 | class MediaStore final : public virtual MediaStoreBase { | 41 | class MediaStore final : public virtual MediaStoreBase { |
391 | 35 | private: | 42 | private: |
392 | 36 | MediaStorePrivate *p; | 43 | MediaStorePrivate *p; |
394 | 37 | 44 | // MediaStore(std::shared_ptr<core::dbus::Bus> testing_dbus){}; | |
395 | 45 | // friend class MediaStoreTest; | ||
396 | 38 | public: | 46 | public: |
397 | 39 | MediaStore(OpenType access, const std::string &retireprefix=""); | 47 | MediaStore(OpenType access, const std::string &retireprefix=""); |
398 | 40 | MediaStore(const std::string &filename, OpenType access, const std::string &retireprefix=""); | 48 | MediaStore(const std::string &filename, OpenType access, const std::string &retireprefix=""); |
399 | 41 | 49 | ||
400 | === added directory 'src/mediascanner/d-bus' | |||
401 | === renamed file 'src/ms-dbus/dbus-codec.cc' => 'src/mediascanner/d-bus/dbus-codec.cc' | |||
402 | === renamed file 'src/ms-dbus/dbus-codec.hh' => 'src/mediascanner/d-bus/dbus-codec.hh' | |||
403 | === renamed file 'src/ms-dbus/dbus-interface.hh' => 'src/mediascanner/d-bus/dbus-interface.hh' | |||
404 | === renamed file 'src/ms-dbus/service-stub.cc' => 'src/mediascanner/d-bus/service-stub.cc' | |||
405 | --- src/ms-dbus/service-stub.cc 2014-08-21 03:55:40 +0000 | |||
406 | +++ src/mediascanner/d-bus/service-stub.cc 2015-02-16 14:24:40 +0000 | |||
407 | @@ -43,6 +43,12 @@ | |||
408 | 43 | core::dbus::types::ObjectPath(core::dbus::traits::Service<MediaStoreService>::object_path()))}) { | 43 | core::dbus::types::ObjectPath(core::dbus::traits::Service<MediaStoreService>::object_path()))}) { |
409 | 44 | } | 44 | } |
410 | 45 | 45 | ||
411 | 46 | ServiceStub::ServiceStub() | ||
412 | 47 | : core::dbus::Stub<MediaStoreService>(std::make_shared<core::dbus::Bus>(core::dbus::WellKnownBus::session)), | ||
413 | 48 | p(new Private{access_service()->object_for_path( | ||
414 | 49 | core::dbus::types::ObjectPath(core::dbus::traits::Service<MediaStoreService>::object_path()))}) { | ||
415 | 50 | } | ||
416 | 51 | |||
417 | 46 | ServiceStub::~ServiceStub() { | 52 | ServiceStub::~ServiceStub() { |
418 | 47 | } | 53 | } |
419 | 48 | 54 | ||
420 | 49 | 55 | ||
421 | === renamed file 'src/ms-dbus/service-stub.hh' => 'src/mediascanner/d-bus/service-stub.hh' | |||
422 | --- src/ms-dbus/service-stub.hh 2014-08-21 03:55:40 +0000 | |||
423 | +++ src/mediascanner/d-bus/service-stub.hh 2015-02-16 14:24:40 +0000 | |||
424 | @@ -40,6 +40,7 @@ | |||
425 | 40 | class ServiceStub : public core::dbus::Stub<MediaStoreService>, public virtual MediaStoreBase { | 40 | class ServiceStub : public core::dbus::Stub<MediaStoreService>, public virtual MediaStoreBase { |
426 | 41 | public: | 41 | public: |
427 | 42 | explicit ServiceStub(core::dbus::Bus::Ptr bus); | 42 | explicit ServiceStub(core::dbus::Bus::Ptr bus); |
428 | 43 | explicit ServiceStub(); | ||
429 | 43 | virtual ~ServiceStub(); | 44 | virtual ~ServiceStub(); |
430 | 44 | 45 | ||
431 | 45 | virtual MediaFile lookup(const std::string &filename) const override; | 46 | virtual MediaFile lookup(const std::string &filename) const override; |
432 | 46 | 47 | ||
433 | === renamed file 'src/ms-dbus/service.hh' => 'src/mediascanner/d-bus/service.hh' | |||
434 | === modified file 'src/mediascanner/mediascanner-2.0.map' | |||
435 | --- src/mediascanner/mediascanner-2.0.map 2014-06-24 11:10:39 +0000 | |||
436 | +++ src/mediascanner/mediascanner-2.0.map 2015-02-16 14:24:40 +0000 | |||
437 | @@ -11,11 +11,41 @@ | |||
438 | 11 | mediascanner::MediaStoreBase::*; | 11 | mediascanner::MediaStoreBase::*; |
439 | 12 | mediascanner::Filter::*; | 12 | mediascanner::Filter::*; |
440 | 13 | 13 | ||
446 | 14 | typeinfo?for?mediascanner::*; | 14 | typeinfo?for?mediascanner::MediaFile*; |
447 | 15 | typeinfo?name?for?mediascanner::*; | 15 | typeinfo?name?for?mediascanner::MediaFile*; |
448 | 16 | VTT?for?mediascanner::*; | 16 | VTT?for?mediascanner::MediaFile*; |
449 | 17 | virtual?thunk?to?mediascanner::*; | 17 | virtual?thunk?to?mediascanner::MediaFile*; |
450 | 18 | vtable?for?mediascanner::*; | 18 | vtable?for?mediascanner::MediaFile*; |
451 | 19 | |||
452 | 20 | typeinfo?for?mediascanner::Album*; | ||
453 | 21 | typeinfo?name?for?mediascanner::Album*; | ||
454 | 22 | VTT?for?mediascanner::Album*; | ||
455 | 23 | virtual?thunk?to?mediascanner::Album*; | ||
456 | 24 | vtable?for?mediascanner::Album*; | ||
457 | 25 | |||
458 | 26 | typeinfo?for?mediascanner::MediaFileBuilder*; | ||
459 | 27 | typeinfo?name?for?mediascanner::MediaFileBuilder*; | ||
460 | 28 | VTT?for?mediascanner::MediaFileBuilder*; | ||
461 | 29 | virtual?thunk?to?mediascanner::MediaFileBuilder*; | ||
462 | 30 | vtable?for?mediascanner::MediaFileBuilder*; | ||
463 | 31 | |||
464 | 32 | typeinfo?for?mediascanner::MediaStore*; | ||
465 | 33 | typeinfo?name?for?mediascanner::MediaStore*; | ||
466 | 34 | VTT?for?mediascanner::MediaStore*; | ||
467 | 35 | virtual?thunk?to?mediascanner::MediaStore*; | ||
468 | 36 | vtable?for?mediascanner::MediaStore*; | ||
469 | 37 | |||
470 | 38 | typeinfo?for?mediascanner::MediaStoreBase*; | ||
471 | 39 | typeinfo?name?for?mediascanner::MediaStoreBase*; | ||
472 | 40 | VTT?for?mediascanner::MediaStoreBase*; | ||
473 | 41 | virtual?thunk?to?mediascanner::MediaStoreBase*; | ||
474 | 42 | vtable?for?mediascanner::MediaStoreBase*; | ||
475 | 43 | |||
476 | 44 | typeinfo?for?mediascanner::Filter*; | ||
477 | 45 | typeinfo?name?for?mediascanner::Filter*; | ||
478 | 46 | VTT?for?mediascanner::Filter*; | ||
479 | 47 | virtual?thunk?to?mediascanner::Filter*; | ||
480 | 48 | vtable?for?mediascanner::Filter*; | ||
481 | 19 | }; | 49 | }; |
482 | 20 | 50 | ||
483 | 21 | local: | 51 | local: |
484 | 22 | 52 | ||
485 | === modified file 'src/ms-dbus/CMakeLists.txt' | |||
486 | --- src/ms-dbus/CMakeLists.txt 2014-05-29 07:29:58 +0000 | |||
487 | +++ src/ms-dbus/CMakeLists.txt 2015-02-16 14:24:40 +0000 | |||
488 | @@ -2,9 +2,7 @@ | |||
489 | 2 | add_definitions(${MEDIASCANNER_CFLAGS} ${DBUSCPP_CFLAGS} ${APPARMOR_CFLAGS}) | 2 | add_definitions(${MEDIASCANNER_CFLAGS} ${DBUSCPP_CFLAGS} ${APPARMOR_CFLAGS}) |
490 | 3 | 3 | ||
491 | 4 | add_library(ms-dbus STATIC | 4 | add_library(ms-dbus STATIC |
492 | 5 | dbus-codec.cc | ||
493 | 6 | service-skeleton.cc | 5 | service-skeleton.cc |
494 | 7 | service-stub.cc | ||
495 | 8 | ) | 6 | ) |
496 | 9 | 7 | ||
497 | 10 | target_link_libraries(ms-dbus | 8 | target_link_libraries(ms-dbus |
498 | @@ -16,6 +14,7 @@ | |||
499 | 16 | 14 | ||
500 | 17 | add_executable(mediascanner-dbus | 15 | add_executable(mediascanner-dbus |
501 | 18 | main.cc | 16 | main.cc |
502 | 17 | $<TARGET_OBJECTS:mediascanner-dbus-static> | ||
503 | 19 | ) | 18 | ) |
504 | 20 | target_link_libraries(mediascanner-dbus ms-dbus) | 19 | target_link_libraries(mediascanner-dbus ms-dbus) |
505 | 21 | set_target_properties(mediascanner-dbus | 20 | set_target_properties(mediascanner-dbus |
506 | 22 | 21 | ||
507 | === modified file 'src/ms-dbus/main.cc' | |||
508 | --- src/ms-dbus/main.cc 2014-05-20 09:01:59 +0000 | |||
509 | +++ src/ms-dbus/main.cc 2015-02-16 14:24:40 +0000 | |||
510 | @@ -27,10 +27,10 @@ | |||
511 | 27 | using namespace mediascanner; | 27 | using namespace mediascanner; |
512 | 28 | 28 | ||
513 | 29 | int main(int , char **) { | 29 | int main(int , char **) { |
515 | 30 | auto bus = std::make_shared<core::dbus::Bus>(core::dbus::WellKnownBus::session); | 30 | auto bus = std::make_shared<core::dbus::Bus>(getenv("DBUS_SESSION_BUS_ADDRESS")); |
516 | 31 | bus->install_executor(core::dbus::asio::make_executor(bus)); | 31 | bus->install_executor(core::dbus::asio::make_executor(bus)); |
517 | 32 | 32 | ||
519 | 33 | auto store = std::make_shared<MediaStore>(MS_READ_ONLY); | 33 | auto store = std::make_shared<MediaStore>(MS_READ_WRITE); |
520 | 34 | 34 | ||
521 | 35 | dbus::ServiceSkeleton service(bus, store); | 35 | dbus::ServiceSkeleton service(bus, store); |
522 | 36 | service.run(); | 36 | service.run(); |
523 | 37 | 37 | ||
524 | === modified file 'src/ms-dbus/service-skeleton.cc' | |||
525 | --- src/ms-dbus/service-skeleton.cc 2014-08-21 03:55:40 +0000 | |||
526 | +++ src/ms-dbus/service-skeleton.cc 2015-02-16 14:24:40 +0000 | |||
527 | @@ -12,8 +12,8 @@ | |||
528 | 12 | #include <mediascanner/MediaFile.hh> | 12 | #include <mediascanner/MediaFile.hh> |
529 | 13 | #include <mediascanner/MediaStore.hh> | 13 | #include <mediascanner/MediaStore.hh> |
530 | 14 | 14 | ||
533 | 15 | #include "dbus-interface.hh" | 15 | #include <mediascanner/d-bus/dbus-interface.hh> |
534 | 16 | #include "dbus-codec.hh" | 16 | #include <mediascanner/d-bus/dbus-codec.hh> |
535 | 17 | 17 | ||
536 | 18 | using core::dbus::Message; | 18 | using core::dbus::Message; |
537 | 19 | 19 | ||
538 | 20 | 20 | ||
539 | === modified file 'src/ms-dbus/service-skeleton.hh' | |||
540 | --- src/ms-dbus/service-skeleton.hh 2014-05-22 09:26:44 +0000 | |||
541 | +++ src/ms-dbus/service-skeleton.hh 2015-02-16 14:24:40 +0000 | |||
542 | @@ -24,7 +24,7 @@ | |||
543 | 24 | #include <core/dbus/bus.h> | 24 | #include <core/dbus/bus.h> |
544 | 25 | #include <core/dbus/skeleton.h> | 25 | #include <core/dbus/skeleton.h> |
545 | 26 | 26 | ||
547 | 27 | #include "service.hh" | 27 | #include "mediascanner/d-bus/service.hh" |
548 | 28 | 28 | ||
549 | 29 | namespace mediascanner { | 29 | namespace mediascanner { |
550 | 30 | 30 | ||
551 | 31 | 31 | ||
552 | === modified file 'src/qml/Ubuntu/MediaScanner/MediaStoreWrapper.cc' | |||
553 | --- src/qml/Ubuntu/MediaScanner/MediaStoreWrapper.cc 2014-08-21 03:55:40 +0000 | |||
554 | +++ src/qml/Ubuntu/MediaScanner/MediaStoreWrapper.cc 2015-02-16 14:24:40 +0000 | |||
555 | @@ -28,7 +28,7 @@ | |||
556 | 28 | #include <core/dbus/asio/executor.h> | 28 | #include <core/dbus/asio/executor.h> |
557 | 29 | #include <mediascanner/Filter.hh> | 29 | #include <mediascanner/Filter.hh> |
558 | 30 | #include <mediascanner/MediaStore.hh> | 30 | #include <mediascanner/MediaStore.hh> |
560 | 31 | #include <ms-dbus/service-stub.hh> | 31 | #include <mediascanner/d-bus/service-stub.hh> |
561 | 32 | 32 | ||
562 | 33 | using namespace mediascanner::qml; | 33 | using namespace mediascanner::qml; |
563 | 34 | 34 | ||
564 | 35 | 35 | ||
565 | === modified file 'test/CMakeLists.txt' | |||
566 | --- test/CMakeLists.txt 2014-06-24 11:23:31 +0000 | |||
567 | +++ test/CMakeLists.txt 2015-02-16 14:24:40 +0000 | |||
568 | @@ -2,6 +2,9 @@ | |||
569 | 2 | set(GTEST_ROOT /usr/src/gtest) | 2 | set(GTEST_ROOT /usr/src/gtest) |
570 | 3 | endif() | 3 | endif() |
571 | 4 | 4 | ||
572 | 5 | set(SOURCE_BINARY_DIR "${CMAKE_BINARY_DIR}/src") | ||
573 | 6 | add_definitions(-DMS_DBUS_BINARY="${SOURCE_BINARY_DIR}/ms-dbus/mediascanner-dbus-2.0") | ||
574 | 7 | |||
575 | 5 | set(GTEST_SRC_DIR "${GTEST_ROOT}/src") | 8 | set(GTEST_SRC_DIR "${GTEST_ROOT}/src") |
576 | 6 | set(GTEST_INCLUDE_DIR ${GTEST_ROOT}) | 9 | set(GTEST_INCLUDE_DIR ${GTEST_ROOT}) |
577 | 7 | 10 | ||
578 | @@ -9,6 +12,9 @@ | |||
579 | 9 | ${GTEST_SRC_DIR}/gtest-all.cc | 12 | ${GTEST_SRC_DIR}/gtest-all.cc |
580 | 10 | ) | 13 | ) |
581 | 11 | 14 | ||
582 | 15 | pkg_check_modules(QTDBUSTEST REQUIRED libqtdbustest-1 REQUIRED) | ||
583 | 16 | include_directories(${QTDBUSTEST_INCLUDE_DIRS}) | ||
584 | 17 | |||
585 | 12 | set_target_properties(gtest PROPERTIES INCLUDE_DIRECTORIES ${GTEST_INCLUDE_DIR}) | 18 | set_target_properties(gtest PROPERTIES INCLUDE_DIRECTORIES ${GTEST_INCLUDE_DIR}) |
586 | 13 | target_link_libraries(gtest ${CMAKE_THREAD_LIBS_INIT}) | 19 | target_link_libraries(gtest ${CMAKE_THREAD_LIBS_INIT}) |
587 | 14 | 20 | ||
588 | @@ -25,10 +31,14 @@ | |||
589 | 25 | 31 | ||
590 | 26 | add_executable(basic basic.cc) | 32 | add_executable(basic basic.cc) |
591 | 27 | target_link_libraries(basic mediascanner scannerstuff gtest) | 33 | target_link_libraries(basic mediascanner scannerstuff gtest) |
593 | 28 | add_test(basic basic) | 34 | #add_test(basic basic) |
594 | 29 | 35 | ||
597 | 30 | add_executable(test_mediastore test_mediastore.cc ../src/mediascanner/utils.cc) | 36 | add_executable(test_mediastore |
598 | 31 | target_link_libraries(test_mediastore mediascanner gtest) | 37 | test_mediastore.cc |
599 | 38 | ../src/mediascanner/utils.cc | ||
600 | 39 | utils/DBusTest.cpp) | ||
601 | 40 | qt5_use_modules(test_mediastore Core DBus) | ||
602 | 41 | target_link_libraries(test_mediastore mediascanner gtest ${QTDBUSTEST_LDFLAGS}) | ||
603 | 32 | add_test(test_mediastore test_mediastore) | 42 | add_test(test_mediastore test_mediastore) |
604 | 33 | 43 | ||
605 | 34 | add_executable(test_metadataextractor test_metadataextractor.cc) | 44 | add_executable(test_metadataextractor test_metadataextractor.cc) |
606 | @@ -43,11 +53,11 @@ | |||
607 | 43 | target_link_libraries(test_mfbuilder gtest mediascanner) | 53 | target_link_libraries(test_mfbuilder gtest mediascanner) |
608 | 44 | add_test(test_mfbuilder test_mfbuilder) | 54 | add_test(test_mfbuilder test_mfbuilder) |
609 | 45 | 55 | ||
611 | 46 | add_executable(test_dbus test_dbus.cc) | 56 | add_executable(test_dbus test_dbus.cc $<TARGET_OBJECTS:mediascanner-dbus-static>) |
612 | 47 | target_link_libraries(test_dbus gtest mediascanner ms-dbus) | 57 | target_link_libraries(test_dbus gtest mediascanner ms-dbus) |
613 | 48 | add_test(test_dbus test_dbus) | 58 | add_test(test_dbus test_dbus) |
614 | 49 | 59 | ||
616 | 50 | add_executable(test_qml test_qml.cc) | 60 | add_executable(test_qml test_qml.cc $<TARGET_OBJECTS:mediascanner-dbus-static>) |
617 | 51 | qt5_use_modules(test_qml QuickTest) | 61 | qt5_use_modules(test_qml QuickTest) |
618 | 52 | target_link_libraries(test_qml mediascanner ${DBUSCPP_LDFLAGS}) | 62 | target_link_libraries(test_qml mediascanner ${DBUSCPP_LDFLAGS}) |
619 | 53 | add_test(test_qml test_qml -input ${CMAKE_CURRENT_SOURCE_DIR}/qml -import ${CMAKE_BINARY_DIR}/src/qml) | 63 | add_test(test_qml test_qml -input ${CMAKE_CURRENT_SOURCE_DIR}/qml -import ${CMAKE_BINARY_DIR}/src/qml) |
620 | 54 | 64 | ||
621 | === modified file 'test/test_dbus.cc' | |||
622 | --- test/test_dbus.cc 2014-09-03 07:00:02 +0000 | |||
623 | +++ test/test_dbus.cc 2015-02-16 14:24:40 +0000 | |||
624 | @@ -7,7 +7,7 @@ | |||
625 | 7 | #include <mediascanner/MediaFile.hh> | 7 | #include <mediascanner/MediaFile.hh> |
626 | 8 | #include <mediascanner/MediaFileBuilder.hh> | 8 | #include <mediascanner/MediaFileBuilder.hh> |
627 | 9 | #include <mediascanner/Filter.hh> | 9 | #include <mediascanner/Filter.hh> |
629 | 10 | #include <ms-dbus/dbus-codec.hh> | 10 | #include <mediascanner/d-bus/dbus-codec.hh> |
630 | 11 | 11 | ||
631 | 12 | class MediaStoreDBusTests : public ::testing::Test { | 12 | class MediaStoreDBusTests : public ::testing::Test { |
632 | 13 | protected: | 13 | protected: |
633 | 14 | 14 | ||
634 | === modified file 'test/test_mediastore.cc' | |||
635 | --- test/test_mediastore.cc 2014-09-02 10:43:05 +0000 | |||
636 | +++ test/test_mediastore.cc 2015-02-16 14:24:40 +0000 | |||
637 | @@ -29,33 +29,27 @@ | |||
638 | 29 | #include<string> | 29 | #include<string> |
639 | 30 | #include <gtest/gtest.h> | 30 | #include <gtest/gtest.h> |
640 | 31 | 31 | ||
641 | 32 | #include <core/dbus/fixture.h> | ||
642 | 33 | |||
643 | 34 | #include <QProcess> | ||
644 | 35 | #include <QProcessEnvironment> | ||
645 | 36 | #include <QCoreApplication> | ||
646 | 37 | |||
647 | 38 | #include "test_config.h" | ||
648 | 39 | #include "utils/DBusTest.h" | ||
649 | 40 | |||
650 | 32 | using namespace std; | 41 | using namespace std; |
651 | 33 | using namespace mediascanner; | 42 | using namespace mediascanner; |
652 | 34 | 43 | ||
669 | 35 | class MediaStoreTest : public ::testing::Test { | 44 | TEST(MediaStoreTest, init) { |
654 | 36 | protected: | ||
655 | 37 | MediaStoreTest() { | ||
656 | 38 | } | ||
657 | 39 | |||
658 | 40 | virtual ~MediaStoreTest() { | ||
659 | 41 | } | ||
660 | 42 | |||
661 | 43 | virtual void SetUp() { | ||
662 | 44 | } | ||
663 | 45 | |||
664 | 46 | virtual void TearDown() { | ||
665 | 47 | } | ||
666 | 48 | }; | ||
667 | 49 | |||
668 | 50 | TEST_F(MediaStoreTest, init) { | ||
670 | 51 | MediaStore store(":memory:", MS_READ_WRITE); | 45 | MediaStore store(":memory:", MS_READ_WRITE); |
671 | 52 | } | 46 | } |
673 | 53 | TEST_F(MediaStoreTest, mediafile_uri) { | 47 | TEST(MediaStoreTest, mediafile_uri) { |
674 | 54 | MediaFile media = MediaFileBuilder("/path/to/file.ogg"); | 48 | MediaFile media = MediaFileBuilder("/path/to/file.ogg"); |
675 | 55 | EXPECT_EQ(media.getUri(), "file:///path/to/file.ogg"); | 49 | EXPECT_EQ(media.getUri(), "file:///path/to/file.ogg"); |
676 | 56 | } | 50 | } |
677 | 57 | 51 | ||
679 | 58 | TEST_F(MediaStoreTest, equality) { | 52 | TEST(MediaStoreTest, equality) { |
680 | 59 | MediaFile audio1 = MediaFileBuilder("a") | 53 | MediaFile audio1 = MediaFileBuilder("a") |
681 | 60 | .setContentType("type") | 54 | .setContentType("type") |
682 | 61 | .setETag("etag") | 55 | .setETag("etag") |
683 | @@ -136,7 +130,7 @@ | |||
684 | 136 | EXPECT_NE(video1, image1); | 130 | EXPECT_NE(video1, image1); |
685 | 137 | } | 131 | } |
686 | 138 | 132 | ||
688 | 139 | TEST_F(MediaStoreTest, lookup) { | 133 | TEST(MediaStoreTest, lookup) { |
689 | 140 | MediaFile audio = MediaFileBuilder("/aaa") | 134 | MediaFile audio = MediaFileBuilder("/aaa") |
690 | 141 | .setContentType("type") | 135 | .setContentType("type") |
691 | 142 | .setETag("etag") | 136 | .setETag("etag") |
692 | @@ -155,9 +149,11 @@ | |||
693 | 155 | 149 | ||
694 | 156 | EXPECT_EQ(store.lookup("/aaa"), audio); | 150 | EXPECT_EQ(store.lookup("/aaa"), audio); |
695 | 157 | EXPECT_THROW(store.lookup("not found"), std::runtime_error); | 151 | EXPECT_THROW(store.lookup("not found"), std::runtime_error); |
696 | 152 | |||
697 | 153 | store.remove(audio.getFileName()); | ||
698 | 158 | } | 154 | } |
699 | 159 | 155 | ||
701 | 160 | TEST_F(MediaStoreTest, roundtrip) { | 156 | TEST(MediaStoreTest, roundtrip) { |
702 | 161 | MediaFile audio = MediaFileBuilder("/aaa") | 157 | MediaFile audio = MediaFileBuilder("/aaa") |
703 | 162 | .setContentType("type") | 158 | .setContentType("type") |
704 | 163 | .setETag("etag") | 159 | .setETag("etag") |
705 | @@ -208,41 +204,75 @@ | |||
706 | 208 | result = store.query("bbb", ImageMedia, filter); | 204 | result = store.query("bbb", ImageMedia, filter); |
707 | 209 | ASSERT_EQ(1, result.size()); | 205 | ASSERT_EQ(1, result.size()); |
708 | 210 | EXPECT_EQ(image, result[0]); | 206 | EXPECT_EQ(image, result[0]); |
709 | 207 | |||
710 | 208 | store.remove(audio.getFileName()); | ||
711 | 209 | store.remove(video.getFileName()); | ||
712 | 210 | store.remove(image.getFileName()); | ||
713 | 211 | } | 211 | } |
714 | 212 | 212 | ||
725 | 213 | TEST_F(MediaStoreTest, query_by_album) { | 213 | void check_query_by_album(MediaStore const &store, MediaFile const &audio) { |
716 | 214 | MediaFile audio = MediaFileBuilder("/path/foo.ogg") | ||
717 | 215 | .setType(AudioMedia) | ||
718 | 216 | .setTitle("title") | ||
719 | 217 | .setAuthor("artist") | ||
720 | 218 | .setAlbum("album") | ||
721 | 219 | .setAlbumArtist("albumartist"); | ||
722 | 220 | MediaStore store(":memory:", MS_READ_WRITE); | ||
723 | 221 | store.insert(audio); | ||
724 | 222 | |||
726 | 223 | Filter filter; | 214 | Filter filter; |
727 | 224 | vector<MediaFile> result = store.query("album", AudioMedia, filter); | 215 | vector<MediaFile> result = store.query("album", AudioMedia, filter); |
728 | 225 | ASSERT_EQ(result.size(), 1); | 216 | ASSERT_EQ(result.size(), 1); |
729 | 226 | EXPECT_EQ(result[0], audio); | 217 | EXPECT_EQ(result[0], audio); |
730 | 227 | } | 218 | } |
731 | 228 | 219 | ||
733 | 229 | TEST_F(MediaStoreTest, query_by_artist) { | 220 | TEST(MediaStoreTest, query_by_album) { |
734 | 230 | MediaFile audio = MediaFileBuilder("/path/foo.ogg") | 221 | MediaFile audio = MediaFileBuilder("/path/foo.ogg") |
735 | 231 | .setType(AudioMedia) | 222 | .setType(AudioMedia) |
736 | 232 | .setTitle("title") | 223 | .setTitle("title") |
737 | 233 | .setAuthor("artist") | 224 | .setAuthor("artist") |
738 | 234 | .setAlbum("album") | 225 | .setAlbum("album") |
739 | 235 | .setAlbumArtist("albumartist"); | 226 | .setAlbumArtist("albumartist"); |
741 | 236 | MediaStore store(":memory:", MS_READ_WRITE); | 227 | MediaStore store(TEST_DIR "/mediastore.db", MS_READ_WRITE); |
742 | 237 | store.insert(audio); | 228 | store.insert(audio); |
743 | 238 | 229 | ||
744 | 230 | check_query_by_album(store, audio); | ||
745 | 231 | |||
746 | 232 | // test read only | ||
747 | 233 | MediaStore store2(TEST_DIR "/mediastore.db", MS_READ_ONLY); | ||
748 | 234 | check_query_by_album(store2, audio); | ||
749 | 235 | |||
750 | 236 | store.remove(audio.getFileName()); | ||
751 | 237 | |||
752 | 238 | } | ||
753 | 239 | |||
754 | 240 | void check_query_by_artist(MediaStore const &store, MediaFile const &audio) { | ||
755 | 239 | Filter filter; | 241 | Filter filter; |
756 | 240 | vector<MediaFile> result = store.query("artist", AudioMedia, filter); | 242 | vector<MediaFile> result = store.query("artist", AudioMedia, filter); |
757 | 241 | ASSERT_EQ(result.size(), 1); | 243 | ASSERT_EQ(result.size(), 1); |
758 | 242 | EXPECT_EQ(result[0], audio); | 244 | EXPECT_EQ(result[0], audio); |
762 | 243 | } | 245 | } |
763 | 244 | 246 | ||
764 | 245 | TEST_F(MediaStoreTest, query_ranking) { | 247 | TEST(MediaStoreTest, query_by_artist) { |
765 | 248 | MediaFile audio = MediaFileBuilder("/path/foo.ogg") | ||
766 | 249 | .setType(AudioMedia) | ||
767 | 250 | .setTitle("title") | ||
768 | 251 | .setAuthor("artist") | ||
769 | 252 | .setAlbum("album") | ||
770 | 253 | .setAlbumArtist("albumartist"); | ||
771 | 254 | MediaStore store(TEST_DIR "/mediastore.db", MS_READ_WRITE); | ||
772 | 255 | store.insert(audio); | ||
773 | 256 | |||
774 | 257 | check_query_by_artist(store, audio); | ||
775 | 258 | |||
776 | 259 | MediaStore store_ro(TEST_DIR "/mediastore.db", MS_READ_ONLY); | ||
777 | 260 | check_query_by_artist(store_ro, audio); | ||
778 | 261 | |||
779 | 262 | store.remove(audio.getFileName()); | ||
780 | 263 | } | ||
781 | 264 | |||
782 | 265 | void check_query_ranking(MediaStore const &store, std::vector<MediaFile> const &files) { | ||
783 | 266 | Filter filter; | ||
784 | 267 | vector<MediaFile> result = store.query("aaa", AudioMedia, filter); | ||
785 | 268 | ASSERT_EQ(result.size(), 4); | ||
786 | 269 | EXPECT_EQ(result[0], files[4]); // Term appears in title, artist and album | ||
787 | 270 | EXPECT_EQ(result[1], files[1]); // title has highest weighting | ||
788 | 271 | EXPECT_EQ(result[2], files[3]); // then album | ||
789 | 272 | EXPECT_EQ(result[3], files[2]); // then artist | ||
790 | 273 | } | ||
791 | 274 | |||
792 | 275 | TEST(MediaStoreTest, query_ranking) { | ||
793 | 246 | MediaFile audio1 = MediaFileBuilder("/path/foo1.ogg") | 276 | MediaFile audio1 = MediaFileBuilder("/path/foo1.ogg") |
794 | 247 | .setType(AudioMedia) | 277 | .setType(AudioMedia) |
795 | 248 | .setTitle("title") | 278 | .setTitle("title") |
796 | @@ -274,47 +304,38 @@ | |||
797 | 274 | .setAlbum("album aaa") | 304 | .setAlbum("album aaa") |
798 | 275 | .setAlbumArtist("albumartist"); | 305 | .setAlbumArtist("albumartist"); |
799 | 276 | 306 | ||
801 | 277 | MediaStore store(":memory:", MS_READ_WRITE); | 307 | MediaStore store(TEST_DIR "/mediastore.db", MS_READ_WRITE); |
802 | 308 | |||
803 | 309 | std::vector<MediaFile> files; | ||
804 | 278 | store.insert(audio1); | 310 | store.insert(audio1); |
805 | 311 | files.push_back(audio1); | ||
806 | 312 | |||
807 | 279 | store.insert(audio2); | 313 | store.insert(audio2); |
808 | 314 | files.push_back(audio2); | ||
809 | 315 | |||
810 | 280 | store.insert(audio3); | 316 | store.insert(audio3); |
811 | 317 | files.push_back(audio3); | ||
812 | 318 | |||
813 | 281 | store.insert(audio4); | 319 | store.insert(audio4); |
814 | 320 | files.push_back(audio4); | ||
815 | 321 | |||
816 | 282 | store.insert(audio5); | 322 | store.insert(audio5); |
825 | 283 | 323 | files.push_back(audio5); | |
826 | 284 | Filter filter; | 324 | |
827 | 285 | vector<MediaFile> result = store.query("aaa", AudioMedia, filter); | 325 | check_query_ranking(store, files); |
828 | 286 | ASSERT_EQ(result.size(), 4); | 326 | |
829 | 287 | EXPECT_EQ(result[0], audio5); // Term appears in title, artist and album | 327 | MediaStore store_ro(TEST_DIR "/mediastore.db", MS_READ_ONLY); |
830 | 288 | EXPECT_EQ(result[1], audio2); // title has highest weighting | 328 | check_query_ranking(store_ro, files); |
831 | 289 | EXPECT_EQ(result[2], audio4); // then album | 329 | |
832 | 290 | EXPECT_EQ(result[3], audio3); // then artist | 330 | for(auto item: files) { |
833 | 331 | store.remove(item.getFileName()); | ||
834 | 332 | } | ||
835 | 291 | } | 333 | } |
836 | 292 | 334 | ||
862 | 293 | TEST_F(MediaStoreTest, query_limit) { | 335 | void check_query_limit(MediaStore const &store, |
863 | 294 | MediaFile audio1 = MediaFileBuilder("/path/foo5.ogg") | 336 | MediaFile const &audio1, |
864 | 295 | .setType(AudioMedia) | 337 | MediaFile const &audio2, |
865 | 296 | .setTitle("title aaa") | 338 | MediaFile const &) { |
841 | 297 | .setAuthor("artist aaa") | ||
842 | 298 | .setAlbum("album aaa") | ||
843 | 299 | .setAlbumArtist("albumartist"); | ||
844 | 300 | MediaFile audio2 = MediaFileBuilder("/path/foo2.ogg") | ||
845 | 301 | .setType(AudioMedia) | ||
846 | 302 | .setTitle("title aaa") | ||
847 | 303 | .setAuthor("artist") | ||
848 | 304 | .setAlbum("album") | ||
849 | 305 | .setAlbumArtist("albumartist"); | ||
850 | 306 | MediaFile audio3 = MediaFileBuilder("/path/foo4.ogg") | ||
851 | 307 | .setType(AudioMedia) | ||
852 | 308 | .setTitle("title") | ||
853 | 309 | .setAuthor("artist") | ||
854 | 310 | .setAlbum("album aaa") | ||
855 | 311 | .setAlbumArtist("albumartist"); | ||
856 | 312 | |||
857 | 313 | MediaStore store(":memory:", MS_READ_WRITE); | ||
858 | 314 | store.insert(audio1); | ||
859 | 315 | store.insert(audio2); | ||
860 | 316 | store.insert(audio3); | ||
861 | 317 | |||
866 | 318 | Filter filter; | 339 | Filter filter; |
867 | 319 | filter.setLimit(2); | 340 | filter.setLimit(2); |
868 | 320 | vector<MediaFile> result = store.query("aaa", AudioMedia, filter); | 341 | vector<MediaFile> result = store.query("aaa", AudioMedia, filter); |
869 | @@ -323,24 +344,42 @@ | |||
870 | 323 | EXPECT_EQ(result[1], audio2); // title has highest weighting | 344 | EXPECT_EQ(result[1], audio2); // title has highest weighting |
871 | 324 | } | 345 | } |
872 | 325 | 346 | ||
874 | 326 | TEST_F(MediaStoreTest, query_short) { | 347 | TEST(MediaStoreTest, query_limit) { |
875 | 327 | MediaFile audio1 = MediaFileBuilder("/path/foo5.ogg") | 348 | MediaFile audio1 = MediaFileBuilder("/path/foo5.ogg") |
876 | 328 | .setType(AudioMedia) | 349 | .setType(AudioMedia) |
880 | 329 | .setTitle("title xyz") | 350 | .setTitle("title aaa") |
881 | 330 | .setAuthor("artist") | 351 | .setAuthor("artist aaa") |
882 | 331 | .setAlbum("album") | 352 | .setAlbum("album aaa") |
883 | 332 | .setAlbumArtist("albumartist"); | 353 | .setAlbumArtist("albumartist"); |
884 | 333 | MediaFile audio2 = MediaFileBuilder("/path/foo2.ogg") | 354 | MediaFile audio2 = MediaFileBuilder("/path/foo2.ogg") |
885 | 334 | .setType(AudioMedia) | 355 | .setType(AudioMedia) |
887 | 335 | .setTitle("title xzy") | 356 | .setTitle("title aaa") |
888 | 336 | .setAuthor("artist") | 357 | .setAuthor("artist") |
889 | 337 | .setAlbum("album") | 358 | .setAlbum("album") |
890 | 338 | .setAlbumArtist("albumartist"); | 359 | .setAlbumArtist("albumartist"); |
891 | 360 | MediaFile audio3 = MediaFileBuilder("/path/foo4.ogg") | ||
892 | 361 | .setType(AudioMedia) | ||
893 | 362 | .setTitle("title") | ||
894 | 363 | .setAuthor("artist") | ||
895 | 364 | .setAlbum("album aaa") | ||
896 | 365 | .setAlbumArtist("albumartist"); | ||
897 | 339 | 366 | ||
899 | 340 | MediaStore store(":memory:", MS_READ_WRITE); | 367 | MediaStore store(TEST_DIR "/mediastore.db", MS_READ_WRITE); |
900 | 341 | store.insert(audio1); | 368 | store.insert(audio1); |
901 | 342 | store.insert(audio2); | 369 | store.insert(audio2); |
903 | 343 | 370 | store.insert(audio3); | |
904 | 371 | |||
905 | 372 | check_query_limit(store, audio1, audio2, audio3); | ||
906 | 373 | |||
907 | 374 | MediaStore store_ro(TEST_DIR "/mediastore.db", MS_READ_ONLY); | ||
908 | 375 | check_query_limit(store_ro, audio1, audio2, audio3); | ||
909 | 376 | |||
910 | 377 | store.remove(audio1.getFileName()); | ||
911 | 378 | store.remove(audio2.getFileName()); | ||
912 | 379 | store.remove(audio3.getFileName()); | ||
913 | 380 | } | ||
914 | 381 | |||
915 | 382 | void check_query_short(MediaStore const &store, MediaFile const &, MediaFile const &) { | ||
916 | 344 | Filter filter; | 383 | Filter filter; |
917 | 345 | vector<MediaFile> result = store.query("x", AudioMedia, filter); | 384 | vector<MediaFile> result = store.query("x", AudioMedia, filter); |
918 | 346 | EXPECT_EQ(result.size(), 2); | 385 | EXPECT_EQ(result.size(), 2); |
919 | @@ -348,31 +387,34 @@ | |||
920 | 348 | EXPECT_EQ(result.size(), 1); | 387 | EXPECT_EQ(result.size(), 1); |
921 | 349 | } | 388 | } |
922 | 350 | 389 | ||
924 | 351 | TEST_F(MediaStoreTest, query_empty) { | 390 | TEST(MediaStoreTest, query_short) { |
925 | 352 | MediaFile audio1 = MediaFileBuilder("/path/foo5.ogg") | 391 | MediaFile audio1 = MediaFileBuilder("/path/foo5.ogg") |
926 | 353 | .setType(AudioMedia) | 392 | .setType(AudioMedia) |
930 | 354 | .setTitle("title aaa") | 393 | .setTitle("title xyz") |
931 | 355 | .setAuthor("artist aaa") | 394 | .setAuthor("artist") |
932 | 356 | .setAlbum("album aaa") | 395 | .setAlbum("album") |
933 | 357 | .setAlbumArtist("albumartist"); | 396 | .setAlbumArtist("albumartist"); |
934 | 358 | MediaFile audio2 = MediaFileBuilder("/path/foo2.ogg") | 397 | MediaFile audio2 = MediaFileBuilder("/path/foo2.ogg") |
935 | 359 | .setType(AudioMedia) | 398 | .setType(AudioMedia) |
937 | 360 | .setTitle("title aaa") | 399 | .setTitle("title xzy") |
938 | 361 | .setAuthor("artist") | 400 | .setAuthor("artist") |
939 | 362 | .setAlbum("album") | 401 | .setAlbum("album") |
940 | 363 | .setAlbumArtist("albumartist"); | 402 | .setAlbumArtist("albumartist"); |
941 | 364 | MediaFile audio3 = MediaFileBuilder("/path/foo4.ogg") | ||
942 | 365 | .setType(AudioMedia) | ||
943 | 366 | .setTitle("title") | ||
944 | 367 | .setAuthor("artist") | ||
945 | 368 | .setAlbum("album aaa") | ||
946 | 369 | .setAlbumArtist("albumartist"); | ||
947 | 370 | 403 | ||
949 | 371 | MediaStore store(":memory:", MS_READ_WRITE); | 404 | MediaStore store(TEST_DIR "/mediastore.db", MS_READ_WRITE); |
950 | 372 | store.insert(audio1); | 405 | store.insert(audio1); |
951 | 373 | store.insert(audio2); | 406 | store.insert(audio2); |
954 | 374 | store.insert(audio3); | 407 | |
955 | 375 | 408 | check_query_short(store, audio1, audio2); | |
956 | 409 | |||
957 | 410 | MediaStore store_ro(TEST_DIR "/mediastore.db", MS_READ_ONLY); | ||
958 | 411 | check_query_short(store_ro, audio1, audio2); | ||
959 | 412 | |||
960 | 413 | store.remove(audio1.getFileName()); | ||
961 | 414 | store.remove(audio2.getFileName()); | ||
962 | 415 | } | ||
963 | 416 | |||
964 | 417 | void check_query_empty(MediaStore const &store) { | ||
965 | 376 | // An empty query should return some results | 418 | // An empty query should return some results |
966 | 377 | Filter filter; | 419 | Filter filter; |
967 | 378 | filter.setLimit(2); | 420 | filter.setLimit(2); |
968 | @@ -380,91 +422,140 @@ | |||
969 | 380 | ASSERT_EQ(result.size(), 2); | 422 | ASSERT_EQ(result.size(), 2); |
970 | 381 | } | 423 | } |
971 | 382 | 424 | ||
974 | 383 | TEST_F(MediaStoreTest, query_order) { | 425 | TEST(MediaStoreTest, query_empty) { |
975 | 384 | MediaFile audio1 = MediaFileBuilder("/path/foo1.ogg") | 426 | MediaFile audio1 = MediaFileBuilder("/path/foo5.ogg") |
976 | 385 | .setType(AudioMedia) | 427 | .setType(AudioMedia) |
981 | 386 | .setTitle("foo") | 428 | .setTitle("title aaa") |
982 | 387 | .setDate("2010-01-01") | 429 | .setAuthor("artist aaa") |
983 | 388 | .setAuthor("artist") | 430 | .setAlbum("album aaa") |
984 | 389 | .setAlbum("album"); | 431 | .setAlbumArtist("albumartist"); |
985 | 390 | MediaFile audio2 = MediaFileBuilder("/path/foo2.ogg") | 432 | MediaFile audio2 = MediaFileBuilder("/path/foo2.ogg") |
986 | 391 | .setType(AudioMedia) | 433 | .setType(AudioMedia) |
989 | 392 | .setTitle("foo foo") | 434 | .setTitle("title aaa") |
988 | 393 | .setDate("2010-01-03") | ||
990 | 394 | .setAuthor("artist") | 435 | .setAuthor("artist") |
993 | 395 | .setAlbum("album"); | 436 | .setAlbum("album") |
994 | 396 | MediaFile audio3 = MediaFileBuilder("/path/foo3.ogg") | 437 | .setAlbumArtist("albumartist"); |
995 | 438 | MediaFile audio3 = MediaFileBuilder("/path/foo4.ogg") | ||
996 | 397 | .setType(AudioMedia) | 439 | .setType(AudioMedia) |
999 | 398 | .setTitle("foo foo foo") | 440 | .setTitle("title") |
998 | 399 | .setDate("2010-01-02") | ||
1000 | 400 | .setAuthor("artist") | 441 | .setAuthor("artist") |
1002 | 401 | .setAlbum("album"); | 442 | .setAlbum("album aaa") |
1003 | 443 | .setAlbumArtist("albumartist"); | ||
1004 | 402 | 444 | ||
1006 | 403 | MediaStore store(":memory:", MS_READ_WRITE); | 445 | MediaStore store(TEST_DIR "/mediastore.db", MS_READ_WRITE); |
1007 | 404 | store.insert(audio1); | 446 | store.insert(audio1); |
1008 | 405 | store.insert(audio2); | 447 | store.insert(audio2); |
1009 | 406 | store.insert(audio3); | 448 | store.insert(audio3); |
1010 | 407 | 449 | ||
1011 | 450 | check_query_empty(store); | ||
1012 | 451 | |||
1013 | 452 | MediaStore store_ro(TEST_DIR "/mediastore.db", MS_READ_ONLY); | ||
1014 | 453 | check_query_empty(store_ro); | ||
1015 | 454 | |||
1016 | 455 | store.remove(audio1.getFileName()); | ||
1017 | 456 | store.remove(audio2.getFileName()); | ||
1018 | 457 | store.remove(audio3.getFileName()); | ||
1019 | 458 | } | ||
1020 | 459 | |||
1021 | 460 | void check_query_order(MediaStore const &store, | ||
1022 | 461 | std::string const &name1, | ||
1023 | 462 | std::string const &name2, | ||
1024 | 463 | std::string const &name3) { | ||
1025 | 408 | Filter filter; | 464 | Filter filter; |
1026 | 409 | // Default sort order is by rank | 465 | // Default sort order is by rank |
1027 | 410 | vector<MediaFile> result = store.query("foo", AudioMedia, filter); | 466 | vector<MediaFile> result = store.query("foo", AudioMedia, filter); |
1028 | 411 | ASSERT_EQ(3, result.size()); | 467 | ASSERT_EQ(3, result.size()); |
1032 | 412 | EXPECT_EQ("/path/foo3.ogg", result[0].getFileName()); | 468 | EXPECT_EQ(name3, result[0].getFileName()); |
1033 | 413 | EXPECT_EQ("/path/foo2.ogg", result[1].getFileName()); | 469 | EXPECT_EQ(name2, result[1].getFileName()); |
1034 | 414 | EXPECT_EQ("/path/foo1.ogg", result[2].getFileName()); | 470 | EXPECT_EQ(name1, result[2].getFileName()); |
1035 | 415 | 471 | ||
1036 | 416 | // Sorting by rank (same as default) | 472 | // Sorting by rank (same as default) |
1037 | 417 | filter.setOrder(MediaOrder::Rank); | 473 | filter.setOrder(MediaOrder::Rank); |
1038 | 418 | result = store.query("foo", AudioMedia, filter); | 474 | result = store.query("foo", AudioMedia, filter); |
1039 | 419 | ASSERT_EQ(3, result.size()); | 475 | ASSERT_EQ(3, result.size()); |
1043 | 420 | EXPECT_EQ("/path/foo3.ogg", result[0].getFileName()); | 476 | EXPECT_EQ(name3, result[0].getFileName()); |
1044 | 421 | EXPECT_EQ("/path/foo2.ogg", result[1].getFileName()); | 477 | EXPECT_EQ(name2, result[1].getFileName()); |
1045 | 422 | EXPECT_EQ("/path/foo1.ogg", result[2].getFileName()); | 478 | EXPECT_EQ(name1, result[2].getFileName()); |
1046 | 423 | 479 | ||
1047 | 424 | // Sorting by rank, reversed | 480 | // Sorting by rank, reversed |
1048 | 425 | filter.setReverse(true); | 481 | filter.setReverse(true); |
1049 | 426 | result = store.query("foo", AudioMedia, filter); | 482 | result = store.query("foo", AudioMedia, filter); |
1050 | 427 | ASSERT_EQ(3, result.size()); | 483 | ASSERT_EQ(3, result.size()); |
1054 | 428 | EXPECT_EQ("/path/foo1.ogg", result[0].getFileName()); | 484 | EXPECT_EQ(name1, result[0].getFileName()); |
1055 | 429 | EXPECT_EQ("/path/foo2.ogg", result[1].getFileName()); | 485 | EXPECT_EQ(name2, result[1].getFileName()); |
1056 | 430 | EXPECT_EQ("/path/foo3.ogg", result[2].getFileName()); | 486 | EXPECT_EQ(name3, result[2].getFileName()); |
1057 | 431 | 487 | ||
1058 | 432 | // Sorting by title | 488 | // Sorting by title |
1059 | 433 | filter.setReverse(false); | 489 | filter.setReverse(false); |
1060 | 434 | filter.setOrder(MediaOrder::Title); | 490 | filter.setOrder(MediaOrder::Title); |
1061 | 435 | result = store.query("foo", AudioMedia, filter); | 491 | result = store.query("foo", AudioMedia, filter); |
1062 | 436 | ASSERT_EQ(3, result.size()); | 492 | ASSERT_EQ(3, result.size()); |
1066 | 437 | EXPECT_EQ("/path/foo1.ogg", result[0].getFileName()); | 493 | EXPECT_EQ(name1, result[0].getFileName()); |
1067 | 438 | EXPECT_EQ("/path/foo2.ogg", result[1].getFileName()); | 494 | EXPECT_EQ(name2, result[1].getFileName()); |
1068 | 439 | EXPECT_EQ("/path/foo3.ogg", result[2].getFileName()); | 495 | EXPECT_EQ(name3, result[2].getFileName()); |
1069 | 440 | 496 | ||
1070 | 441 | // Sorting by title, reversed | 497 | // Sorting by title, reversed |
1071 | 442 | filter.setReverse(true); | 498 | filter.setReverse(true); |
1072 | 443 | result = store.query("foo", AudioMedia, filter); | 499 | result = store.query("foo", AudioMedia, filter); |
1073 | 444 | ASSERT_EQ(3, result.size()); | 500 | ASSERT_EQ(3, result.size()); |
1077 | 445 | EXPECT_EQ("/path/foo3.ogg", result[0].getFileName()); | 501 | EXPECT_EQ(name3, result[0].getFileName()); |
1078 | 446 | EXPECT_EQ("/path/foo2.ogg", result[1].getFileName()); | 502 | EXPECT_EQ(name2, result[1].getFileName()); |
1079 | 447 | EXPECT_EQ("/path/foo1.ogg", result[2].getFileName()); | 503 | EXPECT_EQ(name1, result[2].getFileName()); |
1080 | 448 | 504 | ||
1081 | 449 | // Sorting by date | 505 | // Sorting by date |
1082 | 450 | filter.setReverse(false); | 506 | filter.setReverse(false); |
1083 | 451 | filter.setOrder(MediaOrder::Date); | 507 | filter.setOrder(MediaOrder::Date); |
1084 | 452 | result = store.query("foo", AudioMedia, filter); | 508 | result = store.query("foo", AudioMedia, filter); |
1085 | 453 | ASSERT_EQ(3, result.size()); | 509 | ASSERT_EQ(3, result.size()); |
1089 | 454 | EXPECT_EQ("/path/foo1.ogg", result[0].getFileName()); | 510 | EXPECT_EQ(name1, result[0].getFileName()); |
1090 | 455 | EXPECT_EQ("/path/foo3.ogg", result[1].getFileName()); | 511 | EXPECT_EQ(name3, result[1].getFileName()); |
1091 | 456 | EXPECT_EQ("/path/foo2.ogg", result[2].getFileName()); | 512 | EXPECT_EQ(name2, result[2].getFileName()); |
1092 | 457 | 513 | ||
1093 | 458 | // Sorting by date, reversed | 514 | // Sorting by date, reversed |
1094 | 459 | filter.setReverse(true); | 515 | filter.setReverse(true); |
1095 | 460 | result = store.query("foo", AudioMedia, filter); | 516 | result = store.query("foo", AudioMedia, filter); |
1096 | 461 | ASSERT_EQ(3, result.size()); | 517 | ASSERT_EQ(3, result.size()); |
1103 | 462 | EXPECT_EQ("/path/foo2.ogg", result[0].getFileName()); | 518 | EXPECT_EQ(name2, result[0].getFileName()); |
1104 | 463 | EXPECT_EQ("/path/foo3.ogg", result[1].getFileName()); | 519 | EXPECT_EQ(name3, result[1].getFileName()); |
1105 | 464 | EXPECT_EQ("/path/foo1.ogg", result[2].getFileName()); | 520 | EXPECT_EQ(name1, result[2].getFileName()); |
1106 | 465 | } | 521 | } |
1107 | 466 | 522 | ||
1108 | 467 | TEST_F(MediaStoreTest, unmount) { | 523 | TEST(MediaStoreTest, query_order) { |
1109 | 524 | MediaFile audio1 = MediaFileBuilder("/path/foo1.ogg") | ||
1110 | 525 | .setType(AudioMedia) | ||
1111 | 526 | .setTitle("foo") | ||
1112 | 527 | .setDate("2010-01-01") | ||
1113 | 528 | .setAuthor("artist") | ||
1114 | 529 | .setAlbum("album"); | ||
1115 | 530 | MediaFile audio2 = MediaFileBuilder("/path/foo2.ogg") | ||
1116 | 531 | .setType(AudioMedia) | ||
1117 | 532 | .setTitle("foo foo") | ||
1118 | 533 | .setDate("2010-01-03") | ||
1119 | 534 | .setAuthor("artist") | ||
1120 | 535 | .setAlbum("album"); | ||
1121 | 536 | MediaFile audio3 = MediaFileBuilder("/path/foo3.ogg") | ||
1122 | 537 | .setType(AudioMedia) | ||
1123 | 538 | .setTitle("foo foo foo") | ||
1124 | 539 | .setDate("2010-01-02") | ||
1125 | 540 | .setAuthor("artist") | ||
1126 | 541 | .setAlbum("album"); | ||
1127 | 542 | |||
1128 | 543 | MediaStore store(TEST_DIR "/mediastore.db", MS_READ_WRITE); | ||
1129 | 544 | store.insert(audio1); | ||
1130 | 545 | store.insert(audio2); | ||
1131 | 546 | store.insert(audio3); | ||
1132 | 547 | |||
1133 | 548 | check_query_order(store, "/path/foo1.ogg", "/path/foo2.ogg", "/path/foo3.ogg"); | ||
1134 | 549 | |||
1135 | 550 | MediaStore store_ro(TEST_DIR "/mediastore.db", MS_READ_ONLY); | ||
1136 | 551 | check_query_order(store_ro, "/path/foo1.ogg", "/path/foo2.ogg", "/path/foo3.ogg"); | ||
1137 | 552 | |||
1138 | 553 | store.remove(audio1.getFileName()); | ||
1139 | 554 | store.remove(audio2.getFileName()); | ||
1140 | 555 | store.remove(audio3.getFileName()); | ||
1141 | 556 | } | ||
1142 | 557 | |||
1143 | 558 | TEST(MediaStoreTest, unmount) { | ||
1144 | 468 | MediaFile audio1 = MediaFileBuilder("/media/username/dir/fname.ogg") | 559 | MediaFile audio1 = MediaFileBuilder("/media/username/dir/fname.ogg") |
1145 | 469 | .setType(AudioMedia) | 560 | .setType(AudioMedia) |
1146 | 470 | .setTitle("bbb bbb"); | 561 | .setTitle("bbb bbb"); |
1147 | @@ -488,7 +579,7 @@ | |||
1148 | 488 | ASSERT_EQ(result.size(), 2); | 579 | ASSERT_EQ(result.size(), 2); |
1149 | 489 | } | 580 | } |
1150 | 490 | 581 | ||
1152 | 491 | TEST_F(MediaStoreTest, utils) { | 582 | TEST(MediaStoreTest, utils) { |
1153 | 492 | string source("_a.b(c)[d]{e}f.mp3"); | 583 | string source("_a.b(c)[d]{e}f.mp3"); |
1154 | 493 | string correct = {" a b c d e f"}; | 584 | string correct = {" a b c d e f"}; |
1155 | 494 | string result = filenameToTitle(source); | 585 | string result = filenameToTitle(source); |
1156 | @@ -499,54 +590,7 @@ | |||
1157 | 499 | EXPECT_EQ(sqlQuote(unquoted), quoted); | 590 | EXPECT_EQ(sqlQuote(unquoted), quoted); |
1158 | 500 | } | 591 | } |
1159 | 501 | 592 | ||
1208 | 502 | TEST_F(MediaStoreTest, queryAlbums) { | 593 | void check_query_albums(MediaStore const &store) { |
1161 | 503 | MediaFile audio1 = MediaFileBuilder("/home/username/Music/track1.ogg") | ||
1162 | 504 | .setType(AudioMedia) | ||
1163 | 505 | .setTitle("TitleOne") | ||
1164 | 506 | .setAuthor("ArtistOne") | ||
1165 | 507 | .setAlbum("AlbumOne") | ||
1166 | 508 | .setAlbumArtist("Various Artists") | ||
1167 | 509 | .setDate("2000-01-01") | ||
1168 | 510 | .setDiscNumber(1) | ||
1169 | 511 | .setTrackNumber(1) | ||
1170 | 512 | .setGenre("GenreOne"); | ||
1171 | 513 | MediaFile audio2 = MediaFileBuilder("/home/username/Music/track2.ogg") | ||
1172 | 514 | .setType(AudioMedia) | ||
1173 | 515 | .setTitle("TitleTwo") | ||
1174 | 516 | .setAuthor("ArtistTwo") | ||
1175 | 517 | .setAlbum("AlbumOne") | ||
1176 | 518 | .setAlbumArtist("Various Artists") | ||
1177 | 519 | .setDate("2000-01-01") | ||
1178 | 520 | .setDiscNumber(1) | ||
1179 | 521 | .setTrackNumber(2) | ||
1180 | 522 | .setGenre("GenreOne"); | ||
1181 | 523 | MediaFile audio3 = MediaFileBuilder("/home/username/Music/track3.ogg") | ||
1182 | 524 | .setType(AudioMedia) | ||
1183 | 525 | .setTitle("TitleThree") | ||
1184 | 526 | .setAuthor("ArtistThree") | ||
1185 | 527 | .setAlbum("AlbumOne") | ||
1186 | 528 | .setAlbumArtist("Various Artists") | ||
1187 | 529 | .setDate("2000-01-01") | ||
1188 | 530 | .setDiscNumber(2) | ||
1189 | 531 | .setTrackNumber(1) | ||
1190 | 532 | .setGenre("GenreOne"); | ||
1191 | 533 | MediaFile audio4 = MediaFileBuilder("/home/username/Music/fname.ogg") | ||
1192 | 534 | .setType(AudioMedia) | ||
1193 | 535 | .setTitle("TitleFour") | ||
1194 | 536 | .setAuthor("ArtistFour") | ||
1195 | 537 | .setAlbum("AlbumTwo") | ||
1196 | 538 | .setAlbumArtist("ArtistFour") | ||
1197 | 539 | .setDate("2014-06-01") | ||
1198 | 540 | .setTrackNumber(1) | ||
1199 | 541 | .setGenre("GenreTwo") | ||
1200 | 542 | .setHasThumbnail(true); | ||
1201 | 543 | |||
1202 | 544 | MediaStore store(":memory:", MS_READ_WRITE); | ||
1203 | 545 | store.insert(audio1); | ||
1204 | 546 | store.insert(audio2); | ||
1205 | 547 | store.insert(audio3); | ||
1206 | 548 | store.insert(audio4); | ||
1207 | 549 | |||
1209 | 550 | // Query a track title | 594 | // Query a track title |
1210 | 551 | Filter filter; | 595 | Filter filter; |
1211 | 552 | vector<Album> albums = store.queryAlbums("TitleOne", filter); | 596 | vector<Album> albums = store.queryAlbums("TitleOne", filter); |
1212 | @@ -573,45 +617,66 @@ | |||
1213 | 573 | EXPECT_EQ(albums[0].getArtist(), "Various Artists"); | 617 | EXPECT_EQ(albums[0].getArtist(), "Various Artists"); |
1214 | 574 | } | 618 | } |
1215 | 575 | 619 | ||
1217 | 576 | TEST_F(MediaStoreTest, queryAlbums_limit) { | 620 | TEST(MediaStoreTest, queryAlbums) { |
1218 | 577 | MediaFile audio1 = MediaFileBuilder("/home/username/Music/track1.ogg") | 621 | MediaFile audio1 = MediaFileBuilder("/home/username/Music/track1.ogg") |
1219 | 578 | .setType(AudioMedia) | 622 | .setType(AudioMedia) |
1220 | 579 | .setTitle("TitleOne") | 623 | .setTitle("TitleOne") |
1221 | 580 | .setAuthor("ArtistOne") | 624 | .setAuthor("ArtistOne") |
1222 | 581 | .setAlbum("AlbumOne") | 625 | .setAlbum("AlbumOne") |
1223 | 582 | .setAlbumArtist("Various Artists") | 626 | .setAlbumArtist("Various Artists") |
1224 | 627 | .setDate("2000-01-01") | ||
1225 | 583 | .setDiscNumber(1) | 628 | .setDiscNumber(1) |
1227 | 584 | .setTrackNumber(1); | 629 | .setTrackNumber(1) |
1228 | 630 | .setGenre("GenreOne"); | ||
1229 | 585 | MediaFile audio2 = MediaFileBuilder("/home/username/Music/track2.ogg") | 631 | MediaFile audio2 = MediaFileBuilder("/home/username/Music/track2.ogg") |
1230 | 586 | .setType(AudioMedia) | 632 | .setType(AudioMedia) |
1231 | 587 | .setTitle("TitleTwo") | 633 | .setTitle("TitleTwo") |
1232 | 588 | .setAuthor("ArtistTwo") | 634 | .setAuthor("ArtistTwo") |
1233 | 589 | .setAlbum("AlbumOne") | 635 | .setAlbum("AlbumOne") |
1234 | 590 | .setAlbumArtist("Various Artists") | 636 | .setAlbumArtist("Various Artists") |
1235 | 637 | .setDate("2000-01-01") | ||
1236 | 591 | .setDiscNumber(1) | 638 | .setDiscNumber(1) |
1238 | 592 | .setTrackNumber(2); | 639 | .setTrackNumber(2) |
1239 | 640 | .setGenre("GenreOne"); | ||
1240 | 593 | MediaFile audio3 = MediaFileBuilder("/home/username/Music/track3.ogg") | 641 | MediaFile audio3 = MediaFileBuilder("/home/username/Music/track3.ogg") |
1241 | 594 | .setType(AudioMedia) | 642 | .setType(AudioMedia) |
1242 | 595 | .setTitle("TitleThree") | 643 | .setTitle("TitleThree") |
1243 | 596 | .setAuthor("ArtistThree") | 644 | .setAuthor("ArtistThree") |
1244 | 597 | .setAlbum("AlbumOne") | 645 | .setAlbum("AlbumOne") |
1245 | 598 | .setAlbumArtist("Various Artists") | 646 | .setAlbumArtist("Various Artists") |
1246 | 647 | .setDate("2000-01-01") | ||
1247 | 599 | .setDiscNumber(2) | 648 | .setDiscNumber(2) |
1249 | 600 | .setTrackNumber(1); | 649 | .setTrackNumber(1) |
1250 | 650 | .setGenre("GenreOne"); | ||
1251 | 601 | MediaFile audio4 = MediaFileBuilder("/home/username/Music/fname.ogg") | 651 | MediaFile audio4 = MediaFileBuilder("/home/username/Music/fname.ogg") |
1252 | 602 | .setType(AudioMedia) | 652 | .setType(AudioMedia) |
1253 | 603 | .setTitle("TitleFour") | 653 | .setTitle("TitleFour") |
1254 | 604 | .setAuthor("ArtistFour") | 654 | .setAuthor("ArtistFour") |
1255 | 605 | .setAlbum("AlbumTwo") | 655 | .setAlbum("AlbumTwo") |
1256 | 606 | .setAlbumArtist("ArtistFour") | 656 | .setAlbumArtist("ArtistFour") |
1258 | 607 | .setTrackNumber(1); | 657 | .setDate("2014-06-01") |
1259 | 658 | .setTrackNumber(1) | ||
1260 | 659 | .setGenre("GenreTwo") | ||
1261 | 660 | .setHasThumbnail(true); | ||
1262 | 608 | 661 | ||
1264 | 609 | MediaStore store(":memory:", MS_READ_WRITE); | 662 | MediaStore store(TEST_DIR "/mediastore.db", MS_READ_WRITE); |
1265 | 610 | store.insert(audio1); | 663 | store.insert(audio1); |
1266 | 611 | store.insert(audio2); | 664 | store.insert(audio2); |
1267 | 612 | store.insert(audio3); | 665 | store.insert(audio3); |
1268 | 613 | store.insert(audio4); | 666 | store.insert(audio4); |
1269 | 614 | 667 | ||
1270 | 668 | check_query_albums(store); | ||
1271 | 669 | |||
1272 | 670 | MediaStore store_ro(TEST_DIR "/mediastore.db", MS_READ_ONLY); | ||
1273 | 671 | check_query_albums(store_ro); | ||
1274 | 672 | |||
1275 | 673 | store.remove(audio1.getFileName()); | ||
1276 | 674 | store.remove(audio2.getFileName()); | ||
1277 | 675 | store.remove(audio3.getFileName()); | ||
1278 | 676 | store.remove(audio4.getFileName()); | ||
1279 | 677 | } | ||
1280 | 678 | |||
1281 | 679 | void check_query_albums_limit(MediaStore const &store) { | ||
1282 | 615 | Filter filter; | 680 | Filter filter; |
1283 | 616 | vector<Album> albums = store.queryAlbums("Artist", filter); | 681 | vector<Album> albums = store.queryAlbums("Artist", filter); |
1284 | 617 | EXPECT_EQ(2, albums.size()); | 682 | EXPECT_EQ(2, albums.size()); |
1285 | @@ -620,7 +685,7 @@ | |||
1286 | 620 | EXPECT_EQ(1, albums.size()); | 685 | EXPECT_EQ(1, albums.size()); |
1287 | 621 | } | 686 | } |
1288 | 622 | 687 | ||
1290 | 623 | TEST_F(MediaStoreTest, queryAlbums_empty) { | 688 | TEST(MediaStoreTest, queryAlbums_limit) { |
1291 | 624 | MediaFile audio1 = MediaFileBuilder("/home/username/Music/track1.ogg") | 689 | MediaFile audio1 = MediaFileBuilder("/home/username/Music/track1.ogg") |
1292 | 625 | .setType(AudioMedia) | 690 | .setType(AudioMedia) |
1293 | 626 | .setTitle("TitleOne") | 691 | .setTitle("TitleOne") |
1294 | @@ -653,12 +718,24 @@ | |||
1295 | 653 | .setAlbumArtist("ArtistFour") | 718 | .setAlbumArtist("ArtistFour") |
1296 | 654 | .setTrackNumber(1); | 719 | .setTrackNumber(1); |
1297 | 655 | 720 | ||
1299 | 656 | MediaStore store(":memory:", MS_READ_WRITE); | 721 | MediaStore store(TEST_DIR "/mediastore.db", MS_READ_WRITE); |
1300 | 657 | store.insert(audio1); | 722 | store.insert(audio1); |
1301 | 658 | store.insert(audio2); | 723 | store.insert(audio2); |
1302 | 659 | store.insert(audio3); | 724 | store.insert(audio3); |
1303 | 660 | store.insert(audio4); | 725 | store.insert(audio4); |
1304 | 661 | 726 | ||
1305 | 727 | check_query_albums_limit(store); | ||
1306 | 728 | |||
1307 | 729 | MediaStore store_ro(TEST_DIR "/mediastore.db", MS_READ_ONLY); | ||
1308 | 730 | check_query_albums_limit(store_ro); | ||
1309 | 731 | |||
1310 | 732 | store.remove(audio1.getFileName()); | ||
1311 | 733 | store.remove(audio2.getFileName()); | ||
1312 | 734 | store.remove(audio3.getFileName()); | ||
1313 | 735 | store.remove(audio4.getFileName()); | ||
1314 | 736 | } | ||
1315 | 737 | |||
1316 | 738 | void check_query_albums_empty(MediaStore const &store) { | ||
1317 | 662 | Filter filter; | 739 | Filter filter; |
1318 | 663 | vector<Album> albums = store.queryAlbums("", filter); | 740 | vector<Album> albums = store.queryAlbums("", filter); |
1319 | 664 | EXPECT_EQ(2, albums.size()); | 741 | EXPECT_EQ(2, albums.size()); |
1320 | @@ -667,7 +744,89 @@ | |||
1321 | 667 | EXPECT_EQ(1, albums.size()); | 744 | EXPECT_EQ(1, albums.size()); |
1322 | 668 | } | 745 | } |
1323 | 669 | 746 | ||
1325 | 670 | TEST_F(MediaStoreTest, queryAlbums_order) { | 747 | TEST(MediaStoreTest, queryAlbums_empty) { |
1326 | 748 | MediaFile audio1 = MediaFileBuilder("/home/username/Music/track1.ogg") | ||
1327 | 749 | .setType(AudioMedia) | ||
1328 | 750 | .setTitle("TitleOne") | ||
1329 | 751 | .setAuthor("ArtistOne") | ||
1330 | 752 | .setAlbum("AlbumOne") | ||
1331 | 753 | .setAlbumArtist("Various Artists") | ||
1332 | 754 | .setDiscNumber(1) | ||
1333 | 755 | .setTrackNumber(1); | ||
1334 | 756 | MediaFile audio2 = MediaFileBuilder("/home/username/Music/track2.ogg") | ||
1335 | 757 | .setType(AudioMedia) | ||
1336 | 758 | .setTitle("TitleTwo") | ||
1337 | 759 | .setAuthor("ArtistTwo") | ||
1338 | 760 | .setAlbum("AlbumOne") | ||
1339 | 761 | .setAlbumArtist("Various Artists") | ||
1340 | 762 | .setDiscNumber(1) | ||
1341 | 763 | .setTrackNumber(2); | ||
1342 | 764 | MediaFile audio3 = MediaFileBuilder("/home/username/Music/track3.ogg") | ||
1343 | 765 | .setType(AudioMedia) | ||
1344 | 766 | .setTitle("TitleThree") | ||
1345 | 767 | .setAuthor("ArtistThree") | ||
1346 | 768 | .setAlbum("AlbumOne") | ||
1347 | 769 | .setAlbumArtist("Various Artists") | ||
1348 | 770 | .setDiscNumber(2) | ||
1349 | 771 | .setTrackNumber(1); | ||
1350 | 772 | MediaFile audio4 = MediaFileBuilder("/home/username/Music/fname.ogg") | ||
1351 | 773 | .setType(AudioMedia) | ||
1352 | 774 | .setTitle("TitleFour") | ||
1353 | 775 | .setAuthor("ArtistFour") | ||
1354 | 776 | .setAlbum("AlbumTwo") | ||
1355 | 777 | .setAlbumArtist("ArtistFour") | ||
1356 | 778 | .setTrackNumber(1); | ||
1357 | 779 | |||
1358 | 780 | MediaStore store(TEST_DIR "/mediastore.db", MS_READ_WRITE); | ||
1359 | 781 | store.insert(audio1); | ||
1360 | 782 | store.insert(audio2); | ||
1361 | 783 | store.insert(audio3); | ||
1362 | 784 | store.insert(audio4); | ||
1363 | 785 | |||
1364 | 786 | check_query_albums_empty(store); | ||
1365 | 787 | |||
1366 | 788 | MediaStore store_ro(TEST_DIR "/mediastore.db", MS_READ_ONLY); | ||
1367 | 789 | check_query_albums_empty(store_ro); | ||
1368 | 790 | |||
1369 | 791 | store.remove(audio1.getFileName()); | ||
1370 | 792 | store.remove(audio2.getFileName()); | ||
1371 | 793 | store.remove(audio3.getFileName()); | ||
1372 | 794 | store.remove(audio4.getFileName()); | ||
1373 | 795 | } | ||
1374 | 796 | |||
1375 | 797 | void check_query_albums_order(MediaStore const &store) { | ||
1376 | 798 | // Default sort | ||
1377 | 799 | Filter filter; | ||
1378 | 800 | vector<Album> albums = store.queryAlbums("foo", filter); | ||
1379 | 801 | ASSERT_EQ(3, albums.size()); | ||
1380 | 802 | EXPECT_EQ("foo", albums[0].getTitle()); | ||
1381 | 803 | EXPECT_EQ("foo foo", albums[1].getTitle()); | ||
1382 | 804 | EXPECT_EQ("foo foo foo", albums[2].getTitle()); | ||
1383 | 805 | |||
1384 | 806 | // Sort by title (same as default) | ||
1385 | 807 | filter.setOrder(MediaOrder::Title); | ||
1386 | 808 | albums = store.queryAlbums("foo", filter); | ||
1387 | 809 | ASSERT_EQ(3, albums.size()); | ||
1388 | 810 | EXPECT_EQ("foo", albums[0].getTitle()); | ||
1389 | 811 | EXPECT_EQ("foo foo", albums[1].getTitle()); | ||
1390 | 812 | EXPECT_EQ("foo foo foo", albums[2].getTitle()); | ||
1391 | 813 | |||
1392 | 814 | // Sort by title, reversed | ||
1393 | 815 | filter.setReverse(true); | ||
1394 | 816 | albums = store.queryAlbums("foo", filter); | ||
1395 | 817 | ASSERT_EQ(3, albums.size()); | ||
1396 | 818 | EXPECT_EQ("foo foo foo", albums[0].getTitle()); | ||
1397 | 819 | EXPECT_EQ("foo foo", albums[1].getTitle()); | ||
1398 | 820 | EXPECT_EQ("foo", albums[2].getTitle()); | ||
1399 | 821 | |||
1400 | 822 | // Other orders are not supported | ||
1401 | 823 | filter.setOrder(MediaOrder::Rank); | ||
1402 | 824 | EXPECT_THROW(store.queryAlbums("foo", filter), std::runtime_error); | ||
1403 | 825 | filter.setOrder(MediaOrder::Date); | ||
1404 | 826 | EXPECT_THROW(store.queryAlbums("foo", filter), std::runtime_error); | ||
1405 | 827 | } | ||
1406 | 828 | |||
1407 | 829 | TEST(MediaStoreTest, queryAlbums_order) { | ||
1408 | 671 | MediaFile audio1 = MediaFileBuilder("/path/foo1.ogg") | 830 | MediaFile audio1 = MediaFileBuilder("/path/foo1.ogg") |
1409 | 672 | .setType(AudioMedia) | 831 | .setType(AudioMedia) |
1410 | 673 | .setTitle("title") | 832 | .setTitle("title") |
1411 | @@ -687,81 +846,22 @@ | |||
1412 | 687 | .setAuthor("artist") | 846 | .setAuthor("artist") |
1413 | 688 | .setAlbum("foo foo foo"); | 847 | .setAlbum("foo foo foo"); |
1414 | 689 | 848 | ||
1416 | 690 | MediaStore store(":memory:", MS_READ_WRITE); | 849 | MediaStore store(TEST_DIR "/mediastore.db", MS_READ_WRITE); |
1417 | 691 | store.insert(audio1); | 850 | store.insert(audio1); |
1418 | 692 | store.insert(audio2); | 851 | store.insert(audio2); |
1419 | 693 | store.insert(audio3); | 852 | store.insert(audio3); |
1420 | 694 | 853 | ||
1450 | 695 | // Default sort | 854 | check_query_albums_order(store); |
1451 | 696 | Filter filter; | 855 | |
1452 | 697 | vector<Album> albums = store.queryAlbums("foo", filter); | 856 | MediaStore store_ro(TEST_DIR "/mediastore.db", MS_READ_ONLY); |
1453 | 698 | ASSERT_EQ(3, albums.size()); | 857 | check_query_albums_order(store_ro); |
1454 | 699 | EXPECT_EQ("foo", albums[0].getTitle()); | 858 | |
1455 | 700 | EXPECT_EQ("foo foo", albums[1].getTitle()); | 859 | store.remove(audio1.getFileName()); |
1456 | 701 | EXPECT_EQ("foo foo foo", albums[2].getTitle()); | 860 | store.remove(audio2.getFileName()); |
1457 | 702 | 861 | store.remove(audio3.getFileName()); | |
1429 | 703 | // Sort by title (same as default) | ||
1430 | 704 | filter.setOrder(MediaOrder::Title); | ||
1431 | 705 | albums = store.queryAlbums("foo", filter); | ||
1432 | 706 | ASSERT_EQ(3, albums.size()); | ||
1433 | 707 | EXPECT_EQ("foo", albums[0].getTitle()); | ||
1434 | 708 | EXPECT_EQ("foo foo", albums[1].getTitle()); | ||
1435 | 709 | EXPECT_EQ("foo foo foo", albums[2].getTitle()); | ||
1436 | 710 | |||
1437 | 711 | // Sort by title, reversed | ||
1438 | 712 | filter.setReverse(true); | ||
1439 | 713 | albums = store.queryAlbums("foo", filter); | ||
1440 | 714 | ASSERT_EQ(3, albums.size()); | ||
1441 | 715 | EXPECT_EQ("foo foo foo", albums[0].getTitle()); | ||
1442 | 716 | EXPECT_EQ("foo foo", albums[1].getTitle()); | ||
1443 | 717 | EXPECT_EQ("foo", albums[2].getTitle()); | ||
1444 | 718 | |||
1445 | 719 | // Other orders are not supported | ||
1446 | 720 | filter.setOrder(MediaOrder::Rank); | ||
1447 | 721 | EXPECT_THROW(store.queryAlbums("foo", filter), std::runtime_error); | ||
1448 | 722 | filter.setOrder(MediaOrder::Date); | ||
1449 | 723 | EXPECT_THROW(store.queryAlbums("foo", filter), std::runtime_error); | ||
1458 | 724 | } | 862 | } |
1459 | 725 | 863 | ||
1499 | 726 | TEST_F(MediaStoreTest, queryArtists) { | 864 | void check_query_artists(MediaStore const &store) { |
1461 | 727 | MediaFile audio1 = MediaFileBuilder("/home/username/Music/track1.ogg") | ||
1462 | 728 | .setType(AudioMedia) | ||
1463 | 729 | .setTitle("TitleOne") | ||
1464 | 730 | .setAuthor("ArtistOne") | ||
1465 | 731 | .setAlbum("AlbumOne") | ||
1466 | 732 | .setAlbumArtist("Various Artists") | ||
1467 | 733 | .setDiscNumber(1) | ||
1468 | 734 | .setTrackNumber(1); | ||
1469 | 735 | MediaFile audio2 = MediaFileBuilder("/home/username/Music/track2.ogg") | ||
1470 | 736 | .setType(AudioMedia) | ||
1471 | 737 | .setTitle("TitleTwo") | ||
1472 | 738 | .setAuthor("ArtistTwo") | ||
1473 | 739 | .setAlbum("AlbumOne") | ||
1474 | 740 | .setAlbumArtist("Various Artists") | ||
1475 | 741 | .setDiscNumber(1) | ||
1476 | 742 | .setTrackNumber(2); | ||
1477 | 743 | MediaFile audio3 = MediaFileBuilder("/home/username/Music/track3.ogg") | ||
1478 | 744 | .setType(AudioMedia) | ||
1479 | 745 | .setTitle("TitleThree") | ||
1480 | 746 | .setAuthor("ArtistThree") | ||
1481 | 747 | .setAlbum("AlbumOne") | ||
1482 | 748 | .setAlbumArtist("Various Artists") | ||
1483 | 749 | .setDiscNumber(2) | ||
1484 | 750 | .setTrackNumber(1); | ||
1485 | 751 | MediaFile audio4 = MediaFileBuilder("/home/username/Music/fname.ogg") | ||
1486 | 752 | .setType(AudioMedia) | ||
1487 | 753 | .setTitle("TitleFour") | ||
1488 | 754 | .setAuthor("ArtistFour") | ||
1489 | 755 | .setAlbum("AlbumTwo") | ||
1490 | 756 | .setAlbumArtist("ArtistFour") | ||
1491 | 757 | .setTrackNumber(1); | ||
1492 | 758 | |||
1493 | 759 | MediaStore store(":memory:", MS_READ_WRITE); | ||
1494 | 760 | store.insert(audio1); | ||
1495 | 761 | store.insert(audio2); | ||
1496 | 762 | store.insert(audio3); | ||
1497 | 763 | store.insert(audio4); | ||
1498 | 764 | |||
1500 | 765 | // Query a track title | 865 | // Query a track title |
1501 | 766 | Filter filter; | 866 | Filter filter; |
1502 | 767 | vector<string> artists = store.queryArtists("TitleOne", filter); | 867 | vector<string> artists = store.queryArtists("TitleOne", filter); |
1503 | @@ -779,7 +879,7 @@ | |||
1504 | 779 | EXPECT_EQ(artists[0], "ArtistTwo"); | 879 | EXPECT_EQ(artists[0], "ArtistTwo"); |
1505 | 780 | } | 880 | } |
1506 | 781 | 881 | ||
1508 | 782 | TEST_F(MediaStoreTest, queryArtists_limit) { | 882 | TEST(MediaStoreTest, queryArtists) { |
1509 | 783 | MediaFile audio1 = MediaFileBuilder("/home/username/Music/track1.ogg") | 883 | MediaFile audio1 = MediaFileBuilder("/home/username/Music/track1.ogg") |
1510 | 784 | .setType(AudioMedia) | 884 | .setType(AudioMedia) |
1511 | 785 | .setTitle("TitleOne") | 885 | .setTitle("TitleOne") |
1512 | @@ -796,11 +896,40 @@ | |||
1513 | 796 | .setAlbumArtist("Various Artists") | 896 | .setAlbumArtist("Various Artists") |
1514 | 797 | .setDiscNumber(1) | 897 | .setDiscNumber(1) |
1515 | 798 | .setTrackNumber(2); | 898 | .setTrackNumber(2); |
1516 | 899 | MediaFile audio3 = MediaFileBuilder("/home/username/Music/track3.ogg") | ||
1517 | 900 | .setType(AudioMedia) | ||
1518 | 901 | .setTitle("TitleThree") | ||
1519 | 902 | .setAuthor("ArtistThree") | ||
1520 | 903 | .setAlbum("AlbumOne") | ||
1521 | 904 | .setAlbumArtist("Various Artists") | ||
1522 | 905 | .setDiscNumber(2) | ||
1523 | 906 | .setTrackNumber(1); | ||
1524 | 907 | MediaFile audio4 = MediaFileBuilder("/home/username/Music/fname.ogg") | ||
1525 | 908 | .setType(AudioMedia) | ||
1526 | 909 | .setTitle("TitleFour") | ||
1527 | 910 | .setAuthor("ArtistFour") | ||
1528 | 911 | .setAlbum("AlbumTwo") | ||
1529 | 912 | .setAlbumArtist("ArtistFour") | ||
1530 | 913 | .setTrackNumber(1); | ||
1531 | 799 | 914 | ||
1533 | 800 | MediaStore store(":memory:", MS_READ_WRITE); | 915 | MediaStore store(TEST_DIR "/mediastore.db", MS_READ_WRITE); |
1534 | 801 | store.insert(audio1); | 916 | store.insert(audio1); |
1535 | 802 | store.insert(audio2); | 917 | store.insert(audio2); |
1537 | 803 | 918 | store.insert(audio3); | |
1538 | 919 | store.insert(audio4); | ||
1539 | 920 | |||
1540 | 921 | check_query_artists(store); | ||
1541 | 922 | |||
1542 | 923 | MediaStore store_ro(TEST_DIR "/mediastore.db", MS_READ_ONLY); | ||
1543 | 924 | check_query_artists(store_ro); | ||
1544 | 925 | |||
1545 | 926 | store.remove(audio1.getFileName()); | ||
1546 | 927 | store.remove(audio2.getFileName()); | ||
1547 | 928 | store.remove(audio3.getFileName()); | ||
1548 | 929 | store.remove(audio4.getFileName()); | ||
1549 | 930 | } | ||
1550 | 931 | |||
1551 | 932 | void check_query_artists_limit(MediaStore const &store) { | ||
1552 | 804 | Filter filter; | 933 | Filter filter; |
1553 | 805 | vector<string> artists = store.queryArtists("Artist", filter); | 934 | vector<string> artists = store.queryArtists("Artist", filter); |
1554 | 806 | EXPECT_EQ(2, artists.size()); | 935 | EXPECT_EQ(2, artists.size()); |
1555 | @@ -809,7 +938,7 @@ | |||
1556 | 809 | EXPECT_EQ(1, artists.size()); | 938 | EXPECT_EQ(1, artists.size()); |
1557 | 810 | } | 939 | } |
1558 | 811 | 940 | ||
1560 | 812 | TEST_F(MediaStoreTest, queryArtists_empty) { | 941 | TEST(MediaStoreTest, queryArtists_limit) { |
1561 | 813 | MediaFile audio1 = MediaFileBuilder("/home/username/Music/track1.ogg") | 942 | MediaFile audio1 = MediaFileBuilder("/home/username/Music/track1.ogg") |
1562 | 814 | .setType(AudioMedia) | 943 | .setType(AudioMedia) |
1563 | 815 | .setTitle("TitleOne") | 944 | .setTitle("TitleOne") |
1564 | @@ -827,10 +956,20 @@ | |||
1565 | 827 | .setDiscNumber(1) | 956 | .setDiscNumber(1) |
1566 | 828 | .setTrackNumber(2); | 957 | .setTrackNumber(2); |
1567 | 829 | 958 | ||
1569 | 830 | MediaStore store(":memory:", MS_READ_WRITE); | 959 | MediaStore store(TEST_DIR "/mediastore.db", MS_READ_WRITE); |
1570 | 831 | store.insert(audio1); | 960 | store.insert(audio1); |
1571 | 832 | store.insert(audio2); | 961 | store.insert(audio2); |
1572 | 833 | 962 | ||
1573 | 963 | check_query_artists_limit(store); | ||
1574 | 964 | |||
1575 | 965 | MediaStore store_ro(TEST_DIR "/mediastore.db", MS_READ_ONLY); | ||
1576 | 966 | check_query_artists_limit(store_ro); | ||
1577 | 967 | |||
1578 | 968 | store.remove(audio1.getFileName()); | ||
1579 | 969 | store.remove(audio2.getFileName()); | ||
1580 | 970 | } | ||
1581 | 971 | |||
1582 | 972 | void check_query_artists_empty(MediaStore const &store) { | ||
1583 | 834 | Filter filter; | 973 | Filter filter; |
1584 | 835 | vector<string> artists = store.queryArtists("", filter); | 974 | vector<string> artists = store.queryArtists("", filter); |
1585 | 836 | EXPECT_EQ(2, artists.size()); | 975 | EXPECT_EQ(2, artists.size()); |
1586 | @@ -839,7 +978,70 @@ | |||
1587 | 839 | EXPECT_EQ(1, artists.size()); | 978 | EXPECT_EQ(1, artists.size()); |
1588 | 840 | } | 979 | } |
1589 | 841 | 980 | ||
1591 | 842 | TEST_F(MediaStoreTest, queryArtists_order) { | 981 | TEST(MediaStoreTest, queryArtists_empty) { |
1592 | 982 | MediaFile audio1 = MediaFileBuilder("/home/username/Music/track1.ogg") | ||
1593 | 983 | .setType(AudioMedia) | ||
1594 | 984 | .setTitle("TitleOne") | ||
1595 | 985 | .setAuthor("ArtistOne") | ||
1596 | 986 | .setAlbum("AlbumOne") | ||
1597 | 987 | .setAlbumArtist("Various Artists") | ||
1598 | 988 | .setDiscNumber(1) | ||
1599 | 989 | .setTrackNumber(1); | ||
1600 | 990 | MediaFile audio2 = MediaFileBuilder("/home/username/Music/track2.ogg") | ||
1601 | 991 | .setType(AudioMedia) | ||
1602 | 992 | .setTitle("TitleTwo") | ||
1603 | 993 | .setAuthor("ArtistTwo") | ||
1604 | 994 | .setAlbum("AlbumOne") | ||
1605 | 995 | .setAlbumArtist("Various Artists") | ||
1606 | 996 | .setDiscNumber(1) | ||
1607 | 997 | .setTrackNumber(2); | ||
1608 | 998 | |||
1609 | 999 | MediaStore store(TEST_DIR "/mediastore.db", MS_READ_WRITE); | ||
1610 | 1000 | store.insert(audio1); | ||
1611 | 1001 | store.insert(audio2); | ||
1612 | 1002 | |||
1613 | 1003 | check_query_artists_empty(store); | ||
1614 | 1004 | |||
1615 | 1005 | MediaStore store_ro(TEST_DIR "/mediastore.db", MS_READ_ONLY); | ||
1616 | 1006 | check_query_artists_empty(store_ro); | ||
1617 | 1007 | |||
1618 | 1008 | store.remove(audio1.getFileName()); | ||
1619 | 1009 | store.remove(audio2.getFileName()); | ||
1620 | 1010 | } | ||
1621 | 1011 | |||
1622 | 1012 | void check_query_artists_order(MediaStore const &store) { | ||
1623 | 1013 | // Default sort | ||
1624 | 1014 | Filter filter; | ||
1625 | 1015 | vector<std::string> artists = store.queryArtists("foo", filter); | ||
1626 | 1016 | ASSERT_EQ(3, artists.size()); | ||
1627 | 1017 | EXPECT_EQ("foo", artists[0]); | ||
1628 | 1018 | EXPECT_EQ("foo foo", artists[1]); | ||
1629 | 1019 | EXPECT_EQ("foo foo foo", artists[2]); | ||
1630 | 1020 | |||
1631 | 1021 | // Sort by title (same as default) | ||
1632 | 1022 | filter.setOrder(MediaOrder::Title); | ||
1633 | 1023 | artists = store.queryArtists("foo", filter); | ||
1634 | 1024 | ASSERT_EQ(3, artists.size()); | ||
1635 | 1025 | EXPECT_EQ("foo", artists[0]); | ||
1636 | 1026 | EXPECT_EQ("foo foo", artists[1]); | ||
1637 | 1027 | EXPECT_EQ("foo foo foo", artists[2]); | ||
1638 | 1028 | |||
1639 | 1029 | // Sort by title, reversed | ||
1640 | 1030 | filter.setReverse(true); | ||
1641 | 1031 | artists = store.queryArtists("foo", filter); | ||
1642 | 1032 | ASSERT_EQ(3, artists.size()); | ||
1643 | 1033 | EXPECT_EQ("foo foo foo", artists[0]); | ||
1644 | 1034 | EXPECT_EQ("foo foo", artists[1]); | ||
1645 | 1035 | EXPECT_EQ("foo", artists[2]); | ||
1646 | 1036 | |||
1647 | 1037 | // Other orders are not supported | ||
1648 | 1038 | filter.setOrder(MediaOrder::Rank); | ||
1649 | 1039 | EXPECT_THROW(store.queryArtists("foo", filter), std::runtime_error); | ||
1650 | 1040 | filter.setOrder(MediaOrder::Date); | ||
1651 | 1041 | EXPECT_THROW(store.queryArtists("foo", filter), std::runtime_error); | ||
1652 | 1042 | } | ||
1653 | 1043 | |||
1654 | 1044 | TEST(MediaStoreTest, queryArtists_order) { | ||
1655 | 843 | MediaFile audio1 = MediaFileBuilder("/path/foo1.ogg") | 1045 | MediaFile audio1 = MediaFileBuilder("/path/foo1.ogg") |
1656 | 844 | .setType(AudioMedia) | 1046 | .setType(AudioMedia) |
1657 | 845 | .setTitle("title") | 1047 | .setTitle("title") |
1658 | @@ -859,73 +1061,22 @@ | |||
1659 | 859 | .setAuthor("foo foo foo") | 1061 | .setAuthor("foo foo foo") |
1660 | 860 | .setAlbum("album"); | 1062 | .setAlbum("album"); |
1661 | 861 | 1063 | ||
1663 | 862 | MediaStore store(":memory:", MS_READ_WRITE); | 1064 | MediaStore store(TEST_DIR "/mediastore.db", MS_READ_WRITE); |
1664 | 863 | store.insert(audio1); | 1065 | store.insert(audio1); |
1665 | 864 | store.insert(audio2); | 1066 | store.insert(audio2); |
1666 | 865 | store.insert(audio3); | 1067 | store.insert(audio3); |
1667 | 866 | 1068 | ||
1697 | 867 | // Default sort | 1069 | check_query_artists_order(store); |
1698 | 868 | Filter filter; | 1070 | |
1699 | 869 | vector<std::string> artists = store.queryArtists("foo", filter); | 1071 | MediaStore store_ro(TEST_DIR "/mediastore.db", MS_READ_ONLY); |
1700 | 870 | ASSERT_EQ(3, artists.size()); | 1072 | check_query_artists_order(store_ro); |
1701 | 871 | EXPECT_EQ("foo", artists[0]); | 1073 | |
1702 | 872 | EXPECT_EQ("foo foo", artists[1]); | 1074 | store.remove(audio1.getFileName()); |
1703 | 873 | EXPECT_EQ("foo foo foo", artists[2]); | 1075 | store.remove(audio2.getFileName()); |
1704 | 874 | 1076 | store.remove(audio3.getFileName()); | |
1676 | 875 | // Sort by title (same as default) | ||
1677 | 876 | filter.setOrder(MediaOrder::Title); | ||
1678 | 877 | artists = store.queryArtists("foo", filter); | ||
1679 | 878 | ASSERT_EQ(3, artists.size()); | ||
1680 | 879 | EXPECT_EQ("foo", artists[0]); | ||
1681 | 880 | EXPECT_EQ("foo foo", artists[1]); | ||
1682 | 881 | EXPECT_EQ("foo foo foo", artists[2]); | ||
1683 | 882 | |||
1684 | 883 | // Sort by title, reversed | ||
1685 | 884 | filter.setReverse(true); | ||
1686 | 885 | artists = store.queryArtists("foo", filter); | ||
1687 | 886 | ASSERT_EQ(3, artists.size()); | ||
1688 | 887 | EXPECT_EQ("foo foo foo", artists[0]); | ||
1689 | 888 | EXPECT_EQ("foo foo", artists[1]); | ||
1690 | 889 | EXPECT_EQ("foo", artists[2]); | ||
1691 | 890 | |||
1692 | 891 | // Other orders are not supported | ||
1693 | 892 | filter.setOrder(MediaOrder::Rank); | ||
1694 | 893 | EXPECT_THROW(store.queryArtists("foo", filter), std::runtime_error); | ||
1695 | 894 | filter.setOrder(MediaOrder::Date); | ||
1696 | 895 | EXPECT_THROW(store.queryArtists("foo", filter), std::runtime_error); | ||
1705 | 896 | } | 1077 | } |
1706 | 897 | 1078 | ||
1738 | 898 | TEST_F(MediaStoreTest, getAlbumSongs) { | 1079 | void check_album_songs(MediaStore const &store) { |
1708 | 899 | MediaFile audio1 = MediaFileBuilder("/home/username/Music/track1.ogg") | ||
1709 | 900 | .setType(AudioMedia) | ||
1710 | 901 | .setTitle("TitleOne") | ||
1711 | 902 | .setAuthor("ArtistOne") | ||
1712 | 903 | .setAlbum("AlbumOne") | ||
1713 | 904 | .setAlbumArtist("Various Artists") | ||
1714 | 905 | .setDiscNumber(1) | ||
1715 | 906 | .setTrackNumber(1); | ||
1716 | 907 | MediaFile audio2 = MediaFileBuilder("/home/username/Music/track2.ogg") | ||
1717 | 908 | .setType(AudioMedia) | ||
1718 | 909 | .setTitle("TitleTwo") | ||
1719 | 910 | .setAuthor("ArtistTwo") | ||
1720 | 911 | .setAlbum("AlbumOne") | ||
1721 | 912 | .setAlbumArtist("Various Artists") | ||
1722 | 913 | .setDiscNumber(1) | ||
1723 | 914 | .setTrackNumber(2); | ||
1724 | 915 | MediaFile audio3 = MediaFileBuilder("/home/username/Music/track3.ogg") | ||
1725 | 916 | .setType(AudioMedia) | ||
1726 | 917 | .setTitle("TitleThree") | ||
1727 | 918 | .setAuthor("ArtistThree") | ||
1728 | 919 | .setAlbum("AlbumOne") | ||
1729 | 920 | .setAlbumArtist("Various Artists") | ||
1730 | 921 | .setDiscNumber(2) | ||
1731 | 922 | .setTrackNumber(1); | ||
1732 | 923 | |||
1733 | 924 | MediaStore store(":memory:", MS_READ_WRITE); | ||
1734 | 925 | store.insert(audio1); | ||
1735 | 926 | store.insert(audio2); | ||
1736 | 927 | store.insert(audio3); | ||
1737 | 928 | |||
1739 | 929 | vector<MediaFile> tracks = store.getAlbumSongs( | 1080 | vector<MediaFile> tracks = store.getAlbumSongs( |
1740 | 930 | Album("AlbumOne", "Various Artists")); | 1081 | Album("AlbumOne", "Various Artists")); |
1741 | 931 | ASSERT_EQ(tracks.size(), 3); | 1082 | ASSERT_EQ(tracks.size(), 3); |
1742 | @@ -934,20 +1085,69 @@ | |||
1743 | 934 | EXPECT_EQ(tracks[2].getTitle(), "TitleThree"); | 1085 | EXPECT_EQ(tracks[2].getTitle(), "TitleThree"); |
1744 | 935 | } | 1086 | } |
1745 | 936 | 1087 | ||
1747 | 937 | TEST_F(MediaStoreTest, getETag) { | 1088 | TEST(MediaStoreTest, getAlbumSongs) { |
1748 | 1089 | MediaFile audio1 = MediaFileBuilder("/home/username/Music/track1.ogg") | ||
1749 | 1090 | .setType(AudioMedia) | ||
1750 | 1091 | .setTitle("TitleOne") | ||
1751 | 1092 | .setAuthor("ArtistOne") | ||
1752 | 1093 | .setAlbum("AlbumOne") | ||
1753 | 1094 | .setAlbumArtist("Various Artists") | ||
1754 | 1095 | .setDiscNumber(1) | ||
1755 | 1096 | .setTrackNumber(1); | ||
1756 | 1097 | MediaFile audio2 = MediaFileBuilder("/home/username/Music/track2.ogg") | ||
1757 | 1098 | .setType(AudioMedia) | ||
1758 | 1099 | .setTitle("TitleTwo") | ||
1759 | 1100 | .setAuthor("ArtistTwo") | ||
1760 | 1101 | .setAlbum("AlbumOne") | ||
1761 | 1102 | .setAlbumArtist("Various Artists") | ||
1762 | 1103 | .setDiscNumber(1) | ||
1763 | 1104 | .setTrackNumber(2); | ||
1764 | 1105 | MediaFile audio3 = MediaFileBuilder("/home/username/Music/track3.ogg") | ||
1765 | 1106 | .setType(AudioMedia) | ||
1766 | 1107 | .setTitle("TitleThree") | ||
1767 | 1108 | .setAuthor("ArtistThree") | ||
1768 | 1109 | .setAlbum("AlbumOne") | ||
1769 | 1110 | .setAlbumArtist("Various Artists") | ||
1770 | 1111 | .setDiscNumber(2) | ||
1771 | 1112 | .setTrackNumber(1); | ||
1772 | 1113 | |||
1773 | 1114 | MediaStore store(TEST_DIR "/mediastore.db", MS_READ_WRITE); | ||
1774 | 1115 | store.insert(audio1); | ||
1775 | 1116 | store.insert(audio2); | ||
1776 | 1117 | store.insert(audio3); | ||
1777 | 1118 | |||
1778 | 1119 | check_album_songs(store); | ||
1779 | 1120 | |||
1780 | 1121 | MediaStore store_ro(TEST_DIR "/mediastore.db", MS_READ_ONLY); | ||
1781 | 1122 | check_album_songs(store_ro); | ||
1782 | 1123 | |||
1783 | 1124 | store.remove(audio1.getFileName()); | ||
1784 | 1125 | store.remove(audio2.getFileName()); | ||
1785 | 1126 | store.remove(audio3.getFileName()); | ||
1786 | 1127 | } | ||
1787 | 1128 | |||
1788 | 1129 | void check_get_etag(MediaStore const &store) { | ||
1789 | 1130 | EXPECT_EQ(store.getETag("/path/file.ogg"), "etag"); | ||
1790 | 1131 | EXPECT_EQ(store.getETag("/something-else.mp3"), ""); | ||
1791 | 1132 | } | ||
1792 | 1133 | |||
1793 | 1134 | TEST(MediaStoreTest, getETag) { | ||
1794 | 938 | MediaFile file = MediaFileBuilder("/path/file.ogg") | 1135 | MediaFile file = MediaFileBuilder("/path/file.ogg") |
1795 | 939 | .setETag("etag") | 1136 | .setETag("etag") |
1796 | 940 | .setType(AudioMedia); | 1137 | .setType(AudioMedia); |
1797 | 941 | 1138 | ||
1799 | 942 | MediaStore store(":memory:", MS_READ_WRITE); | 1139 | MediaStore store(TEST_DIR "/mediastore.db", MS_READ_WRITE); |
1800 | 943 | store.insert(file); | 1140 | store.insert(file); |
1801 | 944 | 1141 | ||
1804 | 945 | EXPECT_EQ(store.getETag("/path/file.ogg"), "etag"); | 1142 | check_get_etag(store); |
1805 | 946 | EXPECT_EQ(store.getETag("/something-else.mp3"), ""); | 1143 | |
1806 | 1144 | MediaStore store_ro(TEST_DIR "/mediastore.db", MS_READ_ONLY); | ||
1807 | 1145 | check_get_etag(store_ro); | ||
1808 | 1146 | |||
1809 | 1147 | store.remove(file.getFileName()); | ||
1810 | 947 | } | 1148 | } |
1811 | 948 | 1149 | ||
1814 | 949 | 1150 | TEST(MediaStoreTest, constraints) { | |
1813 | 950 | TEST_F(MediaStoreTest, constraints) { | ||
1815 | 951 | MediaFile file = MediaFileBuilder("no_slash_at_beginning.ogg") | 1151 | MediaFile file = MediaFileBuilder("no_slash_at_beginning.ogg") |
1816 | 952 | .setETag("etag") | 1152 | .setETag("etag") |
1817 | 953 | .setType(AudioMedia); | 1153 | .setType(AudioMedia); |
1818 | @@ -959,52 +1159,7 @@ | |||
1819 | 959 | ASSERT_THROW(store.insert(file2), std::runtime_error); | 1159 | ASSERT_THROW(store.insert(file2), std::runtime_error); |
1820 | 960 | } | 1160 | } |
1821 | 961 | 1161 | ||
1868 | 962 | TEST_F(MediaStoreTest, listSongs) { | 1162 | void check_list_songs(MediaStore const &store) { |
1823 | 963 | MediaFile audio1 = MediaFileBuilder("/home/username/Music/track1.ogg") | ||
1824 | 964 | .setType(AudioMedia) | ||
1825 | 965 | .setTitle("TitleOne") | ||
1826 | 966 | .setAuthor("ArtistOne") | ||
1827 | 967 | .setAlbum("AlbumOne") | ||
1828 | 968 | .setTrackNumber(1); | ||
1829 | 969 | MediaFile audio2 = MediaFileBuilder("/home/username/Music/track2.ogg") | ||
1830 | 970 | .setType(AudioMedia) | ||
1831 | 971 | .setTitle("TitleTwo") | ||
1832 | 972 | .setAuthor("ArtistOne") | ||
1833 | 973 | .setAlbum("AlbumOne") | ||
1834 | 974 | .setTrackNumber(2); | ||
1835 | 975 | MediaFile audio3 = MediaFileBuilder("/home/username/Music/track3.ogg") | ||
1836 | 976 | .setType(AudioMedia) | ||
1837 | 977 | .setTitle("TitleThree") | ||
1838 | 978 | .setAuthor("ArtistOne") | ||
1839 | 979 | .setAlbum("AlbumTwo"); | ||
1840 | 980 | MediaFile audio4 = MediaFileBuilder("/home/username/Music/track4.ogg") | ||
1841 | 981 | .setType(AudioMedia) | ||
1842 | 982 | .setTitle("TitleFour") | ||
1843 | 983 | .setAuthor("ArtistTwo") | ||
1844 | 984 | .setAlbum("AlbumThree"); | ||
1845 | 985 | MediaFile audio5 = MediaFileBuilder("/home/username/Music/track5.ogg") | ||
1846 | 986 | .setType(AudioMedia) | ||
1847 | 987 | .setTitle("TitleFive") | ||
1848 | 988 | .setAuthor("ArtistOne") | ||
1849 | 989 | .setAlbum("AlbumFour") | ||
1850 | 990 | .setAlbumArtist("Various Artists") | ||
1851 | 991 | .setTrackNumber(1); | ||
1852 | 992 | MediaFile audio6 = MediaFileBuilder("/home/username/Music/track6.ogg") | ||
1853 | 993 | .setType(AudioMedia) | ||
1854 | 994 | .setTitle("TitleSix") | ||
1855 | 995 | .setAuthor("ArtistTwo") | ||
1856 | 996 | .setAlbum("AlbumFour") | ||
1857 | 997 | .setAlbumArtist("Various Artists") | ||
1858 | 998 | .setTrackNumber(2); | ||
1859 | 999 | |||
1860 | 1000 | MediaStore store(":memory:", MS_READ_WRITE); | ||
1861 | 1001 | store.insert(audio1); | ||
1862 | 1002 | store.insert(audio2); | ||
1863 | 1003 | store.insert(audio3); | ||
1864 | 1004 | store.insert(audio4); | ||
1865 | 1005 | store.insert(audio5); | ||
1866 | 1006 | store.insert(audio6); | ||
1867 | 1007 | |||
1869 | 1008 | Filter filter; | 1163 | Filter filter; |
1870 | 1009 | vector<MediaFile> tracks = store.listSongs(filter); | 1164 | vector<MediaFile> tracks = store.listSongs(filter); |
1871 | 1010 | ASSERT_EQ(6, tracks.size()); | 1165 | ASSERT_EQ(6, tracks.size()); |
1872 | @@ -1060,31 +1215,37 @@ | |||
1873 | 1060 | EXPECT_EQ(3, tracks.size()); | 1215 | EXPECT_EQ(3, tracks.size()); |
1874 | 1061 | } | 1216 | } |
1875 | 1062 | 1217 | ||
1877 | 1063 | TEST_F(MediaStoreTest, listAlbums) { | 1218 | TEST(MediaStoreTest, listSongs) { |
1878 | 1064 | MediaFile audio1 = MediaFileBuilder("/home/username/Music/track1.ogg") | 1219 | MediaFile audio1 = MediaFileBuilder("/home/username/Music/track1.ogg") |
1879 | 1065 | .setType(AudioMedia) | 1220 | .setType(AudioMedia) |
1880 | 1066 | .setTitle("TitleOne") | 1221 | .setTitle("TitleOne") |
1881 | 1067 | .setAuthor("ArtistOne") | 1222 | .setAuthor("ArtistOne") |
1882 | 1068 | .setAlbum("AlbumOne") | 1223 | .setAlbum("AlbumOne") |
1883 | 1069 | .setTrackNumber(1); | 1224 | .setTrackNumber(1); |
1885 | 1070 | MediaFile audio2 = MediaFileBuilder("/home/username/Music/track3.ogg") | 1225 | MediaFile audio2 = MediaFileBuilder("/home/username/Music/track2.ogg") |
1886 | 1226 | .setType(AudioMedia) | ||
1887 | 1227 | .setTitle("TitleTwo") | ||
1888 | 1228 | .setAuthor("ArtistOne") | ||
1889 | 1229 | .setAlbum("AlbumOne") | ||
1890 | 1230 | .setTrackNumber(2); | ||
1891 | 1231 | MediaFile audio3 = MediaFileBuilder("/home/username/Music/track3.ogg") | ||
1892 | 1071 | .setType(AudioMedia) | 1232 | .setType(AudioMedia) |
1893 | 1072 | .setTitle("TitleThree") | 1233 | .setTitle("TitleThree") |
1894 | 1073 | .setAuthor("ArtistOne") | 1234 | .setAuthor("ArtistOne") |
1895 | 1074 | .setAlbum("AlbumTwo"); | 1235 | .setAlbum("AlbumTwo"); |
1897 | 1075 | MediaFile audio3 = MediaFileBuilder("/home/username/Music/track4.ogg") | 1236 | MediaFile audio4 = MediaFileBuilder("/home/username/Music/track4.ogg") |
1898 | 1076 | .setType(AudioMedia) | 1237 | .setType(AudioMedia) |
1899 | 1077 | .setTitle("TitleFour") | 1238 | .setTitle("TitleFour") |
1900 | 1078 | .setAuthor("ArtistTwo") | 1239 | .setAuthor("ArtistTwo") |
1901 | 1079 | .setAlbum("AlbumThree"); | 1240 | .setAlbum("AlbumThree"); |
1903 | 1080 | MediaFile audio4 = MediaFileBuilder("/home/username/Music/track5.ogg") | 1241 | MediaFile audio5 = MediaFileBuilder("/home/username/Music/track5.ogg") |
1904 | 1081 | .setType(AudioMedia) | 1242 | .setType(AudioMedia) |
1905 | 1082 | .setTitle("TitleFive") | 1243 | .setTitle("TitleFive") |
1906 | 1083 | .setAuthor("ArtistOne") | 1244 | .setAuthor("ArtistOne") |
1907 | 1084 | .setAlbum("AlbumFour") | 1245 | .setAlbum("AlbumFour") |
1908 | 1085 | .setAlbumArtist("Various Artists") | 1246 | .setAlbumArtist("Various Artists") |
1909 | 1086 | .setTrackNumber(1); | 1247 | .setTrackNumber(1); |
1911 | 1087 | MediaFile audio5 = MediaFileBuilder("/home/username/Music/track6.ogg") | 1248 | MediaFile audio6 = MediaFileBuilder("/home/username/Music/track6.ogg") |
1912 | 1088 | .setType(AudioMedia) | 1249 | .setType(AudioMedia) |
1913 | 1089 | .setTitle("TitleSix") | 1250 | .setTitle("TitleSix") |
1914 | 1090 | .setAuthor("ArtistTwo") | 1251 | .setAuthor("ArtistTwo") |
1915 | @@ -1092,44 +1253,59 @@ | |||
1916 | 1092 | .setAlbumArtist("Various Artists") | 1253 | .setAlbumArtist("Various Artists") |
1917 | 1093 | .setTrackNumber(2); | 1254 | .setTrackNumber(2); |
1918 | 1094 | 1255 | ||
1920 | 1095 | MediaStore store(":memory:", MS_READ_WRITE); | 1256 | MediaStore store(TEST_DIR "/mediastore.db", MS_READ_WRITE); |
1921 | 1096 | store.insert(audio1); | 1257 | store.insert(audio1); |
1922 | 1097 | store.insert(audio2); | 1258 | store.insert(audio2); |
1923 | 1098 | store.insert(audio3); | 1259 | store.insert(audio3); |
1924 | 1099 | store.insert(audio4); | 1260 | store.insert(audio4); |
1925 | 1100 | store.insert(audio5); | 1261 | store.insert(audio5); |
1927 | 1101 | 1262 | store.insert(audio6); | |
1928 | 1263 | |||
1929 | 1264 | check_list_songs(store); | ||
1930 | 1265 | |||
1931 | 1266 | MediaStore store_ro(TEST_DIR "/mediastore.db", MS_READ_ONLY); | ||
1932 | 1267 | check_list_songs(store_ro); | ||
1933 | 1268 | |||
1934 | 1269 | store.remove(audio1.getFileName()); | ||
1935 | 1270 | store.remove(audio2.getFileName()); | ||
1936 | 1271 | store.remove(audio3.getFileName()); | ||
1937 | 1272 | store.remove(audio4.getFileName()); | ||
1938 | 1273 | store.remove(audio5.getFileName()); | ||
1939 | 1274 | store.remove(audio6.getFileName()); | ||
1940 | 1275 | } | ||
1941 | 1276 | |||
1942 | 1277 | void check_list_albums(MediaStore const &store) { | ||
1943 | 1102 | Filter filter; | 1278 | Filter filter; |
1971 | 1103 | vector<Album> albums = store.listAlbums(filter); | 1279 | vector<Album> albums = store.listAlbums(filter); |
1972 | 1104 | ASSERT_EQ(4, albums.size()); | 1280 | ASSERT_EQ(4, albums.size()); |
1973 | 1105 | EXPECT_EQ("AlbumOne", albums[0].getTitle()); | 1281 | EXPECT_EQ("AlbumOne", albums[0].getTitle()); |
1974 | 1106 | 1282 | ||
1975 | 1107 | // test limit | 1283 | // test limit |
1976 | 1108 | filter.setLimit(2); | 1284 | filter.setLimit(2); |
1977 | 1109 | albums = store.listAlbums(filter); | 1285 | albums = store.listAlbums(filter); |
1978 | 1110 | EXPECT_EQ(2, albums.size()); | 1286 | EXPECT_EQ(2, albums.size()); |
1979 | 1111 | filter.setLimit(-1); | 1287 | filter.setLimit(-1); |
1980 | 1112 | 1288 | ||
1981 | 1113 | // Songs by artist | 1289 | // Songs by artist |
1982 | 1114 | filter.setArtist("ArtistOne"); | 1290 | filter.setArtist("ArtistOne"); |
1983 | 1115 | albums = store.listAlbums(filter); | 1291 | albums = store.listAlbums(filter); |
1984 | 1116 | EXPECT_EQ(3, albums.size()); | 1292 | EXPECT_EQ(3, albums.size()); |
1985 | 1117 | 1293 | ||
1986 | 1118 | // Songs by album artist | 1294 | // Songs by album artist |
1987 | 1119 | filter.clear(); | 1295 | filter.clear(); |
1988 | 1120 | filter.setAlbumArtist("ArtistOne"); | 1296 | filter.setAlbumArtist("ArtistOne"); |
1989 | 1121 | albums = store.listAlbums(filter); | 1297 | albums = store.listAlbums(filter); |
1990 | 1122 | EXPECT_EQ(2, albums.size()); | 1298 | EXPECT_EQ(2, albums.size()); |
1991 | 1123 | 1299 | ||
1992 | 1124 | // Combination | 1300 | // Combination |
1993 | 1125 | filter.clear(); | 1301 | filter.clear(); |
1994 | 1126 | filter.setArtist("ArtistOne"); | 1302 | filter.setArtist("ArtistOne"); |
1995 | 1127 | filter.setAlbumArtist("Various Artists"); | 1303 | filter.setAlbumArtist("Various Artists"); |
1996 | 1128 | albums = store.listAlbums(filter); | 1304 | albums = store.listAlbums(filter); |
1997 | 1129 | EXPECT_EQ(1, albums.size()); | 1305 | EXPECT_EQ(1, albums.size()); |
1998 | 1130 | } | 1306 | } |
1999 | 1131 | 1307 | ||
2001 | 1132 | TEST_F(MediaStoreTest, listArtists) { | 1308 | TEST(MediaStoreTest, listAlbums) { |
2002 | 1133 | MediaFile audio1 = MediaFileBuilder("/home/username/Music/track1.ogg") | 1309 | MediaFile audio1 = MediaFileBuilder("/home/username/Music/track1.ogg") |
2003 | 1134 | .setType(AudioMedia) | 1310 | .setType(AudioMedia) |
2004 | 1135 | .setTitle("TitleOne") | 1311 | .setTitle("TitleOne") |
2005 | @@ -1161,13 +1337,26 @@ | |||
2006 | 1161 | .setAlbumArtist("Various Artists") | 1337 | .setAlbumArtist("Various Artists") |
2007 | 1162 | .setTrackNumber(2); | 1338 | .setTrackNumber(2); |
2008 | 1163 | 1339 | ||
2010 | 1164 | MediaStore store(":memory:", MS_READ_WRITE); | 1340 | MediaStore store(TEST_DIR "/mediastore.db", MS_READ_WRITE); |
2011 | 1165 | store.insert(audio1); | 1341 | store.insert(audio1); |
2012 | 1166 | store.insert(audio2); | 1342 | store.insert(audio2); |
2013 | 1167 | store.insert(audio3); | 1343 | store.insert(audio3); |
2014 | 1168 | store.insert(audio4); | 1344 | store.insert(audio4); |
2015 | 1169 | store.insert(audio5); | 1345 | store.insert(audio5); |
2016 | 1170 | 1346 | ||
2017 | 1347 | check_list_albums(store); | ||
2018 | 1348 | |||
2019 | 1349 | MediaStore store_ro(TEST_DIR "/mediastore.db", MS_READ_ONLY); | ||
2020 | 1350 | check_list_albums(store_ro); | ||
2021 | 1351 | |||
2022 | 1352 | store.remove(audio1.getFileName()); | ||
2023 | 1353 | store.remove(audio2.getFileName()); | ||
2024 | 1354 | store.remove(audio3.getFileName()); | ||
2025 | 1355 | store.remove(audio4.getFileName()); | ||
2026 | 1356 | store.remove(audio5.getFileName()); | ||
2027 | 1357 | } | ||
2028 | 1358 | |||
2029 | 1359 | void check_list_artists(MediaStore const &store) { | ||
2030 | 1171 | Filter filter; | 1360 | Filter filter; |
2031 | 1172 | vector<string> artists = store.listArtists(filter); | 1361 | vector<string> artists = store.listArtists(filter); |
2032 | 1173 | ASSERT_EQ(2, artists.size()); | 1362 | ASSERT_EQ(2, artists.size()); |
2033 | @@ -1188,7 +1377,58 @@ | |||
2034 | 1188 | EXPECT_EQ("Various Artists", artists[2]); | 1377 | EXPECT_EQ("Various Artists", artists[2]); |
2035 | 1189 | } | 1378 | } |
2036 | 1190 | 1379 | ||
2038 | 1191 | TEST_F(MediaStoreTest, brokenFiles) { | 1380 | TEST(MediaStoreTest, listArtists) { |
2039 | 1381 | MediaFile audio1 = MediaFileBuilder("/home/username/Music/track1.ogg") | ||
2040 | 1382 | .setType(AudioMedia) | ||
2041 | 1383 | .setTitle("TitleOne") | ||
2042 | 1384 | .setAuthor("ArtistOne") | ||
2043 | 1385 | .setAlbum("AlbumOne") | ||
2044 | 1386 | .setTrackNumber(1); | ||
2045 | 1387 | MediaFile audio2 = MediaFileBuilder("/home/username/Music/track3.ogg") | ||
2046 | 1388 | .setType(AudioMedia) | ||
2047 | 1389 | .setTitle("TitleThree") | ||
2048 | 1390 | .setAuthor("ArtistOne") | ||
2049 | 1391 | .setAlbum("AlbumTwo"); | ||
2050 | 1392 | MediaFile audio3 = MediaFileBuilder("/home/username/Music/track4.ogg") | ||
2051 | 1393 | .setType(AudioMedia) | ||
2052 | 1394 | .setTitle("TitleFour") | ||
2053 | 1395 | .setAuthor("ArtistTwo") | ||
2054 | 1396 | .setAlbum("AlbumThree"); | ||
2055 | 1397 | MediaFile audio4 = MediaFileBuilder("/home/username/Music/track5.ogg") | ||
2056 | 1398 | .setType(AudioMedia) | ||
2057 | 1399 | .setTitle("TitleFive") | ||
2058 | 1400 | .setAuthor("ArtistOne") | ||
2059 | 1401 | .setAlbum("AlbumFour") | ||
2060 | 1402 | .setAlbumArtist("Various Artists") | ||
2061 | 1403 | .setTrackNumber(1); | ||
2062 | 1404 | MediaFile audio5 = MediaFileBuilder("/home/username/Music/track6.ogg") | ||
2063 | 1405 | .setType(AudioMedia) | ||
2064 | 1406 | .setTitle("TitleSix") | ||
2065 | 1407 | .setAuthor("ArtistTwo") | ||
2066 | 1408 | .setAlbum("AlbumFour") | ||
2067 | 1409 | .setAlbumArtist("Various Artists") | ||
2068 | 1410 | .setTrackNumber(2); | ||
2069 | 1411 | |||
2070 | 1412 | MediaStore store(TEST_DIR "/mediastore.db", MS_READ_WRITE); | ||
2071 | 1413 | store.insert(audio1); | ||
2072 | 1414 | store.insert(audio2); | ||
2073 | 1415 | store.insert(audio3); | ||
2074 | 1416 | store.insert(audio4); | ||
2075 | 1417 | store.insert(audio5); | ||
2076 | 1418 | |||
2077 | 1419 | check_list_artists(store); | ||
2078 | 1420 | |||
2079 | 1421 | MediaStore store_ro(TEST_DIR "/mediastore.db", MS_READ_ONLY); | ||
2080 | 1422 | check_list_artists(store_ro); | ||
2081 | 1423 | |||
2082 | 1424 | store.remove(audio1.getFileName()); | ||
2083 | 1425 | store.remove(audio2.getFileName()); | ||
2084 | 1426 | store.remove(audio3.getFileName()); | ||
2085 | 1427 | store.remove(audio4.getFileName()); | ||
2086 | 1428 | store.remove(audio5.getFileName()); | ||
2087 | 1429 | } | ||
2088 | 1430 | |||
2089 | 1431 | TEST(MediaStoreTest, brokenFiles) { | ||
2090 | 1192 | MediaStore store(":memory:", MS_READ_WRITE); | 1432 | MediaStore store(":memory:", MS_READ_WRITE); |
2091 | 1193 | std::string file = "/foo/bar/baz.mp3"; | 1433 | std::string file = "/foo/bar/baz.mp3"; |
2092 | 1194 | std::string other_file = "/foo/bar/abc.mp3"; | 1434 | std::string other_file = "/foo/bar/abc.mp3"; |
2093 | @@ -1214,6 +1454,12 @@ | |||
2094 | 1214 | } | 1454 | } |
2095 | 1215 | 1455 | ||
2096 | 1216 | int main(int argc, char **argv) { | 1456 | int main(int argc, char **argv) { |
2097 | 1457 | QCoreApplication app(argc, argv); | ||
2098 | 1458 | |||
2099 | 1459 | MediaScannerTestUtils::DBusTest test; | ||
2100 | 1460 | test.SetUp(); | ||
2101 | 1217 | ::testing::InitGoogleTest(&argc, argv); | 1461 | ::testing::InitGoogleTest(&argc, argv); |
2103 | 1218 | return RUN_ALL_TESTS(); | 1462 | auto ret_code=RUN_ALL_TESTS(); |
2104 | 1463 | std::cout << "WE'LL SEE NOW SOME ERRORS WHEN DESTROYING THE D-BUS INTERNALS. This is due bug: https://bugs.launchpad.net/dbus-cpp/+bug/1422304" << std::endl; | ||
2105 | 1464 | return ret_code; | ||
2106 | 1219 | } | 1465 | } |
2107 | 1220 | 1466 | ||
2108 | === added directory 'test/utils' | |||
2109 | === added file 'test/utils/DBusTest.cpp' | |||
2110 | --- test/utils/DBusTest.cpp 1970-01-01 00:00:00 +0000 | |||
2111 | +++ test/utils/DBusTest.cpp 2015-02-16 14:24:40 +0000 | |||
2112 | @@ -0,0 +1,50 @@ | |||
2113 | 1 | /* | ||
2114 | 2 | * Copyright (C) 2013 Canonical, Ltd. | ||
2115 | 3 | * | ||
2116 | 4 | * This program is free software; you can redistribute it and/or modify | ||
2117 | 5 | * it under the terms of the GNU General Public License as published by | ||
2118 | 6 | * the Free Software Foundation; version 3. | ||
2119 | 7 | * | ||
2120 | 8 | * This program is distributed in the hope that it will be useful, | ||
2121 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
2122 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
2123 | 11 | * GNU General Public License for more details. | ||
2124 | 12 | * | ||
2125 | 13 | * You should have received a copy of the GNU General Public License | ||
2126 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
2127 | 15 | * | ||
2128 | 16 | * Author: Pete Woods <pete.woods@canonical.com> | ||
2129 | 17 | */ | ||
2130 | 18 | |||
2131 | 19 | #include "DBusTest.h" | ||
2132 | 20 | #include "test_config.h" | ||
2133 | 21 | |||
2134 | 22 | #include <QtTest/QSignalSpy> | ||
2135 | 23 | #include <libqtdbustest/QProcessDBusService.h> | ||
2136 | 24 | #include <QtDBus/QtDBus> | ||
2137 | 25 | |||
2138 | 26 | using namespace MediaScannerTestUtils; | ||
2139 | 27 | using namespace QtDBusTest; | ||
2140 | 28 | |||
2141 | 29 | DBusTest::DBusTest() { | ||
2142 | 30 | qputenv("MEDIASCANNER_CACHEDIR", TEST_DIR); | ||
2143 | 31 | DBusServicePtr dBusService( | ||
2144 | 32 | new QProcessDBusService("com.canonical.MediaScanner2", | ||
2145 | 33 | QDBusConnection::SessionBus, MS_DBUS_BINARY, | ||
2146 | 34 | QStringList())); | ||
2147 | 35 | dbus.registerService(dBusService); | ||
2148 | 36 | } | ||
2149 | 37 | |||
2150 | 38 | DBusTest::~DBusTest() { | ||
2151 | 39 | } | ||
2152 | 40 | |||
2153 | 41 | void DBusTest::SetUp() { | ||
2154 | 42 | dbus.startServices(); | ||
2155 | 43 | } | ||
2156 | 44 | |||
2157 | 45 | void DBusTest::TearDown() { | ||
2158 | 46 | } | ||
2159 | 47 | |||
2160 | 48 | const QDBusConnection & DBusTest::systemConnection() const { | ||
2161 | 49 | return dbus.systemConnection(); | ||
2162 | 50 | } | ||
2163 | 0 | 51 | ||
2164 | === added file 'test/utils/DBusTest.h' | |||
2165 | --- test/utils/DBusTest.h 1970-01-01 00:00:00 +0000 | |||
2166 | +++ test/utils/DBusTest.h 2015-02-16 14:24:40 +0000 | |||
2167 | @@ -0,0 +1,47 @@ | |||
2168 | 1 | /* | ||
2169 | 2 | * Copyright (C) 2013 Canonical, Ltd. | ||
2170 | 3 | * | ||
2171 | 4 | * This program is free software; you can redistribute it and/or modify | ||
2172 | 5 | * it under the terms of the GNU General Public License as published by | ||
2173 | 6 | * the Free Software Foundation; version 3. | ||
2174 | 7 | * | ||
2175 | 8 | * This program is distributed in the hope that it will be useful, | ||
2176 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
2177 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
2178 | 11 | * GNU General Public License for more details. | ||
2179 | 12 | * | ||
2180 | 13 | * You should have received a copy of the GNU General Public License | ||
2181 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
2182 | 15 | * | ||
2183 | 16 | * Author: Pete Woods <pete.woods@canonical.com> | ||
2184 | 17 | */ | ||
2185 | 18 | |||
2186 | 19 | #include <QtCore/QCoreApplication> | ||
2187 | 20 | #include <QtCore/QProcess> | ||
2188 | 21 | |||
2189 | 22 | #include <QtDBus/QtDBus> | ||
2190 | 23 | |||
2191 | 24 | #include <libqtdbustest/DBusTestRunner.h> | ||
2192 | 25 | |||
2193 | 26 | #ifndef USERMETRICS_TESTUTILS_TESTCOMMON_H_ | ||
2194 | 27 | #define USERMETRICS_TESTUTILS_TESTCOMMON_H_ | ||
2195 | 28 | |||
2196 | 29 | namespace MediaScannerTestUtils { | ||
2197 | 30 | |||
2198 | 31 | class DBusTest { | ||
2199 | 32 | public: | ||
2200 | 33 | DBusTest(); | ||
2201 | 34 | |||
2202 | 35 | virtual ~DBusTest(); | ||
2203 | 36 | |||
2204 | 37 | virtual void SetUp(); | ||
2205 | 38 | |||
2206 | 39 | virtual void TearDown(); | ||
2207 | 40 | |||
2208 | 41 | QtDBusTest::DBusTestRunner dbus; | ||
2209 | 42 | |||
2210 | 43 | virtual const QDBusConnection & systemConnection() const; | ||
2211 | 44 | }; | ||
2212 | 45 | |||
2213 | 46 | } | ||
2214 | 47 | #endif // USERMETRICS_TESTUTILS_TESTCOMMON_H_ |
Looking quite nice. However one thing that is a bit concerning is that the tests duplicate a lot of code in the dbus and non-dbus cases. Would it be possible to consolidate these so that every test is run with common code. So something along the lines of this:
void testImplementat ion(MediaStore &writer, MediaStore &queryer) { insert( whatevs) ;
// First set up
writer.
// Then query EQ(queryer. query(" ..."), result);
ASSERT_
}
And then have the actual dbus and non-dbus test cases just do basically this:
void testWithoutDbus() {
MediaStore local(READWRITE);
testImplement ation(local, local);
}
void testWithDbus() {
MediaStore writer(READWRITE);
MediaStore queryer(READONLY);
testImplement ation(writer, queryer);
}