@@ -764,7 +764,7 @@ def test_path_traversal_dots_validation_double_star_valid(name_val, expected_pat
764764 ],
765765)
766766def test_path_traversal_dots_validation_double_star_invalid (name_val ):
767- with pytest .raises (ValueError , match = "Invalid value .* for name\ \ ." ):
767+ with pytest .raises (ValueError , match = r "Invalid value .* for name\." ):
768768 path_template .expand (
769769 "/v3/{name=projects/*/monitoredResourceDescriptors/**}" ,
770770 name = name_val ,
@@ -786,3 +786,29 @@ def test_percent_encoding_unreserved_characters(tmpl, kwargs, expected_result):
786786 # For single-segment with '/', validate should fail because '/' is preserved
787787 if "/" in kwargs .get ("name" , "" ) and tmpl == "/v1/{name}" :
788788 assert not path_template .validate (tmpl , result )
789+
790+
791+ @pytest .mark .parametrize (
792+ "tmpl, args, kwargs, expected_err_match" ,
793+ [
794+ ("/v1/**" , [".." ], {}, r"Invalid value .* for positional variable\." ),
795+ ("/v1/{name=**}" , [], {"name" : ".." }, r"Invalid value .* for name\." ),
796+ ],
797+ )
798+ def test_path_traversal_dots_validation_bare_double_star (tmpl , args , kwargs , expected_err_match ):
799+ with pytest .raises (ValueError , match = expected_err_match ):
800+ path_template .expand (tmpl , * args , ** kwargs )
801+
802+ @pytest .mark .parametrize (
803+ "template_str, expected_pattern, expected_wildcards" ,
804+ [
805+ ("projects/{project}/locations/{location}" , "projects/([^/]+)/locations/([^/]+)" , ("*" , "*" )),
806+ ("projects/{project=**}" , "projects/(.+)" , ("**" ,)),
807+ ("projects/{project=locations/*}" , "projects/locations/([^/]+)" , ("*" ,)),
808+ ("projects/*/locations/**" , "projects/([^/]+)/locations/(.+)" , ("*" , "**" )),
809+ ],
810+ )
811+ def test_build_capture_pattern (template_str , expected_pattern , expected_wildcards ):
812+ pattern , wildcards = path_template ._build_capture_pattern (template_str )
813+ assert pattern .pattern == expected_pattern
814+ assert wildcards == expected_wildcards
0 commit comments