Merge lp:~xavi-garcia-mena/mediascanner2/ms-dbus-wal into lp:mediascanner2

Proposed by Xavi Garcia
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
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.

To post a comment you must log in.
Revision history for this message
Jussi Pakkanen (jpakkane) wrote :

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 testImplementation(MediaStore &writer, MediaStore &queryer) {
  // First set up
  writer.insert(whatevs);

  // Then query
  ASSERT_EQ(queryer.query("..."), result);
}

And then have the actual dbus and non-dbus test cases just do basically this:

void testWithoutDbus() {
  MediaStore local(READWRITE);

  testImplementation(local, local);
}

void testWithDbus() {
  MediaStore writer(READWRITE);
  MediaStore queryer(READONLY);

  testImplementation(writer, queryer);
}

review: Needs Fixing
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

Revision history for this message
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).

review: Needs Fixing
303. By Xavi Garcia

Erased final _ for member variables

Revision history for this message
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://code.launchpad.net/~xavi-garcia-mena/mediascanner2/ms-dbus-wal/+merge/249346
> 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

Revision history for this message
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/mediascanner-2.0. This MR changes it so that they no longer may access the file directly, instead they call a small dbus server binary instead.

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?

Revision history for this message
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://code.launchpad.net/~xavi-garcia-mena/mediascanner2/ms-dbus-wal/+merge/249346/+edit-commit-message

http://jenkins.qa.ubuntu.com/job/mediascanner2-ci/188/
Executed test runs:
    FAILURE: http://jenkins.qa.ubuntu.com/job/mediascanner2-vivid-amd64-ci/25/console
    FAILURE: http://jenkins.qa.ubuntu.com/job/mediascanner2-vivid-armhf-ci/25/console
    FAILURE: http://jenkins.qa.ubuntu.com/job/mediascanner2-vivid-i386-ci/25/console

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/mediascanner2-ci/188/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :
review: Needs Fixing (continuous-integration)

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

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

Subscribers

People subscribed via source and target branches

to all changes: