Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / api / tests / images.py @ 0c09b1c0

History | View | Annotate | Download (15.7 kB)

1 039e3e61 Christos Stavrakakis
# Copyright 2012 GRNET S.A. All rights reserved.
2 039e3e61 Christos Stavrakakis
#
3 039e3e61 Christos Stavrakakis
# Redistribution and use in source and binary forms, with or
4 039e3e61 Christos Stavrakakis
# without modification, are permitted provided that the following
5 039e3e61 Christos Stavrakakis
# conditions are met:
6 039e3e61 Christos Stavrakakis
#
7 039e3e61 Christos Stavrakakis
#   1. Redistributions of source code must retain the above
8 039e3e61 Christos Stavrakakis
#      copyright notice, this list of conditions and the following
9 039e3e61 Christos Stavrakakis
#      disclaimer.
10 039e3e61 Christos Stavrakakis
#
11 039e3e61 Christos Stavrakakis
#   2. Redistributions in binary form must reproduce the above
12 039e3e61 Christos Stavrakakis
#      copyright notice, this list of conditions and the following
13 039e3e61 Christos Stavrakakis
#      disclaimer in the documentation and/or other materials
14 039e3e61 Christos Stavrakakis
#      provided with the distribution.
15 039e3e61 Christos Stavrakakis
#
16 039e3e61 Christos Stavrakakis
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 039e3e61 Christos Stavrakakis
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 039e3e61 Christos Stavrakakis
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 039e3e61 Christos Stavrakakis
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 039e3e61 Christos Stavrakakis
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 039e3e61 Christos Stavrakakis
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 039e3e61 Christos Stavrakakis
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 039e3e61 Christos Stavrakakis
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 039e3e61 Christos Stavrakakis
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 039e3e61 Christos Stavrakakis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 039e3e61 Christos Stavrakakis
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 039e3e61 Christos Stavrakakis
# POSSIBILITY OF SUCH DAMAGE.
28 039e3e61 Christos Stavrakakis
#
29 039e3e61 Christos Stavrakakis
# The views and conclusions contained in the software and
30 039e3e61 Christos Stavrakakis
# documentation are those of the authors and should not be
31 039e3e61 Christos Stavrakakis
# interpreted as representing official policies, either expressed
32 039e3e61 Christos Stavrakakis
# or implied, of GRNET S.A.
33 039e3e61 Christos Stavrakakis
34 039e3e61 Christos Stavrakakis
import json
35 039e3e61 Christos Stavrakakis
36 bd40abfa Christos Stavrakakis
from snf_django.lib.api import faults
37 d2b8ec7b Christos Stavrakakis
from snf_django.utils.testing import BaseAPITest
38 dc99330c Georgios D. Tsoukalas
from synnefo.lib.services import get_service_path
39 dc99330c Georgios D. Tsoukalas
from synnefo.cyclades_settings import cyclades_services
40 dc99330c Georgios D. Tsoukalas
from synnefo.lib import join_urls
41 039e3e61 Christos Stavrakakis
42 039e3e61 Christos Stavrakakis
from mock import patch
43 039e3e61 Christos Stavrakakis
from functools import wraps
44 039e3e61 Christos Stavrakakis
45 039e3e61 Christos Stavrakakis
46 039e3e61 Christos Stavrakakis
def assert_backend_closed(func):
47 039e3e61 Christos Stavrakakis
    """Decorator for ensuring that ImageBackend is returned to pool."""
48 039e3e61 Christos Stavrakakis
    @wraps(func)
49 039e3e61 Christos Stavrakakis
    def wrapper(self, backend):
50 039e3e61 Christos Stavrakakis
        result = func(self, backend)
51 039e3e61 Christos Stavrakakis
        if backend.called is True:
52 184a2a8c Christos Stavrakakis
            backend.return_value.close.asssert_called
53 039e3e61 Christos Stavrakakis
        return result
54 039e3e61 Christos Stavrakakis
    return wrapper
55 039e3e61 Christos Stavrakakis
56 039e3e61 Christos Stavrakakis
57 dc99330c Georgios D. Tsoukalas
class ComputeAPITest(BaseAPITest):
58 dc99330c Georgios D. Tsoukalas
    def setUp(self, *args, **kwargs):
59 dc99330c Georgios D. Tsoukalas
        super(ComputeAPITest, self).setUp(*args, **kwargs)
60 dc99330c Georgios D. Tsoukalas
        self.compute_path = get_service_path(cyclades_services, 'compute',
61 dc99330c Georgios D. Tsoukalas
                                             version='v2.0')
62 dc99330c Georgios D. Tsoukalas
    def myget(self, path, *args, **kwargs):
63 dc99330c Georgios D. Tsoukalas
        path = join_urls(self.compute_path, path)
64 dc99330c Georgios D. Tsoukalas
        return self.get(path, *args, **kwargs)
65 dc99330c Georgios D. Tsoukalas
66 dc99330c Georgios D. Tsoukalas
    def myput(self, path, *args, **kwargs):
67 dc99330c Georgios D. Tsoukalas
        path = join_urls(self.compute_path, path)
68 dc99330c Georgios D. Tsoukalas
        return self.put(path, *args, **kwargs)
69 dc99330c Georgios D. Tsoukalas
70 dc99330c Georgios D. Tsoukalas
    def mypost(self, path, *args, **kwargs):
71 dc99330c Georgios D. Tsoukalas
        path = join_urls(self.compute_path, path)
72 dc99330c Georgios D. Tsoukalas
        return self.post(path, *args, **kwargs)
73 dc99330c Georgios D. Tsoukalas
74 dc99330c Georgios D. Tsoukalas
    def mydelete(self, path, *args, **kwargs):
75 dc99330c Georgios D. Tsoukalas
        path = join_urls(self.compute_path, path)
76 dc99330c Georgios D. Tsoukalas
        return self.delete(path, *args, **kwargs)
77 dc99330c Georgios D. Tsoukalas
78 dc99330c Georgios D. Tsoukalas
79 cda71050 Christos Stavrakakis
@patch('synnefo.plankton.backend.ImageBackend')
80 dc99330c Georgios D. Tsoukalas
class ImageAPITest(ComputeAPITest):
81 039e3e61 Christos Stavrakakis
    @assert_backend_closed
82 039e3e61 Christos Stavrakakis
    def test_create_image(self, mimage):
83 039e3e61 Christos Stavrakakis
        """Test that create image is not implemented"""
84 dc99330c Georgios D. Tsoukalas
        response = self.mypost('images/', 'user', json.dumps(''), 'json')
85 bd40abfa Christos Stavrakakis
        self.assertEqual(response.status_code, 501)
86 039e3e61 Christos Stavrakakis
87 039e3e61 Christos Stavrakakis
    @assert_backend_closed
88 039e3e61 Christos Stavrakakis
    def test_list_images(self, mimage):
89 039e3e61 Christos Stavrakakis
        """Test that expected list of images is returned"""
90 039e3e61 Christos Stavrakakis
        images = [{'id': 1, 'name': 'image-1'},
91 039e3e61 Christos Stavrakakis
                  {'id': 2, 'name': 'image-2'},
92 039e3e61 Christos Stavrakakis
                  {'id': 3, 'name': 'image-3'}]
93 14c94c48 Christos Stavrakakis
        mimage().list_images.return_value = images
94 dc99330c Georgios D. Tsoukalas
        response = self.myget('images', 'user')
95 039e3e61 Christos Stavrakakis
        self.assertSuccess(response)
96 2d04422f Christos Stavrakakis
        api_images = json.loads(response.content)['images']
97 039e3e61 Christos Stavrakakis
        self.assertEqual(images, api_images)
98 039e3e61 Christos Stavrakakis
99 039e3e61 Christos Stavrakakis
    @assert_backend_closed
100 039e3e61 Christos Stavrakakis
    def test_list_images_detail(self, mimage):
101 039e3e61 Christos Stavrakakis
        images = [{'id': 1,
102 039e3e61 Christos Stavrakakis
                   'name': 'image-1',
103 039e3e61 Christos Stavrakakis
                   'status':'available',
104 039e3e61 Christos Stavrakakis
                   'created_at': '2012-11-26 11:52:54',
105 039e3e61 Christos Stavrakakis
                   'updated_at': '2012-12-26 11:52:54',
106 936e0be3 Christos Stavrakakis
                   'owner': 'user1',
107 039e3e61 Christos Stavrakakis
                   'deleted_at': '',
108 039e3e61 Christos Stavrakakis
                   'properties': {'foo':'bar'}},
109 039e3e61 Christos Stavrakakis
                  {'id': 2,
110 039e3e61 Christos Stavrakakis
                   'name': 'image-2',
111 039e3e61 Christos Stavrakakis
                   'status': 'deleted',
112 039e3e61 Christos Stavrakakis
                   'created_at': '2012-11-26 11:52:54',
113 039e3e61 Christos Stavrakakis
                   'updated_at': '2012-12-26 11:52:54',
114 936e0be3 Christos Stavrakakis
                   'owner': 'user1',
115 039e3e61 Christos Stavrakakis
                   'deleted_at': '2012-12-27 11:52:54',
116 039e3e61 Christos Stavrakakis
                   'properties': ''},
117 039e3e61 Christos Stavrakakis
                  {'id': 3,
118 039e3e61 Christos Stavrakakis
                   'name': 'image-3',
119 039e3e61 Christos Stavrakakis
                   'status': 'available',
120 039e3e61 Christos Stavrakakis
                   'created_at': '2012-11-26 11:52:54',
121 039e3e61 Christos Stavrakakis
                   'deleted_at': '',
122 039e3e61 Christos Stavrakakis
                   'updated_at': '2012-12-26 11:52:54',
123 936e0be3 Christos Stavrakakis
                   'owner': 'user1',
124 039e3e61 Christos Stavrakakis
                   'properties': ''}]
125 039e3e61 Christos Stavrakakis
        result_images = [
126 039e3e61 Christos Stavrakakis
                  {'id': 1,
127 039e3e61 Christos Stavrakakis
                   'name': 'image-1',
128 039e3e61 Christos Stavrakakis
                   'status':'ACTIVE',
129 039e3e61 Christos Stavrakakis
                   'progress': 100,
130 039e3e61 Christos Stavrakakis
                   'created': '2012-11-26T11:52:54+00:00',
131 039e3e61 Christos Stavrakakis
                   'updated': '2012-12-26T11:52:54+00:00',
132 936e0be3 Christos Stavrakakis
                   'user_id': 'user1',
133 c25cf3ea Christos Stavrakakis
                   'tenant_id': 'user1',
134 2d04422f Christos Stavrakakis
                   'metadata': {'foo':'bar'}},
135 039e3e61 Christos Stavrakakis
                  {'id': 2,
136 039e3e61 Christos Stavrakakis
                   'name': 'image-2',
137 039e3e61 Christos Stavrakakis
                   'status': 'DELETED',
138 039e3e61 Christos Stavrakakis
                   'progress': 0,
139 936e0be3 Christos Stavrakakis
                   'user_id': 'user1',
140 c25cf3ea Christos Stavrakakis
                   'tenant_id': 'user1',
141 039e3e61 Christos Stavrakakis
                   'created': '2012-11-26T11:52:54+00:00',
142 936e0be3 Christos Stavrakakis
                   'updated': '2012-12-26T11:52:54+00:00',
143 936e0be3 Christos Stavrakakis
                   'metadata': {}},
144 039e3e61 Christos Stavrakakis
                  {'id': 3,
145 039e3e61 Christos Stavrakakis
                   'name': 'image-3',
146 039e3e61 Christos Stavrakakis
                   'status': 'ACTIVE',
147 039e3e61 Christos Stavrakakis
                   'progress': 100,
148 936e0be3 Christos Stavrakakis
                   'user_id': 'user1',
149 c25cf3ea Christos Stavrakakis
                   'tenant_id': 'user1',
150 039e3e61 Christos Stavrakakis
                   'created': '2012-11-26T11:52:54+00:00',
151 936e0be3 Christos Stavrakakis
                   'updated': '2012-12-26T11:52:54+00:00',
152 936e0be3 Christos Stavrakakis
                   'metadata': {}}]
153 14c94c48 Christos Stavrakakis
        mimage().list_images.return_value = images
154 dc99330c Georgios D. Tsoukalas
        response = self.myget('images/detail', 'user')
155 039e3e61 Christos Stavrakakis
        self.assertSuccess(response)
156 2d04422f Christos Stavrakakis
        api_images = json.loads(response.content)['images']
157 039e3e61 Christos Stavrakakis
        self.assertEqual(len(result_images), len(api_images))
158 c25cf3ea Christos Stavrakakis
        map(lambda image: image.pop("links"), api_images)
159 039e3e61 Christos Stavrakakis
        self.assertEqual(result_images, api_images)
160 039e3e61 Christos Stavrakakis
161 039e3e61 Christos Stavrakakis
    @assert_backend_closed
162 039e3e61 Christos Stavrakakis
    def test_list_images_detail_since(self, mimage):
163 039e3e61 Christos Stavrakakis
        from datetime import datetime, timedelta
164 039e3e61 Christos Stavrakakis
        from time import sleep
165 039e3e61 Christos Stavrakakis
        old_time = datetime.now()
166 039e3e61 Christos Stavrakakis
        new_time = old_time + timedelta(seconds=0.1)
167 039e3e61 Christos Stavrakakis
        sleep(0.1)
168 039e3e61 Christos Stavrakakis
        images = [
169 039e3e61 Christos Stavrakakis
                  {'id': 1,
170 039e3e61 Christos Stavrakakis
                   'name': 'image-1',
171 039e3e61 Christos Stavrakakis
                   'status':'available',
172 039e3e61 Christos Stavrakakis
                   'progress': 100,
173 039e3e61 Christos Stavrakakis
                   'created_at': old_time.isoformat(),
174 039e3e61 Christos Stavrakakis
                   'deleted_at': '',
175 039e3e61 Christos Stavrakakis
                   'updated_at': old_time.isoformat(),
176 936e0be3 Christos Stavrakakis
                   'owner': 'user1',
177 039e3e61 Christos Stavrakakis
                   'properties': ''},
178 039e3e61 Christos Stavrakakis
                  {'id': 2,
179 039e3e61 Christos Stavrakakis
                   'name': 'image-2',
180 039e3e61 Christos Stavrakakis
                   'status': 'deleted',
181 039e3e61 Christos Stavrakakis
                   'progress': 0,
182 936e0be3 Christos Stavrakakis
                   'owner': 'user2',
183 039e3e61 Christos Stavrakakis
                   'created_at': new_time.isoformat(),
184 039e3e61 Christos Stavrakakis
                   'updated_at': new_time.isoformat(),
185 039e3e61 Christos Stavrakakis
                   'deleted_at': new_time.isoformat(),
186 039e3e61 Christos Stavrakakis
                   'properties': ''}]
187 14c94c48 Christos Stavrakakis
        mimage().list_images.return_value = images
188 039e3e61 Christos Stavrakakis
        response =\
189 dc99330c Georgios D. Tsoukalas
            self.myget('images/detail?changes-since=%sUTC' % new_time)
190 039e3e61 Christos Stavrakakis
        self.assertSuccess(response)
191 2d04422f Christos Stavrakakis
        api_images = json.loads(response.content)['images']
192 039e3e61 Christos Stavrakakis
        self.assertEqual(1, len(api_images))
193 039e3e61 Christos Stavrakakis
194 039e3e61 Christos Stavrakakis
    @assert_backend_closed
195 039e3e61 Christos Stavrakakis
    def test_get_image_details(self, mimage):
196 039e3e61 Christos Stavrakakis
        image = {'id': 42,
197 039e3e61 Christos Stavrakakis
                 'name': 'image-1',
198 039e3e61 Christos Stavrakakis
                 'status': 'available',
199 039e3e61 Christos Stavrakakis
                 'created_at': '2012-11-26 11:52:54',
200 039e3e61 Christos Stavrakakis
                 'updated_at': '2012-12-26 11:52:54',
201 039e3e61 Christos Stavrakakis
                 'deleted_at': '',
202 936e0be3 Christos Stavrakakis
                 'owner': 'user1',
203 039e3e61 Christos Stavrakakis
                 'properties': {'foo': 'bar'}}
204 039e3e61 Christos Stavrakakis
        result_image = \
205 039e3e61 Christos Stavrakakis
                  {'id': 42,
206 039e3e61 Christos Stavrakakis
                   'name': 'image-1',
207 039e3e61 Christos Stavrakakis
                   'status': 'ACTIVE',
208 039e3e61 Christos Stavrakakis
                   'progress': 100,
209 039e3e61 Christos Stavrakakis
                   'created': '2012-11-26T11:52:54+00:00',
210 039e3e61 Christos Stavrakakis
                   'updated': '2012-12-26T11:52:54+00:00',
211 936e0be3 Christos Stavrakakis
                   'user_id': 'user1',
212 c25cf3ea Christos Stavrakakis
                   'tenant_id': 'user1',
213 2d04422f Christos Stavrakakis
                   'metadata': {'foo': 'bar'}}
214 cda71050 Christos Stavrakakis
        mimage.return_value.get_image.return_value = image
215 dc99330c Georgios D. Tsoukalas
        response = self.myget('images/42', 'user')
216 039e3e61 Christos Stavrakakis
        self.assertSuccess(response)
217 039e3e61 Christos Stavrakakis
        api_image = json.loads(response.content)['image']
218 c25cf3ea Christos Stavrakakis
        api_image.pop("links")
219 039e3e61 Christos Stavrakakis
        self.assertEqual(api_image, result_image)
220 039e3e61 Christos Stavrakakis
221 039e3e61 Christos Stavrakakis
    @assert_backend_closed
222 039e3e61 Christos Stavrakakis
    def test_invalid_image(self, mimage):
223 cda71050 Christos Stavrakakis
        mimage.return_value.get_image.side_effect = faults.ItemNotFound('Image not found')
224 dc99330c Georgios D. Tsoukalas
        response = self.myget('images/42', 'user')
225 039e3e61 Christos Stavrakakis
        self.assertItemNotFound(response)
226 039e3e61 Christos Stavrakakis
227 cda71050 Christos Stavrakakis
    @assert_backend_closed
228 039e3e61 Christos Stavrakakis
    def test_delete_image(self, mimage):
229 dc99330c Georgios D. Tsoukalas
        response = self.mydelete("images/42", "user")
230 039e3e61 Christos Stavrakakis
        self.assertEqual(response.status_code, 204)
231 f13aab5d Christos Stavrakakis
        mimage.return_value.unregister.assert_called_once_with('42')
232 f13aab5d Christos Stavrakakis
        mimage.return_value._delete.assert_not_called('42')
233 039e3e61 Christos Stavrakakis
234 a3accf03 Georgios D. Tsoukalas
    @assert_backend_closed
235 a3accf03 Georgios D. Tsoukalas
    def test_catch_wrong_api_paths(self, *args):
236 a3accf03 Georgios D. Tsoukalas
        response = self.myget('nonexistent')
237 a3accf03 Georgios D. Tsoukalas
        self.assertEqual(response.status_code, 400)
238 a3accf03 Georgios D. Tsoukalas
        try:
239 a3accf03 Georgios D. Tsoukalas
            error = json.loads(response.content)
240 a3accf03 Georgios D. Tsoukalas
        except ValueError:
241 a3accf03 Georgios D. Tsoukalas
            self.assertTrue(False)
242 a3accf03 Georgios D. Tsoukalas
243 16437e4d Kostas Papadimitriou
    @assert_backend_closed
244 16437e4d Kostas Papadimitriou
    def test_method_not_allowed(self, *args):
245 16437e4d Kostas Papadimitriou
        # /images/ allows only POST, GET
246 16437e4d Kostas Papadimitriou
        response = self.myput('images', '', '')
247 16437e4d Kostas Papadimitriou
        self.assertMethodNotAllowed(response)
248 16437e4d Kostas Papadimitriou
        response = self.mydelete('images')
249 16437e4d Kostas Papadimitriou
        self.assertMethodNotAllowed(response)
250 16437e4d Kostas Papadimitriou
251 16437e4d Kostas Papadimitriou
        # /images/<imgid>/ allows only GET, DELETE
252 16437e4d Kostas Papadimitriou
        response = self.mypost("images/42")
253 16437e4d Kostas Papadimitriou
        self.assertMethodNotAllowed(response)
254 16437e4d Kostas Papadimitriou
        response = self.myput('images/42', '', '')
255 16437e4d Kostas Papadimitriou
        self.assertMethodNotAllowed(response)
256 16437e4d Kostas Papadimitriou
257 16437e4d Kostas Papadimitriou
        # /images/<imgid>/metadata/ allows only POST, GET
258 16437e4d Kostas Papadimitriou
        response = self.myput('images/42/metadata', '', '')
259 16437e4d Kostas Papadimitriou
        self.assertMethodNotAllowed(response)
260 16437e4d Kostas Papadimitriou
        response = self.mydelete('images/42/metadata')
261 16437e4d Kostas Papadimitriou
        self.assertMethodNotAllowed(response)
262 16437e4d Kostas Papadimitriou
263 16437e4d Kostas Papadimitriou
        # /images/<imgid>/metadata/ allows only POST, GET
264 16437e4d Kostas Papadimitriou
        response = self.myput('images/42/metadata', '', '')
265 16437e4d Kostas Papadimitriou
        self.assertMethodNotAllowed(response)
266 16437e4d Kostas Papadimitriou
        response = self.mydelete('images/42/metadata')
267 16437e4d Kostas Papadimitriou
        self.assertMethodNotAllowed(response)
268 16437e4d Kostas Papadimitriou
269 16437e4d Kostas Papadimitriou
        # /images/<imgid>/metadata/<key> allows only PUT, GET, DELETE
270 16437e4d Kostas Papadimitriou
        response = self.mypost('images/42/metadata/foo')
271 16437e4d Kostas Papadimitriou
        self.assertMethodNotAllowed(response)
272 16437e4d Kostas Papadimitriou
273 039e3e61 Christos Stavrakakis
274 cda71050 Christos Stavrakakis
@patch('synnefo.plankton.backend.ImageBackend')
275 dc99330c Georgios D. Tsoukalas
class ImageMetadataAPITest(ComputeAPITest):
276 039e3e61 Christos Stavrakakis
    def setUp(self):
277 039e3e61 Christos Stavrakakis
        self.image = {'id': 42,
278 039e3e61 Christos Stavrakakis
                 'name': 'image-1',
279 039e3e61 Christos Stavrakakis
                 'status': 'available',
280 039e3e61 Christos Stavrakakis
                 'created_at': '2012-11-26 11:52:54',
281 039e3e61 Christos Stavrakakis
                 'updated_at': '2012-12-26 11:52:54',
282 039e3e61 Christos Stavrakakis
                 'deleted_at': '',
283 039e3e61 Christos Stavrakakis
                 'properties': {'foo': 'bar', 'foo2': 'bar2'}}
284 039e3e61 Christos Stavrakakis
        self.result_image = \
285 039e3e61 Christos Stavrakakis
                  {'id': 42,
286 039e3e61 Christos Stavrakakis
                   'name': 'image-1',
287 039e3e61 Christos Stavrakakis
                   'status': 'ACTIVE',
288 039e3e61 Christos Stavrakakis
                   'progress': 100,
289 039e3e61 Christos Stavrakakis
                   'created': '2012-11-26T11:52:54+00:00',
290 039e3e61 Christos Stavrakakis
                   'updated': '2012-12-26T11:52:54+00:00',
291 2d04422f Christos Stavrakakis
                   'metadata': {'foo': 'bar'}}
292 dc99330c Georgios D. Tsoukalas
        super(ImageMetadataAPITest, self).setUp()
293 039e3e61 Christos Stavrakakis
294 039e3e61 Christos Stavrakakis
    @assert_backend_closed
295 039e3e61 Christos Stavrakakis
    def test_list_metadata(self, backend):
296 039e3e61 Christos Stavrakakis
        backend.return_value.get_image.return_value = self.image
297 dc99330c Georgios D. Tsoukalas
        response = self.myget('images/42/metadata', 'user')
298 039e3e61 Christos Stavrakakis
        self.assertSuccess(response)
299 2d04422f Christos Stavrakakis
        meta = json.loads(response.content)['metadata']
300 039e3e61 Christos Stavrakakis
        self.assertEqual(meta, self.image['properties'])
301 039e3e61 Christos Stavrakakis
302 039e3e61 Christos Stavrakakis
    @assert_backend_closed
303 039e3e61 Christos Stavrakakis
    def test_get_metadata(self, backend):
304 039e3e61 Christos Stavrakakis
        backend.return_value.get_image.return_value = self.image
305 dc99330c Georgios D. Tsoukalas
        response = self.myget('images/42/metadata/foo', 'user')
306 039e3e61 Christos Stavrakakis
        self.assertSuccess(response)
307 039e3e61 Christos Stavrakakis
        meta = json.loads(response.content)['meta']
308 039e3e61 Christos Stavrakakis
        self.assertEqual(meta['foo'], 'bar')
309 039e3e61 Christos Stavrakakis
310 039e3e61 Christos Stavrakakis
    @assert_backend_closed
311 039e3e61 Christos Stavrakakis
    def test_get_invalid_metadata(self, backend):
312 039e3e61 Christos Stavrakakis
        backend.return_value.get_image.return_value = self.image
313 dc99330c Georgios D. Tsoukalas
        response = self.myget('images/42/metadata/not_found', 'user')
314 039e3e61 Christos Stavrakakis
        self.assertItemNotFound(response)
315 039e3e61 Christos Stavrakakis
316 039e3e61 Christos Stavrakakis
    def test_delete_metadata_item(self, backend):
317 039e3e61 Christos Stavrakakis
        backend.return_value.get_image.return_value = self.image
318 dc99330c Georgios D. Tsoukalas
        response = self.mydelete('images/42/metadata/foo', 'user')
319 b3fd98ae Christos Stavrakakis
        self.assertEqual(response.status_code, 204)
320 14c94c48 Christos Stavrakakis
        backend.return_value.update_metadata.assert_called_once_with('42', {'properties': {'foo2':
321 b3fd98ae Christos Stavrakakis
                                                    'bar2'}})
322 039e3e61 Christos Stavrakakis
323 039e3e61 Christos Stavrakakis
    @assert_backend_closed
324 039e3e61 Christos Stavrakakis
    def test_create_metadata_item(self, backend):
325 039e3e61 Christos Stavrakakis
        backend.return_value.get_image.return_value = self.image
326 b3fd98ae Christos Stavrakakis
        request = {'meta': {'foo3': 'bar3'}}
327 dc99330c Georgios D. Tsoukalas
        response = self.myput('images/42/metadata/foo3', 'user',
328 dc99330c Georgios D. Tsoukalas
                              json.dumps(request), 'json')
329 b3fd98ae Christos Stavrakakis
        self.assertEqual(response.status_code, 201)
330 14c94c48 Christos Stavrakakis
        backend.return_value.update_metadata.assert_called_once_with('42',
331 b3fd98ae Christos Stavrakakis
                {'properties':
332 b3fd98ae Christos Stavrakakis
                    {'foo': 'bar', 'foo2': 'bar2', 'foo3': 'bar3'}})
333 039e3e61 Christos Stavrakakis
334 039e3e61 Christos Stavrakakis
    @assert_backend_closed
335 039e3e61 Christos Stavrakakis
    def test_create_metadata_malformed_1(self, backend):
336 039e3e61 Christos Stavrakakis
        backend.return_value.get_image.return_value = self.image
337 b3fd98ae Christos Stavrakakis
        request = {'met': {'foo3': 'bar3'}}
338 dc99330c Georgios D. Tsoukalas
        response = self.myput('images/42/metadata/foo3', 'user',
339 dc99330c Georgios D. Tsoukalas
                              json.dumps(request), 'json')
340 b3fd98ae Christos Stavrakakis
        self.assertBadRequest(response)
341 039e3e61 Christos Stavrakakis
342 039e3e61 Christos Stavrakakis
    @assert_backend_closed
343 039e3e61 Christos Stavrakakis
    def test_create_metadata_malformed_2(self, backend):
344 039e3e61 Christos Stavrakakis
        backend.return_value.get_image.return_value = self.image
345 2d04422f Christos Stavrakakis
        request = {'metadata': [('foo3', 'bar3')]}
346 dc99330c Georgios D. Tsoukalas
        response = self.myput('images/42/metadata/foo3', 'user',
347 dc99330c Georgios D. Tsoukalas
                              json.dumps(request), 'json')
348 b3fd98ae Christos Stavrakakis
        self.assertBadRequest(response)
349 039e3e61 Christos Stavrakakis
350 039e3e61 Christos Stavrakakis
    @assert_backend_closed
351 039e3e61 Christos Stavrakakis
    def test_create_metadata_malformed_3(self, backend):
352 039e3e61 Christos Stavrakakis
        backend.return_value.get_image.return_value = self.image
353 b3fd98ae Christos Stavrakakis
        request = {'met': {'foo3': 'bar3', 'foo4': 'bar4'}}
354 dc99330c Georgios D. Tsoukalas
        response = self.myput('images/42/metadata/foo3', 'user',
355 b3fd98ae Christos Stavrakakis
                                json.dumps(request), 'json')
356 b3fd98ae Christos Stavrakakis
        self.assertBadRequest(response)
357 039e3e61 Christos Stavrakakis
358 039e3e61 Christos Stavrakakis
    @assert_backend_closed
359 039e3e61 Christos Stavrakakis
    def test_create_metadata_malformed_4(self, backend):
360 039e3e61 Christos Stavrakakis
        backend.return_value.get_image.return_value = self.image
361 b3fd98ae Christos Stavrakakis
        request = {'met': {'foo3': 'bar3'}}
362 dc99330c Georgios D. Tsoukalas
        response = self.myput('images/42/metadata/foo4', 'user',
363 dc99330c Georgios D. Tsoukalas
                              json.dumps(request), 'json')
364 b3fd98ae Christos Stavrakakis
        self.assertBadRequest(response)
365 039e3e61 Christos Stavrakakis
366 039e3e61 Christos Stavrakakis
    @assert_backend_closed
367 039e3e61 Christos Stavrakakis
    def test_update_metadata_item(self, backend):
368 039e3e61 Christos Stavrakakis
        backend.return_value.get_image.return_value = self.image
369 b3fd98ae Christos Stavrakakis
        request = {'metadata': {'foo': 'bar_new', 'foo4': 'bar4'}}
370 dc99330c Georgios D. Tsoukalas
        response = self.mypost('images/42/metadata', 'user',
371 dc99330c Georgios D. Tsoukalas
                               json.dumps(request), 'json')
372 b3fd98ae Christos Stavrakakis
        self.assertEqual(response.status_code, 201)
373 14c94c48 Christos Stavrakakis
        backend.return_value.update_metadata.assert_called_once_with('42',
374 b3fd98ae Christos Stavrakakis
                {'properties':
375 b3fd98ae Christos Stavrakakis
                    {'foo': 'bar_new', 'foo2': 'bar2', 'foo4': 'bar4'}
376 b3fd98ae Christos Stavrakakis
                })
377 039e3e61 Christos Stavrakakis
378 039e3e61 Christos Stavrakakis
    @assert_backend_closed
379 039e3e61 Christos Stavrakakis
    def test_update_metadata_malformed(self, backend):
380 039e3e61 Christos Stavrakakis
        backend.return_value.get_image.return_value = self.image
381 b3fd98ae Christos Stavrakakis
        request = {'meta': {'foo': 'bar_new', 'foo4': 'bar4'}}
382 dc99330c Georgios D. Tsoukalas
        response = self.mypost('images/42/metadata', 'user',
383 dc99330c Georgios D. Tsoukalas
                               json.dumps(request), 'json')
384 b3fd98ae Christos Stavrakakis
        self.assertBadRequest(response)