1# This program is free software; you can redistribute it and/or modify
2# it under the terms of the GNU General Public License as published by
3# the Free Software Foundation; either version 2 of the License, or
4# (at your option) any later version.
5
6from quodlibet.util.path import mtime
7from tests import TestCase, NamedTemporaryFile, get_data_path
8
9from gi.repository import GdkPixbuf
10from senf import fsn2uri, fsnative
11
12import os
13
14try:
15    import hashlib as hash
16except ImportError:
17    import md5 as hash
18
19from quodlibet.util import thumbnails
20
21
22class TThumb(TestCase):
23
24    def setUp(s):
25        s.wide = GdkPixbuf.Pixbuf.new(
26            GdkPixbuf.Colorspace.RGB, True, 8, 150, 10)
27        s.high = GdkPixbuf.Pixbuf.new(
28            GdkPixbuf.Colorspace.RGB, True, 8, 10, 100)
29        s.small = GdkPixbuf.Pixbuf.new(
30            GdkPixbuf.Colorspace.RGB, True, 8, 10, 20)
31        s.filename = get_data_path("test.png")
32
33    def tearDown(self):
34        p1 = thumbnails.get_cache_info(self.filename, (10, 10))[0]
35        p2 = thumbnails.get_cache_info(self.filename, (1000, 1000))[0]
36        for path in [p1, p2]:
37            try:
38                os.remove(path)
39            except OSError:
40                pass
41
42    def test_get_thumbnail_folder(self):
43        path = thumbnails.get_thumbnail_folder()
44        self.assertTrue(isinstance(path, fsnative))
45
46    def test_thumb_from_file(self):
47        with open(self.filename, "rb") as h:
48            thumb = thumbnails.get_thumbnail_from_file(h, (50, 60))
49            self.assertTrue(thumb)
50
51    def test_thumb_from_file_temp(self):
52        fn = NamedTemporaryFile()
53        with open(self.filename, "rb") as h:
54            fn.write(h.read())
55        fn.flush()
56        fn.seek(0, 0)
57
58        thumb = thumbnails.get_thumbnail_from_file(fn, (50, 60))
59        self.assertTrue(thumb)
60        fn.close()
61
62    def test_thumb_from_file_temp_partial(self):
63        fn = NamedTemporaryFile()
64        with open(self.filename, "rb") as h:
65            fn.write(h.read(10))
66        fn.flush()
67        fn.seek(0, 0)
68
69        thumb = thumbnails.get_thumbnail_from_file(fn, (50, 60))
70        self.assertTrue(thumb is None)
71        fn.close()
72
73    def test_get_cache_info(self):
74        p, s = thumbnails.get_cache_info(self.filename, (20, 20))
75        self.assertEqual(s, 128)
76        self.assertTrue((os.sep + "normal" + os.sep) in p)
77
78        p, s = thumbnails.get_cache_info(self.filename, (20, 300))
79        self.assertEqual(s, 256)
80        self.assertTrue((os.sep + "large" + os.sep) in p)
81
82    def test_recreate_broken_cache_file(self):
83        thumb = thumbnails.get_thumbnail(
84            self.filename, (50, 60), ignore_temp=False)
85        self.assertTrue(thumb)
86        path, size = thumbnails.get_cache_info(self.filename, (50, 60))
87        open(path, "wb").close()
88        thumb = thumbnails.get_thumbnail(
89            self.filename, (50, 60), ignore_temp=False)
90        self.assertTrue(thumb)
91
92    def test_thumb(s):
93        thumb = thumbnails.get_thumbnail(
94            s.filename, (50, 60), ignore_temp=False)
95
96        #check for right scaling
97        s.failUnless(thumb)
98        s.failUnlessEqual((thumb.get_width(), thumb.get_height()), (50, 25))
99
100        #test the thumbnail filename
101        uri = fsn2uri(s.filename)
102        name = hash.md5(uri.encode("ascii")).hexdigest() + ".png"
103
104        path = thumbnails.get_thumbnail_folder()
105        path = os.path.join(path, "normal", name)
106
107        s.failUnless(os.path.isfile(path))
108
109        #check for metadata
110        thumb_pb = GdkPixbuf.Pixbuf.new_from_file(path)
111        meta_mtime = thumb_pb.get_option("tEXt::Thumb::MTime")
112        meta_uri = thumb_pb.get_option("tEXt::Thumb::URI")
113
114        s.failUnlessEqual(int(meta_mtime), int(mtime(s.filename)))
115        s.failUnlessEqual(meta_uri, uri)
116
117        #check rights
118        if os.name != "nt":
119            s.failUnlessEqual(os.stat(path).st_mode, 33152)
120