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

Proposed by Xavi Garcia on 2015-02-11
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 on 2016-07-21
PS Jenkins bot (community) continuous-integration Needs Fixing on 2015-03-06
Jussi Pakkanen (community) 2015-02-11 Needs Fixing on 2015-02-16
Jamie Strandboge 2015-02-18 Pending
James Henstridge 2015-02-11 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.
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 on 2015-02-12

Modifed media store tests to avoid duplicating code

301. By Xavi Garcia on 2015-02-13

Removed Unity-api dependency, as it was not needed

302. By Xavi Garcia on 2015-02-16

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).

review: Needs Fixing
303. By Xavi Garcia on 2015-02-16

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://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 on 2015-02-16

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/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?

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)

Unmerged revisions

304. By Xavi Garcia on 2015-02-16

Added bug link in error message and remove unnecessary try...catch in unit test

303. By Xavi Garcia on 2015-02-16

Erased final _ for member variables

302. By Xavi Garcia on 2015-02-16

Added libqtdbustest to test the d-bus connection

301. By Xavi Garcia on 2015-02-13

Removed Unity-api dependency, as it was not needed

300. By Xavi Garcia on 2015-02-12

Modifed media store tests to avoid duplicating code

299. By Xavi Garcia on 2015-02-11

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: