root / snf-pithos-app / pithos / api / tests.py @ 5ec446aa
History | View | Annotate | Download (10 kB)
1 | 56f3c759 | Sofia Papagiannaki | # Copyright 2011 GRNET S.A. All rights reserved.
|
---|---|---|---|
2 | 56f3c759 | Sofia Papagiannaki | #
|
3 | 56f3c759 | Sofia Papagiannaki | # Redistribution and use in source and binary forms, with or
|
4 | 56f3c759 | Sofia Papagiannaki | # without modification, are permitted provided that the following
|
5 | 56f3c759 | Sofia Papagiannaki | # conditions are met:
|
6 | 56f3c759 | Sofia Papagiannaki | #
|
7 | 56f3c759 | Sofia Papagiannaki | # 1. Redistributions of source code must retain the above
|
8 | 56f3c759 | Sofia Papagiannaki | # copyright notice, this list of conditions and the following
|
9 | 56f3c759 | Sofia Papagiannaki | # disclaimer.
|
10 | 56f3c759 | Sofia Papagiannaki | #
|
11 | 56f3c759 | Sofia Papagiannaki | # 2. Redistributions in binary form must reproduce the above
|
12 | 56f3c759 | Sofia Papagiannaki | # copyright notice, this list of conditions and the following
|
13 | 56f3c759 | Sofia Papagiannaki | # disclaimer in the documentation and/or other materials
|
14 | 56f3c759 | Sofia Papagiannaki | # provided with the distribution.
|
15 | 56f3c759 | Sofia Papagiannaki | #
|
16 | 56f3c759 | Sofia Papagiannaki | # THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
|
17 | 56f3c759 | Sofia Papagiannaki | # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
18 | 56f3c759 | Sofia Papagiannaki | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
19 | 56f3c759 | Sofia Papagiannaki | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
|
20 | 56f3c759 | Sofia Papagiannaki | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
21 | 56f3c759 | Sofia Papagiannaki | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
22 | 56f3c759 | Sofia Papagiannaki | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
23 | 56f3c759 | Sofia Papagiannaki | # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
24 | 56f3c759 | Sofia Papagiannaki | # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
25 | 56f3c759 | Sofia Papagiannaki | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
26 | 56f3c759 | Sofia Papagiannaki | # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
27 | 56f3c759 | Sofia Papagiannaki | # POSSIBILITY OF SUCH DAMAGE.
|
28 | 56f3c759 | Sofia Papagiannaki | #
|
29 | 56f3c759 | Sofia Papagiannaki | # The views and conclusions contained in the software and
|
30 | 56f3c759 | Sofia Papagiannaki | # documentation are those of the authors and should not be
|
31 | 56f3c759 | Sofia Papagiannaki | # interpreted as representing official policies, either expressed
|
32 | 56f3c759 | Sofia Papagiannaki | # or implied, of GRNET S.A.
|
33 | 56f3c759 | Sofia Papagiannaki | |
34 | 56f3c759 | Sofia Papagiannaki | import unittest |
35 | 56f3c759 | Sofia Papagiannaki | import random |
36 | 56f3c759 | Sofia Papagiannaki | import string |
37 | 56f3c759 | Sofia Papagiannaki | import datetime |
38 | 56f3c759 | Sofia Papagiannaki | import time as _time |
39 | 56f3c759 | Sofia Papagiannaki | |
40 | 56f3c759 | Sofia Papagiannaki | import pithos.api.settings as settings |
41 | 56f3c759 | Sofia Papagiannaki | |
42 | 1896d3e4 | Sofia Papagiannaki | from pithos.api.manage_accounts import ManageAccounts |
43 | 56f3c759 | Sofia Papagiannaki | |
44 | 56f3c759 | Sofia Papagiannaki | def get_random_data(length=500): |
45 | 56f3c759 | Sofia Papagiannaki | char_set = string.ascii_uppercase + string.digits |
46 | 56f3c759 | Sofia Papagiannaki | return ''.join(random.choice(char_set) for x in xrange(length)) |
47 | 56f3c759 | Sofia Papagiannaki | |
48 | 56f3c759 | Sofia Papagiannaki | class TestPublic(unittest.TestCase): |
49 | 56f3c759 | Sofia Papagiannaki | def setUp(self): |
50 | 1896d3e4 | Sofia Papagiannaki | self.utils = ManageAccounts()
|
51 | 56f3c759 | Sofia Papagiannaki | self.backend = self.utils.backend |
52 | 56f3c759 | Sofia Papagiannaki | self.utils.create_account('account') |
53 | 56f3c759 | Sofia Papagiannaki | |
54 | 56f3c759 | Sofia Papagiannaki | def tearDown(self): |
55 | 56f3c759 | Sofia Papagiannaki | self.utils._delete_account('account') |
56 | 56f3c759 | Sofia Papagiannaki | self.utils.cleanup()
|
57 | 56f3c759 | Sofia Papagiannaki | |
58 | 56f3c759 | Sofia Papagiannaki | def assert_not_public_object(self, account, container, object): |
59 | 56f3c759 | Sofia Papagiannaki | public = self.backend.get_object_public(
|
60 | 56f3c759 | Sofia Papagiannaki | account, account, container, object
|
61 | 56f3c759 | Sofia Papagiannaki | ) |
62 | 56f3c759 | Sofia Papagiannaki | self.assertTrue(public == None) |
63 | 56f3c759 | Sofia Papagiannaki | self.assertRaises(
|
64 | 56f3c759 | Sofia Papagiannaki | NameError,
|
65 | 56f3c759 | Sofia Papagiannaki | self.backend.get_public,
|
66 | 56f3c759 | Sofia Papagiannaki | '$$account$$',
|
67 | 56f3c759 | Sofia Papagiannaki | public |
68 | 56f3c759 | Sofia Papagiannaki | ) |
69 | 56f3c759 | Sofia Papagiannaki | self.assertRaises(
|
70 | 56f3c759 | Sofia Papagiannaki | Exception, self.backend._can_read, |
71 | 56f3c759 | Sofia Papagiannaki | '$$account$$', account, container, object |
72 | 56f3c759 | Sofia Papagiannaki | ) |
73 | 56f3c759 | Sofia Papagiannaki | return public
|
74 | 56f3c759 | Sofia Papagiannaki | |
75 | 56f3c759 | Sofia Papagiannaki | def assert_public_object(self, account, container, object): |
76 | 56f3c759 | Sofia Papagiannaki | public = self.backend.get_object_public(
|
77 | 56f3c759 | Sofia Papagiannaki | account, account, container, object
|
78 | 56f3c759 | Sofia Papagiannaki | ) |
79 | 56f3c759 | Sofia Papagiannaki | self.assertTrue(public != None) |
80 | 4a105ce2 | Sofia Papagiannaki | self.assertTrue(len(public) >= settings.PUBLIC_URL_SECURITY) |
81 | 56f3c759 | Sofia Papagiannaki | self.assertTrue(set(public) <= set(settings.PUBLIC_URL_ALPHABET)) |
82 | 56f3c759 | Sofia Papagiannaki | self.assertEqual(
|
83 | 56f3c759 | Sofia Papagiannaki | self.backend.get_public('$$account$$', public), |
84 | 56f3c759 | Sofia Papagiannaki | (account, container, object)
|
85 | 56f3c759 | Sofia Papagiannaki | ) |
86 | 56f3c759 | Sofia Papagiannaki | try:
|
87 | 56f3c759 | Sofia Papagiannaki | self.backend._can_read('$$account$$', account, container, object) |
88 | 56f3c759 | Sofia Papagiannaki | except Exception: |
89 | 56f3c759 | Sofia Papagiannaki | self.fail('Public object should be readable.') |
90 | 56f3c759 | Sofia Papagiannaki | return public
|
91 | 56f3c759 | Sofia Papagiannaki | |
92 | 56f3c759 | Sofia Papagiannaki | def test_set_object_public(self): |
93 | 56f3c759 | Sofia Papagiannaki | self.utils.backend.put_container('account', 'account', 'container') |
94 | 56f3c759 | Sofia Papagiannaki | data = get_random_data(int(random.random()))
|
95 | 56f3c759 | Sofia Papagiannaki | self.utils.create_update_object(
|
96 | 56f3c759 | Sofia Papagiannaki | 'account',
|
97 | 56f3c759 | Sofia Papagiannaki | 'container',
|
98 | 56f3c759 | Sofia Papagiannaki | 'object',
|
99 | 56f3c759 | Sofia Papagiannaki | 'application/octet-stream',
|
100 | 56f3c759 | Sofia Papagiannaki | data |
101 | 56f3c759 | Sofia Papagiannaki | ) |
102 | 56f3c759 | Sofia Papagiannaki | self.assert_not_public_object('account', 'container', 'object') |
103 | 56f3c759 | Sofia Papagiannaki | |
104 | 56f3c759 | Sofia Papagiannaki | self.backend.permissions.public_set(
|
105 | 56f3c759 | Sofia Papagiannaki | 'account/container/object',
|
106 | 4a105ce2 | Sofia Papagiannaki | self.backend.public_url_security,
|
107 | 56f3c759 | Sofia Papagiannaki | self.backend.public_url_alphabet
|
108 | 56f3c759 | Sofia Papagiannaki | ) |
109 | 56f3c759 | Sofia Papagiannaki | self.assert_public_object('account', 'container', 'object') |
110 | 56f3c759 | Sofia Papagiannaki | |
111 | 56f3c759 | Sofia Papagiannaki | def test_set_twice(self): |
112 | 56f3c759 | Sofia Papagiannaki | self.utils.backend.put_container('account', 'account', 'container') |
113 | 56f3c759 | Sofia Papagiannaki | data = get_random_data(int(random.random()))
|
114 | 56f3c759 | Sofia Papagiannaki | self.utils.create_update_object(
|
115 | 56f3c759 | Sofia Papagiannaki | 'account',
|
116 | 56f3c759 | Sofia Papagiannaki | 'container',
|
117 | 56f3c759 | Sofia Papagiannaki | 'object',
|
118 | 56f3c759 | Sofia Papagiannaki | 'application/octet-stream',
|
119 | 56f3c759 | Sofia Papagiannaki | data |
120 | 56f3c759 | Sofia Papagiannaki | ) |
121 | 56f3c759 | Sofia Papagiannaki | self.backend.permissions.public_set(
|
122 | 56f3c759 | Sofia Papagiannaki | 'account/container/object',
|
123 | 4a105ce2 | Sofia Papagiannaki | self.backend.public_url_security,
|
124 | 56f3c759 | Sofia Papagiannaki | self.backend.public_url_alphabet
|
125 | 56f3c759 | Sofia Papagiannaki | ) |
126 | 56f3c759 | Sofia Papagiannaki | public = self.assert_public_object('account', 'container', 'object') |
127 | 56f3c759 | Sofia Papagiannaki | |
128 | 56f3c759 | Sofia Papagiannaki | self.backend.permissions.public_set(
|
129 | 56f3c759 | Sofia Papagiannaki | 'account/container/object',
|
130 | 4a105ce2 | Sofia Papagiannaki | self.backend.public_url_security,
|
131 | 56f3c759 | Sofia Papagiannaki | self.backend.public_url_alphabet
|
132 | 56f3c759 | Sofia Papagiannaki | ) |
133 | 56f3c759 | Sofia Papagiannaki | public2 = self.assert_public_object('account', 'container', 'object') |
134 | 56f3c759 | Sofia Papagiannaki | |
135 | 56f3c759 | Sofia Papagiannaki | self.assertEqual(public, public2)
|
136 | 56f3c759 | Sofia Papagiannaki | |
137 | 56f3c759 | Sofia Papagiannaki | def test_set_unset_set(self): |
138 | 56f3c759 | Sofia Papagiannaki | self.utils.backend.put_container('account', 'account', 'container') |
139 | 56f3c759 | Sofia Papagiannaki | data = get_random_data(int(random.random()))
|
140 | 56f3c759 | Sofia Papagiannaki | self.utils.create_update_object(
|
141 | 56f3c759 | Sofia Papagiannaki | 'account',
|
142 | 56f3c759 | Sofia Papagiannaki | 'container',
|
143 | 56f3c759 | Sofia Papagiannaki | 'object',
|
144 | 56f3c759 | Sofia Papagiannaki | 'application/octet-stream',
|
145 | 56f3c759 | Sofia Papagiannaki | data |
146 | 56f3c759 | Sofia Papagiannaki | ) |
147 | 56f3c759 | Sofia Papagiannaki | self.backend.permissions.public_set(
|
148 | 56f3c759 | Sofia Papagiannaki | 'account/container/object',
|
149 | 4a105ce2 | Sofia Papagiannaki | self.backend.public_url_security,
|
150 | 56f3c759 | Sofia Papagiannaki | self.backend.public_url_alphabet
|
151 | 56f3c759 | Sofia Papagiannaki | ) |
152 | 56f3c759 | Sofia Papagiannaki | public = self.assert_public_object('account', 'container', 'object') |
153 | 56f3c759 | Sofia Papagiannaki | |
154 | 56f3c759 | Sofia Papagiannaki | self.backend.permissions.public_unset('account/container/object') |
155 | 56f3c759 | Sofia Papagiannaki | self.assert_not_public_object('account', 'container', 'object') |
156 | 56f3c759 | Sofia Papagiannaki | |
157 | 56f3c759 | Sofia Papagiannaki | self.backend.permissions.public_set(
|
158 | 56f3c759 | Sofia Papagiannaki | 'account/container/object',
|
159 | 4a105ce2 | Sofia Papagiannaki | self.backend.public_url_security,
|
160 | 56f3c759 | Sofia Papagiannaki | self.backend.public_url_alphabet
|
161 | 56f3c759 | Sofia Papagiannaki | ) |
162 | 56f3c759 | Sofia Papagiannaki | public3 = self.assert_public_object('account', 'container', 'object') |
163 | 56f3c759 | Sofia Papagiannaki | |
164 | 56f3c759 | Sofia Papagiannaki | self.assertTrue(public != public3)
|
165 | 56f3c759 | Sofia Papagiannaki | |
166 | 56f3c759 | Sofia Papagiannaki | def test_update_object_public(self): |
167 | 56f3c759 | Sofia Papagiannaki | self.utils.backend.put_container('account', 'account', 'container') |
168 | 56f3c759 | Sofia Papagiannaki | data = get_random_data(int(random.random()))
|
169 | 56f3c759 | Sofia Papagiannaki | self.utils.create_update_object(
|
170 | 56f3c759 | Sofia Papagiannaki | 'account',
|
171 | 56f3c759 | Sofia Papagiannaki | 'container',
|
172 | 56f3c759 | Sofia Papagiannaki | 'object',
|
173 | 56f3c759 | Sofia Papagiannaki | 'application/octet-stream',
|
174 | 56f3c759 | Sofia Papagiannaki | data |
175 | 56f3c759 | Sofia Papagiannaki | ) |
176 | 56f3c759 | Sofia Papagiannaki | |
177 | 56f3c759 | Sofia Papagiannaki | self.backend.update_object_public(
|
178 | 56f3c759 | Sofia Papagiannaki | 'account', 'account', 'container', 'object', public=False |
179 | 56f3c759 | Sofia Papagiannaki | ) |
180 | 56f3c759 | Sofia Papagiannaki | self.assert_not_public_object('account', 'container', 'object') |
181 | 56f3c759 | Sofia Papagiannaki | |
182 | 56f3c759 | Sofia Papagiannaki | self.backend.update_object_public(
|
183 | 56f3c759 | Sofia Papagiannaki | 'account', 'account', 'container', 'object', public=True |
184 | 56f3c759 | Sofia Papagiannaki | ) |
185 | 56f3c759 | Sofia Papagiannaki | public = self.assert_public_object('account', 'container', 'object') |
186 | 56f3c759 | Sofia Papagiannaki | |
187 | 56f3c759 | Sofia Papagiannaki | self.backend.update_object_public(
|
188 | 56f3c759 | Sofia Papagiannaki | 'account', 'account', 'container', 'object', public=False |
189 | 56f3c759 | Sofia Papagiannaki | ) |
190 | 56f3c759 | Sofia Papagiannaki | self.assert_not_public_object('account', 'container', 'object') |
191 | 56f3c759 | Sofia Papagiannaki | |
192 | 56f3c759 | Sofia Papagiannaki | self.backend.update_object_public(
|
193 | 56f3c759 | Sofia Papagiannaki | 'account', 'account', 'container', 'object', public=True |
194 | 56f3c759 | Sofia Papagiannaki | ) |
195 | 56f3c759 | Sofia Papagiannaki | new_public = self.assert_public_object('account', 'container', 'object') |
196 | 56f3c759 | Sofia Papagiannaki | self.assertTrue(public != new_public)
|
197 | 56f3c759 | Sofia Papagiannaki | |
198 | 56f3c759 | Sofia Papagiannaki | def test_delete_not_public_object(self): |
199 | 56f3c759 | Sofia Papagiannaki | self.utils.backend.put_container('account', 'account', 'container') |
200 | 56f3c759 | Sofia Papagiannaki | data = get_random_data(int(random.random()))
|
201 | 56f3c759 | Sofia Papagiannaki | self.utils.create_update_object(
|
202 | 56f3c759 | Sofia Papagiannaki | 'account',
|
203 | 56f3c759 | Sofia Papagiannaki | 'container',
|
204 | 56f3c759 | Sofia Papagiannaki | 'object',
|
205 | 56f3c759 | Sofia Papagiannaki | 'application/octet-stream',
|
206 | 56f3c759 | Sofia Papagiannaki | data |
207 | 56f3c759 | Sofia Papagiannaki | ) |
208 | 56f3c759 | Sofia Papagiannaki | self.assert_not_public_object('account', 'container', 'object') |
209 | 56f3c759 | Sofia Papagiannaki | |
210 | 56f3c759 | Sofia Papagiannaki | self.backend.delete_object('account', 'account', 'container', 'object') |
211 | 56f3c759 | Sofia Papagiannaki | |
212 | 56f3c759 | Sofia Papagiannaki | self.assert_not_public_object('account', 'container', 'object') |
213 | 56f3c759 | Sofia Papagiannaki | |
214 | 56f3c759 | Sofia Papagiannaki | def test_delete_public_object(self): |
215 | 56f3c759 | Sofia Papagiannaki | self.utils.backend.put_container('account', 'account', 'container') |
216 | 56f3c759 | Sofia Papagiannaki | data = get_random_data(int(random.random()))
|
217 | 56f3c759 | Sofia Papagiannaki | self.utils.create_update_object(
|
218 | 56f3c759 | Sofia Papagiannaki | 'account',
|
219 | 56f3c759 | Sofia Papagiannaki | 'container',
|
220 | 56f3c759 | Sofia Papagiannaki | 'object',
|
221 | 56f3c759 | Sofia Papagiannaki | 'application/octet-stream',
|
222 | 56f3c759 | Sofia Papagiannaki | data |
223 | 56f3c759 | Sofia Papagiannaki | ) |
224 | 56f3c759 | Sofia Papagiannaki | self.assert_not_public_object('account', 'container', 'object') |
225 | 56f3c759 | Sofia Papagiannaki | |
226 | 56f3c759 | Sofia Papagiannaki | self.backend.permissions.public_set(
|
227 | 56f3c759 | Sofia Papagiannaki | 'account/container/object',
|
228 | 4a105ce2 | Sofia Papagiannaki | self.backend.public_url_security,
|
229 | 56f3c759 | Sofia Papagiannaki | self.backend.public_url_alphabet
|
230 | 56f3c759 | Sofia Papagiannaki | ) |
231 | 56f3c759 | Sofia Papagiannaki | self.assert_public_object('account', 'container', 'object') |
232 | 56f3c759 | Sofia Papagiannaki | |
233 | 56f3c759 | Sofia Papagiannaki | self.backend.delete_object('account', 'account', 'container', 'object') |
234 | 56f3c759 | Sofia Papagiannaki | self.assert_not_public_object('account', 'container', 'object') |
235 | 56f3c759 | Sofia Papagiannaki | |
236 | 56f3c759 | Sofia Papagiannaki | def test_delete_public_object_history(self): |
237 | 56f3c759 | Sofia Papagiannaki | self.utils.backend.put_container('account', 'account', 'container') |
238 | 56f3c759 | Sofia Papagiannaki | for i in range(random.randint(1, 10)): |
239 | 56f3c759 | Sofia Papagiannaki | data = get_random_data(int(random.random()))
|
240 | 56f3c759 | Sofia Papagiannaki | self.utils.create_update_object(
|
241 | 56f3c759 | Sofia Papagiannaki | 'account',
|
242 | 56f3c759 | Sofia Papagiannaki | 'container',
|
243 | 56f3c759 | Sofia Papagiannaki | 'object',
|
244 | 56f3c759 | Sofia Papagiannaki | 'application/octet-stream',
|
245 | 56f3c759 | Sofia Papagiannaki | data |
246 | 56f3c759 | Sofia Papagiannaki | ) |
247 | 56f3c759 | Sofia Papagiannaki | _time.sleep(1)
|
248 | 56f3c759 | Sofia Papagiannaki | versions = self.backend.list_versions(
|
249 | 56f3c759 | Sofia Papagiannaki | 'account', 'account', 'container', 'object' |
250 | 56f3c759 | Sofia Papagiannaki | ) |
251 | 56f3c759 | Sofia Papagiannaki | mtime = [int(i[1]) for i in versions] |
252 | 56f3c759 | Sofia Papagiannaki | self.assert_not_public_object('account', 'container', 'object') |
253 | 56f3c759 | Sofia Papagiannaki | |
254 | 56f3c759 | Sofia Papagiannaki | self.backend.permissions.public_set(
|
255 | 56f3c759 | Sofia Papagiannaki | 'account/container/object',
|
256 | 4a105ce2 | Sofia Papagiannaki | self.backend.public_url_security,
|
257 | 56f3c759 | Sofia Papagiannaki | self.backend.public_url_alphabet
|
258 | 56f3c759 | Sofia Papagiannaki | ) |
259 | 56f3c759 | Sofia Papagiannaki | public = self.assert_public_object('account', 'container', 'object') |
260 | 56f3c759 | Sofia Papagiannaki | |
261 | 56f3c759 | Sofia Papagiannaki | i = random.randrange(len(mtime))
|
262 | 56f3c759 | Sofia Papagiannaki | self.backend.delete_object(
|
263 | 56f3c759 | Sofia Papagiannaki | 'account', 'account', 'container', 'object', until=mtime[i] |
264 | 56f3c759 | Sofia Papagiannaki | ) |
265 | 56f3c759 | Sofia Papagiannaki | self.assert_public_object('account', 'container', 'object') |
266 | 56f3c759 | Sofia Papagiannaki | public = self.assert_public_object('account', 'container', 'object') |
267 | 56f3c759 | Sofia Papagiannaki | |
268 | 56f3c759 | Sofia Papagiannaki | _time.sleep(1)
|
269 | 56f3c759 | Sofia Papagiannaki | t = datetime.datetime.utcnow() |
270 | 56f3c759 | Sofia Papagiannaki | now = int(_time.mktime(t.timetuple()))
|
271 | 56f3c759 | Sofia Papagiannaki | self.backend.delete_object(
|
272 | 56f3c759 | Sofia Papagiannaki | 'account', 'account', 'container', 'object', until=now |
273 | 56f3c759 | Sofia Papagiannaki | ) |
274 | 56f3c759 | Sofia Papagiannaki | self.assertRaises(
|
275 | 56f3c759 | Sofia Papagiannaki | NameError,
|
276 | 56f3c759 | Sofia Papagiannaki | self.backend.get_public,
|
277 | 56f3c759 | Sofia Papagiannaki | '$$account$$',
|
278 | 56f3c759 | Sofia Papagiannaki | public |
279 | 56f3c759 | Sofia Papagiannaki | ) |
280 | 56f3c759 | Sofia Papagiannaki | |
281 | 56f3c759 | Sofia Papagiannaki | if __name__ == '__main__': |
282 | 56f3c759 | Sofia Papagiannaki | unittest.main() |