text: # -*- coding: utf-8 -*-
  """
      tests.routing
      ~~~~~~~~~~~~~
  
      Routing tests.
  
      :copyright: 2007 Pallets
      :license: BSD-3-Clause
  """
  import gc
  import uuid
  
  import pytest
  
  from . import strict_eq
  from werkzeug import routing as r
  from werkzeug.datastructures import ImmutableDict
  from werkzeug.datastructures import MultiDict
  from werkzeug.test import create_environ
  from werkzeug.wrappers import Response
  
  
  def test_basic_routing():
      map = r.Map(
          [
              r.Rule("/", endpoint="index"),
              r.Rule("/foo", endpoint="foo"),
              r.Rule("/bar/", endpoint="bar"),
          ]
      )
      adapter = map.bind("example.org", "/")
      assert adapter.match("/") == ("index", {})
      assert adapter.match("/foo") == ("foo", {})
      assert adapter.match("/bar/") == ("bar", {})
      pytest.raises(r.RequestRedirect, lambda: adapter.match("/bar"))
      pytest.raises(r.NotFound, lambda: adapter.match("/blub"))
  
      adapter = map.bind("example.org", "/test")
      with pytest.raises(r.RequestRedirect) as excinfo:
          adapter.match("/bar")
      assert excinfo.value.new_url == "http://example.org/test/bar/"
  
      adapter = map.bind("example.org", "/")
      with pytest.raises(r.RequestRedirect) as excinfo:
          adapter.match("/bar")
      assert excinfo.value.new_url == "http://example.org/bar/"
  
      adapter = map.bind("example.org", "/")
      with pytest.raises(r.RequestRedirect) as excinfo:
          adapter.match("/bar", query_args={"aha": "muhaha"})
      assert excinfo.value.new_url == "http://example.org/bar/?aha=muhaha"
  
      adapter = map.bind("example.org", "/")
      with pytest.raises(r.RequestRedirect) as excinfo:
          adapter.match("/bar", query_args="aha=muhaha")
      assert excinfo.value.new_url == "http://example.org/bar/?aha=muhaha"
  
      adapter = map.bind_to_environ(create_environ("/bar?foo=bar", "http://example.org/"))
      with pytest.raises(r.RequestRedirect) as excinfo:
          adapter.match()
      assert excinfo.value.new_url == "http://example.org/bar/?foo=bar"
  
  
  def test_strict_slashes_redirect():
      map = r.Map(
          [
              r.Rule("/bar/", endpoint="get", methods=["GET"]),
              r.Rule("/bar", endpoint="post", methods=["POST"]),
              r.Rule("/foo/", endpoint="foo", methods=["POST"]),
          ]
      )
      adapter = map.bind("example.org", "/")
  
      # Check if the actual routes works
      assert adapter.match("/bar/", method="GET") == ("get", {})
      assert adapter.match("/bar", method="POST") == ("post", {})
  
      # Check if exceptions are correct
      pytest.raises(r.RequestRedirect, adapter.match, "/bar", method="GET")
      pytest.raises(r.MethodNotAllowed, adapter.match, "/bar/", method="POST")
      with pytest.raises(r.RequestRedirect) as error_info:
          adapter.match("/foo", method="POST")
      assert error_info.value.code == 308
  
      # Check differently defined order
      map = r.Map(
          [
              r.Rule("/bar", endpoint="post", methods=["POST"]),
              r.Rule("/bar/", endpoint="get", methods=["GET"]),
          ]
      )
      adapter = map.bind("example.org", "/")
  
      # Check if the actual routes works
      assert adapter.match("/bar/", method="GET") == ("get", {})
      assert adapter.match("/bar", method="POST") == ("post", {})
  
      # Check if exceptions are correct
      pytest.raises(r.RequestRedirect, adapter.match, "/bar", method="GET")
      pytest.raises(r.MethodNotAllowed, adapter.match, "/bar/", method="POST")
  
      # Check what happens when only slash route is defined
      map = r.Map([r.Rule("/bar/", endpoint="get", methods=["GET"])])
      adapter = map.bind("example.org", "/")
  
      # Check if the actual routes works
      assert adapter.match("/bar/", method="GET") == ("get", {})
  
      # Check if exceptions are correct
      pytest.raises(r.RequestRedirect, adapter.match, "/bar", method="GET")
      pytest.raises(r.MethodNotAllowed, adapter.match, "/bar/", method="POST")
      pytest.raises(r.MethodNotAllowed, adapter.match, "/bar", method="POST")
  
  
  def test_environ_defaults():
      environ = create_environ("/foo")
      strict_eq(environ["PATH_INFO"], "/foo")
      m = r.Map([r.Rule("/foo", endpoint="foo"), r.Rule("/bar", endpoint="bar")])
      a = m.bind_to_environ(environ)
      strict_eq(a.match("/foo"), ("foo", {}))
      strict_eq(a.match(), ("foo", {}))
      strict_eq(a.match("/bar"), ("bar", {}))
      pytest.raises(r.NotFound, a.match, "/bars")
  
  
  def test_environ_nonascii_pathinfo():
      environ = create_environ(u"/лошадь")
      m = r.Map([r.Rule(u"/", endpoint="index"), r.Rule(u"/лошадь", endpoint="horse")])
      a = m.bind_to_environ(environ)
      strict_eq(a.match(u"/"), ("index", {}))
      strict_eq(a.match(u"/лошадь"), ("horse", {}))
      pytest.raises(r.NotFound, a.match, u"/барсук")
  
  
  def test_basic_building():
      map = r.Map(
          [
              r.Rule("/", endpoint="index"),
              r.Rule("/foo", endpoint="foo"),
              r.Rule("/bar/<baz>", endpoint="bar"),
              r.Rule("/bar/<int:bazi>", endpoint="bari"),
              r.Rule("/bar/<float:bazf>", endpoint="barf"),
              r.Rule("/bar/<path:bazp>", endpoint="barp"),
              r.Rule("/hehe", endpoint="blah", subdomain="blah"),
          ]
      )
      adapter = map.bind("example.org", "/", subdomain="blah")
  
      assert adapter.build("index", {}) == "http://example.org/"
      assert adapter.build("foo", {}) == "http://example.org/foo"
      assert adapter.build("bar", {"baz": "blub"}) == "http://example.org/bar/blub"
      assert adapter.build("bari", {"bazi": 50}) == "http://example.org/bar/50"
      assert adapter.build("barf", {"bazf": 0.815}) == "http://example.org/bar/0.815"
      assert adapter.build("barp", {"bazp": "la/di"}) == "http://example.org/bar/la/di"
      assert adapter.build("blah", {}) == "/hehe"
      pytest.raises(r.BuildError, lambda: adapter.build("urks"))
  
      adapter = map.bind("example.org", "/test", subdomain="blah")
      assert adapter.build("index", {}) == "http://example.org/test/"
      assert adapter.build("foo", {}) == "http://example.org/test/foo"
      assert adapter.build("bar", {"baz": "blub"}) == "http://example.org/test/bar/blub"
      assert adapter.build("bari", {"bazi": 50}) == "http://example.org/test/bar/50"
      assert adapter.build("barf", {"bazf": 0.815}) == "http://example.org/test/bar/0.815"
      assert (
          adapter.build("barp", {"bazp": "la/di"}) == "http://example.org/test/bar/la/di"
      )
      assert adapter.build("blah", {}) == "/test/hehe"
  
      adapter = map.bind("example.org")
      assert adapter.build("foo", {}) == "/foo"
      assert adapter.build("foo", {}, force_external=True) == "http://example.org/foo"
      adapter = map.bind("example.org", url_scheme="")
      assert adapter.build("foo", {}) == "/foo"
      assert adapter.build("foo", {}, force_external=True) == "//example.org/foo"
  
  
  def test_long_build():
      long_args = dict(("v%d" % x, x) for x in range(10000))
      map = r.Map(
          [
              r.Rule(
                  "".join("/<%s>" % k for k in long_args.keys()),
                  endpoint="bleep",
                  build_only=True,
              )
          ]
      )
      adapter = map.bind("localhost", "/")
      url = adapter.build("bleep", long_args)
      url += "/"
      for v in long_args.values():
          assert "/%d" % v in url
  
  
  def test_defaults():
      map = r.Map(
          [
              r.Rule("/foo/", defaults={"page": 1}, endpoint="foo"),
              r.Rule("/foo/<int:page>", endpoint="foo"),
          ]
      )
      adapter = map.bind("example.org", "/")
  
      assert adapter.match("/foo/") == ("foo", {"page": 1})
      pytest.raises(r.RequestRedirect, lambda: adapter.match("/foo/1"))
      assert adapter.match("/foo/2") == ("foo", {"page": 2})
      assert adapter.build("foo", {}) == "/foo/"
      assert adapter.build("foo", {"page": 1}) == "/foo/"
      assert adapter.build("foo", {"page": 2}) == "/foo/2"
  
  
  def test_negative():
      map = r.Map(
          [
              r.Rule("/foos/<int(signed=True):page>", endpoint="foos"),
              r.Rule("/bars/<float(signed=True):page>", endpoint="bars"),
              r.Rule("/foo/<int:page>", endpoint="foo"),
              r.Rule("/bar/<float:page>", endpoint="bar"),
          ]
      )
      adapter = map.bind("example.org", "/")
  
      assert adapter.match("/foos/-2") == ("foos", {"page": -2})
      assert adapter.match("/foos/-50") == ("foos", {"page": -50})
      assert adapter.match("/bars/-2.0") == ("bars", {"page": -2.0})
      assert adapter.match("/bars/-0.185") == ("bars", {"page": -0.185})
  
      # Make sure signed values are rejected in unsigned mode
      pytest.raises(r.NotFound, lambda: adapter.match("/foo/-2"))
      pytest.raises(r.NotFound, lambda: adapter.match("/foo/-50"))
      pytest.raises(r.NotFound, lambda: adapter.match("/bar/-0.185"))
      pytest.raises(r.NotFound, lambda: adapter.match("/bar/-2.0"))
  
  
  def test_greedy():
      map = r.Map(
          [
              r.Rule("/foo", endpoint="foo"),
              r.Rule("/<path:bar>", endpoint="bar"),
              r.Rule("/<path:bar>/<path:blub>", endpoint="bar"),
          ]
      )
      adapter = map.bind("example.org", "/")
  
      assert adapter.match("/foo") == ("foo", {})
      assert adapter.match("/blub") == ("bar", {"bar": "blub"})
      assert adapter.match("/he/he") == ("bar", {"bar": "he", "blub": "he"})
  
      assert adapter.build("foo", {}) == "/foo"
      assert adapter.build("bar", {"bar": "blub"}) == "/blub"
      assert adapter.build("bar", {"bar": "blub", "blub": "bar"}) == "/blub/bar"
  
  
  def test_path():
      map = r.Map(
          [
              r.Rule("/", defaults={"name": "FrontPage"}, endpoint="page"),
              r.Rule("/Special", endpoint="special"),
              r.Rule("/<int:year>", endpoint="year"),
              r.Rule("/<path:name>:foo", endpoint="foopage"),
              r.Rule("/<path:name>:<path:name2>", endpoint="twopage"),
              r.Rule("/<path:name>", endpoint="page"),
              r.Rule("/<path:name>/edit", endpoint="editpage"),
              r.Rule("/<path:name>/silly/<path:name2>", endpoint="sillypage"),
              r.Rule("/<path:name>/silly/<path:name2>/edit", endpoint="editsillypage"),
              r.Rule("/Talk:<path:name>", endpoint="talk"),
              r.Rule("/User:<username>", endpoint="user"),
              r.Rule("/User:<username>/<path:name>", endpoint="userpage"),
              r.Rule(
                  "/User:<username>/comment/<int:id>-<int:replyId>",
                  endpoint="usercomment",
              ),
              r.Rule("/Files/<path:file>", endpoint="files"),
              r.Rule("/<admin>/<manage>/<things>", endpoint="admin"),
          ]
      )
      adapter = map.bind("example.org", "/")
  
      assert adapter.match("/") == ("page", {"name": "FrontPage"})
      pytest.raises(r.RequestRedirect, lambda: adapter.match("/FrontPage"))
      assert adapter.match("/Special") == ("special", {})
      assert adapter.match("/2007") == ("year", {"year": 2007})
      assert adapter.match("/Some:foo") == ("foopage", {"name": "Some"})
      assert adapter.match("/Some:bar") == ("twopage", {"name": "Some", "name2": "bar"})
      assert adapter.match("/Some/Page") == ("page", {"name": "Some/Page"})
      assert adapter.match("/Some/Page/edit") == ("editpage", {"name": "Some/Page"})
      assert adapter.match("/Foo/silly/bar") == (
          "sillypage",
          {"name": "Foo", "name2": "bar"},
      )
      assert adapter.match("/Foo/silly/bar/edit") == (
          "editsillypage",
          {"name": "Foo", "name2": "bar"},
      )
      assert adapter.match("/Talk:Foo/Bar") == ("talk", {"name": "Foo/Bar"})
      assert adapter.match("/User:thomas") == ("user", {"username": "thomas"})
      assert adapter.match("/User:thomas/projects/werkzeug") == (
          "userpage",
          {"username": "thomas", "name": "projects/werkzeug"},
      )
      assert adapter.match("/User:thomas/comment/123-456") == (
          "usercomment",
          {"username": "thomas", "id": 123, "replyId": 456},
      )
      assert adapter.match("/Files/downloads/werkzeug/0.2.zip") == (
          "files",
          {"file": "downloads/werkzeug/0.2.zip"},
      )
      assert adapter.match("/Jerry/eats/cheese") == (
          "admin",
          {"admin": "Jerry", "manage": "eats", "things": "cheese"},
      )
  
  
  def test_dispatch():
      env = create_environ("/")
      map = r.Map([r.Rule("/", endpoint="root"), r.Rule("/foo/", endpoint="foo")])
      adapter = map.bind_to_environ(env)
  
      raise_this = None
  
      def view_func(endpoint, values):
          if raise_this is not None:
              raise raise_this
          return Response(repr((endpoint, values)))
  
      def dispatch(path, quiet=False):
          return Response.force_type(
              adapter.dispatch(view_func, path, catch_http_exceptions=quiet), env
          )
  
      assert dispatch("/").data == b"('root', {})"
      assert dispatch("/foo").status_code == 308
      raise_this = r.NotFound()
      pytest.raises(r.NotFound, lambda: dispatch("/bar"))
      assert dispatch("/bar", True).status_code == 404
  
  
  def test_http_host_before_server_name():
      env = {
          "HTTP_HOST": "wiki.example.com",
          "SERVER_NAME": "web0.example.com",
          "SERVER_PORT": "80",
          "SCRIPT_NAME": "",
          "PATH_INFO": "",
          "REQUEST_METHOD": "GET",
          "wsgi.url_scheme": "http",
      }
      map = r.Map([r.Rule("/", endpoint="index", subdomain="wiki")])
      adapter = map.bind_to_environ(env, server_name="example.com")
      assert adapter.match("/") == ("index", {})
      assert adapter.build("index", force_external=True) == "http://wiki.example.com/"
      assert adapter.build("index") == "/"
  
      env["HTTP_HOST"] = "admin.example.com"
      adapter = map.bind_to_environ(env, server_name="example.com")
      assert adapter.build("index") == "http://wiki.example.com/"
  
  
  def test_invalid_subdomain_warning():
      env = create_environ("/foo")
      env["SERVER_NAME"] = env["HTTP_HOST"] = "foo.example.com"
      m = r.Map([r.Rule("/foo", endpoint="foo")])
      with pytest.warns(UserWarning) as record:
          a = m.bind_to_environ(env, server_name="bar.example.com")
      assert a.subdomain == "<invalid>"
      assert len(record) == 1
  
  
  def test_adapter_url_parameter_sorting():
      map = r.Map(
          [r.Rule("/", endpoint="index")], sort_parameters=True, sort_key=lambda x: x[1]
      )
      adapter = map.bind("localhost", "/")
      assert (
          adapter.build("index", {"x": 20, "y": 10, "z": 30}, force_external=True)
          == "http://localhost/?y=10&x=20&z=30"
      )
  
  
  def test_request_direct_charset_bug():
      map = r.Map([r.Rule(u"/öäü/")])
      adapter = map.bind("localhost", "/")
  
      with pytest.raises(r.RequestRedirect) as excinfo:
          adapter.match(u"/öäü")
      assert excinfo.value.new_url == "http://localhost/%C3%B6%C3%A4%C3%BC/"
  
  
  def test_request_redirect_default():
      map = r.Map([r.Rule(u"/foo", defaults={"bar": 42}), r.Rule(u"/foo/<int:bar>")])
      adapter = map.bind("localhost", "/")
  
      with pytest.raises(r.RequestRedirect) as excinfo:
          adapter.match(u"/foo/42")
      assert excinfo.value.new_url == "http://localhost/foo"
  
  
  def test_request_redirect_default_subdomain():
      map = r.Map(
          [
              r.Rule(u"/foo", defaults={"bar": 42}, subdomain="test"),
              r.Rule(u"/foo/<int:bar>", subdomain="other"),
          ]
      )
      adapter = map.bind("localhost", "/", subdomain="other")
  
      with pytest.raises(r.RequestRedirect) as excinfo:
          adapter.match(u"/foo/42")
      assert excinfo.value.new_url == "http://test.localhost/foo"
  
  
  def test_adapter_match_return_rule():
      rule = r.Rule("/foo/", endpoint="foo")
      map = r.Map([rule])
      adapter = map.bind("localhost", "/")
      assert adapter.match("/foo/", return_rule=True) == (rule, {})
  
  
  def test_server_name_interpolation():
      server_name = "example.invalid"
      map = r.Map(
          [r.Rule("/", endpoint="index"), r.Rule("/", endpoint="alt", subdomain="alt")]
      )
  
      env = create_environ("/", "http://%s/" % server_name)
      adapter = map.bind_to_environ(env, server_name=server_name)
      assert adapter.match() == ("index", {})
  
      env = create_environ("/", "http://alt.%s/" % server_name)
      adapter = map.bind_to_environ(env, server_name=server_name)
      assert adapter.match() == ("alt", {})
  
      env = create_environ("/", "http://%s/" % server_name)
      adapter = map.bind_to_environ(env, server_name="foo")
      assert adapter.subdomain == "<invalid>"
  
  
  def test_rule_emptying():
      rule = r.Rule("/foo", {"meh": "muh"}, "x", ["POST"], False, "x", True, None)
      rule2 = rule.empty()
      assert rule.__dict__ == rule2.__dict__
      rule.methods.add("GET")
      assert rule.__dict__ != rule2.__dict__
      rule.methods.discard("GET")
      rule.defaults["meh"] = "aha"
      assert rule.__dict__ != rule2.__dict__
  
  
  def test_rule_unhashable():
      rule = r.Rule("/foo", {"meh": "muh"}, "x", ["POST"], False, "x", True, None)
      pytest.raises(TypeError, hash, rule)
  
  
  def test_rule_templates():
      testcase = r.RuleTemplate(
          [
              r.Submount(
                  "/test/$app",
                  [
                      r.Rule("/foo/", endpoint="handle_foo"),
                      r.Rule("/bar/", endpoint="handle_bar"),
                      r.Rule("/baz/", endpoint="handle_baz"),
                  ],
              ),
              r.EndpointPrefix(
                  "${app}",
                  [
                      r.Rule("/${app}-blah", endpoint="bar"),
                      r.Rule("/${app}-meh", endpoint="baz"),
                  ],
              ),
              r.Subdomain(
                  "$app",
                  [r.Rule("/blah", endpoint="x_bar"), r.Rule("/meh", endpoint="x_baz")],
              ),
          ]
      )
  
      url_map = r.Map(
          [
              testcase(app="test1"),
              testcase(app="test2"),
              testcase(app="test3"),
              testcase(app="test4"),
          ]
      )
  
      out = sorted([(x.rule, x.subdomain, x.endpoint) for x in url_map.iter_rules()])
  
      assert out == [
          ("/blah", "test1", "x_bar"),
          ("/blah", "test2", "x_bar"),
          ("/blah", "test3", "x_bar"),
          ("/blah", "test4", "x_bar"),
          ("/meh", "test1", "x_baz"),
          ("/meh", "test2", "x_baz"),
          ("/meh", "test3", "x_baz"),
          ("/meh", "test4", "x_baz"),
          ("/test/test1/bar/", "", "handle_bar"),
          ("/test/test1/baz/", "", "handle_baz"),
          ("/test/test1/foo/", "", "handle_foo"),
          ("/test/test2/bar/", "", "handle_bar"),
          ("/test/test2/baz/", "", "handle_baz"),
          ("/test/test2/foo/", "", "handle_foo"),
          ("/test/test3/bar/", "", "handle_bar"),
          ("/test/test3/baz/", "", "handle_baz"),
          ("/test/test3/foo/", "", "handle_foo"),
          ("/test/test4/bar/", "", "handle_bar"),
          ("/test/test4/baz/", "", "handle_baz"),
          ("/test/test4/foo/", "", "handle_foo"),
          ("/test1-blah", "", "test1bar"),
          ("/test1-meh", "", "test1baz"),
          ("/test2-blah", "", "test2bar"),
          ("/test2-meh", "", "test2baz"),
          ("/test3-blah", "", "test3bar"),
          ("/test3-meh", "", "test3baz"),
          ("/test4-blah", "", "test4bar"),
          ("/test4-meh", "", "test4baz"),
      ]
  
  
  def test_non_string_parts():
      m = r.Map([r.Rule("/<foo>", endpoint="foo")])
      a = m.bind("example.com")
      assert a.build("foo", {"foo": 42}) == "/42"
  
  
  def test_complex_routing_rules():
      m = r.Map(
          [
              r.Rule("/", endpoint="index"),
              r.Rule("/<int:blub>", endpoint="an_int"),
              r.Rule("/<blub>", endpoint="a_string"),
              r.Rule("/foo/", endpoint="nested"),
              r.Rule("/foobar/", endpoint="nestedbar"),
              r.Rule("/foo/<path:testing>/", endpoint="nested_show"),
              r.Rule("/foo/<path:testing>/edit", endpoint="nested_edit"),
              r.Rule("/users/", endpoint="users", defaults={"page": 1}),
              r.Rule("/users/page/<int:page>", endpoint="users"),
              r.Rule("/foox", endpoint="foox"),
              r.Rule("/<path:bar>/<path:blub>", endpoint="barx_path_path"),
          ]
      )
      a = m.bind("example.com")
  
      assert a.match("/") == ("index", {})
      assert a.match("/42") == ("an_int", {"blub": 42})
      assert a.match("/blub") == ("a_string", {"blub": "blub"})
      assert a.match("/foo/") == ("nested", {})
      assert a.match("/foobar/") == ("nestedbar", {})
      assert a.match("/foo/1/2/3/") == ("nested_show", {"testing": "1/2/3"})
      assert a.match("/foo/1/2/3/edit") == ("nested_edit", {"testing": "1/2/3"})
      assert a.match("/users/") == ("users", {"page": 1})
      assert a.match("/users/page/2") == ("users", {"page": 2})
      assert a.match("/foox") == ("foox", {})
      assert a.match("/1/2/3") == ("barx_path_path", {"bar": "1", "blub": "2/3"})
  
      assert a.build("index") == "/"
      assert a.build("an_int", {"blub": 42}) == "/42"
      assert a.build("a_string", {"blub": "test"}) == "/test"
      assert a.build("nested") == "/foo/"
      assert a.build("nestedbar") == "/foobar/"
      assert a.build("nested_show", {"testing": "1/2/3"}) == "/foo/1/2/3/"
      assert a.build("nested_edit", {"testing": "1/2/3"}) == "/foo/1/2/3/edit"
      assert a.build("users", {"page": 1}) == "/users/"
      assert a.build("users", {"page": 2}) == "/users/page/2"
      assert a.build("foox") == "/foox"
      assert a.build("barx_path_path", {"bar": "1", "blub": "2/3"}) == "/1/2/3"
  
  
  def test_default_converters():
      class MyMap(r.Map):
          default_converters = r.Map.default_converters.copy()
          default_converters["foo"] = r.UnicodeConverter
  
      assert isinstance(r.Map.default_converters, ImmutableDict)
      m = MyMap(
          [
              r.Rule("/a/<foo:a>", endpoint="a"),
              r.Rule("/b/<foo:b>", endpoint="b"),
              r.Rule("/c/<c>", endpoint="c"),
          ],
          converters={"bar": r.UnicodeConverter},
      )
      a = m.bind("example.org", "/")
      assert a.match("/a/1") == ("a", {"a": "1"})
      assert a.match("/b/2") == ("b", {"b": "2"})
      assert a.match("/c/3") == ("c", {"c": "3"})
      assert "foo" not in r.Map.default_converters
  
  
  def test_uuid_converter():
      m = r.Map([r.Rule("/a/<uuid:a_uuid>", endpoint="a")])
      a = m.bind("example.org", "/")
      rooute, kwargs = a.match("/a/a8098c1a-f86e-11da-bd1a-00112444be1e")
      assert type(kwargs["a_uuid"]) == uuid.UUID
  
  
  def test_converter_with_tuples():
      """
      Regression test for https://github.com/pallets/werkzeug/issues/709
      """
  
      class TwoValueConverter(r.BaseConverter):
          def __init__(self, *args, **kwargs):
              super(TwoValueConverter, self).__init__(*args, **kwargs)
              self.regex = r"(\w\w+)/(\w\w+)"
  
          def to_python(self, two_values):
              one, two = two_values.split("/")
              return one, two
  
          def to_url(self, values):
              return "%s/%s" % (values[0], values[1])
  
      map = r.Map(
          [r.Rule("/<two:foo>/", endpoint="handler")],
          converters={"two": TwoValueConverter},
      )
      a = map.bind("example.org", "/")
      route, kwargs = a.match("/qwert/yuiop/")
      assert kwargs["foo"] == ("qwert", "yuiop")
  
  
  def test_anyconverter():
      m = r.Map(
          [
              r.Rule("/<any(a1, a2):a>", endpoint="no_dot"),
              r.Rule("/<any(a.1, a.2):a>", endpoint="yes_dot"),
          ]
      )
      a = m.bind("example.org", "/")
      assert a.match("/a1") == ("no_dot", {"a": "a1"})
      assert a.match("/a2") == ("no_dot", {"a": "a2"})
      assert a.match("/a.1") == ("yes_dot", {"a": "a.1"})
      assert a.match("/a.2") == ("yes_dot", {"a": "a.2"})
  
  
  def test_build_append_unknown():
      map = r.Map([r.Rule("/bar/<float:bazf>", endpoint="barf")])
      adapter = map.bind("example.org", "/", subdomain="blah")
      assert (
          adapter.build("barf", {"bazf": 0.815, "bif": 1.0})
          == "http://example.org/bar/0.815?bif=1.0"
      )
      assert (
          adapter.build("barf", {"bazf": 0.815, "bif": 1.0}, append_unknown=False)
          == "http://example.org/bar/0.815"
      )
  
  
  def test_build_append_multiple():
      map = r.Map([r.Rule("/bar/<float:foo>", endpoint="endp")])
      adapter = map.bind("example.org", "/", subdomain="subd")
      params = {"foo": 0.815, "x": [1.0, 3.0], "y": 2.0}
      a, b = adapter.build("endp", params).split("?")
      assert a == "http://example.org/bar/0.815"
      assert set(b.split("&")) == set("y=2.0&x=1.0&x=3.0".split("&"))
  
  
  def test_build_append_multidict():
      map = r.Map([r.Rule("/bar/<float:foo>", endpoint="endp")])
      adapter = map.bind("example.org", "/", subdomain="subd")
      params = MultiDict((("foo", 0.815), ("x", 1.0), ("x", 3.0), ("y", 2.0)))
      a, b = adapter.build("endp", params).split("?")
      assert a == "http://example.org/bar/0.815"
      assert set(b.split("&")) == set("y=2.0&x=1.0&x=3.0".split("&"))
  
  
  def test_build_drop_none():
      map = r.Map([r.Rule("/flob/<flub>", endpoint="endp")])
      adapter = map.bind("", "/")
      params = {"flub": None, "flop": None}
      with pytest.raises(r.BuildError):
          x = adapter.build("endp", params)
          assert not x
      params = {"flub": "x", "flop": None}
      url = adapter.build("endp", params)
      assert "flop" not in url
  
  
  def test_method_fallback():
      map = r.Map(
          [
              r.Rule("/", endpoint="index", methods=["GET"]),
              r.Rule("/<name>", endpoint="hello_name", methods=["GET"]),
              r.Rule("/select", endpoint="hello_select", methods=["POST"]),
              r.Rule("/search_get", endpoint="search", methods=["GET"]),
              r.Rule("/search_post", endpoint="search", methods=["POST"]),
          ]
      )
      adapter = map.bind("example.com")
      assert adapter.build("index") == "/"
      assert adapter.build("index", method="GET") == "/"
      assert adapter.build("hello_name", {"name": "foo"}) == "/foo"
      assert adapter.build("hello_select") == "/select"
      assert adapter.build("hello_select", method="POST") == "/select"
      assert adapter.build("search") == "/search_get"
      assert adapter.build("search", method="GET") == "/search_get"
      assert adapter.build("search", method="POST") == "/search_post"
  
  
  def test_implicit_head():
      url_map = r.Map(
          [
              r.Rule("/get", methods=["GET"], endpoint="a"),
              r.Rule("/post", methods=["POST"], endpoint="b"),
          ]
      )
      adapter = url_map.bind("example.org")
      assert adapter.match("/get", method="HEAD") == ("a", {})
      pytest.raises(r.MethodNotAllowed, adapter.match, "/post", method="HEAD")
  
  
  def test_pass_str_as_router_methods():
      with pytest.raises(TypeError):
          r.Rule("/get", methods="GET")
  
  
  def test_protocol_joining_bug():
      m = r.Map([r.Rule("/<foo>", endpoint="x")])
      a = m.bind("example.org")
      assert a.build("x", {"foo": "x:y"}) == "/x:y"
      assert a.build("x", {"foo": "x:y"}, force_external=True) == "http://example.org/x:y"
  
  
  def test_allowed_methods_querying():
      m = r.Map(
          [r.Rule("/<foo>", methods=["GET", "HEAD"]), r.Rule("/foo", methods=["POST"])]
      )
      a = m.bind("example.org")
      assert sorted(a.allowed_methods("/foo")) == ["GET", "HEAD", "POST"]
  
  
  def test_external_building_with_port():
      map = r.Map([r.Rule("/", endpoint="index")])
      adapter = map.bind("example.org:5000", "/")
      built_url = adapter.build("index", {}, force_external=True)
      assert built_url == "http://example.org:5000/", built_url
  
  
  def test_external_building_with_port_bind_to_environ():
      map = r.Map([r.Rule("/", endpoint="index")])
      adapter = map.bind_to_environ(
          create_environ("/", "http://example.org:5000/"), server_name="example.org:5000"
      )
      built_url = adapter.build("index", {}, force_external=True)
      assert built_url == "http://example.org:5000/", built_url
  
  
  def test_external_building_with_port_bind_to_environ_wrong_servername():
      map = r.Map([r.Rule("/", endpoint="index")])
      environ = create_environ("/", "http://example.org:5000/")
      adapter = map.bind_to_environ(environ, server_name="example.org")
      assert adapter.subdomain == "<invalid>"
  
  
  def test_converter_parser():
      args, kwargs = r.parse_converter_args(u"test, a=1, b=3.0")
  
      assert args == ("test",)
      assert kwargs == {"a": 1, "b": 3.0}
  
      args, kwargs = r.parse_converter_args("")
      assert not args and not kwargs
  
      args, kwargs = r.parse_converter_args("a, b, c,")
      assert args == ("a", "b", "c")
      assert not kwargs
  
      args, kwargs = r.parse_converter_args("True, False, None")
      assert args == (True, False, None)
  
      args, kwargs = r.parse_converter_args('"foo", u"bar"')
      assert args == ("foo", "bar")
  
  
  def test_alias_redirects():
      m = r.Map(
          [
              r.Rule("/", endpoint="index"),
              r.Rule("/index.html", endpoint="index", alias=True),
              r.Rule("/users/", defaults={"page": 1}, endpoint="users"),
              r.Rule(
                  "/users/index.html", defaults={"page": 1}, alias=True, endpoint="users"
              ),
              r.Rule("/users/page/<int:page>", endpoint="users"),
              r.Rule("/users/page-<int:page>.html", alias=True, endpoint="users"),
          ]
      )
      a = m.bind("example.com")
  
      def ensure_redirect(path, new_url, args=None):
          with pytest.raises(r.RequestRedirect) as excinfo:
              a.match(path, query_args=args)
          assert excinfo.value.new_url == "http://example.com" + new_url
  
      ensure_redirect("/index.html", "/")
      ensure_redirect("/users/index.html", "/users/")
      ensure_redirect("/users/page-2.html", "/users/page/2")
      ensure_redirect("/users/page-1.html", "/users/")
      ensure_redirect("/users/page-1.html", "/users/?foo=bar", {"foo": "bar"})
  
      assert a.build("index") == "/"
      assert a.build("users", {"page": 1}) == "/users/"
      assert a.build("users", {"page": 2}) == "/users/page/2"
  
  
  @pytest.mark.parametrize("prefix", ("", "/aaa"))
  def test_double_defaults(prefix):
      m = r.Map(
          [
              r.Rule(prefix + "/", defaults={"foo": 1, "bar": False}, endpoint="x"),
              r.Rule(prefix + "/<int:foo>", defaults={"bar": False}, endpoint="x"),
              r.Rule(prefix + "/bar/", defaults={"foo": 1, "bar": True}, endpoint="x"),
              r.Rule(prefix + "/bar/<int:foo>", defaults={"bar": True}, endpoint="x"),
          ]
      )
      a = m.bind("example.com")
  
      assert a.match(prefix + "/") == ("x", {"foo": 1, "bar": False})
      assert a.match(prefix + "/2") == ("x", {"foo": 2, "bar": False})
      assert a.match(prefix + "/bar/") == ("x", {"foo": 1, "bar": True})
      assert a.match(prefix + "/bar/2") == ("x", {"foo": 2, "bar": True})
  
      assert a.build("x", {"foo": 1, "bar": False}) == prefix + "/"
      assert a.build("x", {"foo": 2, "bar": False}) == prefix + "/2"
      assert a.build("x", {"bar": False}) == prefix + "/"
      assert a.build("x", {"foo": 1, "bar": True}) == prefix + "/bar/"
      assert a.build("x", {"foo": 2, "bar": True}) == prefix + "/bar/2"
      assert a.build("x", {"bar": True}) == prefix + "/bar/"
  
  
  def test_building_bytes():
      m = r.Map(
          [
              r.Rule("/<a>", endpoint="a"),
              r.Rule("/<b>", defaults={"b": b"\x01\x02\x03"}, endpoint="b"),
          ]
      )
      a = m.bind("example.org", "/")
      assert a.build("a", {"a": b"\x01\x02\x03"}) == "/%01%02%03"
      assert a.build("b") == "/%01%02%03"
  
  
  def test_host_matching():
      m = r.Map(
          [
              r.Rule("/", endpoint="index", host="www.<domain>"),
              r.Rule("/", endpoint="files", host="files.<domain>"),
              r.Rule("/foo/", defaults={"page": 1}, host="www.<domain>", endpoint="x"),
              r.Rule("/<int:page>", host="files.<domain>", endpoint="x"),
          ],
          host_matching=True,
      )
  
      a = m.bind("www.example.com")
      assert a.match("/") == ("index", {"domain": "example.com"})
      assert a.match("/foo/") == ("x", {"domain": "example.com", "page": 1})
  
      with pytest.raises(r.RequestRedirect) as excinfo:
          a.match("/foo")
      assert excinfo.value.new_url == "http://www.example.com/foo/"
  
      a = m.bind("files.example.com")
      assert a.match("/") == ("files", {"domain": "example.com"})
      assert a.match("/2") == ("x", {"domain": "example.com", "page": 2})
  
      with pytest.raises(r.RequestRedirect) as excinfo:
          a.match("/1")
      assert excinfo.value.new_url == "http://www.example.com/foo/"
  
  
  def test_host_matching_building():
      m = r.Map(
          [
              r.Rule("/", endpoint="index", host="www.domain.com"),
              r.Rule("/", endpoint="foo", host="my.domain.com"),
          ],
          host_matching=True,
      )
  
      www = m.bind("www.domain.com")
      assert www.match("/") == ("index", {})
      assert www.build("index") == "/"
      assert www.build("foo") == "http://my.domain.com/"
  
      my = m.bind("my.domain.com")
      assert my.match("/") == ("foo", {})
      assert my.build("foo") == "/"
      assert my.build("index") == "http://www.domain.com/"
  
  
  def test_server_name_casing():
      m = r.Map([r.Rule("/", endpoint="index", subdomain="foo")])
  
      env = create_environ()
      env["SERVER_NAME"] = env["HTTP_HOST"] = "FOO.EXAMPLE.COM"
      a = m.bind_to_environ(env, server_name="example.com")
      assert a.match("/") == ("index", {})
  
      env = create_environ()
      env["SERVER_NAME"] = "127.0.0.1"
      env["SERVER_PORT"] = "5000"
      del env["HTTP_HOST"]
      a = m.bind_to_environ(env, server_name="example.com")
      with pytest.raises(r.NotFound):
          a.match()
  
  
  def test_redirect_request_exception_code():
      exc = r.RequestRedirect("http://www.google.com/")
      exc.code = 307
      env = create_environ()
      strict_eq(exc.get_response(env).status_code, exc.code)
  
  
  def test_redirect_path_quoting():
      url_map = r.Map(
          [
              r.Rule("/<category>", defaults={"page": 1}, endpoint="category"),
              r.Rule("/<category>/page/<int:page>", endpoint="category"),
          ]
      )
      adapter = url_map.bind("example.com")
  
      with pytest.raises(r.RequestRedirect) as excinfo:
          adapter.match("/foo bar/page/1")
      response = excinfo.value.get_response({})
      strict_eq(response.headers["location"], u"http://example.com/foo%20bar")
  
  
  def test_unicode_rules():
      m = r.Map(
          [r.Rule(u"/войти/", endpoint="enter"), r.Rule(u"/foo+bar/", endpoint="foobar")]
      )
      a = m.bind(u"☃.example.com")
      with pytest.raises(r.RequestRedirect) as excinfo:
          a.match(u"/войти")
      strict_eq(
          excinfo.value.new_url,
          "http://xn--n3h.example.com/%D0%B2%D0%BE%D0%B9%D1%82%D0%B8/",
      )
  
      endpoint, values = a.match(u"/войти/")
      strict_eq(endpoint, "enter")
      strict_eq(values, {})
  
      with pytest.raises(r.RequestRedirect) as excinfo:
          a.match(u"/foo+bar")
      strict_eq(excinfo.value.new_url, "http://xn--n3h.example.com/foo+bar/")
  
      endpoint, values = a.match(u"/foo+bar/")
      strict_eq(endpoint, "foobar")
      strict_eq(values, {})
  
      url = a.build("enter", {}, force_external=True)
      strict_eq(url, "http://xn--n3h.example.com/%D0%B2%D0%BE%D0%B9%D1%82%D0%B8/")
  
      url = a.build("foobar", {}, force_external=True)
      strict_eq(url, "http://xn--n3h.example.com/foo+bar/")
  
  
  def test_empty_path_info():
      m = r.Map([r.Rule("/", endpoint="index")])
  
      b = m.bind("example.com", script_name="/approot")
      with pytest.raises(r.RequestRedirect) as excinfo:
          b.match("")
      assert excinfo.value.new_url == "http://example.com/approot/"
  
      a = m.bind("example.com")
      with pytest.raises(r.RequestRedirect) as excinfo:
          a.match("")
      assert excinfo.value.new_url == "http://example.com/"
  
  
  def test_both_bind_and_match_path_info_are_none():
      m = r.Map([r.Rule(u"/", endpoint="index")])
      ma = m.bind("example.org")
      strict_eq(ma.match(), ("index", {}))
  
  
  def test_map_repr():
      m = r.Map([r.Rule(u"/wat", endpoint="enter"), r.Rule(u"/woop", endpoint="foobar")])
      rv = repr(m)
      strict_eq(rv, "Map([<Rule '/woop' -> foobar>, <Rule '/wat' -> enter>])")
  
  
  def test_empty_subclass_rules_with_custom_kwargs():
      class CustomRule(r.Rule):
          def __init__(self, string=None, custom=None, *args, **kwargs):
              self.custom = custom
              super(CustomRule, self).__init__(string, *args, **kwargs)
  
      rule1 = CustomRule(u"/foo", endpoint="bar")
      try:
          rule2 = rule1.empty()
          assert rule1.rule == rule2.rule
      except TypeError as e:  # raised without fix in PR #675
          raise e
  
  
  def test_finding_closest_match_by_endpoint():
      m = r.Map(
          [
              r.Rule(u"/foo/", endpoint="users.here"),
              r.Rule(u"/wat/", endpoint="admin.users"),
              r.Rule(u"/woop", endpoint="foo.users"),
          ]
      )
      adapter = m.bind("example.com")
      assert (
          r.BuildError("admin.user", None, None, adapter).suggested.endpoint
          == "admin.users"
      )
  
  
  def test_finding_closest_match_by_values():
      rule_id = r.Rule(u"/user/id/<id>/", endpoint="users")
      rule_slug = r.Rule(u"/user/<slug>/", endpoint="users")
      rule_random = r.Rule(u"/user/emails/<email>/", endpoint="users")
      m = r.Map([rule_id, rule_slug, rule_random])
      adapter = m.bind("example.com")
      assert r.BuildError("x", {"slug": ""}, None, adapter).suggested == rule_slug
  
  
  def test_finding_closest_match_by_method():
      post = r.Rule(u"/post/", endpoint="foobar", methods=["POST"])
      get = r.Rule(u"/get/", endpoint="foobar", methods=["GET"])
      put = r.Rule(u"/put/", endpoint="foobar", methods=["PUT"])
      m = r.Map([post, get, put])
      adapter = m.bind("example.com")
      assert r.BuildError("invalid", {}, "POST", adapter).suggested == post
      assert r.BuildError("invalid", {}, "GET", adapter).suggested == get
      assert r.BuildError("invalid", {}, "PUT", adapter).suggested == put
  
  
  def test_finding_closest_match_when_none_exist():
      m = r.Map([])
      assert not r.BuildError("invalid", {}, None, m.bind("test.com")).suggested
  
  
  def test_error_message_without_suggested_rule():
      m = r.Map([r.Rule(u"/foo/", endpoint="world", methods=["GET"])])
      adapter = m.bind("example.com")
  
      with pytest.raises(r.BuildError) as excinfo:
          adapter.build("urks")
      assert str(excinfo.value).startswith("Could not build url for endpoint 'urks'.")
  
      with pytest.raises(r.BuildError) as excinfo:
          adapter.build("world", method="POST")
      assert str(excinfo.value).startswith(
          "Could not build url for endpoint 'world' ('POST')."
      )
  
      with pytest.raises(r.BuildError) as excinfo:
          adapter.build("urks", values={"user_id": 5})
      assert str(excinfo.value).startswith(
          "Could not build url for endpoint 'urks' with values ['user_id']."
      )
  
  
  def test_error_message_suggestion():
      m = r.Map([r.Rule(u"/foo/<id>/", endpoint="world", methods=["GET"])])
      adapter = m.bind("example.com")
  
      with pytest.raises(r.BuildError) as excinfo:
          adapter.build("helloworld")
      assert "Did you mean 'world' instead?" in str(excinfo.value)
  
      with pytest.raises(r.BuildError) as excinfo:
          adapter.build("world")
      assert "Did you forget to specify values ['id']?" in str(excinfo.value)
      assert "Did you mean to use methods" not in str(excinfo.value)
  
      with pytest.raises(r.BuildError) as excinfo:
          adapter.build("world", {"id": 2}, method="POST")
      assert "Did you mean to use methods ['GET', 'HEAD']?" in str(excinfo.value)
  
  
  def test_no_memory_leak_from_Rule_builder():
      """See #1520"""
  
      # generate a bunch of objects that *should* get collected
      for _ in range(100):
          r.Map([r.Rule("/a/<string:b>")])
  
      # ensure that the garbage collection has had a chance to collect cyclic
      # objects
      for _ in range(5):
          gc.collect()
  
      # assert they got collected!
      count = sum(1 for obj in gc.get_objects() if isinstance(obj, r.Rule))
      assert count == 0
  
  
  def test_build_url_with_arg_self():
      map = r.Map([r.Rule("/foo/<string:self>", endpoint="foo")])
      adapter = map.bind("example.org", "/", subdomain="blah")
  
      ret = adapter.build("foo", {"self": "bar"})
      assert ret == "http://example.org/foo/bar"
  
  
  def test_build_url_with_arg_keyword():
      map = r.Map([r.Rule("/foo/<string:class>", endpoint="foo")])
      adapter = map.bind("example.org", "/", subdomain="blah")
  
      ret = adapter.build("foo", {"class": "bar"})
      assert ret == "http://example.org/foo/bar"
  