Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / plankton / tests.py @ cda71050

History | View | Annotate | Download (9.6 kB)

1 37f87d98 Christos Stavrakakis
# Copyright 2012 GRNET S.A. All rights reserved.
2 37f87d98 Christos Stavrakakis
#
3 37f87d98 Christos Stavrakakis
# Redistribution and use in source and binary forms, with or
4 37f87d98 Christos Stavrakakis
# without modification, are permitted provided that the following
5 37f87d98 Christos Stavrakakis
# conditions are met:
6 37f87d98 Christos Stavrakakis
#
7 37f87d98 Christos Stavrakakis
#   1. Redistributions of source code must retain the above
8 37f87d98 Christos Stavrakakis
#      copyright notice, this list of conditions and the following
9 37f87d98 Christos Stavrakakis
#      disclaimer.
10 37f87d98 Christos Stavrakakis
#
11 37f87d98 Christos Stavrakakis
#   2. Redistributions in binary form must reproduce the above
12 37f87d98 Christos Stavrakakis
#      copyright notice, this list of conditions and the following
13 37f87d98 Christos Stavrakakis
#      disclaimer in the documentation and/or other materials
14 37f87d98 Christos Stavrakakis
#      provided with the distribution.
15 37f87d98 Christos Stavrakakis
#
16 37f87d98 Christos Stavrakakis
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 37f87d98 Christos Stavrakakis
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 37f87d98 Christos Stavrakakis
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 37f87d98 Christos Stavrakakis
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 37f87d98 Christos Stavrakakis
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 37f87d98 Christos Stavrakakis
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 37f87d98 Christos Stavrakakis
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 37f87d98 Christos Stavrakakis
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 37f87d98 Christos Stavrakakis
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 37f87d98 Christos Stavrakakis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 37f87d98 Christos Stavrakakis
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 37f87d98 Christos Stavrakakis
# POSSIBILITY OF SUCH DAMAGE.
28 37f87d98 Christos Stavrakakis
#
29 37f87d98 Christos Stavrakakis
# The views and conclusions contained in the software and
30 37f87d98 Christos Stavrakakis
# documentation are those of the authors and should not be
31 37f87d98 Christos Stavrakakis
# interpreted as representing official policies, either expressed
32 37f87d98 Christos Stavrakakis
# or implied, of GRNET S.A.
33 37f87d98 Christos Stavrakakis
34 37f87d98 Christos Stavrakakis
import json
35 37f87d98 Christos Stavrakakis
36 37f87d98 Christos Stavrakakis
from mock import patch
37 37f87d98 Christos Stavrakakis
from functools import wraps
38 37f87d98 Christos Stavrakakis
from copy import deepcopy
39 cda71050 Christos Stavrakakis
from snf_django.utils.testing import BaseAPITest
40 37f87d98 Christos Stavrakakis
41 37f87d98 Christos Stavrakakis
42 37f87d98 Christos Stavrakakis
FILTERS = ('name', 'container_format', 'disk_format', 'status', 'size_min',
43 37f87d98 Christos Stavrakakis
           'size_max')
44 37f87d98 Christos Stavrakakis
PARAMS = ('sort_key', 'sort_dir')
45 37f87d98 Christos Stavrakakis
SORT_KEY_OPTIONS = ('id', 'name', 'status', 'size', 'disk_format',
46 37f87d98 Christos Stavrakakis
                    'container_format', 'created_at', 'updated_at')
47 37f87d98 Christos Stavrakakis
SORT_DIR_OPTIONS = ('asc', 'desc')
48 37f87d98 Christos Stavrakakis
LIST_FIELDS = ('status', 'name', 'disk_format', 'container_format', 'size',
49 37f87d98 Christos Stavrakakis
               'id')
50 37f87d98 Christos Stavrakakis
DETAIL_FIELDS = ('name', 'disk_format', 'container_format', 'size', 'checksum',
51 37f87d98 Christos Stavrakakis
                 'location', 'created_at', 'updated_at', 'deleted_at',
52 37f87d98 Christos Stavrakakis
                 'status', 'is_public', 'owner', 'properties', 'id')
53 37f87d98 Christos Stavrakakis
ADD_FIELDS = ('name', 'id', 'store', 'disk_format', 'container_format', 'size',
54 37f87d98 Christos Stavrakakis
              'checksum', 'is_public', 'owner', 'properties', 'location')
55 37f87d98 Christos Stavrakakis
UPDATE_FIELDS = ('name', 'disk_format', 'container_format', 'is_public',
56 37f87d98 Christos Stavrakakis
                 'owner', 'properties', 'status')
57 37f87d98 Christos Stavrakakis
58 37f87d98 Christos Stavrakakis
59 37f87d98 Christos Stavrakakis
DummyImages = {
60 37f87d98 Christos Stavrakakis
 '0786a349-9725-48ec-8b86-8598eefc4043':
61 37f87d98 Christos Stavrakakis
 {'checksum': u'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855',
62 37f87d98 Christos Stavrakakis
  u'container_format': u'bare',
63 37f87d98 Christos Stavrakakis
  'created_at': '2012-12-04 09:50:20',
64 37f87d98 Christos Stavrakakis
  'deleted_at': '',
65 37f87d98 Christos Stavrakakis
  u'disk_format': u'diskdump',
66 37f87d98 Christos Stavrakakis
  'id': u'0786a349-9725-48ec-8b86-8598eefc4043',
67 37f87d98 Christos Stavrakakis
  'is_public': True,
68 37f87d98 Christos Stavrakakis
  'location': u'pithos://foo@example.com/container/foo3',
69 37f87d98 Christos Stavrakakis
  u'name': u'dummyname',
70 37f87d98 Christos Stavrakakis
  'owner': u'foo@example.com',
71 37f87d98 Christos Stavrakakis
  'properties': {},
72 37f87d98 Christos Stavrakakis
  'size': 500L,
73 37f87d98 Christos Stavrakakis
  u'status': u'available',
74 37f87d98 Christos Stavrakakis
  'store': 'pithos',
75 37f87d98 Christos Stavrakakis
  'updated_at': '2012-12-04 09:50:54'},
76 37f87d98 Christos Stavrakakis
77 37f87d98 Christos Stavrakakis
 'd8aa85b8-410b-4550-953d-6797572534e6':
78 37f87d98 Christos Stavrakakis
 {'checksum': u'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855',
79 37f87d98 Christos Stavrakakis
  u'container_format': u'bare',
80 37f87d98 Christos Stavrakakis
  'created_at': '2012-11-26 11:56:42',
81 37f87d98 Christos Stavrakakis
  'deleted_at': '',
82 37f87d98 Christos Stavrakakis
  u'disk_format': u'diskdump',
83 37f87d98 Christos Stavrakakis
  'id': u'd8aa85b8-410b-4550-953d-6797572534e6',
84 37f87d98 Christos Stavrakakis
  'is_public': False,
85 37f87d98 Christos Stavrakakis
  'location': u'pithos://foo@example.com/container/private',
86 37f87d98 Christos Stavrakakis
  u'name': u'dummyname2',
87 37f87d98 Christos Stavrakakis
  'owner': u'foo@example.com',
88 37f87d98 Christos Stavrakakis
  'properties': {},
89 37f87d98 Christos Stavrakakis
  'size': 10000L,
90 37f87d98 Christos Stavrakakis
  u'status': u'available',
91 37f87d98 Christos Stavrakakis
  'store': 'pithos',
92 37f87d98 Christos Stavrakakis
  'updated_at': '2012-11-26 11:57:09'},
93 37f87d98 Christos Stavrakakis
94 37f87d98 Christos Stavrakakis
 '264fb9ac-2458-421c-b460-6a765a92825c':
95 37f87d98 Christos Stavrakakis
 {'checksum': u'0c6d0586744781218672fff2d7ed94cc32efb02a6a8eb589a0628f0e22bd5a7f',
96 37f87d98 Christos Stavrakakis
  u'container_format': u'bare',
97 37f87d98 Christos Stavrakakis
  'created_at': '2012-11-26 11:52:54',
98 37f87d98 Christos Stavrakakis
  'deleted_at': '',
99 37f87d98 Christos Stavrakakis
  u'disk_format': u'diskdump',
100 37f87d98 Christos Stavrakakis
  'id': u'264fb9ac-2458-421c-b460-6a765a92825c',
101 37f87d98 Christos Stavrakakis
  'is_public': True,
102 37f87d98 Christos Stavrakakis
  'location': u'pithos://foo@example.com/container/baz.diskdump',
103 37f87d98 Christos Stavrakakis
  u'name': u'"dummyname3"',
104 37f87d98 Christos Stavrakakis
  'owner': u'foo@example.com',
105 37f87d98 Christos Stavrakakis
  'properties': {u'description': u'Debian Squeeze Base System',
106 37f87d98 Christos Stavrakakis
                 u'gui': u'No GUI',
107 37f87d98 Christos Stavrakakis
                 u'kernel': u'2.6.32',
108 37f87d98 Christos Stavrakakis
                 u'os': u'debian',
109 37f87d98 Christos Stavrakakis
                 u'osfamily': u'linux',
110 37f87d98 Christos Stavrakakis
                 u'root_partition': u'1',
111 37f87d98 Christos Stavrakakis
                 u'size': u'451',
112 37f87d98 Christos Stavrakakis
                 u'sortorder': u'1',
113 37f87d98 Christos Stavrakakis
                 u'users': u'root'},
114 37f87d98 Christos Stavrakakis
  'size': 473772032L,
115 37f87d98 Christos Stavrakakis
  u'status': u'available',
116 37f87d98 Christos Stavrakakis
  'store': 'pithos',
117 37f87d98 Christos Stavrakakis
  'updated_at': '2012-11-26 11:55:40'}}
118 37f87d98 Christos Stavrakakis
119 37f87d98 Christos Stavrakakis
120 37f87d98 Christos Stavrakakis
def assert_backend_closed(func):
121 37f87d98 Christos Stavrakakis
    @wraps(func)
122 37f87d98 Christos Stavrakakis
    def wrapper(self, backend):
123 37f87d98 Christos Stavrakakis
        result = func(self, backend)
124 37f87d98 Christos Stavrakakis
        if backend.called is True:
125 37f87d98 Christos Stavrakakis
            backend.return_value.close.assert_called_once_with()
126 37f87d98 Christos Stavrakakis
        return result
127 37f87d98 Christos Stavrakakis
    return wrapper
128 37f87d98 Christos Stavrakakis
129 37f87d98 Christos Stavrakakis
130 cda71050 Christos Stavrakakis
@patch("synnefo.plankton.backend.ImageBackend")
131 52194c77 Christos Stavrakakis
class PlanktonTest(BaseAPITest):
132 37f87d98 Christos Stavrakakis
    @assert_backend_closed
133 37f87d98 Christos Stavrakakis
    def test_list_images(self, backend):
134 37f87d98 Christos Stavrakakis
        backend.return_value.list.return_value =\
135 37f87d98 Christos Stavrakakis
                deepcopy(DummyImages).values()
136 37f87d98 Christos Stavrakakis
        response = self.get("/plankton/images/")
137 37f87d98 Christos Stavrakakis
        self.assertSuccess(response)
138 37f87d98 Christos Stavrakakis
        images = json.loads(response.content)
139 37f87d98 Christos Stavrakakis
        for api_image in images:
140 37f87d98 Christos Stavrakakis
            id = api_image['id']
141 37f87d98 Christos Stavrakakis
            pithos_image = dict([(key, val)\
142 37f87d98 Christos Stavrakakis
                                for key, val in DummyImages[id].items()\
143 37f87d98 Christos Stavrakakis
                                if key in LIST_FIELDS])
144 37f87d98 Christos Stavrakakis
            self.assertEqual(api_image, pithos_image)
145 37f87d98 Christos Stavrakakis
        backend.return_value\
146 37f87d98 Christos Stavrakakis
                .list.assert_called_once_with({}, {'sort_key': 'created_at',
147 37f87d98 Christos Stavrakakis
                                                   'sort_dir': 'desc'})
148 37f87d98 Christos Stavrakakis
149 37f87d98 Christos Stavrakakis
    @assert_backend_closed
150 37f87d98 Christos Stavrakakis
    def test_list_images_detail(self, backend):
151 37f87d98 Christos Stavrakakis
        backend.return_value.list.return_value =\
152 37f87d98 Christos Stavrakakis
                deepcopy(DummyImages).values()
153 37f87d98 Christos Stavrakakis
        response = self.get("/plankton/images/detail")
154 37f87d98 Christos Stavrakakis
        self.assertSuccess(response)
155 37f87d98 Christos Stavrakakis
        images = json.loads(response.content)
156 37f87d98 Christos Stavrakakis
        for api_image in images:
157 37f87d98 Christos Stavrakakis
            id = api_image['id']
158 37f87d98 Christos Stavrakakis
            pithos_image = dict([(key, val)\
159 37f87d98 Christos Stavrakakis
                                for key, val in DummyImages[id].items()\
160 37f87d98 Christos Stavrakakis
                                if key in DETAIL_FIELDS])
161 37f87d98 Christos Stavrakakis
            self.assertEqual(api_image, pithos_image)
162 37f87d98 Christos Stavrakakis
        backend.return_value\
163 37f87d98 Christos Stavrakakis
                .list.assert_called_once_with({}, {'sort_key': 'created_at',
164 37f87d98 Christos Stavrakakis
                                                   'sort_dir': 'desc'})
165 37f87d98 Christos Stavrakakis
166 37f87d98 Christos Stavrakakis
    @assert_backend_closed
167 37f87d98 Christos Stavrakakis
    def test_list_images_filters(self, backend):
168 37f87d98 Christos Stavrakakis
        backend.return_value.list.return_value =\
169 37f87d98 Christos Stavrakakis
                deepcopy(DummyImages).values()
170 37f87d98 Christos Stavrakakis
        response = self.get("/plankton/images/?size_max=1000")
171 37f87d98 Christos Stavrakakis
        self.assertSuccess(response)
172 37f87d98 Christos Stavrakakis
        backend.return_value\
173 450a6d2b Christos Stavrakakis
                .list.assert_called_once_with({'size_max': 1000},
174 37f87d98 Christos Stavrakakis
                                              {'sort_key': 'created_at',
175 37f87d98 Christos Stavrakakis
                                               'sort_dir': 'desc'})
176 37f87d98 Christos Stavrakakis
177 37f87d98 Christos Stavrakakis
    @assert_backend_closed
178 450a6d2b Christos Stavrakakis
    def test_list_images_filters_error_1(self, backend):
179 450a6d2b Christos Stavrakakis
        response = self.get("/plankton/images/?size_max=")
180 450a6d2b Christos Stavrakakis
        self.assertBadRequest(response)
181 450a6d2b Christos Stavrakakis
182 450a6d2b Christos Stavrakakis
    @assert_backend_closed
183 450a6d2b Christos Stavrakakis
    def test_list_images_filters_error_2(self, backend):
184 450a6d2b Christos Stavrakakis
        response = self.get("/plankton/images/?size_min=foo")
185 450a6d2b Christos Stavrakakis
        self.assertBadRequest(response)
186 450a6d2b Christos Stavrakakis
187 450a6d2b Christos Stavrakakis
    @assert_backend_closed
188 37f87d98 Christos Stavrakakis
    def test_update_image(self, backend):
189 37f87d98 Christos Stavrakakis
        db_image = DummyImages.values()[0]
190 37f87d98 Christos Stavrakakis
        response = self.put("/plankton/images/%s" % db_image['id'],
191 37f87d98 Christos Stavrakakis
                            json.dumps({}),
192 37f87d98 Christos Stavrakakis
                            'json', HTTP_X_IMAGE_META_OWNER='user2')
193 37f87d98 Christos Stavrakakis
        self.assertSuccess(response)
194 37f87d98 Christos Stavrakakis
        backend.return_value.update.assert_called_once_with(db_image['id'],
195 37f87d98 Christos Stavrakakis
                                                            {"owner": "user2"})
196 37f87d98 Christos Stavrakakis
197 37f87d98 Christos Stavrakakis
    @assert_backend_closed
198 37f87d98 Christos Stavrakakis
    def test_add_image_member(self, backend):
199 37f87d98 Christos Stavrakakis
        image_id = DummyImages.values()[0]['id']
200 37f87d98 Christos Stavrakakis
        response = self.put("/plankton/images/%s/members/user3" % image_id,
201 37f87d98 Christos Stavrakakis
                            json.dumps({}), 'json')
202 37f87d98 Christos Stavrakakis
        self.assertSuccess(response)
203 37f87d98 Christos Stavrakakis
        backend.return_value.add_user.assert_called_once_with(image_id,
204 37f87d98 Christos Stavrakakis
                                                             'user3')
205 37f87d98 Christos Stavrakakis
206 37f87d98 Christos Stavrakakis
    @assert_backend_closed
207 37f87d98 Christos Stavrakakis
    def test_remove_image_member(self, backend):
208 37f87d98 Christos Stavrakakis
        image_id = DummyImages.values()[0]['id']
209 37f87d98 Christos Stavrakakis
        response = self.delete("/plankton/images/%s/members/user3" % image_id)
210 37f87d98 Christos Stavrakakis
        self.assertSuccess(response)
211 37f87d98 Christos Stavrakakis
        backend.return_value.remove_user.assert_called_once_with(image_id,
212 37f87d98 Christos Stavrakakis
                                                                'user3')
213 37f87d98 Christos Stavrakakis
214 37f87d98 Christos Stavrakakis
    @assert_backend_closed
215 37f87d98 Christos Stavrakakis
    def test_add_image(self, backend):
216 37f87d98 Christos Stavrakakis
        response = self.post("/plankton/images/",
217 37f87d98 Christos Stavrakakis
                             json.dumps({}),
218 37f87d98 Christos Stavrakakis
                             'json',
219 37f87d98 Christos Stavrakakis
                             HTTP_X_IMAGE_META_NAME='dummy_name',
220 37f87d98 Christos Stavrakakis
                             HTTP_X_IMAGE_META_OWNER='dummy_owner',
221 37f87d98 Christos Stavrakakis
                             HTTP_X_IMAGE_META_LOCATION='dummy_location')
222 37f87d98 Christos Stavrakakis
        self.assertSuccess(response)
223 37f87d98 Christos Stavrakakis
        backend.return_value.register.assert_called_once_with('dummy_name',
224 37f87d98 Christos Stavrakakis
                                                              'dummy_location',
225 52194c77 Christos Stavrakakis
                                                      {'owner': 'dummy_owner'})
226 37f87d98 Christos Stavrakakis
227 37f87d98 Christos Stavrakakis
    @assert_backend_closed
228 37f87d98 Christos Stavrakakis
    def test_get_image(self, backend):
229 37f87d98 Christos Stavrakakis
        response = self.get("/plankton/images/123")
230 37f87d98 Christos Stavrakakis
        self.assertEqual(response.status_code, 501)
231 f13aab5d Christos Stavrakakis
232 f13aab5d Christos Stavrakakis
    @assert_backend_closed
233 f13aab5d Christos Stavrakakis
    def test_delete_image(self, backend):
234 f13aab5d Christos Stavrakakis
        response = self.delete("/plankton/images/123")
235 f13aab5d Christos Stavrakakis
        self.assertEqual(response.status_code, 204)
236 f13aab5d Christos Stavrakakis
        backend.return_value.unregister.assert_called_once_with('123')
237 f13aab5d Christos Stavrakakis
        backend.return_value._delete.assert_not_called()