blob: 281affb2e7cb8dde89116eab1aaf6238afcb89b2 [file] [log] [blame]
Joe Gregorioba9ea7f2010-08-19 15:49:04 -04001#!/usr/bin/python2.4
2#
Joe Gregorio6d5e94f2010-08-25 23:49:30 -04003# Copyright 2010 Google Inc.
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
Joe Gregorioba9ea7f2010-08-19 15:49:04 -040016
Joe Gregorio6d5e94f2010-08-25 23:49:30 -040017"""JSON Model tests
Joe Gregorioba9ea7f2010-08-19 15:49:04 -040018
Joe Gregorio6d5e94f2010-08-25 23:49:30 -040019Unit tests for the JSON model.
Joe Gregorioba9ea7f2010-08-19 15:49:04 -040020"""
21
22__author__ = 'jcgregorio@google.com (Joe Gregorio)'
23
Joe Gregorio34044bc2011-03-07 16:58:33 -050024import copy
Joe Gregorioba9ea7f2010-08-19 15:49:04 -040025import os
26import unittest
Joe Gregorioc5c5a372010-09-22 11:42:32 -040027import httplib2
Joe Gregorio34044bc2011-03-07 16:58:33 -050028import apiclient.model
ade@google.comd69e5e42010-08-31 15:28:20 +010029
Joe Gregorioe1de4162011-02-23 11:30:29 -050030from apiclient.errors import HttpError
Joe Gregorio34044bc2011-03-07 16:58:33 -050031from apiclient.model import JsonModel
Joe Gregorio549230c2012-01-11 10:38:05 -050032from oauth2client.anyjson import simplejson
Joe Gregorio34044bc2011-03-07 16:58:33 -050033
ade@google.comd69e5e42010-08-31 15:28:20 +010034# Python 2.5 requires different modules
35try:
36 from urlparse import parse_qs
37except ImportError:
38 from cgi import parse_qs
39
Joe Gregorioba9ea7f2010-08-19 15:49:04 -040040
Joe Gregorioba9ea7f2010-08-19 15:49:04 -040041class Model(unittest.TestCase):
42 def test_json_no_body(self):
Joe Gregoriod433b2a2011-02-22 10:51:51 -050043 model = JsonModel(data_wrapper=False)
Joe Gregorioba9ea7f2010-08-19 15:49:04 -040044
45 headers = {}
ade@google.com850cf552010-08-20 23:24:56 +010046 path_params = {}
47 query_params = {}
48 body = None
Joe Gregorioba9ea7f2010-08-19 15:49:04 -040049
ade@google.com850cf552010-08-20 23:24:56 +010050 headers, params, query, body = model.request(headers, path_params, query_params, body)
Joe Gregorioba9ea7f2010-08-19 15:49:04 -040051
52 self.assertEqual(headers['accept'], 'application/json')
53 self.assertTrue('content-type' not in headers)
54 self.assertNotEqual(query, '')
55 self.assertEqual(body, None)
56
57 def test_json_body(self):
Joe Gregoriod433b2a2011-02-22 10:51:51 -050058 model = JsonModel(data_wrapper=False)
Joe Gregorioba9ea7f2010-08-19 15:49:04 -040059
60 headers = {}
ade@google.com850cf552010-08-20 23:24:56 +010061 path_params = {}
62 query_params = {}
63 body = {}
Joe Gregorioba9ea7f2010-08-19 15:49:04 -040064
ade@google.com850cf552010-08-20 23:24:56 +010065 headers, params, query, body = model.request(headers, path_params, query_params, body)
Joe Gregorioba9ea7f2010-08-19 15:49:04 -040066
67 self.assertEqual(headers['accept'], 'application/json')
68 self.assertEqual(headers['content-type'], 'application/json')
69 self.assertNotEqual(query, '')
Joe Gregorio913e70d2010-11-05 15:38:23 -040070 self.assertEqual(body, '{}')
Joe Gregorioba9ea7f2010-08-19 15:49:04 -040071
Joe Gregoriod433b2a2011-02-22 10:51:51 -050072 def test_json_body_data_wrapper(self):
73 model = JsonModel(data_wrapper=True)
74
75 headers = {}
76 path_params = {}
77 query_params = {}
78 body = {}
79
80 headers, params, query, body = model.request(headers, path_params, query_params, body)
81
82 self.assertEqual(headers['accept'], 'application/json')
83 self.assertEqual(headers['content-type'], 'application/json')
84 self.assertNotEqual(query, '')
85 self.assertEqual(body, '{"data": {}}')
86
Joe Gregorio8963ff92010-10-11 13:14:43 -040087 def test_json_body_default_data(self):
88 """Test that a 'data' wrapper doesn't get added if one is already present."""
Joe Gregoriod433b2a2011-02-22 10:51:51 -050089 model = JsonModel(data_wrapper=True)
Joe Gregorio8963ff92010-10-11 13:14:43 -040090
91 headers = {}
92 path_params = {}
93 query_params = {}
94 body = {'data': 'foo'}
95
96 headers, params, query, body = model.request(headers, path_params, query_params, body)
97
98 self.assertEqual(headers['accept'], 'application/json')
99 self.assertEqual(headers['content-type'], 'application/json')
100 self.assertNotEqual(query, '')
101 self.assertEqual(body, '{"data": "foo"}')
102
Joe Gregoriofe695fb2010-08-30 12:04:04 -0400103 def test_json_build_query(self):
Joe Gregoriod433b2a2011-02-22 10:51:51 -0500104 model = JsonModel(data_wrapper=False)
Joe Gregoriofe695fb2010-08-30 12:04:04 -0400105
106 headers = {}
107 path_params = {}
Joe Gregorio61d7e962011-02-22 22:52:07 -0500108 query_params = {'foo': 1, 'bar': u'\N{COMET}',
109 'baz': ['fe', 'fi', 'fo', 'fum'], # Repeated parameters
110 'qux': []}
Joe Gregoriofe695fb2010-08-30 12:04:04 -0400111 body = {}
112
113 headers, params, query, body = model.request(headers, path_params, query_params, body)
114
115 self.assertEqual(headers['accept'], 'application/json')
116 self.assertEqual(headers['content-type'], 'application/json')
117
Joe Gregorio61d7e962011-02-22 22:52:07 -0500118 query_dict = parse_qs(query[1:])
Joe Gregoriofe695fb2010-08-30 12:04:04 -0400119 self.assertEqual(query_dict['foo'], ['1'])
120 self.assertEqual(query_dict['bar'], [u'\N{COMET}'.encode('utf-8')])
Joe Gregorio61d7e962011-02-22 22:52:07 -0500121 self.assertEqual(query_dict['baz'], ['fe', 'fi', 'fo', 'fum'])
122 self.assertTrue('qux' not in query_dict)
Joe Gregorio913e70d2010-11-05 15:38:23 -0400123 self.assertEqual(body, '{}')
Joe Gregoriofe695fb2010-08-30 12:04:04 -0400124
Joe Gregorioc5c5a372010-09-22 11:42:32 -0400125 def test_user_agent(self):
Joe Gregoriod433b2a2011-02-22 10:51:51 -0500126 model = JsonModel(data_wrapper=False)
Joe Gregorioc5c5a372010-09-22 11:42:32 -0400127
128 headers = {'user-agent': 'my-test-app/1.23.4'}
129 path_params = {}
130 query_params = {}
131 body = {}
132
133 headers, params, query, body = model.request(headers, path_params, query_params, body)
134
135 self.assertEqual(headers['user-agent'], 'my-test-app/1.23.4 google-api-python-client/1.0')
136
137 def test_bad_response(self):
Joe Gregoriod433b2a2011-02-22 10:51:51 -0500138 model = JsonModel(data_wrapper=False)
Joe Gregorioc5c5a372010-09-22 11:42:32 -0400139 resp = httplib2.Response({'status': '401'})
140 resp.reason = 'Unauthorized'
Joe Gregoriod4e14562011-01-04 09:51:45 -0500141 content = '{"error": {"message": "not authorized"}}'
Joe Gregorioc5c5a372010-09-22 11:42:32 -0400142
143 try:
144 content = model.response(resp, content)
145 self.fail('Should have thrown an exception')
146 except HttpError, e:
Joe Gregorio20b54fb2012-07-26 09:59:35 -0400147 self.assertTrue('not authorized' in str(e))
Joe Gregorioc5c5a372010-09-22 11:42:32 -0400148
149 resp['content-type'] = 'application/json'
150
151 try:
152 content = model.response(resp, content)
153 self.fail('Should have thrown an exception')
154 except HttpError, e:
155 self.assertTrue('not authorized' in str(e))
156
Joe Gregorioc5c5a372010-09-22 11:42:32 -0400157 def test_good_response(self):
Joe Gregoriod433b2a2011-02-22 10:51:51 -0500158 model = JsonModel(data_wrapper=True)
Joe Gregorioc5c5a372010-09-22 11:42:32 -0400159 resp = httplib2.Response({'status': '200'})
160 resp.reason = 'OK'
161 content = '{"data": "is good"}'
162
163 content = model.response(resp, content)
164 self.assertEqual(content, 'is good')
Joe Gregoriofe695fb2010-08-30 12:04:04 -0400165
Joe Gregorio78a508d2010-10-26 16:36:36 -0400166 def test_good_response_wo_data(self):
Joe Gregoriod433b2a2011-02-22 10:51:51 -0500167 model = JsonModel(data_wrapper=False)
Joe Gregorio78a508d2010-10-26 16:36:36 -0400168 resp = httplib2.Response({'status': '200'})
169 resp.reason = 'OK'
170 content = '{"foo": "is good"}'
171
172 content = model.response(resp, content)
173 self.assertEqual(content, {'foo': 'is good'})
174
175 def test_good_response_wo_data_str(self):
Joe Gregoriod433b2a2011-02-22 10:51:51 -0500176 model = JsonModel(data_wrapper=False)
Joe Gregorio78a508d2010-10-26 16:36:36 -0400177 resp = httplib2.Response({'status': '200'})
178 resp.reason = 'OK'
179 content = '"data goes here"'
180
181 content = model.response(resp, content)
182 self.assertEqual(content, 'data goes here')
183
Matt McDonald2a5f4132011-04-29 16:32:27 -0400184 def test_no_content_response(self):
185 model = JsonModel(data_wrapper=False)
186 resp = httplib2.Response({'status': '204'})
187 resp.reason = 'No Content'
188 content = ''
Joe Gregorio34044bc2011-03-07 16:58:33 -0500189
Matt McDonald2a5f4132011-04-29 16:32:27 -0400190 content = model.response(resp, content)
191 self.assertEqual(content, {})
Joe Gregorio34044bc2011-03-07 16:58:33 -0500192
Matt McDonald2a5f4132011-04-29 16:32:27 -0400193 def test_logging(self):
Joe Gregorio34044bc2011-03-07 16:58:33 -0500194 class MockLogging(object):
195 def __init__(self):
196 self.info_record = []
197 self.debug_record = []
198 def info(self, message, *args):
199 self.info_record.append(message % args)
200
201 def debug(self, message, *args):
202 self.debug_record.append(message % args)
203
204 class MockResponse(dict):
205 def __init__(self, items):
206 super(MockResponse, self).__init__()
207 self.status = items['status']
208 for key, value in items.iteritems():
209 self[key] = value
Matt McDonald2a5f4132011-04-29 16:32:27 -0400210 old_logging = apiclient.model.logging
Joe Gregorio34044bc2011-03-07 16:58:33 -0500211 apiclient.model.logging = MockLogging()
Joe Gregorio79daca02013-03-29 16:25:52 -0400212 apiclient.model.dump_request_response = True
Matt McDonald2a5f4132011-04-29 16:32:27 -0400213 model = JsonModel()
Joe Gregorio34044bc2011-03-07 16:58:33 -0500214 request_body = {
215 'field1': 'value1',
216 'field2': 'value2'
217 }
218 body_string = model.request({}, {}, {}, request_body)[-1]
219 json_body = simplejson.loads(body_string)
220 self.assertEqual(request_body, json_body)
221
222 response = {'status': 200,
223 'response_field_1': 'response_value_1',
224 'response_field_2': 'response_value_2'}
225 response_body = model.response(MockResponse(response), body_string)
226 self.assertEqual(request_body, response_body)
Joe Gregorioafdf50b2011-03-08 09:41:52 -0500227 self.assertEqual(apiclient.model.logging.info_record[:2],
228 ['--request-start--',
229 '-headers-start-'])
230 self.assertTrue('response_field_1: response_value_1' in
231 apiclient.model.logging.info_record)
232 self.assertTrue('response_field_2: response_value_2' in
233 apiclient.model.logging.info_record)
Joe Gregorio34044bc2011-03-07 16:58:33 -0500234 self.assertEqual(simplejson.loads(apiclient.model.logging.info_record[-2]),
235 request_body)
236 self.assertEqual(apiclient.model.logging.info_record[-1],
237 '--response-end--')
Matt McDonald2a5f4132011-04-29 16:32:27 -0400238 apiclient.model.logging = old_logging
Joe Gregorio34044bc2011-03-07 16:58:33 -0500239
Ali Afshar81fde8e2012-10-23 11:14:28 -0700240 def test_no_data_wrapper_deserialize(self):
241 model = JsonModel(data_wrapper=False)
242 resp = httplib2.Response({'status': '200'})
243 resp.reason = 'OK'
244 content = '{"data": "is good"}'
245 content = model.response(resp, content)
246 self.assertEqual(content, {'data': 'is good'})
247
248 def test_data_wrapper_deserialize(self):
249 model = JsonModel(data_wrapper=True)
250 resp = httplib2.Response({'status': '200'})
251 resp.reason = 'OK'
252 content = '{"data": "is good"}'
253 content = model.response(resp, content)
254 self.assertEqual(content, 'is good')
255
256 def test_data_wrapper_deserialize_nodata(self):
257 model = JsonModel(data_wrapper=True)
258 resp = httplib2.Response({'status': '200'})
259 resp.reason = 'OK'
260 content = '{"atad": "is good"}'
261 content = model.response(resp, content)
262 self.assertEqual(content, {'atad': 'is good'})
263
264
Joe Gregorio34044bc2011-03-07 16:58:33 -0500265
Joe Gregorioba9ea7f2010-08-19 15:49:04 -0400266if __name__ == '__main__':
267 unittest.main()