85a952885926b7ea9e2e32bc46dbebd24cfc95c3
[joel/kofoto.git] / src / test / shelftests.py
1 #! /usr/bin/env python
2
3 import gc
4 import os
5 import shutil
6 import sys
7 import threading
8 import unittest
9 import Image as PILImage
10
11 if __name__ == "__main__":
12     cwd = os.getcwd()
13     libdir = unicode(os.path.realpath(
14         os.path.join(os.path.dirname(sys.argv[0]), "..", "lib")))
15     os.chdir(libdir)
16     sys.path.insert(0, libdir)
17 from kofoto.shelf import *
18
19 PICDIR = unicode(os.path.realpath(
20     os.path.join("..", "reference_pictures", "working")))
21
22 ######################################################################
23
24 db = "shelf.tmp"
25 codeset = "latin1"
26
27 def removeTmpDb():
28     for x in [db, db + "-journal"]:
29         if os.path.exists(x):
30             os.unlink(x)
31
32 class LockerThread(threading.Thread):
33     def __init__(self, mContinue, ltContinue):
34         threading.Thread.__init__(self)
35         self.mContinue = mContinue
36         self.ltContinue = ltContinue
37
38     def run(self):
39         s = Shelf(db, codeset)
40         s.create()
41         s.begin()
42         self.mContinue.set()
43         self.ltContinue.wait()
44         s.rollback()
45
46 ######################################################################
47
48 class TestPublicShelfFunctions(unittest.TestCase):
49     def test_computeImageHash(self):
50         s = computeImageHash(os.path.join(PICDIR, "arlaharen.png"))
51         assert s == "39a1266d2689f53d48b09a5e0ca0af1f"
52         try:
53             computeImageHash("nonexisting")
54         except IOError:
55             pass
56         else:
57             assert False, s
58
59     def test_verifyValidAlbumTag(self):
60         # Valid tags.
61         for x in ("foo", "1foo", "and", "exactly", "not", "or"):
62             try:
63                 verifyValidAlbumTag(x)
64             except:
65                 assert False, x
66         # Invalid tags.
67         for x in (None, 1, 1L, "1" "foo " "@foo"):
68             try:
69                 verifyValidAlbumTag(x)
70             except BadAlbumTagError:
71                 pass
72             else:
73                 assert False, x
74
75     def test_verifyValidCategoryTag(self):
76         # Valid tags.
77         for x in ("foo", "1foo"):
78             try:
79                 verifyValidCategoryTag(x)
80             except:
81                 assert False, x
82         # Invalid tags.
83         for x in (None, 1, 1L, "1" "foo " "@foo",
84                   "and", "exactly", "not", "or"):
85             try:
86                 verifyValidCategoryTag(x)
87             except BadCategoryTagError:
88                 pass
89             else:
90                 assert False, x
91
92     def test_makeValidTag(self):
93         for tag, validTag in [("", "_"),
94                               ("@", "_"),
95                               (" ", "_"),
96                               ("1", "1_"),
97                               ("@foo_", "foo_"),
98                               ("fo@o __", "fo@o__")]:
99             assert makeValidTag(tag) == validTag, (tag, validTag)
100
101 class TestNegativeShelfOpens(unittest.TestCase):
102     def tearDown(self):
103         removeTmpDb()
104
105     def test_NonexistingShelf(self):
106         try:
107             s = Shelf(db, codeset)
108             s.begin()
109         except ShelfNotFoundError:
110             pass
111         else:
112             assert False
113         assert not os.path.exists(db)
114
115     def test_BadShelf(self):
116         file(db, "w") # Create empty file.
117         try:
118             s = Shelf(db, codeset)
119             s.begin()
120         except UnsupportedShelfError:
121             pass
122         else:
123             assert False
124
125     def test_LockedShelf(self):
126         mContinue = threading.Event()
127         ltContinue = threading.Event()
128         lt = LockerThread(mContinue, ltContinue)
129         lt.start()
130         mContinue.wait()
131         try:
132             try:
133                 s = Shelf(db, codeset)
134                 s.begin()
135             except ShelfLockedError:
136                 pass
137             else:
138                 assert False
139         finally:
140             ltContinue.set()
141             lt.join()
142
143 class TestShelfCreation(unittest.TestCase):
144     def tearDown(self):
145         removeTmpDb()
146
147     def test_CreateShelf1(self):
148         s = Shelf(db, codeset)
149         s.create()
150         assert os.path.exists(db)
151
152     def test_CreateShelf2(self):
153         file(db, "w") # Create empty file.
154         s = Shelf(db, codeset)
155         try:
156             s.create()
157         except FailedWritingError:
158             pass
159         else:
160             assert False
161
162 class TestShelfMemoryLeakage(unittest.TestCase):
163     def tearDown(self):
164         removeTmpDb()
165
166     def test_MemoryLeak1(self):
167         s = Shelf(db, codeset)
168         s.create()
169         assert gc.collect() == 0
170
171     def test_MemoryLeak2(self):
172         s = Shelf(db, codeset)
173         s.create()
174         s.begin()
175         s.getObject(0)
176         s.rollback()
177         assert gc.collect() == 0
178
179     def test_MemoryLeak3(self):
180         s = Shelf(db, codeset)
181         s.create()
182         s.begin()
183         s.getObject(0)
184         s.commit()
185         assert gc.collect() == 0
186
187 class TestShelfTransactions(unittest.TestCase):
188     def tearDown(self):
189         removeTmpDb()
190
191     def test_commit(self):
192         s = Shelf(db, codeset)
193         s.create()
194         s.begin()
195         s.createAlbum(u"foo")
196         assert s.getAlbumByTag(u"foo")
197         s.commit()
198         s = Shelf(db, codeset)
199         s.begin()
200         assert s.getAlbumByTag(u"foo")
201         s.rollback()
202
203     def test_rollback(self):
204         s = Shelf(db, codeset)
205         s.create()
206         s.begin()
207         s.createAlbum(u"foo")
208         s.rollback()
209         s.begin()
210         try:
211             s.getAlbumByTag(u"foo")
212         except AlbumDoesNotExistError:
213             pass
214         else:
215             assert False
216
217     def test_isModified(self):
218         s = Shelf(db, codeset)
219         s.create()
220         s.begin()
221         assert not s.isModified()
222         s.createAlbum(u"foo")
223         assert s.isModified()
224         s.rollback()
225         s.begin()
226         assert not s.isModified()
227         s.rollback()
228
229     def test_registerModificationCallback(self):
230         res = [False]
231         def f(x):
232             res[0] = True
233         s = Shelf(db, codeset)
234         s.create()
235         s.begin()
236         s.registerModificationCallback(f)
237         assert not res[0]
238         s.createAlbum(u"foo")
239         assert res[0]
240         s.rollback()
241         res[0] = False
242         s.begin()
243         assert not res[0]
244         s.unregisterModificationCallback(f)
245         s.createAlbum(u"foo")
246         assert not res[0]
247         s.rollback()
248
249 class TestShelfFixture(unittest.TestCase):
250     def setUp(self):
251         self.shelf = Shelf(db, codeset)
252         self.shelf.create()
253         self.shelf.begin()
254         root = self.shelf.getRootAlbum()
255         alpha = self.shelf.createAlbum(u"alpha")
256         beta = self.shelf.createAlbum(u"beta")
257         children = [beta]
258         for x in os.listdir(PICDIR):
259             loc = os.path.join(PICDIR, x)
260             if not os.path.isfile(loc):
261                 continue
262             image = self.shelf.createImage()
263             imageversion = self.shelf.createImageVersion(
264                 image, loc, ImageVersionType.Original)
265             children.append(imageversion)
266         del children[-1] # The last image becomes orphaned.
267         alpha.setChildren(children)
268         beta.setChildren(list(beta.getChildren()) + [children[-1]])
269         root.setChildren(list(root.getChildren()) + [alpha, beta])
270         self.shelf.createAlbum(u"epsilon", u"plain") # Orphaned album.
271         zeta = self.shelf.createAlbum(u"zeta", u"search")
272         zeta.setAttribute(u"query", u"a")
273         root.setChildren(list(root.getChildren()) + [zeta])
274
275         cat_a = self.shelf.createCategory(u"a", u"A")
276         cat_b = self.shelf.createCategory(u"b", u"B")
277         cat_c = self.shelf.createCategory(u"c", u"C")
278         cat_d = self.shelf.createCategory(u"d", u"D")
279         cat_a.connectChild(cat_b)
280         cat_a.connectChild(cat_c)
281         cat_b.connectChild(cat_d)
282         cat_c.connectChild(cat_d)
283
284         self.shelf.flushObjectCache()
285         self.shelf.flushCategoryCache()
286
287     def tearDown(self):
288         self.shelf.rollback()
289         removeTmpDb()
290
291 class TestShelfMethods(TestShelfFixture):
292     def test_flushCaches(self):
293         self.shelf.flushCategoryCache()
294         self.shelf.flushObjectCache()
295
296     def test_getStatistics(self):
297         s = self.shelf.getStatistics()
298         assert s["nalbums"] == 6
299         assert s["nimages"] == 11
300
301     def test_createdObjects(self):
302         root = self.shelf.getRootAlbum()
303         children = list(root.getChildren())
304         assert len(children) == 4
305         orphans, alpha, beta, zeta = children
306         assert self.shelf.getAlbum(alpha.getId()) == alpha
307         assert self.shelf.getAlbumByTag(u"beta") == beta
308         assert len(list(alpha.getChildren())) == 11
309         assert len(list(beta.getChildren())) == 1
310
311     def test_createdAttributes(self):
312         imageversion = self.shelf.getImageVersionByLocation(
313             os.path.join(PICDIR, "Canon_Digital_IXUS.jpg"))
314         image = imageversion.getImage()
315         assert image.getAttribute(u"captured") == "2002-02-02 22:20:51"
316         assert image.getAttribute(u"cameramake") == "Canon"
317         assert image.getAttribute(u"cameramodel") == "Canon DIGITAL IXUS"
318
319     def test_negativeAlbumCreation(self):
320         try:
321             self.shelf.createAlbum(u"beta")
322         except AlbumExistsError:
323             pass
324         else:
325             assert False
326
327     def test_getAlbum(self):
328         album = self.shelf.getAlbum(0)
329         assert album == self.shelf.getRootAlbum()
330
331     def test_negativeGetAlbum(self):
332         try:
333             self.shelf.getAlbum(12345678)
334         except AlbumDoesNotExistError:
335             pass
336         else:
337             assert False
338
339     def test_getAlbumByTag(self):
340         album = self.shelf.getAlbumByTag(u"root")
341         assert album == self.shelf.getRootAlbum()
342
343     def test_negativeGetAlbumByTag(self):
344         try:
345             self.shelf.getAlbum(u"12345678")
346         except AlbumDoesNotExistError:
347             pass
348         else:
349             assert False
350
351     def test_getRootAlbum(self):
352         root = self.shelf.getRootAlbum()
353         assert root.getId() == 0
354         assert root == self.shelf.getAlbumByTag(u"root")
355
356     def test_getAllAlbums(self):
357         albums = list(self.shelf.getAllAlbums())
358         assert len(albums) == 6
359
360     def test_getAllImageVersions(self):
361         imageversions = list(self.shelf.getAllImageVersions())
362         assert len(imageversions) == 11
363
364     def test_getImageVersionsInDirectory(self):
365         imageversions = list(self.shelf.getImageVersionsInDirectory(u"."))
366         assert len(imageversions) == 0
367         imageversions = list(self.shelf.getImageVersionsInDirectory(PICDIR))
368         assert len(imageversions) == 11
369
370     def test_deleteAlbum(self):
371         album = self.shelf.getAlbumByTag(u"beta")
372         self.shelf.deleteAlbum(album.getId())
373
374     def test_negativeRootAlbumDeletion(self):
375         root = self.shelf.getRootAlbum()
376         try:
377             self.shelf.deleteAlbum(root.getId())
378         except UndeletableAlbumError:
379             pass
380         else:
381             assert False
382
383     def test_negativeAlbumDeletion(self):
384         try:
385             self.shelf.deleteAlbum(12345678)
386         except AlbumDoesNotExistError:
387             pass
388         else:
389             assert False
390
391     def test_negativeImageCreation(self):
392         try:
393             image = self.shelf.createImage()
394             self.shelf.createImageVersion(
395                 image,
396                 os.path.join(PICDIR, "arlaharen.png"),
397                 ImageVersionType.Original)
398         except ImageVersionExistsError:
399             pass
400         else:
401             assert False
402
403     def test_getImage(self):
404         imageversion = self.shelf.getImageVersionByLocation(
405             os.path.join(PICDIR, "arlaharen.png"))
406         image = imageversion.getImage()
407         assert self.shelf.getImage(image.getId()) == image
408
409     def test_negativeGetImage(self):
410         try:
411             self.shelf.getImage(12345678)
412         except ImageDoesNotExistError:
413             pass
414         else:
415             assert False
416
417     def test_getImageVersion(self):
418         imageversion = self.shelf.getImageVersionByLocation(
419             os.path.join(PICDIR, "arlaharen.png"))
420         assert self.shelf.getImageVersion(imageversion.getId()) == imageversion
421
422     def test_negativeGetImageVersion(self):
423         try:
424             self.shelf.getImageVersion(12345678)
425         except ImageVersionDoesNotExistError:
426             pass
427         else:
428             assert False
429
430     def test_getImageVersionByHash(self):
431         imageversion = self.shelf.getImageVersionByLocation(
432             os.path.join(PICDIR, "arlaharen.png"))
433         assert self.shelf.getImageVersionByHash(
434             imageversion.getHash()) == imageversion
435
436     def test_negativeGetImageVersionByHash(self):
437         try:
438             self.shelf.getImageVersion(u"badhash")
439         except ImageVersionDoesNotExistError:
440             pass
441         else:
442             assert False
443
444     def test_getImageVersionByLocation(self):
445         imageversion = self.shelf.getImageVersionByLocation(
446             os.path.join(PICDIR, "arlaharen.png"))
447
448     def test_negativeGetImageVersionByHash(self):
449         try:
450             self.shelf.getImageVersionByLocation("/bad/location")
451         except ImageVersionDoesNotExistError:
452             pass
453         else:
454             assert False
455
456     def test_deleteImage(self):
457         imageversion = self.shelf.getImageVersionByLocation(
458             os.path.join(PICDIR, "arlaharen.png"))
459         imageid = imageversion.getImage().getId()
460         self.shelf.deleteImage(imageid)
461         try:
462             self.shelf.getImageVersionByLocation(
463                 os.path.join(PICDIR, "arlaharen.png"))
464         except ImageVersionDoesNotExistError:
465             pass
466         else:
467             assert False
468
469     def test_negativeImageDeletion(self):
470         try:
471             self.shelf.deleteImage(12345678)
472         except ImageDoesNotExistError:
473             pass
474         else:
475             assert False
476
477     def test_deleteImageVersion(self):
478         imageversion = self.shelf.getImageVersionByLocation(
479             os.path.join(PICDIR, "arlaharen.png"))
480         self.shelf.deleteImageVersion(imageversion.getId())
481
482     def test_negativeImageVersionDeletion(self):
483         try:
484             self.shelf.deleteImageVersion(12345678)
485         except ImageVersionDoesNotExistError:
486             pass
487         else:
488             assert False
489
490     def test_getObject(self):
491         rootalbum = self.shelf.getRootAlbum()
492         album = self.shelf.getObject(rootalbum.getId())
493         assert album == rootalbum
494
495     def test_deleteObject(self):
496         albumid = self.shelf.getAlbumByTag(u"beta").getId()
497         imageversion = self.shelf.getImageVersionByLocation(
498             os.path.join(PICDIR, "arlaharen.png"))
499         imageid = imageversion.getImage().getId()
500         self.shelf.deleteObject(albumid)
501         self.shelf.deleteObject(imageid)
502         try:
503             self.shelf.getAlbum(albumid)
504         except AlbumDoesNotExistError:
505             pass
506         else:
507             assert False
508         try:
509             self.shelf.getImage(imageid)
510         except ImageDoesNotExistError:
511             pass
512         else:
513             assert False
514
515     def test_getAllAttributeNames(self):
516         attrnames = list(self.shelf.getAllAttributeNames())
517         attrnames.sort()
518         assert attrnames == [
519             "cameramake", "cameramodel", "captured", "description",
520             "digitalzoom", "exposurebias", "exposureprogram", "exposuretime",
521             "flash", "fnumber", "focallength", "iso", "orientation", "query",
522             "title"
523             ], attrnames
524
525     def test_getCategory(self):
526         category = self.shelf.getCategory(1)
527         assert category.getId() == 1
528
529     def test_getCategoryByTag(self):
530         category = self.shelf.getCategory(u"a")
531         assert category.getTag() == u"a"
532
533     def test_negativeCreateCategory(self):
534         try:
535             self.shelf.createCategory(u"a", u"Foo")
536         except CategoryExistsError:
537             pass
538         else:
539             assert False
540
541     def test_deleteCategory(self):
542         category = self.shelf.getCategoryByTag(u"a")
543         self.shelf.deleteCategory(category.getId())
544
545     def test_negativeDeleteCategory(self):
546         try:
547             self.shelf.deleteCategory(12345678)
548         except CategoryDoesNotExistError:
549             pass
550         else:
551             assert False
552
553     def test_getRootCategories(self):
554         categories = list(self.shelf.getRootCategories())
555         cat_a = self.shelf.getCategoryByTag(u"a")
556         cat_events = self.shelf.getCategoryByTag(u"events")
557         cat_locations = self.shelf.getCategoryByTag(u"locations")
558         cat_people = self.shelf.getCategoryByTag(u"people")
559         categories.sort(lambda x, y: cmp(x.getTag(), y.getTag()))
560         assert categories == [cat_a, cat_events, cat_locations, cat_people], \
561                categories
562
563 class TestCategory(TestShelfFixture):
564     def test_categoryMethods(self):
565         cat_a = self.shelf.getCategoryByTag(u"a")
566         cat_b = self.shelf.getCategoryByTag(u"b")
567         cat_c = self.shelf.getCategoryByTag(u"c")
568         cat_d = self.shelf.getCategoryByTag(u"d")
569
570         assert self.shelf.getCategory(cat_a.getId()) == cat_a
571         cat_a.setTag(u"foo")
572         assert self.shelf.getCategoryByTag(u"foo") == cat_a
573
574         assert cat_a.getDescription() == "A"
575         cat_a.setDescription(u"foo")
576         assert cat_a.getDescription() == "foo"
577
578         a_children = list(cat_a.getChildren())
579         a_children.sort(lambda x, y: cmp(x.getId(), y.getId()))
580         assert a_children == [cat_b, cat_c]
581         b_children = list(cat_b.getChildren())
582         assert b_children == [cat_d]
583         d_children = list(cat_d.getChildren())
584         assert d_children == []
585
586         a_parents = list(cat_a.getParents())
587         assert a_parents == []
588         b_parents = list(cat_b.getParents())
589         assert b_parents == [cat_a]
590         d_parents = list(cat_d.getParents())
591         d_parents.sort(lambda x, y: cmp(x.getTag(), y.getTag()))
592         assert d_parents == [cat_b, cat_c]
593
594         assert not cat_a.isChildOf(cat_a)
595         assert cat_b.isChildOf(cat_a)
596         assert cat_c.isChildOf(cat_a)
597         assert not cat_d.isChildOf(cat_a)
598         assert cat_a.isChildOf(cat_a, recursive=True)
599         assert cat_b.isChildOf(cat_a, recursive=True)
600         assert cat_c.isChildOf(cat_a, recursive=True)
601         assert cat_d.isChildOf(cat_a, recursive=True)
602
603         assert not cat_d.isParentOf(cat_d)
604         assert cat_b.isParentOf(cat_d)
605         assert cat_c.isParentOf(cat_d)
606         assert not cat_a.isParentOf(cat_d)
607         assert cat_d.isParentOf(cat_d, recursive=True)
608         assert cat_b.isParentOf(cat_d, recursive=True)
609         assert cat_c.isParentOf(cat_d, recursive=True)
610         assert cat_a.isParentOf(cat_d, recursive=True)
611
612     def test_negativeCategoryConnectChild(self):
613         cat_a = self.shelf.getCategoryByTag(u"a")
614         cat_b = self.shelf.getCategoryByTag(u"b")
615         try:
616             cat_a.connectChild(cat_b)
617         except CategoriesAlreadyConnectedError:
618             pass
619         else:
620             assert False
621         try:
622             cat_b.connectChild(cat_a)
623         except CategoryLoopError:
624             pass
625         else:
626             assert False
627
628     def test_categoryDisconnectChild(self):
629         cat_a = self.shelf.getCategoryByTag(u"a")
630         cat_b = self.shelf.getCategoryByTag(u"b")
631         cat_a.disconnectChild(cat_b)
632         assert not cat_a.isParentOf(cat_b)
633
634     def test_negativeCategoryDisconnectChild(self):
635         cat_a = self.shelf.getCategoryByTag(u"a")
636         cat_d = self.shelf.getCategoryByTag(u"d")
637         cat_a.disconnectChild(cat_d) # No exception.
638
639 class TestObject(TestShelfFixture):
640     def test_getParents(self):
641         root = self.shelf.getRootAlbum()
642         alpha = self.shelf.getAlbumByTag(u"alpha")
643         beta = self.shelf.getAlbumByTag(u"beta")
644         parents = list(beta.getParents())
645         parents.sort(lambda x, y: cmp(x.getTag(), y.getTag()))
646         assert parents == [alpha, root]
647
648     def test_getAttribute(self):
649         orphans = self.shelf.getAlbumByTag(u"orphans")
650         assert orphans.getAttribute(u"title")
651         assert orphans.getAttribute(u"description")
652         assert not orphans.getAttribute(u"nonexisting")
653
654     def test_getAttributeMap(self):
655         orphans = self.shelf.getAlbumByTag(u"orphans")
656         map = orphans.getAttributeMap()
657         assert "description" in map
658         assert "title" in map
659
660     def test_getAttributeNames(self):
661         orphans = self.shelf.getAlbumByTag(u"orphans")
662         names = list(orphans.getAttributeNames())
663         names.sort()
664         assert names == ["description", "title"]
665
666     def test_setAttribute(self):
667         orphans = self.shelf.getAlbumByTag(u"orphans")
668         orphans.setAttribute(u"foo", u"fie") # New.
669         assert orphans.getAttribute(u"foo") == u"fie"
670         assert u"foo" in orphans.getAttributeMap()
671         assert u"foo" in orphans.getAttributeNames()
672         assert orphans.getAttribute(u"title")
673         orphans.setAttribute(u"title", u"gazonk") # Existing
674         assert orphans.getAttribute(u"title") == u"gazonk"
675         assert u"foo" in orphans.getAttributeMap()
676         assert u"foo" in orphans.getAttributeNames()
677
678     def test_deleteAttribute(self):
679         orphans = self.shelf.getAlbumByTag(u"orphans")
680         orphans.deleteAttribute(u"nonexisting") # No exception.
681         assert orphans.getAttribute(u"title")
682         orphans.deleteAttribute(u"title")
683         assert not orphans.getAttribute(u"title")
684
685     def test_addCategory(self):
686         orphans = self.shelf.getAlbumByTag(u"orphans")
687         cat_a = self.shelf.getCategoryByTag(u"a")
688         assert list(orphans.getCategories()) == []
689         orphans.addCategory(cat_a)
690         assert list(orphans.getCategories()) == [cat_a]
691         try:
692             orphans.addCategory(cat_a)
693         except CategoryPresentError:
694             pass
695         else:
696             assert False
697         assert list(orphans.getCategories()) == [cat_a]
698
699     def test_removeCategory(self):
700         orphans = self.shelf.getAlbumByTag(u"orphans")
701         assert list(orphans.getCategories()) == []
702         cat_a = self.shelf.getCategoryByTag(u"a")
703         orphans.addCategory(cat_a)
704         assert list(orphans.getCategories()) == [cat_a]
705         orphans.removeCategory(cat_a)
706         assert list(orphans.getCategories()) == []
707
708     def test_deleteCategoryInvalidatesCategoryCache(self):
709         orphans = self.shelf.getAlbumByTag(u"orphans")
710         assert list(orphans.getCategories()) == []
711         cat_a = self.shelf.getCategoryByTag(u"a")
712         orphans.addCategory(cat_a)
713         assert list(orphans.getCategories()) == [cat_a]
714         self.shelf.deleteCategory(cat_a.getId())
715         assert list(orphans.getCategories()) == []
716
717 class TestAlbum(TestShelfFixture):
718     def test_getType(self):
719         alpha = self.shelf.getAlbumByTag(u"alpha")
720         assert alpha.getType() == "plain"
721
722     def test_isMutable(self):
723         alpha = self.shelf.getAlbumByTag(u"alpha")
724         assert alpha.isMutable()
725
726     def test_getTag(self):
727         alpha = self.shelf.getAlbumByTag(u"alpha")
728         assert alpha.getTag() == u"alpha"
729
730     def test_setTag(self):
731         alpha = self.shelf.getAlbumByTag(u"alpha")
732         alpha.setTag(u"alfa")
733         assert alpha.getTag() == u"alfa"
734
735     def test_getAlbumParents(self):
736         root = self.shelf.getRootAlbum()
737         alpha = self.shelf.getAlbumByTag(u"alpha")
738         parents = list(alpha.getAlbumParents())
739         parents.sort(lambda x, y: cmp(x.getTag(), y.getTag()))
740         assert parents == [root]
741
742     def test_isAlbum(self):
743         assert self.shelf.getRootAlbum().isAlbum()
744
745 class TestPlainAlbum(TestShelfFixture):
746     def test_getType(self):
747         alpha = self.shelf.getAlbumByTag(u"alpha")
748         assert alpha.getType() == "plain"
749
750     def test_isMutable(self):
751         alpha = self.shelf.getAlbumByTag(u"alpha")
752         assert alpha.isMutable()
753
754     def test_getChildren(self):
755         epsilon = self.shelf.getAlbumByTag(u"epsilon")
756         alpha = self.shelf.getAlbumByTag(u"alpha")
757         beta = self.shelf.getAlbumByTag(u"beta")
758         assert list(epsilon.getChildren()) == []
759         alphaChildren = list(alpha.getChildren())
760         assert list(beta.getChildren()) == [alphaChildren[-1]]
761
762     def test_getAlbumChildren(self):
763         alpha = self.shelf.getAlbumByTag(u"alpha")
764         beta = self.shelf.getAlbumByTag(u"beta")
765         epsilon = self.shelf.getAlbumByTag(u"epsilon")
766         alphaAlbumChildren = list(alpha.getAlbumChildren())
767         assert alphaAlbumChildren == [beta]
768         assert list(epsilon.getAlbumChildren()) == []
769
770     def test_setChildren(self):
771         root = self.shelf.getRootAlbum()
772         beta = self.shelf.getAlbumByTag(u"beta")
773         assert list(beta.getChildren()) != []
774         beta.setChildren([beta, root])
775         assert list(beta.getChildren()) == [beta, root]
776         beta.setChildren([]) # Break the cycle.
777         assert list(beta.getChildren()) == []
778
779 class TestImage(TestShelfFixture):
780     def test_getImageVersions(self):
781         imageversion = self.shelf.getImageVersionByLocation(
782             os.path.join(PICDIR, "arlaharen.png"))
783         image = imageversion.getImage()
784         assert list(image.getImageVersions()) == [imageversion]
785         imageversion2 = self.shelf.getImageVersionByLocation(
786             os.path.join(PICDIR, "Canon_Digital_IXUS.jpg"))
787         imageversion2.setImage(image)
788         imageversions = list(image.getImageVersions())
789         imageversions.sort(lambda x, y: cmp(x.getHash(), y.getHash()))
790         assert list(image.getImageVersions()) == [imageversion, imageversion2]
791         self.shelf.deleteImageVersion(imageversion.getId())
792         self.shelf.deleteImageVersion(imageversion2.getId())
793         assert list(image.getImageVersions()) == []
794
795     def test_getPrimaryversion(self):
796         imageversion = self.shelf.getImageVersionByLocation(
797             os.path.join(PICDIR, "arlaharen.png"))
798         image = imageversion.getImage()
799         assert image.getPrimaryVersion() == imageversion
800         imageversion2 = self.shelf.getImageVersionByLocation(
801             os.path.join(PICDIR, "Canon_Digital_IXUS.jpg"))
802         imageversion2.setImage(image)
803         assert image.getPrimaryVersion() == imageversion
804         imageversion2.makePrimary()
805         assert image.getPrimaryVersion() == imageversion2
806
807 class TestImageVersion(TestShelfFixture):
808     def test_getType(self):
809         imageversion = self.shelf.getImageVersionByLocation(
810             os.path.join(PICDIR, "arlaharen.png"))
811         assert imageversion.getType() == ImageVersionType.Other
812         imageversion.setType(ImageVersionType.Important)
813         assert imageversion.getType() == ImageVersionType.Important
814         imageversion.setType(ImageVersionType.Original)
815         assert imageversion.getType() == ImageVersionType.Original
816         imageversion.setType(ImageVersionType.Other)
817         assert imageversion.getType() == ImageVersionType.Other
818
819     # ImageVersion.makePrimary tested in TestImage.test_getPrimaryversion.
820     # ImageVersion.setImage tested in TestImage.test_getPrimaryversion.
821     # ImageVersion.setType tested in TestImageVersion.test_getType.
822
823     def test_getHash(self):
824         imageversion = self.shelf.getImageVersionByLocation(
825             os.path.join(PICDIR, "arlaharen.png"))
826         assert imageversion.getHash() == "39a1266d2689f53d48b09a5e0ca0af1f"
827
828     def test_getLocation(self):
829         location = os.path.join(PICDIR, "arlaharen.png")
830         imageversion = self.shelf.getImageVersionByLocation(location)
831         assert imageversion.getLocation() == os.path.realpath(location)
832
833     def test_getModificationTime(self):
834         imageversion = self.shelf.getImageVersionByLocation(
835             os.path.join(PICDIR, "arlaharen.png"))
836         t = imageversion.getModificationTime()
837         assert isinstance(t, int)
838         assert t > 0
839
840     def test_getSize(self):
841         imageversion = self.shelf.getImageVersionByLocation(
842             os.path.join(PICDIR, "arlaharen.png"))
843         assert imageversion.getSize() == (304, 540)
844
845     def test_contentChanged(self):
846         path = os.path.join(PICDIR, "arlaharen.png")
847         imageversion = self.shelf.getImageVersionByLocation(path)
848         self.shelf.deleteImageVersion(imageversion1.getId())
849         newpath = u"tmp.png"
850         try:
851             shutil.copy2(path, newpath)
852             newimage = self.shelf.createImage(newpath)
853             newimageversion = self.shelf.createImageVersion(
854                 newimage, newpath, ImageVersionType.Original)
855             oldmtime = imageversion.getModificationTime()
856             pilimg = PILImage.open(newpath)
857             pilimg.thumbnail((100, 100))
858             pilimg.save(newpath, "PNG")
859             newimageversion.contentChanged()
860             assert newimageversion.getHash() == "d55a9cc74371c09d484b163c71497cab"
861             assert newimageversion.getSize() == (56, 100)
862             assert newimageversion.getModificationTime() > oldmtime
863         finally:
864             try:
865                 os.unlink(newpath)
866             except OSError:
867                 pass
868
869     def test_locationChanged(self):
870         location = os.path.join(PICDIR, "arlaharen.png")
871         imageversion = self.shelf.getImageVersionByLocation(location)
872         imageversion.locationChanged(u"/foo/../bar")
873         assert imageversion.getLocation() == "/bar"
874
875     def test_isAlbum(self):
876         imageversion = self.shelf.getImageVersionByLocation(
877             os.path.join(PICDIR, "arlaharen.png"))
878         assert not imageversion.isAlbum()
879
880     def test_importExifTags(self):
881         imageversion = self.shelf.getImageVersionByLocation(
882             os.path.join(PICDIR, "arlaharen.png"))
883         imageversion.importExifTags() # TODO: Test more.
884
885 class TestOrphansAlbum(TestShelfFixture):
886     def test_getType(self):
887         orphans = self.shelf.getAlbumByTag(u"orphans")
888         assert orphans.getType() == "orphans"
889
890     def test_isMutable(self):
891         orphans = self.shelf.getAlbumByTag(u"orphans")
892         assert not orphans.isMutable()
893
894     def test_getChildren(self):
895         orphans = self.shelf.getAlbumByTag(u"orphans")
896         assert len(list(orphans.getChildren())) == 2
897
898     def test_getAlbumChildren(self):
899         orphans = self.shelf.getAlbumByTag(u"orphans")
900         epsilon = self.shelf.getAlbumByTag(u"epsilon")
901         assert list(orphans.getAlbumChildren()) == [epsilon]
902
903     def test_setChildren(self):
904         orphans = self.shelf.getAlbumByTag(u"orphans")
905         try:
906             orphans.setChildren([])
907         except UnsettableChildrenError:
908             pass
909         else:
910             assert False
911
912     def test_isAlbum(self):
913         assert self.shelf.getAlbumByTag(u"orphans").isAlbum()
914
915 class TestSearchAlbum(TestShelfFixture):
916     def test_getType(self):
917         zeta = self.shelf.getAlbumByTag(u"zeta")
918         assert zeta.getType() == "search"
919
920     def test_isMutable(self):
921         zeta = self.shelf.getAlbumByTag(u"zeta")
922         assert not zeta.isMutable()
923
924     def test_getChildren(self):
925         alpha = self.shelf.getAlbumByTag(u"alpha")
926         image1, image2 = list(alpha.getChildren())[0:2]
927         cat_a = self.shelf.getCategoryByTag(u"a")
928         cat_b = self.shelf.getCategoryByTag(u"b")
929         image1.addCategory(cat_a)
930         image2.addCategory(cat_b)
931         zeta = self.shelf.getAlbumByTag(u"zeta")
932         assert zeta
933         zeta.setAttribute(u"query", u"b")
934         children = zeta.getChildren()
935         assert list(children) == [image2]
936
937     def test_getAlbumChildren(self):
938         alpha = self.shelf.getAlbumByTag(u"alpha")
939         image1, image2 = list(alpha.getChildren())[0:2]
940         cat_a = self.shelf.getCategoryByTag(u"a")
941         cat_b = self.shelf.getCategoryByTag(u"b")
942         image1.addCategory(cat_a)
943         image2.addCategory(cat_b)
944         zeta = self.shelf.getAlbumByTag(u"zeta")
945         assert zeta
946         zeta.setAttribute(u"query", u"b")
947         children = zeta.getAlbumChildren()
948         l = list(children)
949         assert list(children) == []
950
951     def test_setChildren(self):
952         zeta = self.shelf.getAlbumByTag(u"zeta")
953         try:
954             zeta.setChildren([])
955         except UnsettableChildrenError:
956             pass
957         else:
958             assert False
959
960     def test_isAlbum(self):
961         assert self.shelf.getAlbumByTag(u"zeta").isAlbum()
962
963 ######################################################################
964
965 removeTmpDb()
966 if __name__ == "__main__":
967     unittest.main()