OLD | NEW |
(Empty) | |
| 1 # |
| 2 # Copyright 2015 Google Inc. |
| 3 # |
| 4 # Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 # you may not use this file except in compliance with the License. |
| 6 # You may obtain 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, |
| 12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 # See the License for the specific language governing permissions and |
| 14 # limitations under the License. |
| 15 |
| 16 import base64 |
| 17 import datetime |
| 18 import sys |
| 19 import contextlib |
| 20 |
| 21 import six |
| 22 from six.moves import urllib_parse |
| 23 import unittest2 |
| 24 |
| 25 from apitools.base.protorpclite import message_types |
| 26 from apitools.base.protorpclite import messages |
| 27 from apitools.base.py import base_api |
| 28 from apitools.base.py import encoding |
| 29 from apitools.base.py import http_wrapper |
| 30 |
| 31 |
| 32 @contextlib.contextmanager |
| 33 def mock(module, fn_name, patch): |
| 34 unpatch = getattr(module, fn_name) |
| 35 setattr(module, fn_name, patch) |
| 36 try: |
| 37 yield |
| 38 finally: |
| 39 setattr(module, fn_name, unpatch) |
| 40 |
| 41 |
| 42 class SimpleMessage(messages.Message): |
| 43 field = messages.StringField(1) |
| 44 bytes_field = messages.BytesField(2) |
| 45 |
| 46 |
| 47 class MessageWithTime(messages.Message): |
| 48 timestamp = message_types.DateTimeField(1) |
| 49 |
| 50 |
| 51 class MessageWithRemappings(messages.Message): |
| 52 |
| 53 class AnEnum(messages.Enum): |
| 54 value_one = 1 |
| 55 value_two = 2 |
| 56 |
| 57 str_field = messages.StringField(1) |
| 58 enum_field = messages.EnumField('AnEnum', 2) |
| 59 |
| 60 |
| 61 encoding.AddCustomJsonFieldMapping( |
| 62 MessageWithRemappings, 'str_field', 'remapped_field') |
| 63 encoding.AddCustomJsonEnumMapping( |
| 64 MessageWithRemappings.AnEnum, 'value_one', 'ONE/TWO') |
| 65 |
| 66 |
| 67 class StandardQueryParameters(messages.Message): |
| 68 field = messages.StringField(1) |
| 69 prettyPrint = messages.BooleanField( |
| 70 5, default=True) # pylint: disable=invalid-name |
| 71 pp = messages.BooleanField(6, default=True) |
| 72 nextPageToken = messages.BytesField(7) # pylint:disable=invalid-name |
| 73 |
| 74 |
| 75 class FakeCredentials(object): |
| 76 |
| 77 def authorize(self, _): # pylint: disable=invalid-name |
| 78 return None |
| 79 |
| 80 |
| 81 class FakeClient(base_api.BaseApiClient): |
| 82 MESSAGES_MODULE = sys.modules[__name__] |
| 83 _PACKAGE = 'package' |
| 84 _SCOPES = ['scope1'] |
| 85 _CLIENT_ID = 'client_id' |
| 86 _CLIENT_SECRET = 'client_secret' |
| 87 |
| 88 |
| 89 class FakeService(base_api.BaseApiService): |
| 90 |
| 91 def __init__(self, client=None): |
| 92 client = client or FakeClient( |
| 93 'http://www.example.com/', credentials=FakeCredentials()) |
| 94 super(FakeService, self).__init__(client) |
| 95 |
| 96 |
| 97 class BaseApiTest(unittest2.TestCase): |
| 98 |
| 99 def __GetFakeClient(self): |
| 100 return FakeClient('', credentials=FakeCredentials()) |
| 101 |
| 102 def testUrlNormalization(self): |
| 103 client = FakeClient('http://www.googleapis.com', get_credentials=False) |
| 104 self.assertTrue(client.url.endswith('/')) |
| 105 |
| 106 def testNoCredentials(self): |
| 107 client = FakeClient('', get_credentials=False) |
| 108 self.assertIsNotNone(client) |
| 109 self.assertIsNone(client._credentials) |
| 110 |
| 111 def testIncludeEmptyFieldsClient(self): |
| 112 msg = SimpleMessage() |
| 113 client = self.__GetFakeClient() |
| 114 self.assertEqual('{}', client.SerializeMessage(msg)) |
| 115 with client.IncludeFields(('field',)): |
| 116 self.assertEqual('{"field": null}', client.SerializeMessage(msg)) |
| 117 |
| 118 def testJsonResponse(self): |
| 119 method_config = base_api.ApiMethodInfo( |
| 120 response_type_name='SimpleMessage') |
| 121 service = FakeService() |
| 122 http_response = http_wrapper.Response( |
| 123 info={'status': '200'}, content='{"field": "abc"}', |
| 124 request_url='http://www.google.com') |
| 125 response_message = SimpleMessage(field='abc') |
| 126 self.assertEqual(response_message, service.ProcessHttpResponse( |
| 127 method_config, http_response)) |
| 128 with service.client.JsonResponseModel(): |
| 129 self.assertEqual( |
| 130 http_response.content, |
| 131 service.ProcessHttpResponse(method_config, http_response)) |
| 132 |
| 133 def testAdditionalHeaders(self): |
| 134 additional_headers = {'Request-Is-Awesome': '1'} |
| 135 client = self.__GetFakeClient() |
| 136 |
| 137 # No headers to start |
| 138 http_request = http_wrapper.Request('http://www.example.com') |
| 139 new_request = client.ProcessHttpRequest(http_request) |
| 140 self.assertFalse('Request-Is-Awesome' in new_request.headers) |
| 141 |
| 142 # Add a new header and ensure it's added to the request. |
| 143 client.additional_http_headers = additional_headers |
| 144 http_request = http_wrapper.Request('http://www.example.com') |
| 145 new_request = client.ProcessHttpRequest(http_request) |
| 146 self.assertTrue('Request-Is-Awesome' in new_request.headers) |
| 147 |
| 148 def testCustomCheckResponse(self): |
| 149 def check_response(): |
| 150 pass |
| 151 |
| 152 def fakeMakeRequest(*_, **kwargs): |
| 153 self.assertEqual(check_response, kwargs['check_response_func']) |
| 154 return http_wrapper.Response( |
| 155 info={'status': '200'}, content='{"field": "abc"}', |
| 156 request_url='http://www.google.com') |
| 157 http_wrapper.MakeRequest = fakeMakeRequest |
| 158 method_config = base_api.ApiMethodInfo( |
| 159 request_type_name='SimpleMessage', |
| 160 response_type_name='SimpleMessage') |
| 161 client = self.__GetFakeClient() |
| 162 client.check_response_func = check_response |
| 163 service = FakeService(client=client) |
| 164 request = SimpleMessage() |
| 165 with mock(base_api.http_wrapper, 'MakeRequest', fakeMakeRequest): |
| 166 service._RunMethod(method_config, request) |
| 167 |
| 168 def testQueryEncoding(self): |
| 169 method_config = base_api.ApiMethodInfo( |
| 170 request_type_name='MessageWithTime', query_params=['timestamp']) |
| 171 service = FakeService() |
| 172 request = MessageWithTime( |
| 173 timestamp=datetime.datetime(2014, 10, 0o7, 12, 53, 13)) |
| 174 http_request = service.PrepareHttpRequest(method_config, request) |
| 175 |
| 176 url_timestamp = urllib_parse.quote(request.timestamp.isoformat()) |
| 177 self.assertTrue(http_request.url.endswith(url_timestamp)) |
| 178 |
| 179 def testPrettyPrintEncoding(self): |
| 180 method_config = base_api.ApiMethodInfo( |
| 181 request_type_name='MessageWithTime', query_params=['timestamp']) |
| 182 service = FakeService() |
| 183 request = MessageWithTime( |
| 184 timestamp=datetime.datetime(2014, 10, 0o7, 12, 53, 13)) |
| 185 |
| 186 global_params = StandardQueryParameters() |
| 187 http_request = service.PrepareHttpRequest(method_config, request, |
| 188 global_params=global_params) |
| 189 self.assertFalse('prettyPrint' in http_request.url) |
| 190 self.assertFalse('pp' in http_request.url) |
| 191 |
| 192 global_params.prettyPrint = False # pylint: disable=invalid-name |
| 193 global_params.pp = False |
| 194 |
| 195 http_request = service.PrepareHttpRequest(method_config, request, |
| 196 global_params=global_params) |
| 197 self.assertTrue('prettyPrint=0' in http_request.url) |
| 198 self.assertTrue('pp=0' in http_request.url) |
| 199 |
| 200 def testQueryBytesRequest(self): |
| 201 method_config = base_api.ApiMethodInfo( |
| 202 request_type_name='SimpleMessage', query_params=['bytes_field']) |
| 203 service = FakeService() |
| 204 non_unicode_message = b''.join((six.int2byte(100), |
| 205 six.int2byte(200))) |
| 206 request = SimpleMessage(bytes_field=non_unicode_message) |
| 207 global_params = StandardQueryParameters() |
| 208 http_request = service.PrepareHttpRequest(method_config, request, |
| 209 global_params=global_params) |
| 210 want = urllib_parse.urlencode({ |
| 211 'bytes_field': base64.urlsafe_b64encode(non_unicode_message), |
| 212 }) |
| 213 self.assertIn(want, http_request.url) |
| 214 |
| 215 def testQueryBytesGlobalParams(self): |
| 216 method_config = base_api.ApiMethodInfo( |
| 217 request_type_name='SimpleMessage', query_params=['bytes_field']) |
| 218 service = FakeService() |
| 219 non_unicode_message = b''.join((six.int2byte(100), |
| 220 six.int2byte(200))) |
| 221 request = SimpleMessage() |
| 222 global_params = StandardQueryParameters( |
| 223 nextPageToken=non_unicode_message) |
| 224 http_request = service.PrepareHttpRequest(method_config, request, |
| 225 global_params=global_params) |
| 226 want = urllib_parse.urlencode({ |
| 227 'nextPageToken': base64.urlsafe_b64encode(non_unicode_message), |
| 228 }) |
| 229 self.assertIn(want, http_request.url) |
| 230 |
| 231 def testQueryRemapping(self): |
| 232 method_config = base_api.ApiMethodInfo( |
| 233 request_type_name='MessageWithRemappings', |
| 234 query_params=['remapped_field', 'enum_field']) |
| 235 request = MessageWithRemappings( |
| 236 str_field='foo', enum_field=MessageWithRemappings.AnEnum.value_one) |
| 237 http_request = FakeService().PrepareHttpRequest(method_config, request) |
| 238 result_params = urllib_parse.parse_qs( |
| 239 urllib_parse.urlparse(http_request.url).query) |
| 240 expected_params = {'enum_field': 'ONE%2FTWO', 'remapped_field': 'foo'} |
| 241 self.assertTrue(expected_params, result_params) |
| 242 |
| 243 def testPathRemapping(self): |
| 244 method_config = base_api.ApiMethodInfo( |
| 245 relative_path='parameters/{remapped_field}/remap/{enum_field}', |
| 246 request_type_name='MessageWithRemappings', |
| 247 path_params=['remapped_field', 'enum_field']) |
| 248 request = MessageWithRemappings( |
| 249 str_field='gonna', |
| 250 enum_field=MessageWithRemappings.AnEnum.value_one) |
| 251 service = FakeService() |
| 252 expected_url = service.client.url + 'parameters/gonna/remap/ONE%2FTWO' |
| 253 http_request = service.PrepareHttpRequest(method_config, request) |
| 254 self.assertEqual(expected_url, http_request.url) |
| 255 |
| 256 method_config.relative_path = ( |
| 257 'parameters/{+remapped_field}/remap/{+enum_field}') |
| 258 expected_url = service.client.url + 'parameters/gonna/remap/ONE/TWO' |
| 259 http_request = service.PrepareHttpRequest(method_config, request) |
| 260 self.assertEqual(expected_url, http_request.url) |
| 261 |
| 262 def testColonInRelativePath(self): |
| 263 method_config = base_api.ApiMethodInfo( |
| 264 relative_path='path:withJustColon', |
| 265 request_type_name='SimpleMessage') |
| 266 service = FakeService() |
| 267 request = SimpleMessage() |
| 268 http_request = service.PrepareHttpRequest(method_config, request) |
| 269 self.assertEqual('http://www.example.com/path:withJustColon', |
| 270 http_request.url) |
OLD | NEW |