# Copyright 2017 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from __future__ import unicode_literals import mock import pytest from google.api_core import path_template @pytest.mark.parametrize( "tmpl, args, kwargs, expected_result", [ # Basic positional params ["/v1/*", ["a"], {}, "/v1/a"], ["/v1/**", ["a/b"], {}, "/v1/a/b"], ["/v1/*/*", ["a", "b"], {}, "/v1/a/b"], ["/v1/*/*/**", ["a", "b", "c/d"], {}, "/v1/a/b/c/d"], # Basic named params ["/v1/{name}", [], {"name": "parent"}, "/v1/parent"], ["/v1/{name=**}", [], {"name": "parent/child"}, "/v1/parent/child"], # Named params with a sub-template ["/v1/{name=parent/*}", [], {"name": "parent/child"}, "/v1/parent/child"], [ "/v1/{name=parent/**}", [], {"name": "parent/child/object"}, "/v1/parent/child/object", ], # Combining positional and named params ["/v1/*/{name}", ["a"], {"name": "parent"}, "/v1/a/parent"], ["/v1/{name}/*", ["a"], {"name": "parent"}, "/v1/parent/a"], [ "/v1/{parent}/*/{child}/*", ["a", "b"], {"parent": "thor", "child": "thorson"}, "/v1/thor/a/thorson/b", ], ["/v1/{name}/**", ["a/b"], {"name": "parent"}, "/v1/parent/a/b"], # Combining positional and named params with sub-templates. [ "/v1/{name=parent/*}/*", ["a"], {"name": "parent/child"}, "/v1/parent/child/a", ], [ "/v1/*/{name=parent/**}", ["a"], {"name": "parent/child/object"}, "/v1/a/parent/child/object", ], ], ) def test_expand_success(tmpl, args, kwargs, expected_result): result = path_template.expand(tmpl, *args, **kwargs) assert result == expected_result assert path_template.validate(tmpl, result) @pytest.mark.parametrize( "tmpl, args, kwargs, exc_match", [ # Missing positional arg. ["v1/*", [], {}, "Positional"], # Missing named arg. ["v1/{name}", [], {}, "Named"], ], ) def test_expanded_failure(tmpl, args, kwargs, exc_match): with pytest.raises(ValueError, match=exc_match): path_template.expand(tmpl, *args, **kwargs) @pytest.mark.parametrize( "tmpl, path", [ # Single segment template, but multi segment value ["v1/*", "v1/a/b"], ["v1/*/*", "v1/a/b/c"], # Single segement named template, but multi segment value ["v1/{name}", "v1/a/b"], ["v1/{name}/{value}", "v1/a/b/c"], # Named value with a sub-template but invalid value ["v1/{name=parent/*}", "v1/grandparent/child"], ], ) def test_validate_failure(tmpl, path): assert not path_template.validate(tmpl, path) def test__expand_variable_match_unexpected(): match = mock.Mock(spec=["group"]) match.group.return_value = None with pytest.raises(ValueError, match="Unknown"): path_template._expand_variable_match([], {}, match) def test__replace_variable_with_pattern(): match = mock.Mock(spec=["group"]) match.group.return_value = None with pytest.raises(ValueError, match="Unknown"): path_template._replace_variable_with_pattern(match)