1from io import StringIO 2import os 3import platform 4import sys 5import shutil 6import unittest 7from PIL import Image 8 9import pytest 10from django.test import TestCase 11from django.test.utils import override_settings 12 13from sorl.thumbnail import default, delete, get_thumbnail 14from sorl.thumbnail.base import ThumbnailBackend 15from sorl.thumbnail.conf import settings 16from sorl.thumbnail.helpers import get_module_class 17from sorl.thumbnail.images import ImageFile 18from .utils import BaseTestCase, FakeFile, same_open_fd_count 19from .models import Item 20 21 22pytestmark = pytest.mark.django_db 23 24 25class BackendTest(BaseTestCase): 26 def test_delete(self): 27 im1 = Item.objects.get(image='100x100.jpg').image 28 im2 = Item.objects.get(image='500x500.jpg').image 29 default.kvstore.get_or_set(ImageFile(im1)) 30 31 # exists in kvstore and in storage 32 self.assertTrue(bool(default.kvstore.get(ImageFile(im1)))) 33 self.assertTrue(ImageFile(im1).exists()) 34 35 # delete 36 delete(im1) 37 self.assertFalse(bool(default.kvstore.get(ImageFile(im1)))) 38 self.assertFalse(ImageFile(im1).exists()) 39 40 default.kvstore.get_or_set(ImageFile(im2)) 41 42 # exists in kvstore and in storage 43 self.assertTrue(bool(default.kvstore.get(ImageFile(im2)))) 44 self.assertTrue(ImageFile(im2).exists()) 45 46 # delete 47 delete(im2, delete_file=False) 48 self.assertFalse(bool(default.kvstore.get(ImageFile(im2)))) 49 self.assertTrue(ImageFile(im2).exists()) 50 51 52@override_settings(THUMBNAIL_PRESERVE_FORMAT=True, THUMBNAIL_FORMAT='XXX') 53class PreserveFormatTest(TestCase): 54 def setUp(self): 55 self.backend = ThumbnailBackend() 56 57 def test_with_various_formats(self): 58 self.assertEqual(self.backend._get_format(FakeFile('foo.jpg')), 'JPEG') 59 self.assertEqual(self.backend._get_format(FakeFile('foo.jpeg')), 'JPEG') 60 self.assertEqual(self.backend._get_format(FakeFile('foo.png')), 'PNG') 61 self.assertEqual(self.backend._get_format(FakeFile('foo.gif')), 'GIF') 62 63 def test_double_extension(self): 64 self.assertEqual(self.backend._get_format(FakeFile('foo.ext.jpg')), 'JPEG') 65 66 def test_that_capitalization_doesnt_matter(self): 67 self.assertEqual(self.backend._get_format(FakeFile('foo.PNG')), 'PNG') 68 self.assertEqual(self.backend._get_format(FakeFile('foo.JPG')), 'JPEG') 69 70 def test_fallback_format(self): 71 self.assertEqual(self.backend._get_format(FakeFile('foo.txt')), 'XXX') 72 73 def test_with_nonascii(self): 74 self.assertEqual(self.backend._get_format(FakeFile('你好.jpg')), 'JPEG') 75 76 def test_image_remote_url(self): 77 self.assertEqual(self.backend._get_format(FakeFile('http://example.com/1.png')), 'PNG') 78 79 80@unittest.skipIf(platform.system() == "Windows", "Can't easily count descriptors on windows") 81class TestDescriptors(unittest.TestCase): 82 """Make sure we're not leaving open descriptors on file exceptions""" 83 ENGINE = None 84 85 def setUp(self): 86 self.ENGINE = get_module_class(settings.THUMBNAIL_ENGINE)() 87 88 def test_no_source_get_image(self): 89 """If source image does not exists, properly close all file descriptors""" 90 source = ImageFile('nonexistent.jpeg') 91 92 with same_open_fd_count(self): 93 with self.assertRaises(IOError): 94 self.ENGINE.get_image(source) 95 96 def test_is_valid_image(self): 97 with same_open_fd_count(self): 98 self.ENGINE.is_valid_image(b'invalidbinaryimage.jpg') 99 100 @unittest.skipIf('pgmagick_engine' in settings.THUMBNAIL_ENGINE and sys.version_info.major == 2, 101 'No output has been received in the last 10 minutes,' 102 'this potentially indicates something wrong with the build itself.') 103 def test_write(self): 104 with same_open_fd_count(self): 105 with self.assertRaises(Exception): 106 self.ENGINE.write(image=self.ENGINE.get_image(StringIO(b'xxx')), 107 options={'format': 'JPEG', 'quality': 90, 'image_info': {}}, 108 thumbnail=ImageFile('whatever_thumb.jpg', default.storage)) 109 110 111class ModelTestCase(BaseTestCase): 112 def test_field1(self): 113 self.KVSTORE.clear() 114 item = Item.objects.get(image='100x100.jpg') 115 im = ImageFile(item.image) 116 self.assertEqual(None, self.KVSTORE.get(im)) 117 self.BACKEND.get_thumbnail(im, '27x27') 118 self.BACKEND.get_thumbnail(im, '81x81') 119 self.assertNotEqual(None, self.KVSTORE.get(im)) 120 self.assertEqual(3, len(list(self.KVSTORE._find_keys(identity='image')))) 121 self.assertEqual(1, len(list(self.KVSTORE._find_keys(identity='thumbnails')))) 122 123 124class TestInputCase(unittest.TestCase): 125 def setUp(self): 126 if not os.path.exists(settings.MEDIA_ROOT): 127 os.makedirs(settings.MEDIA_ROOT) 128 129 self.name = 'åäö.jpg' 130 131 fn = os.path.join(settings.MEDIA_ROOT, self.name) 132 im = Image.new('L', (666, 666)) 133 im.save(fn) 134 135 def test_nonascii(self): 136 # also test the get_thumbnail shortcut 137 th = get_thumbnail(self.name, '200x200') 138 self.assertEqual(th.url, '/media/test/cache/f5/26/f52608b56718f62abc45a90ff9459f2c.jpg') 139 140 def tearDown(self): 141 shutil.rmtree(settings.MEDIA_ROOT) 142