text: import unittest
  from datetime import datetime
  
  from django.test import SimpleTestCase, ignore_warnings
  from django.utils.datastructures import MultiValueDict
  from django.utils.deprecation import RemovedInDjango30Warning
  from django.utils.http import (
      base36_to_int, cookie_date, escape_leading_slashes, http_date,
      int_to_base36, is_safe_url, is_same_domain, parse_etags, parse_http_date,
      quote_etag, urlencode, urlquote, urlquote_plus, urlsafe_base64_decode,
      urlsafe_base64_encode, urlunquote, urlunquote_plus,
  )
  
  
  class URLEncodeTests(unittest.TestCase):
      def test_tuples(self):
          self.assertEqual(urlencode((('a', 1), ('b', 2), ('c', 3))), 'a=1&b=2&c=3')
  
      def test_dict(self):
          result = urlencode({'a': 1, 'b': 2, 'c': 3})
          # Dictionaries are treated as unordered.
          self.assertIn(result, [
              'a=1&b=2&c=3',
              'a=1&c=3&b=2',
              'b=2&a=1&c=3',
              'b=2&c=3&a=1',
              'c=3&a=1&b=2',
              'c=3&b=2&a=1',
          ])
  
      def test_dict_containing_sequence_not_doseq(self):
          self.assertEqual(urlencode({'a': [1, 2]}, doseq=False), 'a=%5B%271%27%2C+%272%27%5D')
  
      def test_dict_containing_sequence_doseq(self):
          self.assertEqual(urlencode({'a': [1, 2]}, doseq=True), 'a=1&a=2')
  
      def test_dict_containing_empty_sequence_doseq(self):
          self.assertEqual(urlencode({'a': []}, doseq=True), '')
  
      def test_multivaluedict(self):
          result = urlencode(MultiValueDict({
              'name': ['Adrian', 'Simon'],
              'position': ['Developer'],
          }), doseq=True)
          # MultiValueDicts are similarly unordered.
          self.assertIn(result, [
              'name=Adrian&name=Simon&position=Developer',
              'position=Developer&name=Adrian&name=Simon',
          ])
  
      def test_dict_with_bytes_values(self):
          self.assertEqual(urlencode({'a': b'abc'}, doseq=True), 'a=abc')
  
      def test_dict_with_sequence_of_bytes(self):
          self.assertEqual(urlencode({'a': [b'spam', b'eggs', b'bacon']}, doseq=True), 'a=spam&a=eggs&a=bacon')
  
      def test_dict_with_bytearray(self):
          self.assertEqual(urlencode({'a': bytearray(range(2))}, doseq=True), 'a=0&a=1')
          self.assertEqual(urlencode({'a': bytearray(range(2))}, doseq=False), 'a=%5B%270%27%2C+%271%27%5D')
  
      def test_generator(self):
          def gen():
              yield from range(2)
  
          self.assertEqual(urlencode({'a': gen()}, doseq=True), 'a=0&a=1')
          self.assertEqual(urlencode({'a': gen()}, doseq=False), 'a=%5B%270%27%2C+%271%27%5D')
  
  
  class Base36IntTests(SimpleTestCase):
      def test_roundtrip(self):
          for n in [0, 1, 1000, 1000000]:
              self.assertEqual(n, base36_to_int(int_to_base36(n)))
  
      def test_negative_input(self):
          with self.assertRaisesMessage(ValueError, 'Negative base36 conversion input.'):
              int_to_base36(-1)
  
      def test_to_base36_errors(self):
          for n in ['1', 'foo', {1: 2}, (1, 2, 3), 3.141]:
              with self.assertRaises(TypeError):
                  int_to_base36(n)
  
      def test_invalid_literal(self):
          for n in ['#', ' ']:
              with self.assertRaisesMessage(ValueError, "invalid literal for int() with base 36: '%s'" % n):
                  base36_to_int(n)
  
      def test_input_too_large(self):
          with self.assertRaisesMessage(ValueError, 'Base36 input too large'):
              base36_to_int('1' * 14)
  
      def test_to_int_errors(self):
          for n in [123, {1: 2}, (1, 2, 3), 3.141]:
              with self.assertRaises(TypeError):
                  base36_to_int(n)
  
      def test_values(self):
          for n, b36 in [(0, '0'), (1, '1'), (42, '16'), (818469960, 'django')]:
              self.assertEqual(int_to_base36(n), b36)
              self.assertEqual(base36_to_int(b36), n)
  
  
  class IsSafeURLTests(unittest.TestCase):
      def test_bad_urls(self):
          bad_urls = (
              'http://example.com',
              'http:///example.com',
              'https://example.com',
              'ftp://example.com',
              r'\\example.com',
              r'\\\example.com',
              r'/\\/example.com',
              r'\\\example.com',
              r'\\example.com',
              r'\\//example.com',
              r'/\/example.com',
              r'\/example.com',
              r'/\example.com',
              'http:///example.com',
              r'http:/\//example.com',
              r'http:\/example.com',
              r'http:/\example.com',
              'javascript:alert("XSS")',
              '\njavascript:alert(x)',
              '\x08//example.com',
              r'http://otherserver\@example.com',
              r'http:\\testserver\@example.com',
              r'http://testserver\me:pass@example.com',
              r'http://testserver\@example.com',
              r'http:\\testserver\confirm\me@example.com',
              'http:999999999',
              'ftp:9999999999',
              '\n',
              'http://[2001:cdba:0000:0000:0000:0000:3257:9652/',
              'http://2001:cdba:0000:0000:0000:0000:3257:9652]/',
          )
          for bad_url in bad_urls:
              with self.subTest(url=bad_url):
                  self.assertIs(is_safe_url(bad_url, allowed_hosts={'testserver', 'testserver2'}), False)
  
      def test_good_urls(self):
          good_urls = (
              '/view/?param=http://example.com',
              '/view/?param=https://example.com',
              '/view?param=ftp://example.com',
              'view/?param=//example.com',
              'https://testserver/',
              'HTTPS://testserver/',
              '//testserver/',
              'http://testserver/confirm?email=me@example.com',
              '/url%20with%20spaces/',
              'path/http:2222222222',
          )
          for good_url in good_urls:
              with self.subTest(url=good_url):
                  self.assertIs(is_safe_url(good_url, allowed_hosts={'otherserver', 'testserver'}), True)
  
      def test_basic_auth(self):
          # Valid basic auth credentials are allowed.
          self.assertIs(is_safe_url(r'http://user:pass@testserver/', allowed_hosts={'user:pass@testserver'}), True)
  
      def test_no_allowed_hosts(self):
          # A path without host is allowed.
          self.assertIs(is_safe_url('/confirm/me@example.com', allowed_hosts=None), True)
          # Basic auth without host is not allowed.
          self.assertIs(is_safe_url(r'http://testserver\@example.com', allowed_hosts=None), False)
  
      def test_secure_param_https_urls(self):
          secure_urls = (
              'https://example.com/p',
              'HTTPS://example.com/p',
              '/view/?param=http://example.com',
          )
          for url in secure_urls:
              with self.subTest(url=url):
                  self.assertIs(is_safe_url(url, allowed_hosts={'example.com'}, require_https=True), True)
  
      def test_secure_param_non_https_urls(self):
          insecure_urls = (
              'http://example.com/p',
              'ftp://example.com/p',
              '//example.com/p',
          )
          for url in insecure_urls:
              with self.subTest(url=url):
                  self.assertIs(is_safe_url(url, allowed_hosts={'example.com'}, require_https=True), False)
  
  
  class URLSafeBase64Tests(unittest.TestCase):
      def test_roundtrip(self):
          bytestring = b'foo'
          encoded = urlsafe_base64_encode(bytestring)
          decoded = urlsafe_base64_decode(encoded)
          self.assertEqual(bytestring, decoded)
  
  
  class URLQuoteTests(unittest.TestCase):
      def test_quote(self):
          self.assertEqual(urlquote('Paris & Orl\xe9ans'), 'Paris%20%26%20Orl%C3%A9ans')
          self.assertEqual(urlquote('Paris & Orl\xe9ans', safe="&"), 'Paris%20&%20Orl%C3%A9ans')
  
      def test_unquote(self):
          self.assertEqual(urlunquote('Paris%20%26%20Orl%C3%A9ans'), 'Paris & Orl\xe9ans')
          self.assertEqual(urlunquote('Paris%20&%20Orl%C3%A9ans'), 'Paris & Orl\xe9ans')
  
      def test_quote_plus(self):
          self.assertEqual(urlquote_plus('Paris & Orl\xe9ans'), 'Paris+%26+Orl%C3%A9ans')
          self.assertEqual(urlquote_plus('Paris & Orl\xe9ans', safe="&"), 'Paris+&+Orl%C3%A9ans')
  
      def test_unquote_plus(self):
          self.assertEqual(urlunquote_plus('Paris+%26+Orl%C3%A9ans'), 'Paris & Orl\xe9ans')
          self.assertEqual(urlunquote_plus('Paris+&+Orl%C3%A9ans'), 'Paris & Orl\xe9ans')
  
  
  class IsSameDomainTests(unittest.TestCase):
      def test_good(self):
          for pair in (
              ('example.com', 'example.com'),
              ('example.com', '.example.com'),
              ('foo.example.com', '.example.com'),
              ('example.com:8888', 'example.com:8888'),
              ('example.com:8888', '.example.com:8888'),
              ('foo.example.com:8888', '.example.com:8888'),
          ):
              self.assertIs(is_same_domain(*pair), True)
  
      def test_bad(self):
          for pair in (
              ('example2.com', 'example.com'),
              ('foo.example.com', 'example.com'),
              ('example.com:9999', 'example.com:8888'),
          ):
              self.assertIs(is_same_domain(*pair), False)
  
  
  class ETagProcessingTests(unittest.TestCase):
      def test_parsing(self):
          self.assertEqual(
              parse_etags(r'"" ,  "etag", "e\\tag", W/"weak"'),
              ['""', '"etag"', r'"e\\tag"', 'W/"weak"']
          )
          self.assertEqual(parse_etags('*'), ['*'])
  
          # Ignore RFC 2616 ETags that are invalid according to RFC 7232.
          self.assertEqual(parse_etags(r'"etag", "e\"t\"ag"'), ['"etag"'])
  
      def test_quoting(self):
          self.assertEqual(quote_etag('etag'), '"etag"')  # unquoted
          self.assertEqual(quote_etag('"etag"'), '"etag"')  # quoted
          self.assertEqual(quote_etag('W/"etag"'), 'W/"etag"')  # quoted, weak
  
  
  class HttpDateProcessingTests(unittest.TestCase):
      def test_http_date(self):
          t = 1167616461.0
          self.assertEqual(http_date(t), 'Mon, 01 Jan 2007 01:54:21 GMT')
  
      @ignore_warnings(category=RemovedInDjango30Warning)
      def test_cookie_date(self):
          t = 1167616461.0
          self.assertEqual(cookie_date(t), 'Mon, 01-Jan-2007 01:54:21 GMT')
  
      def test_parsing_rfc1123(self):
          parsed = parse_http_date('Sun, 06 Nov 1994 08:49:37 GMT')
          self.assertEqual(datetime.utcfromtimestamp(parsed), datetime(1994, 11, 6, 8, 49, 37))
  
      def test_parsing_rfc850(self):
          parsed = parse_http_date('Sunday, 06-Nov-94 08:49:37 GMT')
          self.assertEqual(datetime.utcfromtimestamp(parsed), datetime(1994, 11, 6, 8, 49, 37))
  
      def test_parsing_asctime(self):
          parsed = parse_http_date('Sun Nov  6 08:49:37 1994')
          self.assertEqual(datetime.utcfromtimestamp(parsed), datetime(1994, 11, 6, 8, 49, 37))
  
  
  class EscapeLeadingSlashesTests(unittest.TestCase):
      def test(self):
          tests = (
              ('//example.com', '/%2Fexample.com'),
              ('//', '/%2F'),
          )
          for url, expected in tests:
              with self.subTest(url=url):
                  self.assertEqual(escape_leading_slashes(url), expected)
  