Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(497)

Side by Side Diff: third_party/google-endpoints/endpoints/test/api_config_manager_test.py

Issue 2666783008: Add google-endpoints to third_party/. (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 # Copyright 2016 Google Inc. All Rights Reserved.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 """Unit tests for the api_config_manager module."""
16
17 import re
18 import unittest
19
20 import endpoints.api_config_manager as api_config_manager
21
22
23 class ApiConfigManagerTest(unittest.TestCase):
24
25 def setUp(self):
26 """Make ApiConfigManager with a few helpful fakes."""
27 self.config_manager = api_config_manager.ApiConfigManager()
28
29 def test_process_api_config_empty_response(self):
30 self.config_manager.process_api_config_response({})
31 actual_method = self.config_manager.lookup_rpc_method('guestbook_api.get',
32 'v1')
33 self.assertEqual(None, actual_method)
34
35 def test_process_api_config_invalid_response(self):
36 self.config_manager.process_api_config_response({'name': 'foo'})
37 actual_method = self.config_manager.lookup_rpc_method('guestbook_api.get',
38 'v1')
39 self.assertEqual(None, actual_method)
40
41 def test_process_api_config(self):
42 fake_method = {'httpMethod': 'GET',
43 'path': 'greetings/{gid}',
44 'rosyMethod': 'baz.bim'}
45 config = {'name': 'guestbook_api',
46 'version': 'X',
47 'methods': {'guestbook_api.foo.bar': fake_method}}
48 self.config_manager.process_api_config_response({'items': [config]})
49 actual_method = self.config_manager.lookup_rpc_method(
50 'guestbook_api.foo.bar', 'X')
51 self.assertEqual(fake_method, actual_method)
52
53 def test_process_api_config_order_length(self):
54 test_method_info = (
55 ('guestbook_api.foo.bar', 'greetings/{gid}', 'baz.bim'),
56 ('guestbook_api.list', 'greetings', 'greetings.list'),
57 ('guestbook_api.f3', 'greetings/{gid}/sender/property/blah',
58 'greetings.f3'),
59 ('guestbook_api.shortgreet', 'greet', 'greetings.short_greeting'))
60 methods = {}
61 for method_name, path, rosy_method in test_method_info:
62 method = {'httpMethod': 'GET',
63 'path': path,
64 'rosyMethod': rosy_method}
65 methods[method_name] = method
66 config = {'name': 'guestbook_api',
67 'version': 'X',
68 'methods': methods}
69 self.config_manager.process_api_config_response(
70 {'items': [config]})
71 # Make sure all methods appear in the result.
72 for method_name, _, _ in test_method_info:
73 self.assertIsNotNone(
74 self.config_manager.lookup_rpc_method(method_name, 'X'))
75 # Make sure paths and partial paths return the right methods.
76 self.assertEqual(
77 self.config_manager.lookup_rest_method(
78 'guestbook_api/X/greetings', 'GET')[0],
79 'guestbook_api.list')
80 self.assertEqual(
81 self.config_manager.lookup_rest_method(
82 'guestbook_api/X/greetings/1', 'GET')[0],
83 'guestbook_api.foo.bar')
84 self.assertEqual(
85 self.config_manager.lookup_rest_method(
86 'guestbook_api/X/greetings/2/sender/property/blah', 'GET')[0],
87 'guestbook_api.f3')
88 self.assertEqual(
89 self.config_manager.lookup_rest_method(
90 'guestbook_api/X/greet', 'GET')[0],
91 'guestbook_api.shortgreet')
92
93 def test_get_sorted_methods1(self):
94 test_method_info = (
95 ('name1', 'greetings', 'POST'),
96 ('name2', 'greetings', 'GET'),
97 ('name3', 'short/but/many/constants', 'GET'),
98 ('name4', 'greetings', ''),
99 ('name5', 'greetings/{gid}', 'GET'),
100 ('name6', 'greetings/{gid}', 'PUT'),
101 ('name7', 'a/b/{var}/{var2}', 'GET'))
102 methods = {}
103 for method_name, path, http_method in test_method_info:
104 method = {'httpMethod': http_method,
105 'path': path}
106 methods[method_name] = method
107 sorted_methods = self.config_manager._get_sorted_methods(methods)
108
109 expected_data = [
110 ('name3', 'short/but/many/constants', 'GET'),
111 ('name7', 'a/b/{var}/{var2}', 'GET'),
112 ('name4', 'greetings', ''),
113 ('name2', 'greetings', 'GET'),
114 ('name1', 'greetings', 'POST'),
115 ('name5', 'greetings/{gid}', 'GET'),
116 ('name6', 'greetings/{gid}', 'PUT')]
117 expected_methods = [(name, {'httpMethod': http_method, 'path': path})
118 for name, path, http_method in expected_data]
119 self.assertEqual(expected_methods, sorted_methods)
120
121 def test_get_sorted_methods2(self):
122 test_method_info = (
123 ('name1', 'abcdefghi', 'GET'),
124 ('name2', 'foo', 'GET'),
125 ('name3', 'greetings', 'GET'),
126 ('name4', 'bar', 'POST'),
127 ('name5', 'baz', 'GET'),
128 ('name6', 'baz', 'PUT'),
129 ('name7', 'baz', 'DELETE'))
130 methods = {}
131 for method_name, path, http_method in test_method_info:
132 method = {'httpMethod': http_method,
133 'path': path}
134 methods[method_name] = method
135 sorted_methods = self.config_manager._get_sorted_methods(methods)
136
137 # Single-part paths should be sorted by path name, http_method.
138 expected_data = [
139 ('name1', 'abcdefghi', 'GET'),
140 ('name4', 'bar', 'POST'),
141 ('name7', 'baz', 'DELETE'),
142 ('name5', 'baz', 'GET'),
143 ('name6', 'baz', 'PUT'),
144 ('name2', 'foo', 'GET'),
145 ('name3', 'greetings', 'GET')]
146 expected_methods = [(name, {'httpMethod': http_method, 'path': path})
147 for name, path, http_method in expected_data]
148 self.assertEqual(expected_methods, sorted_methods)
149
150 def test_process_api_config_convert_https(self):
151 """Test that the parsed API config has switched HTTPS to HTTP."""
152 config = {'name': 'guestbook_api',
153 'version': 'X',
154 'adapter': {'bns': 'https://localhost/_ah/spi',
155 'type': 'lily'},
156 'root': 'https://localhost/_ah/api',
157 'methods': {}}
158 self.config_manager.process_api_config_response({'items': [config]})
159
160 self.assertEqual(
161 'https://localhost/_ah/spi',
162 self.config_manager.configs[('guestbook_api', 'X')]['adapter']['bns'])
163 self.assertEqual(
164 'https://localhost/_ah/api',
165 self.config_manager.configs[('guestbook_api', 'X')]['root'])
166
167 def test_save_lookup_rpc_method(self):
168 # First attempt, guestbook.get does not exist
169 actual_method = self.config_manager.lookup_rpc_method('guestbook_api.get',
170 'v1')
171 self.assertEqual(None, actual_method)
172
173 # Now we manually save it, and should find it
174 fake_method = {'some': 'object'}
175 self.config_manager._save_rpc_method('guestbook_api.get', 'v1', fake_method)
176 actual_method = self.config_manager.lookup_rpc_method('guestbook_api.get',
177 'v1')
178 self.assertEqual(fake_method, actual_method)
179
180 def test_save_lookup_rest_method(self):
181 # First attempt, guestbook.get does not exist
182 method_spec = self.config_manager.lookup_rest_method(
183 'guestbook_api/v1/greetings/i', 'GET')
184 self.assertEqual((None, None, None), method_spec)
185
186 # Now we manually save it, and should find it
187 fake_method = {'httpMethod': 'GET',
188 'path': 'greetings/{id}'}
189 self.config_manager._save_rest_method('guestbook_api.get', 'guestbook_api',
190 'v1', fake_method)
191 method_name, method_spec, params = self.config_manager.lookup_rest_method(
192 'guestbook_api/v1/greetings/i', 'GET')
193 self.assertEqual('guestbook_api.get', method_name)
194 self.assertEqual(fake_method, method_spec)
195 self.assertEqual({'id': 'i'}, params)
196
197 def test_lookup_rest_method_with_colon(self):
198 fake_method = {'httpMethod': 'GET',
199 'path': 'greetings:testcolon'}
200 self.config_manager._save_rest_method('guestbook_api.get', 'guestbook_api',
201 'v1', fake_method)
202 method_name, method_spec, params = self.config_manager.lookup_rest_method(
203 'guestbook_api/v1/greetings%3Atestcolon', 'GET')
204 self.assertEqual('guestbook_api.get', method_name)
205 self.assertEqual(fake_method, method_spec)
206
207 def test_trailing_slash_optional(self):
208 # Create a typical get resource URL.
209 fake_method = {'httpMethod': 'GET', 'path': 'trailingslash'}
210 self.config_manager._save_rest_method('guestbook_api.trailingslash',
211 'guestbook_api', 'v1', fake_method)
212
213 # Make sure we get this method when we query without a slash.
214 method_name, method_spec, params = self.config_manager.lookup_rest_method(
215 'guestbook_api/v1/trailingslash', 'GET')
216 self.assertEqual('guestbook_api.trailingslash', method_name)
217 self.assertEqual(fake_method, method_spec)
218 self.assertEqual({}, params)
219
220 # Make sure we get this method when we query with a slash.
221 method_name, method_spec, params = self.config_manager.lookup_rest_method(
222 'guestbook_api/v1/trailingslash/', 'GET')
223 self.assertEqual('guestbook_api.trailingslash', method_name)
224 self.assertEqual(fake_method, method_spec)
225 self.assertEqual({}, params)
226
227
228 class ParameterizedPathTest(unittest.TestCase):
229
230 # <scrub>
231 # See http://cs/spi/tools/devserver/ParameterizedPathTest.java
232 # </scrub>
233 def test_invalid_variable_name_leading_digit(self):
234 self.assertEqual(
235 None, re.match(api_config_manager._PATH_VARIABLE_PATTERN, '1abc'))
236
237 # Ensure users can not add variables starting with !
238 # This is used for reserved variables (e.g. !name and !version)
239 def test_invalid_var_name_leading_exclamation(self):
240 self.assertEqual(
241 None, re.match(api_config_manager._PATH_VARIABLE_PATTERN, '!abc'))
242
243 def test_valid_variable_name(self):
244 self.assertEqual(
245 'AbC1', re.match(api_config_manager._PATH_VARIABLE_PATTERN,
246 'AbC1').group(0))
247
248 def assert_no_match(self, path, param_path):
249 """Assert that the given path does not match param_path pattern.
250
251 For example, /xyz/123 does not match /abc/{x}.
252
253 Args:
254 path: A string, the inbound request path.
255 param_path: A string, the parameterized path pattern to match against
256 this path.
257 """
258 config_manager = api_config_manager.ApiConfigManager
259 params = config_manager._compile_path_pattern(param_path).match(path)
260 self.assertEqual(None, params)
261
262 def test_prefix_no_match(self):
263 self.assert_no_match('/xyz/123', '/abc/{x}')
264
265 def test_suffix_no_match(self):
266 self.assert_no_match('/abc/123', '/abc/{x}/456')
267
268 def test_suffix_no_match_with_more_variables(self):
269 self.assert_no_match('/abc/456/123/789', '/abc/{x}/123/{y}/xyz')
270
271 def test_no_match_collection_with_item(self):
272 self.assert_no_match('/api/v1/resources/123', '/{name}/{version}/resources')
273
274 def assert_match(self, path, param_path, param_count):
275 """Assert that the given path does match param_path pattern.
276
277 For example, /abc/123 does not match /abc/{x}.
278
279 Args:
280 path: A string, the inbound request path.
281 param_path: A string, the parameterized path pattern to match against
282 this path.
283 param_count: An int, the expected number of parameters to match in
284 pattern.
285
286 Returns:
287 Dict mapping path variable name to path variable value.
288 """
289 config_manager = api_config_manager.ApiConfigManager
290 match = config_manager._compile_path_pattern(param_path).match(path)
291 self.assertTrue(match is not None) # Will be None if path was not matched
292 params = config_manager._get_path_params(match)
293 self.assertEquals(param_count, len(params))
294 return params
295
296 def test_one_variable_match(self):
297 params = self.assert_match('/abc/123', '/abc/{x}', 1)
298 self.assertEquals('123', params.get('x'))
299
300 def test_two_variable_match(self):
301 params = self.assert_match('/abc/456/123/789', '/abc/{x}/123/{y}', 2)
302 self.assertEquals('456', params.get('x'))
303 self.assertEquals('789', params.get('y'))
304
305 def test_message_variable_match(self):
306 params = self.assert_match('/abc/123', '/abc/{x.y}', 1)
307 self.assertEquals('123', params.get('x.y'))
308
309 def test_message_and_simple_variable_match(self):
310 params = self.assert_match('/abc/123/456', '/abc/{x.y.z}/{t}', 2)
311 self.assertEquals('123', params.get('x.y.z'))
312 self.assertEquals('456', params.get('t'))
313
314 def test_space_in_path(self):
315 params = self.assert_match('/abc/foo+bar', '/abc/{x}', 1)
316 self.assertEquals('foo bar', params.get('x'))
317
318 def assert_invalid_value(self, value):
319 """Assert that the path parameter value is not valid.
320
321 For example, /abc/3!:2 is invalid for /abc/{x}.
322
323 Args:
324 value: A string containing a variable value to check for validity.
325 """
326 param_path = '/abc/{x}'
327 path = '/abc/%s' % value
328 config_manager = api_config_manager.ApiConfigManager
329 params = config_manager._compile_path_pattern(param_path).match(path)
330 self.assertEqual(None, params)
331
332 def test_invalid_values(self):
333 for reserved in [':', '?', '#', '[', ']', '{', '}']:
334 self.assert_invalid_value('123%s' % reserved)
335
336
337 if __name__ == '__main__':
338 unittest.main()
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698