~ubuntu-branches/ubuntu/utopic/python-ceilometerclient/utopic

« back to all changes in this revision

Viewing changes to ceilometerclient/openstack/common/apiclient/fake_client.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short, James Page, Chuck Short
  • Date: 2014-01-21 09:53:01 UTC
  • mfrom: (1.1.6)
  • Revision ID: package-import@ubuntu.com-20140121095301-cwxsrtdgddkzprjx
Tags: 1.0.8-0ubuntu1
[ James Page ]
* d/control: Add missing BD on python-babel. 

[ Chuck Short ]
* New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright 2013 OpenStack Foundation
 
2
# All Rights Reserved.
 
3
#
 
4
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
 
5
#    not use this file except in compliance with the License. You may obtain
 
6
#    a copy of the License at
 
7
#
 
8
#         http://www.apache.org/licenses/LICENSE-2.0
 
9
#
 
10
#    Unless required by applicable law or agreed to in writing, software
 
11
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 
12
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 
13
#    License for the specific language governing permissions and limitations
 
14
#    under the License.
 
15
 
 
16
"""
 
17
A fake server that "responds" to API methods with pre-canned responses.
 
18
 
 
19
All of these responses come from the spec, so if for some reason the spec's
 
20
wrong the tests might raise AssertionError. I've indicated in comments the
 
21
places where actual behavior differs from the spec.
 
22
"""
 
23
 
 
24
# W0102: Dangerous default value %s as argument
 
25
# pylint: disable=W0102
 
26
 
 
27
import json
 
28
 
 
29
import requests
 
30
 
 
31
from ceilometerclient.openstack.common.apiclient import client
 
32
from ceilometerclient.openstack.common.py3kcompat import urlutils
 
33
 
 
34
 
 
35
def assert_has_keys(dct, required=[], optional=[]):
 
36
    for k in required:
 
37
        try:
 
38
            assert k in dct
 
39
        except AssertionError:
 
40
            extra_keys = set(dct.keys()).difference(set(required + optional))
 
41
            raise AssertionError("found unexpected keys: %s" %
 
42
                                 list(extra_keys))
 
43
 
 
44
 
 
45
class TestResponse(requests.Response):
 
46
    """Wrap requests.Response and provide a convenient initialization.
 
47
    """
 
48
 
 
49
    def __init__(self, data):
 
50
        super(TestResponse, self).__init__()
 
51
        self._content_consumed = True
 
52
        if isinstance(data, dict):
 
53
            self.status_code = data.get('status_code', 200)
 
54
            # Fake the text attribute to streamline Response creation
 
55
            text = data.get('text', "")
 
56
            if isinstance(text, (dict, list)):
 
57
                self._content = json.dumps(text)
 
58
                default_headers = {
 
59
                    "Content-Type": "application/json",
 
60
                }
 
61
            else:
 
62
                self._content = text
 
63
                default_headers = {}
 
64
            self.headers = data.get('headers') or default_headers
 
65
        else:
 
66
            self.status_code = data
 
67
 
 
68
    def __eq__(self, other):
 
69
        return (self.status_code == other.status_code and
 
70
                self.headers == other.headers and
 
71
                self._content == other._content)
 
72
 
 
73
 
 
74
class FakeHTTPClient(client.HTTPClient):
 
75
 
 
76
    def __init__(self, *args, **kwargs):
 
77
        self.callstack = []
 
78
        self.fixtures = kwargs.pop("fixtures", None) or {}
 
79
        if not args and not "auth_plugin" in kwargs:
 
80
            args = (None, )
 
81
        super(FakeHTTPClient, self).__init__(*args, **kwargs)
 
82
 
 
83
    def assert_called(self, method, url, body=None, pos=-1):
 
84
        """Assert than an API method was just called.
 
85
        """
 
86
        expected = (method, url)
 
87
        called = self.callstack[pos][0:2]
 
88
        assert self.callstack, \
 
89
            "Expected %s %s but no calls were made." % expected
 
90
 
 
91
        assert expected == called, 'Expected %s %s; got %s %s' % \
 
92
            (expected + called)
 
93
 
 
94
        if body is not None:
 
95
            if self.callstack[pos][3] != body:
 
96
                raise AssertionError('%r != %r' %
 
97
                                     (self.callstack[pos][3], body))
 
98
 
 
99
    def assert_called_anytime(self, method, url, body=None):
 
100
        """Assert than an API method was called anytime in the test.
 
101
        """
 
102
        expected = (method, url)
 
103
 
 
104
        assert self.callstack, \
 
105
            "Expected %s %s but no calls were made." % expected
 
106
 
 
107
        found = False
 
108
        entry = None
 
109
        for entry in self.callstack:
 
110
            if expected == entry[0:2]:
 
111
                found = True
 
112
                break
 
113
 
 
114
        assert found, 'Expected %s %s; got %s' % \
 
115
            (method, url, self.callstack)
 
116
        if body is not None:
 
117
            assert entry[3] == body, "%s != %s" % (entry[3], body)
 
118
 
 
119
        self.callstack = []
 
120
 
 
121
    def clear_callstack(self):
 
122
        self.callstack = []
 
123
 
 
124
    def authenticate(self):
 
125
        pass
 
126
 
 
127
    def client_request(self, client, method, url, **kwargs):
 
128
        # Check that certain things are called correctly
 
129
        if method in ["GET", "DELETE"]:
 
130
            assert "json" not in kwargs
 
131
 
 
132
        # Note the call
 
133
        self.callstack.append(
 
134
            (method,
 
135
             url,
 
136
             kwargs.get("headers") or {},
 
137
             kwargs.get("json") or kwargs.get("data")))
 
138
        try:
 
139
            fixture = self.fixtures[url][method]
 
140
        except KeyError:
 
141
            pass
 
142
        else:
 
143
            return TestResponse({"headers": fixture[0],
 
144
                                 "text": fixture[1]})
 
145
 
 
146
        # Call the method
 
147
        args = urlutils.parse_qsl(urlutils.urlparse(url)[4])
 
148
        kwargs.update(args)
 
149
        munged_url = url.rsplit('?', 1)[0]
 
150
        munged_url = munged_url.strip('/').replace('/', '_').replace('.', '_')
 
151
        munged_url = munged_url.replace('-', '_')
 
152
 
 
153
        callback = "%s_%s" % (method.lower(), munged_url)
 
154
 
 
155
        if not hasattr(self, callback):
 
156
            raise AssertionError('Called unknown API method: %s %s, '
 
157
                                 'expected fakes method name: %s' %
 
158
                                 (method, url, callback))
 
159
 
 
160
        resp = getattr(self, callback)(**kwargs)
 
161
        if len(resp) == 3:
 
162
            status, headers, body = resp
 
163
        else:
 
164
            status, body = resp
 
165
            headers = {}
 
166
        return TestResponse({
 
167
            "status_code": status,
 
168
            "text": body,
 
169
            "headers": headers,
 
170
        })