source: main/waeup.kofa/branches/uli-fix-zc-async/src/waeup/kofa/tests/test_imagestorage.py @ 17930

Last change on this file since 17930 was 9286, checked in by uli, 12 years ago

Minor cleanups, also remove the last remaining directory created in tests.

  • Property svn:keywords set to Id
File size: 15.9 KB
Line 
1## $Id: test_imagestorage.py 9286 2012-10-04 09:48:56Z uli $
2##
3## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
4## This program is free software; you can redistribute it and/or modify
5## it under the terms of the GNU General Public License as published by
6## the Free Software Foundation; either version 2 of the License, or
7## (at your option) any later version.
8##
9## This program is distributed in the hope that it will be useful,
10## but WITHOUT ANY WARRANTY; without even the implied warranty of
11## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12## GNU General Public License for more details.
13##
14## You should have received a copy of the GNU General Public License
15## along with this program; if not, write to the Free Software
16## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17##
18import os
19import tempfile
20import shutil
21import unittest
22from StringIO import StringIO
23from hurry.file import HurryFile
24from hurry.file.interfaces import IFileRetrieval
25from zope.component import (
26    getUtility, provideUtility, queryUtility, provideAdapter)
27from zope.component.hooks import setSite
28from zope.interface.verify import verifyClass, verifyObject
29from waeup.kofa.app import University
30from waeup.kofa.testing import FunctionalLayer, FunctionalTestCase
31from waeup.kofa.imagestorage import (
32    FileStoreNameChooser, ExtFileStore, DefaultFileStoreHandler,
33    DefaultStorage)
34from waeup.kofa.interfaces import (
35    IFileStoreNameChooser, IExtFileStore, IFileStoreHandler,)
36
37class FileStoreNameChooserTests(FunctionalTestCase):
38
39    layer = FunctionalLayer
40
41    def test_iface(self):
42        # we provide the interfaces we promise to do
43        obj = FileStoreNameChooser(None)
44        verifyClass(IFileStoreNameChooser, FileStoreNameChooser)
45        verifyObject(IFileStoreNameChooser, obj)
46        return
47
48    def test_accessible_as_adapter(self):
49        # we can get a file name chooser via adapter
50        chooser = IFileStoreNameChooser(object())
51        self.assertTrue(
52            isinstance(chooser, FileStoreNameChooser))
53        return
54
55    def test_check_name(self):
56        # default file name choosers accept any string
57        chooser = FileStoreNameChooser(object())
58        self.assertEqual(chooser.checkName('Hi there!'), True)
59        self.assertEqual(chooser.checkName(None), False)
60        return
61
62    def test_choose_name(self):
63        # we get a simple string if we do not pass in a valid string
64        chooser = FileStoreNameChooser(object())
65        self.assertEqual(chooser.chooseName('myname'), 'myname')
66        self.assertEqual(chooser.chooseName(None), u'unknown_file')
67        return
68
69class ExtFileStoreTests(unittest.TestCase):
70    # Test external file store (non-functional mode)
71
72    def setUp(self):
73        self.workdir = tempfile.mkdtemp()
74        self.root = None
75        return
76
77    def tearDown(self):
78        shutil.rmtree(self.workdir)
79        if self.root is not None:
80            shutil.rmtree(self.root)
81        return
82
83    def test_iface(self):
84        obj = ExtFileStore(None)
85        verifyClass(IExtFileStore, ExtFileStore)
86        verifyObject(IExtFileStore, obj)
87        self.root = obj.root # for cleanup
88        return
89
90    def test_root_setup_wo_site(self):
91        # if no site is available we can use a temporary root
92        fs = ExtFileStore()
93        self.root = fs.root
94        self.assertTrue(isinstance(self.root, basestring))
95        self.assertTrue(os.path.exists(self.root))
96        return
97
98    def test_create_instance(self):
99        # we can create file stores with or without a root dir set
100        storage1 = ExtFileStore()
101        storage2 = ExtFileStore(root=self.workdir)
102        self.root = storage1.root
103        self.assertTrue(storage1.root is not None)
104        self.assertTrue(storage1.root != storage2.root)
105        self.assertEqual(storage2.root, self.workdir)
106        return
107
108    def test_create_file(self):
109        # We can store files
110        storage = ExtFileStore(root=self.workdir)
111        dummy_file = StringIO('sample file')
112        image_file = storage.createFile('mysample', dummy_file)
113        self.assertTrue('mysample' in os.listdir(storage.root))
114        self.assertEqual('mysample', image_file.data)
115        return
116
117    def test_create_file_w_ext(self):
118        # We can store files with filename extension
119        storage = ExtFileStore(root=self.workdir)
120        dummy_file = StringIO('sample file')
121        image_file = storage.createFile('mysample.txt', dummy_file)
122        self.assertTrue('mysample.txt' in os.listdir(storage.root))
123        self.assertEqual('mysample.txt', image_file.data)
124        return
125
126    def test_get_file(self):
127        # We can get files after having them stored
128        storage = ExtFileStore(root=self.workdir)
129        dummy_file = StringIO('sample file')
130        image_file = storage.createFile('mysample', dummy_file)
131        result = storage.getFile(image_file.data)
132        self.assertEqual(result.read(), 'sample file')
133        return
134
135    def test_get_file_w_ext(self):
136        # We can get files with filename extension after having them
137        # stored
138        storage = ExtFileStore(root=self.workdir)
139        dummy_file = StringIO('sample file')
140        image_file = storage.createFile('mysample.txt', dummy_file)
141        result = storage.getFile('mysample')
142        self.assertEqual(result.read(), 'sample file')
143        return
144
145    def test_replace_file_w_new_ext(self):
146        # when we store a file with the same file_id but different
147        # filename extension, the old file will be deleted
148        storage = ExtFileStore(root=self.workdir)
149        dummy_file = StringIO('sample_file')
150        image_file = storage.createFile('mysample.jpg', dummy_file)
151        file1_path = storage.getFile('mysample').name
152        new_file = storage.createFile(
153            'mysample.png', StringIO('new file'))
154        file2 = storage.getFile('mysample')
155        self.assertEqual(file2.name[-12:], 'mysample.png')
156        self.assertEqual(file2.read(), 'new file')
157        # the old file was deleted
158        self.assertFalse(os.path.exists(file1_path))
159        return
160
161    def test_extract_marker(self):
162        # file stores support extracting markers from filenames
163        storage = ExtFileStore(root=self.workdir)
164        result1 = storage.extractMarker(None)
165        result2 = storage.extractMarker('')
166        result3 = storage.extractMarker('no-marker')
167        result4 = storage.extractMarker('no-marker.txt')
168        result5 = storage.extractMarker('__MARKER__foo.jpg')
169        result6 = storage.extractMarker('__MaRkEr__foo.jpg')
170        result7 = storage.extractMarker('__THE_MARKER__foo.jpg')
171        result8 = storage.extractMarker('__A_MARK__my__foo.jpg')
172
173        self.assertEqual(result1, ('', '', '', ''))
174        self.assertEqual(result2, ('', '', '', ''))
175        self.assertEqual(result3, ('', 'no-marker', 'no-marker', ''))
176        self.assertEqual(result4, ('', 'no-marker.txt', 'no-marker', '.txt'))
177        self.assertEqual(result5, ('marker', 'foo.jpg', 'foo', '.jpg'))
178        self.assertEqual(result6, ('marker', 'foo.jpg', 'foo', '.jpg'))
179        self.assertEqual(result7, ('the_marker', 'foo.jpg', 'foo', '.jpg'))
180        self.assertEqual(result8, ('a_mark', 'my__foo.jpg', 'my__foo', '.jpg'))
181        return
182
183class DefaultFileStoreHandlerTests(unittest.TestCase):
184
185    def test_iface(self):
186        obj = DefaultFileStoreHandler()
187        verifyClass(IFileStoreHandler, DefaultFileStoreHandler)
188        verifyObject(IFileStoreHandler, obj)
189        return
190
191class CustomizedFileHandler(object):
192    def pathFromFileID(self, store, root, file_id):
193        return os.path.join(root, file_id[12:])
194
195    def createFile(self, store, root, filename, file_id, f):
196        ext = os.path.splitext(filename)[1]
197        path = self.pathFromFileID(store, root, file_id) + ext
198        return f, path, HurryFile(filename, file_id + ext)
199
200class CustomContext(object):
201    pass
202
203class CustomContextFileChooser(object):
204    def __init__(self, context):
205        self.context = context
206
207    def chooseName(self, name=None, attr=None):
208        # this name chooser returns different file ids depending on
209        # the `attr` parameter, a simple string.
210        if attr=='img':
211            return '__mymarker__mysample_img.jpg'
212        elif attr=='doc':
213            return '__mymarker__mysample_doc.doc'
214        return '__mymarker__mysample.txt'
215
216class FunctionalExtFileStoreTests(FunctionalTestCase):
217
218    layer = FunctionalLayer
219
220    def setUp(self):
221        super(FunctionalExtFileStoreTests, self).setUp()
222        self.workdir = tempfile.mkdtemp()
223        self.root = None
224        self.samplefile = os.path.join(self.workdir, 'sample')
225        self.otherfile = os.path.join(self.workdir, 'other')
226        open(self.samplefile, 'wb').write('Hi there!')
227        open(self.otherfile, 'wb').write('Hi from other!')
228        self.fd = open(self.samplefile, 'r')
229        self.fd2 = open(self.otherfile, 'r')
230        self.getRootFolder()['app'] = University()
231        self.app = self.getRootFolder()['app']
232        self.app['datacenter'].setStoragePath(self.workdir)
233        # register a custom filename mangler
234        provideUtility(
235            CustomizedFileHandler(), IFileStoreHandler, name=u'mymarker')
236        # register a file chooser adapter for CustomContext
237        provideAdapter(
238            CustomContextFileChooser,
239            (CustomContext,), IFileStoreNameChooser)
240        return
241
242
243    def tearDown(self):
244        super(FunctionalExtFileStoreTests, self).tearDown()
245        self.fd.close()
246        self.fd2.close()
247        shutil.rmtree(self.workdir)
248        if self.root is not None and os.path.exists(self.root):
249            shutil.rmtree(self.root)
250        return
251
252    def test_root_setup_w_site(self):
253        # if a site is available we use it to determine the root dir
254        fs = ExtFileStore()
255        setSite(self.app)
256        self.root = fs.root
257        expected_root = os.path.join(
258            self.app['datacenter'].storage, 'media')
259        self.assertTrue(isinstance(self.root, basestring))
260        self.assertEqual(self.root, expected_root)
261        return
262
263    def test_get_utility(self):
264        # we can get an ExtFileStore by global utility lookup
265        fs1 = getUtility(IExtFileStore)
266        fs2 = getUtility(IExtFileStore)
267        self.assertTrue(isinstance(fs1, ExtFileStore))
268        self.assertTrue(fs1 is fs2)
269        return
270
271    def test_default_handler_create_file(self):
272        # we can use the default handler to store files
273        fs = ExtFileStore(root=self.workdir)
274        result = fs.createFile('sample.txt', StringIO('sample text'))
275        self.assertEqual(result.data, 'sample.txt')
276        self.assertTrue('sample.txt' in os.listdir(fs.root))
277        return
278
279    def test_default_handler_get_file(self):
280        # we can get files stored by the default handler
281        fs = ExtFileStore(root=self.workdir)
282        fs.createFile('sample.txt', StringIO('sample text'))
283        result1 = fs.getFile('sample.txt')
284        result2 = fs.getFile('not-existent')
285        self.assertEqual(result1.read(), 'sample text')
286        self.assertTrue(result2 is None)
287        return
288
289    def test_customized_handler_create_file(self):
290        # we can use registered filename handlers
291        fs = ExtFileStore(root=self.workdir)
292        result = fs.createFile(
293            '__MYMARKER__sample.txt', StringIO('sample text'))
294        self.assertEqual(result.data, '__MYMARKER__sample.txt')
295        self.assertTrue('sample.txt' in os.listdir(fs.root))
296        return
297
298    def test_customized_handler_create_file_w_ext(self):
299        # when we create a file of img type, the filename ext is taken
300        # from input file.
301        fs = ExtFileStore(root=self.workdir)
302        result = fs.createFile(
303            '__MYMARKER__sample_img.png', StringIO('sample text'))
304        self.assertEqual(result.data, '__MYMARKER__sample_img.png')
305        self.assertTrue('sample_img.png' in os.listdir(fs.root))
306        return
307
308    def test_customized_handler_get_file(self):
309        # we consider registered filename handlers when asking for
310        # stored files.
311        fs = ExtFileStore(root=self.workdir)
312        fs.createFile('__MYMARKER__sample.txt', StringIO('sample text'))
313        result1 = fs.getFile('__MYMARKER__sample.txt')
314        result2 = fs.getFile('__MYMARKER__not-existent')
315        result3 = fs.getFile('not-existent')
316        self.assertEqual(result1.read(), 'sample text')
317        self.assertTrue(result2 is None)
318        self.assertTrue(result3 is None)
319        return
320
321    def test_get_file_by_context_w_attr(self):
322        # if we register a file name chooser, we can also get a file
323        # by context and attribute
324        context = CustomContext()
325        file_id1 = IFileStoreNameChooser(context).chooseName()
326        file_id2 = IFileStoreNameChooser(context).chooseName(attr='img')
327        file_id3 = IFileStoreNameChooser(context).chooseName(attr='doc')
328        # create three files for a single context, each with different
329        # content
330        fs = ExtFileStore(root=self.workdir)
331        fs.createFile(file_id1, StringIO('my sample 1'))
332        fs.createFile(file_id2, StringIO('my sample 2'))
333        fs.createFile(file_id3, StringIO('my sample 3'))
334        # now get back all files indicated by different `attr` markers
335        result1 = fs.getFileByContext(context)
336        result2 = fs.getFileByContext(context, attr='img')
337        result3 = fs.getFileByContext(context, attr='doc')
338        # each file has a different file id
339        self.assertEqual(file_id1, '__mymarker__mysample.txt')
340        self.assertEqual(file_id2, '__mymarker__mysample_img.jpg')
341        self.assertEqual(file_id3, '__mymarker__mysample_doc.doc')
342        # each file has different content
343        self.assertEqual(result1.read(), 'my sample 1')
344        self.assertEqual(result2.read(), 'my sample 2')
345        self.assertEqual(result3.read(), 'my sample 3')
346        return
347
348    def test_get_default_handler(self):
349        # we can get a default handler
350        result = queryUtility(IFileStoreHandler)
351        self.assertTrue(
352            isinstance(result, DefaultFileStoreHandler))
353        return
354
355    def test_get_default_file_retrieval(self):
356        # we get a file store when requesting a file retrieval
357        result = queryUtility(IFileRetrieval)
358        self.assertTrue(
359            isinstance(result, DefaultStorage))
360
361    def test_delete_file(self):
362        # we can remove stored files from storage
363        fs = ExtFileStore(root=self.workdir)
364        # First, we store a file in file store
365        fs.createFile('sample.txt', StringIO('sample text'))
366        # Then we delete it
367        fs.deleteFile('sample.txt')
368        # 'Deletion' means, next call to getFile should get None
369        result = fs.getFile('sample.txt')
370        self.assertTrue(result is None)
371        # Hm, okay we can also check, whether it was really deleted
372        self.assertTrue('sample.txt' not in os.listdir(fs.root))
373        return
374
375    def test_delete_file_by_context_w_attr(self):
376        # if we register a file name chooser, we can also delete a file
377        # by context and attribute
378        fs = ExtFileStore(root=self.workdir)
379        context = CustomContext()
380        file_id1 = IFileStoreNameChooser(context).chooseName()
381        file_id2 = IFileStoreNameChooser(context).chooseName(attr='img')
382        file_id3 = IFileStoreNameChooser(context).chooseName(attr='doc')
383        fs = ExtFileStore(root=self.workdir)
384        # create three files for a single context, each which
385        # different content
386        fs.createFile(file_id1, StringIO('my sample 1'))
387        fs.createFile(file_id2, StringIO('my sample 2'))
388        fs.createFile(file_id3, StringIO('my sample 3'))
389        # now delete first two of these files
390        fs.deleteFileByContext(context)
391        fs.deleteFileByContext(context, attr='img')
392        # Following getFile calls should give None for two of the
393        # files.
394        result1 = fs.getFileByContext(context)
395        result2 = fs.getFileByContext(context, attr='img')
396        result3 = fs.getFileByContext(context, attr='doc')
397        self.assertEqual(result1, None)
398        self.assertEqual(result2, None)
399        self.assertEqual(result3.read(), 'my sample 3')
400        return
Note: See TracBrowser for help on using the repository browser.