source: main/waeup.sirp/branches/henrik-bootstrap/src/waeup/sirp/tests/test_imagestorage.py @ 10807

Last change on this file since 10807 was 7193, checked in by Henrik Bettermann, 13 years ago

More copyright adjustments.

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