~ubuntu-branches/ubuntu/karmic/quodlibet/karmic

« back to all changes in this revision

Viewing changes to tests/test_formats__audio.py

  • Committer: Bazaar Package Importer
  • Author(s): Luca Falavigna
  • Date: 2009-01-30 23:55:34 UTC
  • mfrom: (1.1.12 upstream)
  • Revision ID: james.westby@ubuntu.com-20090130235534-l4e72ulw0vqfo17w
Tags: 2.0-1ubuntu1
* Merge from Debian experimental (LP: #276856), remaining Ubuntu changes:
  + debian/patches/40-use-music-profile.patch:
    - Use the "Music and Movies" pipeline per default.
* Refresh the above patch for new upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
from tests import TestCase, add
 
2
 
 
3
import os
 
4
 
 
5
from quodlibet import config
 
6
 
 
7
from quodlibet.formats._audio import AudioFile
 
8
 
 
9
bar_1_1 = AudioFile({
 
10
    "title": "A song",
 
11
    "discnumber": "1/2", "tracknumber": "1/3",
 
12
    "artist": "Foo", "album": "Bar" })
 
13
bar_1_2 = AudioFile({
 
14
    "title": "Perhaps another",
 
15
    "discnumber": "1", "tracknumber": "2/3",
 
16
    "artist": "Lali-ho!", "album": "Bar",
 
17
    "date": "2004-12-12"})
 
18
bar_2_1 = AudioFile({
 
19
    "~filename": "does not/exist",
 
20
    "title": "more songs",
 
21
    "discnumber": "2/2", "tracknumber": "1",
 
22
    "artist": "Foo\nI have two artists", "album": "Bar",
 
23
    "lyricist": "Foo", "composer": "Foo", "performer": "I have two artists"})
 
24
 
 
25
quux = AudioFile({
 
26
    "~filename": "tests/data/asong.ogg",
 
27
    "album": "Quuxly"
 
28
    })
 
29
 
 
30
class TAudioFile(TestCase):
 
31
    def setUp(self):
 
32
        file(quux["~filename"], "w")
 
33
 
 
34
    def test_sort(self):
 
35
        l = [quux, bar_1_2, bar_2_1, bar_1_1]
 
36
        l.sort()
 
37
        self.assertEqual(l, [bar_1_1, bar_1_2, bar_2_1, quux])
 
38
        self.assertEqual(quux, quux)
 
39
        self.assertEqual(bar_1_1, bar_1_1)
 
40
        self.assertNotEqual(bar_2_1, bar_1_2)
 
41
        
 
42
    def test_realkeys(self):
 
43
        self.failIf("artist" in quux.realkeys())
 
44
        self.failIf("~filename" in quux.realkeys())
 
45
        self.failUnless("album" in quux.realkeys())
 
46
 
 
47
    def test_trackdisc(self):
 
48
        self.failUnlessEqual(bar_1_1("~#track"), 1)
 
49
        self.failUnlessEqual(bar_1_1("~#disc"), 1)
 
50
        self.failUnlessEqual(bar_1_1("~#tracks"), 3)
 
51
        self.failUnlessEqual(bar_1_1("~#discs"), 2)
 
52
        self.failIf(bar_1_2("~#discs"))
 
53
        self.failIf(bar_2_1("~#tracks"))
 
54
 
 
55
    def test_call(self):
 
56
        # real keys should lookup the same
 
57
        for key in bar_1_1.realkeys():
 
58
            self.failUnlessEqual(bar_1_1[key], bar_1_1(key))
 
59
 
 
60
        # fake/generated key checks
 
61
        self.failIf(quux("not a key"))
 
62
        self.failUnlessEqual(quux("not a key", "foo"), "foo")
 
63
        self.failUnlessEqual(quux("artist"), "")
 
64
        self.failUnlessEqual(quux("~basename"), "asong.ogg")
 
65
        self.failUnlessEqual(quux("~dirname"), "tests/data")
 
66
        self.failUnlessEqual(quux("title"), "asong.ogg [Unknown]")
 
67
        
 
68
        self.failUnlessEqual(bar_1_1("~#disc"), 1)
 
69
        self.failUnlessEqual(bar_1_2("~#disc"), 1)
 
70
        self.failUnlessEqual(bar_2_1("~#disc"), 2)
 
71
        self.failUnlessEqual(bar_1_1("~#track"), 1)
 
72
        self.failUnlessEqual(bar_1_2("~#track"), 2)
 
73
        self.failUnlessEqual(bar_2_1("~#track"), 1)
 
74
 
 
75
    def test_year(self):
 
76
        self.failUnlessEqual(bar_1_2("~year"), "2004")
 
77
        self.failUnlessEqual(bar_1_2("~#year"), 2004)
 
78
        self.failUnlessEqual(bar_1_1("~#year", 1999), 1999)
 
79
 
 
80
    def test_call_people(self):
 
81
        self.failUnlessEqual(quux("~people"), "")
 
82
        self.failUnlessEqual(bar_1_1("~people"), "Foo")
 
83
        self.failUnlessEqual(bar_1_2("~people"), "Lali-ho!")
 
84
        self.failUnlessEqual(bar_2_1("~people"), "Foo\nI have two artists")
 
85
 
 
86
    def test_call_multiple(self):
 
87
        for song in [quux, bar_1_1, bar_2_1]:
 
88
            self.failUnlessEqual(song("~~people"), song("~people"))
 
89
            self.failUnlessEqual(song("~title~people"), song("title"))
 
90
            self.failUnlessEqual(song("~title~~people"), song("~title~artist"))
 
91
 
 
92
    def test_list(self):
 
93
        for key in bar_1_1.realkeys():
 
94
            self.failUnlessEqual(bar_1_1.list(key), [bar_1_1(key)])
 
95
 
 
96
        self.failUnlessEqual(quux.list("artist"), [])
 
97
        self.failUnlessEqual(quux.list("title"), [quux("title")])
 
98
        self.failUnlessEqual(quux.list("not a key"), [])
 
99
 
 
100
        self.failUnlessEqual(len(bar_2_1.list("artist")), 2)
 
101
        self.failUnlessEqual(bar_2_1.list("artist"),
 
102
                             bar_2_1["artist"].split("\n"))
 
103
 
 
104
    def test_comma(self):
 
105
        for key in bar_1_1.realkeys():
 
106
            self.failUnlessEqual(bar_1_1.comma(key), bar_1_1(key))
 
107
        self.failUnless(", " in bar_2_1.comma("artist"))
 
108
 
 
109
    def test_exist(self):
 
110
        self.failIf(bar_2_1.exists())
 
111
        self.failUnless(quux.exists())
 
112
 
 
113
    def test_valid(self):
 
114
        self.failIf(bar_2_1.valid())
 
115
 
 
116
        quux["~#mtime"] = 0
 
117
        self.failIf(quux.valid())
 
118
        quux["~#mtime"] = os.path.getmtime(quux["~filename"])
 
119
        self.failUnless(quux.valid())
 
120
        os.utime(quux["~filename"], (quux["~#mtime"], quux["~#mtime"] - 1))
 
121
        self.failIf(quux.valid())
 
122
        quux["~#mtime"] = os.path.getmtime(quux["~filename"])
 
123
        self.failUnless(quux.valid())
 
124
 
 
125
        os.utime(quux["~filename"], (quux["~#mtime"], quux["~#mtime"] - 1))
 
126
        quux.sanitize()
 
127
        self.failUnless(quux.valid())
 
128
 
 
129
    def test_can_change(self):
 
130
        self.failIf(quux.can_change("~foobar"))
 
131
        self.failIf(quux.can_change("=foobar"))
 
132
        self.failIf(quux.can_change("foo=bar"))
 
133
        self.failIf(quux.can_change(""))
 
134
 
 
135
        self.failUnless(quux.can_change("foo bar"))
 
136
        os.chmod(quux["~filename"], 0444)
 
137
        self.failIf(quux.can_change("foo bar"))
 
138
        os.chmod(quux["~filename"], 0644)
 
139
        self.failUnless(quux.can_change("foo bar"))
 
140
 
 
141
    def test_rename(self):
 
142
        old_fn = quux("~basename")
 
143
        new_fn = "anothersong.mp3"
 
144
        dir = os.getcwd() + "/tests/data/"
 
145
        self.failUnless(quux.exists())
 
146
        quux.rename(new_fn)
 
147
        self.failIf(os.path.exists(dir + old_fn))
 
148
        self.failUnless(quux.exists())
 
149
        quux.rename(old_fn)
 
150
        self.failIf(os.path.exists(dir + new_fn))
 
151
        self.failUnless(quux.exists())
 
152
 
 
153
        # move out of parent dir and back
 
154
        quux.rename("/tmp/more_test_data")
 
155
        self.failIf(os.path.exists(dir + old_fn))
 
156
        self.failUnless(quux.exists())
 
157
        quux.rename(dir + old_fn)
 
158
        self.failUnless(quux.exists())
 
159
 
 
160
    def test_rename_to_existing(self):
 
161
        quux.rename(quux("~basename"))
 
162
        self.failUnlessRaises(ValueError, quux.rename, "/dev/null")
 
163
        self.failUnlessRaises(ValueError, quux.rename, "silence-44-s.ogg")
 
164
 
 
165
    def test_website(self):
 
166
        song = AudioFile()
 
167
        song["comment"] = "www.foo"
 
168
        song["contact"] = "eh@foo.org"
 
169
        self.failUnlessEqual(song.website(), "www.foo")
 
170
        song["contact"] = "https://www.foo.org"
 
171
        self.failUnlessEqual(song.website(), "https://www.foo.org")
 
172
        song["website"] = "foo\nhttps://another.com"
 
173
        self.failUnlessEqual(song.website(), "foo")
 
174
 
 
175
        song = AudioFile({"artist": "Artist", "album": "Album"})
 
176
        for value in song.values(): self.failUnless(value in song.website())
 
177
        song["labelid"] = "QL-12345"
 
178
        self.failIf(song["artist"] in song.website())
 
179
        self.failUnless(song["labelid"] in song.website())
 
180
 
 
181
    def test_sanitize(self):
 
182
        q = AudioFile(quux)
 
183
        b = AudioFile(bar_1_1)
 
184
        q.sanitize()
 
185
        self.failUnlessRaises(ValueError, b.sanitize)
 
186
 
 
187
    def test_performers(self):
 
188
        q = AudioFile([("performer:vocals", "A"), ("performer:guitar", "B"),
 
189
                       ("performer", "C")])
 
190
        self.failUnless("A (vocals)" in q.list("~performers"))
 
191
        self.failUnless("B (guitar)" in q.list("~performers"))
 
192
        self.failUnless("C" in q.list("~performers"))
 
193
        self.failUnless("A (vocals)" in q.list("~people"))
 
194
        self.failUnless("B (guitar)" in q.list("~people"))
 
195
        self.failUnlessEqual(len(q.list("~performers")), 3)
 
196
 
 
197
    def test_to_dump(self):
 
198
        dump = bar_1_1.to_dump()
 
199
        self.failUnlessEqual(dump.count("\n"), len(bar_1_1) + 1)
 
200
        for key, value in bar_1_1.items():
 
201
            self.failUnless(key in dump)
 
202
            self.failUnless(value in dump)
 
203
 
 
204
    def test_to_dump_long(self):
 
205
        b = AudioFile(bar_1_1); b["~#length"] = 200000000000L
 
206
        dump = b.to_dump()
 
207
        self.failUnlessEqual(dump.count("\n"), len(b) + 1)
 
208
 
 
209
    def test_add(self):
 
210
        song = AudioFile()
 
211
        self.failIf("foo" in song)
 
212
        song.add("foo", "bar")
 
213
        self.failUnlessEqual(song["foo"], "bar")
 
214
        song.add("foo", "another")
 
215
        self.failUnlessEqual(song.list("foo"), ["bar", "another"])
 
216
 
 
217
    def test_remove(self):
 
218
        song = AudioFile()
 
219
        song.add("foo", "bar")
 
220
        song.add("foo", "another")
 
221
        song.add("foo", "one more")
 
222
        song.remove("foo", "another")
 
223
        self.failUnlessEqual(song.list("foo"), ["bar", "one more"])
 
224
        song.remove("foo", "bar")
 
225
        self.failUnlessEqual(song.list("foo"), ["one more"])
 
226
        song.remove("foo", "one more")
 
227
        self.failIf("foo" in song)
 
228
 
 
229
        song.add("foo", "bar")
 
230
        song.add("foo", "another")
 
231
        song.add("foo", "one more")
 
232
        song.remove("foo", "not in list")
 
233
        self.failIf("foo" in song)
 
234
        
 
235
    def test_change(self):
 
236
        song = AudioFile()
 
237
        song.add("foo", "bar")
 
238
        song.add("foo", "another")
 
239
        song.change("foo", "bar", "one more")
 
240
        self.failUnlessEqual(song.list("foo"), ["one more", "another"])
 
241
        song.change("foo", "does not exist", "finally")
 
242
        self.failUnlessEqual(song["foo"], "finally")
 
243
        song.change("foo", "finally", "we're done")
 
244
        self.failUnlessEqual(song["foo"], "we're done")
 
245
 
 
246
    def test_bookmarks_none(self):
 
247
        self.failUnlessEqual([], AudioFile().bookmarks)
 
248
 
 
249
    def test_bookmarks_simple(self):
 
250
        af = AudioFile({"~bookmark": "1:20 Mark 1"})
 
251
        self.failUnlessEqual([(80, "Mark 1")], af.bookmarks)
 
252
 
 
253
    def test_bookmarks_two(self):
 
254
        af = AudioFile({"~bookmark": "1:40 Mark 2\n1:20 Mark 1"})
 
255
        self.failUnlessEqual([(80, "Mark 1"), (100, "Mark 2")], af.bookmarks)
 
256
 
 
257
    def test_bookmark_invalid(self):
 
258
        af = AudioFile({"~bookmark": ("Not Valid\n1:40 Mark 2\n"
 
259
                                      "-20 Not Valid 2\n1:20 Mark 1")})
 
260
        self.failUnlessEqual(
 
261
            [(80, "Mark 1"), (100, "Mark 2"), (-1, "Not Valid"),
 
262
             (-1, "-20 Not Valid 2")], af.bookmarks)
 
263
 
 
264
    def test_set_bookmarks_none(self):
 
265
        af = AudioFile({"bookmark": "foo"})
 
266
        af.bookmarks = []
 
267
        self.failUnlessEqual([], AudioFile().bookmarks)
 
268
        self.failIf("~bookmark" in af)
 
269
 
 
270
    def test_set_bookmarks_simple(self):
 
271
        af = AudioFile()
 
272
        af.bookmarks = [(120, "A mark"), (140, "Mark twain")]
 
273
        self.failUnlessEqual(af["~bookmark"], "2:00 A mark\n2:20 Mark twain")
 
274
 
 
275
    def test_set_bookmarks_invalid_value(self):
 
276
        self.failUnlessRaises(
 
277
            ValueError, setattr, AudioFile(), 'bookmarks', "huh?")
 
278
    def test_set_bookmarks_invalid_time(self):
 
279
        self.failUnlessRaises(
 
280
            TypeError, setattr, AudioFile(), 'bookmarks', [("notint", "!")])
 
281
    def test_set_bookmarks_unrealistic_time(self):
 
282
        self.failUnlessRaises(
 
283
            ValueError, setattr, AudioFile(), 'bookmarks', [(-1, "!")])
 
284
 
 
285
    def test_album_key(self):
 
286
        self.failUnlessEqual(AudioFile().album_key, ("", ""))
 
287
 
 
288
        album = AudioFile(album="foo")
 
289
        self.failUnlessEqual(album.album_key, ("foo", ""))
 
290
 
 
291
        labelid = AudioFile(labelid="foo")
 
292
        self.failUnlessEqual(labelid.album_key, ("", "foo"))
 
293
 
 
294
        mbid = AudioFile(musicbrainz_albumid="foo")
 
295
        self.failUnlessEqual(mbid.album_key, ("", "foo"))
 
296
 
 
297
        title_id = AudioFile(album="foo", labelid="bar")
 
298
        self.failUnlessEqual(title_id.album_key, ("foo", "bar"))
 
299
 
 
300
        all = AudioFile(album="foo", labelid="bar", musicbrainz_albumid="quux")
 
301
        self.failUnlessEqual(all.album_key, ("foo", "bar"))
 
302
 
 
303
    def tearDown(self):
 
304
        os.unlink(quux["~filename"])
 
305
add(TAudioFile)
 
306
 
 
307
class Treplay_gain(TestCase):
 
308
    def setUp(self):
 
309
        self.song = AudioFile({"replaygain_album_gain": "-1.00 dB",
 
310
                               "replaygain_album_peak": "1.1",
 
311
                               "replaygain_track_gain": "+1.0 dB",
 
312
                               "replaygain_track_peak": "0.9"})
 
313
 
 
314
    def test_nogain(self):
 
315
        self.failUnlessEqual(self.song.replay_gain(["none", "track"]), 1)
 
316
 
 
317
    def test_trackgain(self):
 
318
        self.failUnless(self.song.replay_gain(["track"]) > 1)
 
319
 
 
320
    def test_albumgain(self):
 
321
        self.failUnless(self.song.replay_gain(["album"]) < 1)
 
322
 
 
323
    def test_invalid(self):
 
324
        self.song["replaygain_album_gain"] = "fdsodgbdf"
 
325
        self.failUnlessEqual(self.song.replay_gain(["album"]), 1)
 
326
 
 
327
    def test_track_fallback(self):
 
328
        radio_rg = self.song.replay_gain(["track"])
 
329
        del(self.song["replaygain_album_gain"])
 
330
        del(self.song["replaygain_album_peak"])
 
331
        # verify defaulting to track when album is present
 
332
        self.failUnlessAlmostEqual(
 
333
            self.song.replay_gain(["album", "track"]), radio_rg)
 
334
add(Treplay_gain)
 
335
 
 
336
# Special test case for find_cover since it has to create/remove
 
337
# various files.
 
338
class Tfind_cover(TestCase):
 
339
    def setUp(self):
 
340
        self.dir = os.path.realpath(quux("~dirname"))
 
341
        self.files = [os.path.join(self.dir, "12345.jpg"),
 
342
                      os.path.join(self.dir, "nothing.jpg")
 
343
                      ]
 
344
        for f in self.files: file(f, "w").close()
 
345
 
 
346
    def test_dir_not_exist(self):
 
347
        self.failIf(bar_2_1.find_cover())
 
348
 
 
349
    def test_nothing(self):
 
350
        self.failIf(quux.find_cover())
 
351
 
 
352
    def test_labelid(self):
 
353
        quux["labelid"] = "12345"
 
354
        self.failUnlessEqual(os.path.abspath(quux.find_cover().name),
 
355
                             os.path.join(self.dir, "12345.jpg"))
 
356
        del(quux["labelid"])
 
357
 
 
358
    def test_regular(self):
 
359
        files = [os.path.join(self.dir, f) for f in
 
360
                 ["cover.png", "frontcover.jpg", "frontfoldercover.gif",
 
361
                  "jacketcoverfrontfolder.jpeg"]]
 
362
        for f in files:
 
363
            file(f, "w").close()
 
364
            self.files.append(f)
 
365
            self.failUnlessEqual(os.path.abspath(quux.find_cover().name), f)
 
366
        self.test_labelid() # labelid must work with other files present        
 
367
 
 
368
    def tearDown(self):
 
369
        map(os.unlink, self.files)
 
370
add(Tfind_cover)