blob: 654aac9001175003adc16409698081be12c0755a [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
Craig Citro6ae34d72014-08-18 23:10:09 -070025import json
Joe Gregorioba9ea7f2010-08-19 15:49:04 -040026import os
27import unittest
Joe Gregorioc5c5a372010-09-22 11:42:32 -040028import httplib2
John Asmuth864311d2014-04-24 15:46:08 -040029import googleapiclient.model
ade@google.comd69e5e42010-08-31 15:28:20 +010030
John Asmuth864311d2014-04-24 15:46:08 -040031from googleapiclient import __version__
32from googleapiclient.errors import HttpError
33from googleapiclient.model import JsonModel
Joe Gregorio34044bc2011-03-07 16:58:33 -050034
ade@google.comd69e5e42010-08-31 15:28:20 +010035# Python 2.5 requires different modules
36try:
37 from urlparse import parse_qs
38except ImportError:
39 from cgi import parse_qs
40
Joe Gregorioba9ea7f2010-08-19 15:49:04 -040041
Joe Gregorioba9ea7f2010-08-19 15:49:04 -040042class Model(unittest.TestCase):
43 def test_json_no_body(self):
Joe Gregoriod433b2a2011-02-22 10:51:51 -050044 model = JsonModel(data_wrapper=False)
Joe Gregorioba9ea7f2010-08-19 15:49:04 -040045
46 headers = {}
ade@google.com850cf552010-08-20 23:24:56 +010047 path_params = {}
48 query_params = {}
49 body = None
Joe Gregorioba9ea7f2010-08-19 15:49:04 -040050
Joe Gregorio5a4c3282013-07-29 13:48:06 -040051 headers, unused_params, query, body = model.request(
Joe Gregorioa314b1f2013-04-05 16:25:11 -040052 headers, path_params, query_params, body)
Joe Gregorioba9ea7f2010-08-19 15:49:04 -040053
54 self.assertEqual(headers['accept'], 'application/json')
55 self.assertTrue('content-type' not in headers)
56 self.assertNotEqual(query, '')
57 self.assertEqual(body, None)
58
59 def test_json_body(self):
Joe Gregoriod433b2a2011-02-22 10:51:51 -050060 model = JsonModel(data_wrapper=False)
Joe Gregorioba9ea7f2010-08-19 15:49:04 -040061
62 headers = {}
ade@google.com850cf552010-08-20 23:24:56 +010063 path_params = {}
64 query_params = {}
65 body = {}
Joe Gregorioba9ea7f2010-08-19 15:49:04 -040066
Joe Gregorio5a4c3282013-07-29 13:48:06 -040067 headers, unused_params, query, body = model.request(
Joe Gregorioa314b1f2013-04-05 16:25:11 -040068 headers, path_params, query_params, body)
Joe Gregorioba9ea7f2010-08-19 15:49:04 -040069
70 self.assertEqual(headers['accept'], 'application/json')
71 self.assertEqual(headers['content-type'], 'application/json')
72 self.assertNotEqual(query, '')
Joe Gregorio913e70d2010-11-05 15:38:23 -040073 self.assertEqual(body, '{}')
Joe Gregorioba9ea7f2010-08-19 15:49:04 -040074
Joe Gregoriod433b2a2011-02-22 10:51:51 -050075 def test_json_body_data_wrapper(self):
76 model = JsonModel(data_wrapper=True)
77
78 headers = {}
79 path_params = {}
80 query_params = {}
81 body = {}
82
Joe Gregorio5a4c3282013-07-29 13:48:06 -040083 headers, unused_params, query, body = model.request(
Joe Gregorioa314b1f2013-04-05 16:25:11 -040084 headers, path_params, query_params, body)
Joe Gregoriod433b2a2011-02-22 10:51:51 -050085
86 self.assertEqual(headers['accept'], 'application/json')
87 self.assertEqual(headers['content-type'], 'application/json')
88 self.assertNotEqual(query, '')
89 self.assertEqual(body, '{"data": {}}')
90
Joe Gregorio8963ff92010-10-11 13:14:43 -040091 def test_json_body_default_data(self):
92 """Test that a 'data' wrapper doesn't get added if one is already present."""
Joe Gregoriod433b2a2011-02-22 10:51:51 -050093 model = JsonModel(data_wrapper=True)
Joe Gregorio8963ff92010-10-11 13:14:43 -040094
95 headers = {}
96 path_params = {}
97 query_params = {}
98 body = {'data': 'foo'}
99
Joe Gregorio5a4c3282013-07-29 13:48:06 -0400100 headers, unused_params, query, body = model.request(
Joe Gregorioa314b1f2013-04-05 16:25:11 -0400101 headers, path_params, query_params, body)
Joe Gregorio8963ff92010-10-11 13:14:43 -0400102
103 self.assertEqual(headers['accept'], 'application/json')
104 self.assertEqual(headers['content-type'], 'application/json')
105 self.assertNotEqual(query, '')
106 self.assertEqual(body, '{"data": "foo"}')
107
Joe Gregoriofe695fb2010-08-30 12:04:04 -0400108 def test_json_build_query(self):
Joe Gregoriod433b2a2011-02-22 10:51:51 -0500109 model = JsonModel(data_wrapper=False)
Joe Gregoriofe695fb2010-08-30 12:04:04 -0400110
111 headers = {}
112 path_params = {}
Joe Gregorio61d7e962011-02-22 22:52:07 -0500113 query_params = {'foo': 1, 'bar': u'\N{COMET}',
114 'baz': ['fe', 'fi', 'fo', 'fum'], # Repeated parameters
115 'qux': []}
Joe Gregoriofe695fb2010-08-30 12:04:04 -0400116 body = {}
117
Joe Gregorio5a4c3282013-07-29 13:48:06 -0400118 headers, unused_params, query, body = model.request(
Joe Gregorioa314b1f2013-04-05 16:25:11 -0400119 headers, path_params, query_params, body)
Joe Gregoriofe695fb2010-08-30 12:04:04 -0400120
121 self.assertEqual(headers['accept'], 'application/json')
122 self.assertEqual(headers['content-type'], 'application/json')
123
Joe Gregorio61d7e962011-02-22 22:52:07 -0500124 query_dict = parse_qs(query[1:])
Joe Gregoriofe695fb2010-08-30 12:04:04 -0400125 self.assertEqual(query_dict['foo'], ['1'])
126 self.assertEqual(query_dict['bar'], [u'\N{COMET}'.encode('utf-8')])
Joe Gregorio61d7e962011-02-22 22:52:07 -0500127 self.assertEqual(query_dict['baz'], ['fe', 'fi', 'fo', 'fum'])
128 self.assertTrue('qux' not in query_dict)
Joe Gregorio913e70d2010-11-05 15:38:23 -0400129 self.assertEqual(body, '{}')
Joe Gregoriofe695fb2010-08-30 12:04:04 -0400130
Joe Gregorioc5c5a372010-09-22 11:42:32 -0400131 def test_user_agent(self):
Joe Gregoriod433b2a2011-02-22 10:51:51 -0500132 model = JsonModel(data_wrapper=False)
Joe Gregorioc5c5a372010-09-22 11:42:32 -0400133
134 headers = {'user-agent': 'my-test-app/1.23.4'}
135 path_params = {}
136 query_params = {}
137 body = {}
138
Joe Gregorio5a4c3282013-07-29 13:48:06 -0400139 headers, unused_params, unused_query, body = model.request(
Joe Gregorioa314b1f2013-04-05 16:25:11 -0400140 headers, path_params, query_params, body)
Joe Gregorioc5c5a372010-09-22 11:42:32 -0400141
Joe Gregorioa314b1f2013-04-05 16:25:11 -0400142 self.assertEqual(headers['user-agent'],
Joe Gregorioc02f5632013-05-13 11:28:56 -0400143 'my-test-app/1.23.4 google-api-python-client/' + __version__ +
144 ' (gzip)')
Joe Gregorioc5c5a372010-09-22 11:42:32 -0400145
146 def test_bad_response(self):
Joe Gregoriod433b2a2011-02-22 10:51:51 -0500147 model = JsonModel(data_wrapper=False)
Joe Gregorioc5c5a372010-09-22 11:42:32 -0400148 resp = httplib2.Response({'status': '401'})
149 resp.reason = 'Unauthorized'
Joe Gregoriod4e14562011-01-04 09:51:45 -0500150 content = '{"error": {"message": "not authorized"}}'
Joe Gregorioc5c5a372010-09-22 11:42:32 -0400151
152 try:
153 content = model.response(resp, content)
154 self.fail('Should have thrown an exception')
155 except HttpError, e:
Joe Gregorio20b54fb2012-07-26 09:59:35 -0400156 self.assertTrue('not authorized' in str(e))
Joe Gregorioc5c5a372010-09-22 11:42:32 -0400157
158 resp['content-type'] = 'application/json'
159
160 try:
161 content = model.response(resp, content)
162 self.fail('Should have thrown an exception')
163 except HttpError, e:
164 self.assertTrue('not authorized' in str(e))
165
Joe Gregorioc5c5a372010-09-22 11:42:32 -0400166 def test_good_response(self):
Joe Gregoriod433b2a2011-02-22 10:51:51 -0500167 model = JsonModel(data_wrapper=True)
Joe Gregorioc5c5a372010-09-22 11:42:32 -0400168 resp = httplib2.Response({'status': '200'})
169 resp.reason = 'OK'
170 content = '{"data": "is good"}'
171
172 content = model.response(resp, content)
173 self.assertEqual(content, 'is good')
Joe Gregoriofe695fb2010-08-30 12:04:04 -0400174
Joe Gregorio78a508d2010-10-26 16:36:36 -0400175 def test_good_response_wo_data(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 = '{"foo": "is good"}'
180
181 content = model.response(resp, content)
182 self.assertEqual(content, {'foo': 'is good'})
183
184 def test_good_response_wo_data_str(self):
Joe Gregoriod433b2a2011-02-22 10:51:51 -0500185 model = JsonModel(data_wrapper=False)
Joe Gregorio78a508d2010-10-26 16:36:36 -0400186 resp = httplib2.Response({'status': '200'})
187 resp.reason = 'OK'
188 content = '"data goes here"'
189
190 content = model.response(resp, content)
191 self.assertEqual(content, 'data goes here')
192
Matt McDonald2a5f4132011-04-29 16:32:27 -0400193 def test_no_content_response(self):
194 model = JsonModel(data_wrapper=False)
195 resp = httplib2.Response({'status': '204'})
196 resp.reason = 'No Content'
197 content = ''
Joe Gregorio34044bc2011-03-07 16:58:33 -0500198
Matt McDonald2a5f4132011-04-29 16:32:27 -0400199 content = model.response(resp, content)
200 self.assertEqual(content, {})
Joe Gregorio34044bc2011-03-07 16:58:33 -0500201
Matt McDonald2a5f4132011-04-29 16:32:27 -0400202 def test_logging(self):
Joe Gregorio34044bc2011-03-07 16:58:33 -0500203 class MockLogging(object):
204 def __init__(self):
205 self.info_record = []
206 self.debug_record = []
207 def info(self, message, *args):
208 self.info_record.append(message % args)
209
210 def debug(self, message, *args):
211 self.debug_record.append(message % args)
212
213 class MockResponse(dict):
214 def __init__(self, items):
215 super(MockResponse, self).__init__()
216 self.status = items['status']
217 for key, value in items.iteritems():
218 self[key] = value
John Asmuth864311d2014-04-24 15:46:08 -0400219 old_logging = googleapiclient.model.logging
220 googleapiclient.model.logging = MockLogging()
221 googleapiclient.model.dump_request_response = True
Matt McDonald2a5f4132011-04-29 16:32:27 -0400222 model = JsonModel()
Joe Gregorio34044bc2011-03-07 16:58:33 -0500223 request_body = {
224 'field1': 'value1',
225 'field2': 'value2'
226 }
227 body_string = model.request({}, {}, {}, request_body)[-1]
Craig Citro6ae34d72014-08-18 23:10:09 -0700228 json_body = json.loads(body_string)
Joe Gregorio34044bc2011-03-07 16:58:33 -0500229 self.assertEqual(request_body, json_body)
230
231 response = {'status': 200,
232 'response_field_1': 'response_value_1',
233 'response_field_2': 'response_value_2'}
234 response_body = model.response(MockResponse(response), body_string)
235 self.assertEqual(request_body, response_body)
John Asmuth864311d2014-04-24 15:46:08 -0400236 self.assertEqual(googleapiclient.model.logging.info_record[:2],
Joe Gregorioafdf50b2011-03-08 09:41:52 -0500237 ['--request-start--',
238 '-headers-start-'])
239 self.assertTrue('response_field_1: response_value_1' in
John Asmuth864311d2014-04-24 15:46:08 -0400240 googleapiclient.model.logging.info_record)
Joe Gregorioafdf50b2011-03-08 09:41:52 -0500241 self.assertTrue('response_field_2: response_value_2' in
John Asmuth864311d2014-04-24 15:46:08 -0400242 googleapiclient.model.logging.info_record)
Craig Citro6ae34d72014-08-18 23:10:09 -0700243 self.assertEqual(json.loads(googleapiclient.model.logging.info_record[-2]),
Joe Gregorio34044bc2011-03-07 16:58:33 -0500244 request_body)
John Asmuth864311d2014-04-24 15:46:08 -0400245 self.assertEqual(googleapiclient.model.logging.info_record[-1],
Joe Gregorio34044bc2011-03-07 16:58:33 -0500246 '--response-end--')
John Asmuth864311d2014-04-24 15:46:08 -0400247 googleapiclient.model.logging = old_logging
Joe Gregorio34044bc2011-03-07 16:58:33 -0500248
Ali Afshar81fde8e2012-10-23 11:14:28 -0700249 def test_no_data_wrapper_deserialize(self):
250 model = JsonModel(data_wrapper=False)
251 resp = httplib2.Response({'status': '200'})
252 resp.reason = 'OK'
253 content = '{"data": "is good"}'
254 content = model.response(resp, content)
255 self.assertEqual(content, {'data': 'is good'})
256
257 def test_data_wrapper_deserialize(self):
258 model = JsonModel(data_wrapper=True)
259 resp = httplib2.Response({'status': '200'})
260 resp.reason = 'OK'
261 content = '{"data": "is good"}'
262 content = model.response(resp, content)
263 self.assertEqual(content, 'is good')
264
265 def test_data_wrapper_deserialize_nodata(self):
266 model = JsonModel(data_wrapper=True)
267 resp = httplib2.Response({'status': '200'})
268 resp.reason = 'OK'
269 content = '{"atad": "is good"}'
270 content = model.response(resp, content)
271 self.assertEqual(content, {'atad': 'is good'})
272
273
Joe Gregorio34044bc2011-03-07 16:58:33 -0500274
Joe Gregorioba9ea7f2010-08-19 15:49:04 -0400275if __name__ == '__main__':
276 unittest.main()