Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (14.5 kB)

1 23808592 Christos Stavrakakis
# Copyright 2012-2014 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 23808592 Christos Stavrakakis
from decimal import Decimal
40 cda71050 Christos Stavrakakis
from snf_django.utils.testing import BaseAPITest
41 fdb15edb Georgios D. Tsoukalas
from synnefo.cyclades_settings import cyclades_services
42 fdb15edb Georgios D. Tsoukalas
from synnefo.lib.services import get_service_path
43 fdb15edb Georgios D. Tsoukalas
from synnefo.lib import join_urls
44 fdb15edb Georgios D. Tsoukalas
45 23808592 Christos Stavrakakis
PLANKTON_URL = get_service_path(cyclades_services, 'image',
46 23808592 Christos Stavrakakis
                                version='v1.0')
47 23808592 Christos Stavrakakis
IMAGES_URL = join_urls(PLANKTON_URL, "images/")
48 37f87d98 Christos Stavrakakis
49 37f87d98 Christos Stavrakakis
50 37f87d98 Christos Stavrakakis
def assert_backend_closed(func):
51 37f87d98 Christos Stavrakakis
    @wraps(func)
52 37f87d98 Christos Stavrakakis
    def wrapper(self, backend):
53 37f87d98 Christos Stavrakakis
        result = func(self, backend)
54 37f87d98 Christos Stavrakakis
        if backend.called is True:
55 37f87d98 Christos Stavrakakis
            backend.return_value.close.assert_called_once_with()
56 37f87d98 Christos Stavrakakis
        return result
57 37f87d98 Christos Stavrakakis
    return wrapper
58 37f87d98 Christos Stavrakakis
59 37f87d98 Christos Stavrakakis
60 23808592 Christos Stavrakakis
@patch("synnefo.plankton.backend.get_pithos_backend")
61 23808592 Christos Stavrakakis
class PlanktonTest(BaseAPITest):
62 23808592 Christos Stavrakakis
    def test_register_image(self, backend):
63 23808592 Christos Stavrakakis
        required = {
64 23808592 Christos Stavrakakis
            "HTTP_X_IMAGE_META_NAME": u"TestImage\u2602",
65 23808592 Christos Stavrakakis
            "HTTP_X_IMAGE_META_LOCATION": "pithos://4321-4321/images/foo"}
66 23808592 Christos Stavrakakis
        # Check valid name
67 23808592 Christos Stavrakakis
        headers = deepcopy(required)
68 23808592 Christos Stavrakakis
        headers.pop("HTTP_X_IMAGE_META_NAME")
69 23808592 Christos Stavrakakis
        response = self.post(IMAGES_URL, **headers)
70 23808592 Christos Stavrakakis
        self.assertBadRequest(response)
71 23808592 Christos Stavrakakis
        self.assertTrue("name" in response.content)
72 23808592 Christos Stavrakakis
        headers["HTTP_X_IMAGE_META_NAME"] = ""
73 23808592 Christos Stavrakakis
        response = self.post(IMAGES_URL, **headers)
74 23808592 Christos Stavrakakis
        self.assertBadRequest(response)
75 23808592 Christos Stavrakakis
        self.assertTrue("name" in response.content)
76 23808592 Christos Stavrakakis
        # Check valid location
77 23808592 Christos Stavrakakis
        headers = deepcopy(required)
78 23808592 Christos Stavrakakis
        headers.pop("HTTP_X_IMAGE_META_LOCATION")
79 23808592 Christos Stavrakakis
        response = self.post(IMAGES_URL, **headers)
80 23808592 Christos Stavrakakis
        self.assertBadRequest(response)
81 23808592 Christos Stavrakakis
        self.assertTrue("location" in response.content)
82 23808592 Christos Stavrakakis
        headers["HTTP_X_IMAGE_META_LOCATION"] = ""
83 23808592 Christos Stavrakakis
        response = self.post(IMAGES_URL, **headers)
84 23808592 Christos Stavrakakis
        self.assertBadRequest(response)
85 23808592 Christos Stavrakakis
        self.assertTrue("location" in response.content)
86 23808592 Christos Stavrakakis
        headers["HTTP_X_IMAGE_META_LOCATION"] = "pitho://4321-4321/images/foo"
87 23808592 Christos Stavrakakis
        response = self.post(IMAGES_URL, **headers)
88 23808592 Christos Stavrakakis
        self.assertBadRequest(response)
89 23808592 Christos Stavrakakis
        self.assertTrue("location" in response.content)
90 23808592 Christos Stavrakakis
        headers["HTTP_X_IMAGE_META_LOCATION"] = "pithos://4321-4321/foo"
91 23808592 Christos Stavrakakis
        response = self.post(IMAGES_URL, **headers)
92 23808592 Christos Stavrakakis
        self.assertBadRequest(response)
93 23808592 Christos Stavrakakis
        self.assertTrue("location" in response.content)
94 23808592 Christos Stavrakakis
        # ID not supported
95 23808592 Christos Stavrakakis
        headers = deepcopy(required)
96 23808592 Christos Stavrakakis
        headers["HTTP_X_IMAGE_META_ID"] = "1234"
97 23808592 Christos Stavrakakis
        response = self.post(IMAGES_URL, **headers)
98 23808592 Christos Stavrakakis
        self.assertBadRequest(response)
99 23808592 Christos Stavrakakis
        headers = deepcopy(required)
100 23808592 Christos Stavrakakis
        # ID not supported
101 23808592 Christos Stavrakakis
        headers = deepcopy(required)
102 23808592 Christos Stavrakakis
        headers["HTTP_X_IMAGE_META_LOLO"] = "1234"
103 23808592 Christos Stavrakakis
        response = self.post(IMAGES_URL, **headers)
104 23808592 Christos Stavrakakis
        self.assertBadRequest(response)
105 23808592 Christos Stavrakakis
        headers = deepcopy(required)
106 23808592 Christos Stavrakakis
        headers["HTTP_X_IMAGE_META_STORE"] = "pitho"
107 23808592 Christos Stavrakakis
        response = self.post(IMAGES_URL, **headers)
108 23808592 Christos Stavrakakis
        self.assertBadRequest(response)
109 23808592 Christos Stavrakakis
        self.assertTrue("store " in response.content)
110 23808592 Christos Stavrakakis
        headers = deepcopy(required)
111 23808592 Christos Stavrakakis
        headers["HTTP_X_IMAGE_META_DISK_FORMAT"] = "diskdumpp"
112 23808592 Christos Stavrakakis
        response = self.post(IMAGES_URL, **headers)
113 23808592 Christos Stavrakakis
        self.assertBadRequest(response)
114 23808592 Christos Stavrakakis
        self.assertTrue("disk format" in response.content)
115 23808592 Christos Stavrakakis
        headers = deepcopy(required)
116 23808592 Christos Stavrakakis
        headers["HTTP_X_IMAGE_META_CONTAINER_FORMAT"] = "baree"
117 23808592 Christos Stavrakakis
        response = self.post(IMAGES_URL, **headers)
118 23808592 Christos Stavrakakis
        self.assertBadRequest(response)
119 23808592 Christos Stavrakakis
        self.assertTrue("container format" in response.content)
120 37f87d98 Christos Stavrakakis
121 23808592 Christos Stavrakakis
        backend().get_object_meta.return_value = {"uuid": "1234-1234-1234",
122 23808592 Christos Stavrakakis
                                                  "bytes": 42,
123 23808592 Christos Stavrakakis
                                                  "hash": "unique_hash"}
124 23808592 Christos Stavrakakis
        headers = deepcopy(required)
125 23808592 Christos Stavrakakis
        headers["HTTP_X_IMAGE_META_SIZE"] = "foo"
126 23808592 Christos Stavrakakis
        response = self.post(IMAGES_URL, **headers)
127 23808592 Christos Stavrakakis
        self.assertBadRequest(response)
128 23808592 Christos Stavrakakis
        self.assertTrue("size" in response.content)
129 23808592 Christos Stavrakakis
        headers["HTTP_X_IMAGE_META_SIZE"] = "43"
130 23808592 Christos Stavrakakis
        response = self.post(IMAGES_URL, **headers)
131 23808592 Christos Stavrakakis
        self.assertBadRequest(response)
132 23808592 Christos Stavrakakis
        self.assertTrue("size" in response.content)
133 23808592 Christos Stavrakakis
134 23808592 Christos Stavrakakis
        headers["HTTP_X_IMAGE_META_SIZE"] = 42
135 23808592 Christos Stavrakakis
        headers["HTTP_X_IMAGE_META_CHECKSUM"] = "wrong_checksum"
136 23808592 Christos Stavrakakis
        response = self.post(IMAGES_URL, **headers)
137 23808592 Christos Stavrakakis
        self.assertBadRequest(response)
138 37f87d98 Christos Stavrakakis
139 23808592 Christos Stavrakakis
        backend().get_uuid.return_value =\
140 23808592 Christos Stavrakakis
            ("4321-4321", "images", "foo")
141 23808592 Christos Stavrakakis
        backend().get_object_permissions.return_value = \
142 23808592 Christos Stavrakakis
            ("foo", "foo", {"read": []})
143 23808592 Christos Stavrakakis
        backend().get_object_meta.side_effect = \
144 23808592 Christos Stavrakakis
            [{"uuid": "1234-1234-1234",
145 23808592 Christos Stavrakakis
              "bytes": 42,
146 23808592 Christos Stavrakakis
              "hash": "unique_hash"},
147 23808592 Christos Stavrakakis
             {"uuid": "1234-1234-1234",
148 23808592 Christos Stavrakakis
              "bytes": 42,
149 23808592 Christos Stavrakakis
              "hash": "unique_hash",
150 23808592 Christos Stavrakakis
              'version_timestamp': Decimal('1392487853.863673'),
151 23808592 Christos Stavrakakis
              "plankton:name": u"TestImage\u2602",
152 23808592 Christos Stavrakakis
              "plankton:container_format": "bare",
153 23808592 Christos Stavrakakis
              "plankton:disk_format": "diskdump",
154 23808592 Christos Stavrakakis
              "plankton:status": u"AVAILABLE"}]
155 23808592 Christos Stavrakakis
        headers = deepcopy(required)
156 23808592 Christos Stavrakakis
        response = self.post(IMAGES_URL, **headers)
157 37f87d98 Christos Stavrakakis
        self.assertSuccess(response)
158 23808592 Christos Stavrakakis
        self.assertEqual(response["x-image-meta-location"],
159 23808592 Christos Stavrakakis
                         "pithos://4321-4321/images/foo")
160 23808592 Christos Stavrakakis
        self.assertEqual(response["x-image-meta-id"], "1234-1234-1234")
161 23808592 Christos Stavrakakis
        self.assertEqual(response["x-image-meta-status"], "AVAILABLE")
162 23808592 Christos Stavrakakis
        self.assertEqual(response["x-image-meta-deleted-at"], "")
163 23808592 Christos Stavrakakis
        self.assertEqual(response["x-image-meta-is-public"], "False")
164 23808592 Christos Stavrakakis
        self.assertEqual(response["x-image-meta-owner"], "4321-4321")
165 23808592 Christos Stavrakakis
        self.assertEqual(response["x-image-meta-size"], "42")
166 23808592 Christos Stavrakakis
        self.assertEqual(response["x-image-meta-checksum"], "unique_hash")
167 23808592 Christos Stavrakakis
        self.assertEqual(response["x-image-meta-name"],
168 23808592 Christos Stavrakakis
                         u"TestImage\u2602".encode("utf-8"))
169 23808592 Christos Stavrakakis
        self.assertEqual(response["x-image-meta-container-format"], "bare")
170 23808592 Christos Stavrakakis
        self.assertEqual(response["x-image-meta-disk-format"], "diskdump")
171 23808592 Christos Stavrakakis
        self.assertEqual(response["x-image-meta-created-at"],
172 23808592 Christos Stavrakakis
                         "2014-02-15 18:10:53")
173 23808592 Christos Stavrakakis
        self.assertEqual(response["x-image-meta-updated-at"],
174 23808592 Christos Stavrakakis
                         "2014-02-15 18:10:53")
175 37f87d98 Christos Stavrakakis
176 23808592 Christos Stavrakakis
        # Extra headers,properties
177 23808592 Christos Stavrakakis
        backend().get_object_meta.side_effect = \
178 23808592 Christos Stavrakakis
            [{"uuid": "1234-1234-1234",
179 23808592 Christos Stavrakakis
              "bytes": 42,
180 23808592 Christos Stavrakakis
              "hash": "unique_hash"},
181 23808592 Christos Stavrakakis
             {"uuid": "1234-1234-1234",
182 23808592 Christos Stavrakakis
              "bytes": 42,
183 23808592 Christos Stavrakakis
              "hash": "unique_hash",
184 23808592 Christos Stavrakakis
              'version_timestamp': Decimal('1392487853.863673'),
185 23808592 Christos Stavrakakis
              "plankton:name": u"TestImage\u2602",
186 23808592 Christos Stavrakakis
              "plankton:container_format": "bare",
187 23808592 Christos Stavrakakis
              "plankton:disk_format": "diskdump",
188 23808592 Christos Stavrakakis
              "plankton:status": u"AVAILABLE"}]
189 23808592 Christos Stavrakakis
        headers = deepcopy(required)
190 23808592 Christos Stavrakakis
        headers["HTTP_X_IMAGE_META_IS_PUBLIC"] = True
191 23808592 Christos Stavrakakis
        headers["HTTP_X_IMAGE_META_PROPERTY_KEY1"] = "val1"
192 23808592 Christos Stavrakakis
        headers["HTTP_X_IMAGE_META_PROPERTY_KEY2"] = u"\u2601"
193 23808592 Christos Stavrakakis
        response = self.post(IMAGES_URL, **headers)
194 23808592 Christos Stavrakakis
        name, args, kwargs = backend().update_object_meta.mock_calls[-1]
195 23808592 Christos Stavrakakis
        metadata = args[5]
196 23808592 Christos Stavrakakis
        self.assertEqual(metadata["plankton:property:key1"], "val1")
197 23808592 Christos Stavrakakis
        self.assertEqual(metadata["plankton:property:key2"],
198 23808592 Christos Stavrakakis
                         u"\u2601".encode("utf-8"))
199 23808592 Christos Stavrakakis
        self.assertSuccess(response)
200 450a6d2b Christos Stavrakakis
201 23808592 Christos Stavrakakis
    def test_unregister_image(self, backend):
202 23808592 Christos Stavrakakis
        backend().get_uuid.return_value = ("img_owner", "images", "foo")
203 23808592 Christos Stavrakakis
        backend().get_object_meta.return_value = {"uuid": "img_uuid",
204 23808592 Christos Stavrakakis
                                                  "bytes": 42,
205 23808592 Christos Stavrakakis
                                                  "plankton:name": "test"}
206 23808592 Christos Stavrakakis
        response = self.delete(join_urls(IMAGES_URL, "img_uuid"))
207 23808592 Christos Stavrakakis
        self.assertEqual(response.status_code, 204)
208 23808592 Christos Stavrakakis
        backend().update_object_meta.assert_called_once_with(
209 23808592 Christos Stavrakakis
            "user", "img_owner", "images", "foo", "plankton", {}, True)
210 450a6d2b Christos Stavrakakis
211 23808592 Christos Stavrakakis
    def test_users(self, backend):
212 23808592 Christos Stavrakakis
        """Test adding/removing and replacing image members"""
213 23808592 Christos Stavrakakis
        # Add user
214 23808592 Christos Stavrakakis
        backend.reset_mock()
215 23808592 Christos Stavrakakis
        backend().get_uuid.return_value = ("img_owner", "images", "foo")
216 23808592 Christos Stavrakakis
        backend().get_object_permissions.return_value = \
217 23808592 Christos Stavrakakis
            ("foo", "foo", {"read": []})
218 23808592 Christos Stavrakakis
        backend().get_object_meta.return_value = {"uuid": "img_uuid",
219 23808592 Christos Stavrakakis
                                                  "bytes": 42,
220 23808592 Christos Stavrakakis
                                                  "plankton:name": "test"}
221 23808592 Christos Stavrakakis
        response = self.put(join_urls(IMAGES_URL, "img_uuid/members/user1"),
222 23808592 Christos Stavrakakis
                            user="user1")
223 37f87d98 Christos Stavrakakis
        self.assertSuccess(response)
224 23808592 Christos Stavrakakis
        backend().update_object_permissions.assert_called_once_with(
225 23808592 Christos Stavrakakis
            "user1", "img_owner", "images", "foo", {"read": ["user1"]})
226 37f87d98 Christos Stavrakakis
227 23808592 Christos Stavrakakis
        # Remove user
228 23808592 Christos Stavrakakis
        backend().update_object_permissions.reset_mock()
229 23808592 Christos Stavrakakis
        backend().get_object_permissions.return_value = \
230 23808592 Christos Stavrakakis
            ("foo", "foo", {"read": ["user1"]})
231 23808592 Christos Stavrakakis
        response = self.delete(join_urls(IMAGES_URL, "img_uuid/members/user1"),
232 23808592 Christos Stavrakakis
                               user="user1")
233 37f87d98 Christos Stavrakakis
        self.assertSuccess(response)
234 23808592 Christos Stavrakakis
        backend().update_object_permissions.assert_called_once_with(
235 23808592 Christos Stavrakakis
            "user1", "img_owner", "images", "foo", {"read": []})
236 37f87d98 Christos Stavrakakis
237 23808592 Christos Stavrakakis
        # Update users
238 23808592 Christos Stavrakakis
        backend().get_object_permissions.return_value = \
239 23808592 Christos Stavrakakis
            ("foo", "foo", {"read": ["user1", "user2", "user3"]})
240 23808592 Christos Stavrakakis
        backend().update_object_permissions.reset_mock()
241 23808592 Christos Stavrakakis
        response = self.put(join_urls(IMAGES_URL, "img_uuid/members"),
242 23808592 Christos Stavrakakis
                            params=json.dumps({"memberships":
243 23808592 Christos Stavrakakis
                                               [{"member_id": "foo1"},
244 23808592 Christos Stavrakakis
                                                {"member_id": "foo2"}]}),
245 23808592 Christos Stavrakakis
                            ctype="json",
246 23808592 Christos Stavrakakis
                            user="user1")
247 37f87d98 Christos Stavrakakis
        self.assertSuccess(response)
248 23808592 Christos Stavrakakis
        backend().update_object_permissions.assert_called_once_with(
249 23808592 Christos Stavrakakis
            "user1", "img_owner", "images", "foo", {"read": ["foo1", "foo2"]})
250 37f87d98 Christos Stavrakakis
251 23808592 Christos Stavrakakis
        # List users
252 23808592 Christos Stavrakakis
        backend().get_object_permissions.return_value = \
253 23808592 Christos Stavrakakis
            ("foo", "foo", {"read": ["user1", "user2", "user3"]})
254 23808592 Christos Stavrakakis
        response = self.get(join_urls(IMAGES_URL, "img_uuid/members"))
255 37f87d98 Christos Stavrakakis
        self.assertSuccess(response)
256 23808592 Christos Stavrakakis
        res_members = [{"member_id": m, "can_share": False}
257 23808592 Christos Stavrakakis
                       for m in ["user1", "user2", "user3"]]
258 23808592 Christos Stavrakakis
        self.assertEqual(json.loads(response.content)["members"], res_members)
259 37f87d98 Christos Stavrakakis
260 23808592 Christos Stavrakakis
    def test_metadata(self, backend):
261 23808592 Christos Stavrakakis
        backend().get_uuid.return_value = ("img_owner", "images", "foo")
262 23808592 Christos Stavrakakis
        backend().get_object_meta.return_value = \
263 23808592 Christos Stavrakakis
            {"uuid": "img_uuid",
264 23808592 Christos Stavrakakis
             "bytes": 42,
265 23808592 Christos Stavrakakis
             "hash": "unique_hash",
266 23808592 Christos Stavrakakis
             'version_timestamp': Decimal('1392487853.863673'),
267 23808592 Christos Stavrakakis
             "plankton:name": u"TestImage\u2602",
268 23808592 Christos Stavrakakis
             "plankton:container_format": "bare",
269 23808592 Christos Stavrakakis
             "plankton:disk_format": "diskdump",
270 23808592 Christos Stavrakakis
             "plankton:status": u"AVAILABLE"}
271 23808592 Christos Stavrakakis
        backend().get_object_permissions.return_value = \
272 23808592 Christos Stavrakakis
            ("foo", "foo", {"read": ["*", "user1"]})
273 23808592 Christos Stavrakakis
        response = self.head(join_urls(IMAGES_URL, "img_uuid2"))
274 23808592 Christos Stavrakakis
        self.assertSuccess(response)
275 23808592 Christos Stavrakakis
        self.assertEqual(response["x-image-meta-location"],
276 23808592 Christos Stavrakakis
                         "pithos://img_owner/images/foo")
277 23808592 Christos Stavrakakis
        self.assertEqual(response["x-image-meta-id"], "img_uuid")
278 23808592 Christos Stavrakakis
        self.assertEqual(response["x-image-meta-status"], "AVAILABLE")
279 23808592 Christos Stavrakakis
        self.assertEqual(response["x-image-meta-deleted-at"], "")
280 23808592 Christos Stavrakakis
        self.assertEqual(response["x-image-meta-is-public"], "True")
281 23808592 Christos Stavrakakis
        self.assertEqual(response["x-image-meta-owner"], "img_owner")
282 23808592 Christos Stavrakakis
        self.assertEqual(response["x-image-meta-size"], "42")
283 23808592 Christos Stavrakakis
        self.assertEqual(response["x-image-meta-checksum"], "unique_hash")
284 23808592 Christos Stavrakakis
        self.assertEqual(response["x-image-meta-name"],
285 23808592 Christos Stavrakakis
                         u"TestImage\u2602".encode("utf-8"))
286 23808592 Christos Stavrakakis
        self.assertEqual(response["x-image-meta-container-format"], "bare")
287 23808592 Christos Stavrakakis
        self.assertEqual(response["x-image-meta-disk-format"], "diskdump")
288 23808592 Christos Stavrakakis
        self.assertEqual(response["x-image-meta-created-at"],
289 23808592 Christos Stavrakakis
                         "2014-02-15 18:10:53")
290 23808592 Christos Stavrakakis
        self.assertEqual(response["x-image-meta-updated-at"],
291 23808592 Christos Stavrakakis
                         "2014-02-15 18:10:53")
292 23808592 Christos Stavrakakis
        response = self.head(join_urls(IMAGES_URL, "img_uuid2"))
293 f13aab5d Christos Stavrakakis
294 23808592 Christos Stavrakakis
        headers = {"HTTP_X_IMAGE_META_IS_PUBLIC": False,
295 23808592 Christos Stavrakakis
                   "HTTP_X_IMAGE_META_PROPERTY_KEY1": "Val1"}
296 23808592 Christos Stavrakakis
        response = self.put(join_urls(IMAGES_URL, "img_uuid"), **headers)
297 23808592 Christos Stavrakakis
        self.assertSuccess(response)
298 23808592 Christos Stavrakakis
        backend().update_object_permissions.assert_called_once_with(
299 23808592 Christos Stavrakakis
            "user", "img_owner", "images", "foo", {"read": ["user1"]})
300 f7d0a71c Georgios D. Tsoukalas
301 f7d0a71c Georgios D. Tsoukalas
    def test_catch_wrong_api_paths(self, *args):
302 23808592 Christos Stavrakakis
        response = self.get(join_urls(PLANKTON_URL, 'nonexistent'))
303 f7d0a71c Georgios D. Tsoukalas
        self.assertEqual(response.status_code, 400)
304 f7d0a71c Georgios D. Tsoukalas
        try:
305 23808592 Christos Stavrakakis
            json.loads(response.content)
306 f7d0a71c Georgios D. Tsoukalas
        except ValueError:
307 f7d0a71c Georgios D. Tsoukalas
            self.assertTrue(False)
308 23808592 Christos Stavrakakis
309 23808592 Christos Stavrakakis
    def test_list_images_filters_error_1(self, backend):
310 23808592 Christos Stavrakakis
        response = self.get(join_urls(IMAGES_URL, "?size_max="))
311 23808592 Christos Stavrakakis
        self.assertBadRequest(response)