""" Tests for django.utils. """ from unittest import TestCase from django.utils import html, checksums from django.utils.functional import SimpleLazyObject import timesince import datastructures import itercompat import tzinfo from decorators import DecoratorFromMiddlewareTests from functional import FunctionalTestCase # We need this because "datastructures" uses sorted() and the tests are run in # the scope of this module. try: sorted except NameError: from django.utils.itercompat import sorted # For Python 2.3 # Extra tests __test__ = { 'timesince': timesince, 'datastructures': datastructures, 'itercompat': itercompat, 'tzinfo': tzinfo, } from dateformat import * from feedgenerator import * from termcolors import * class TestUtilsHtml(TestCase): def check_output(self, function, value, output=None): """ Check that function(value) equals output. If output is None, check that function(value) equals value. """ if output is None: output = value self.assertEqual(function(value), output) def test_escape(self): f = html.escape items = ( ('&','&'), ('<', '<'), ('>', '>'), ('"', '"'), ("'", '''), ) # Substitution patterns for testing the above items. patterns = ("%s", "asdf%sfdsa", "%s1", "1%sb") for value, output in items: for pattern in patterns: self.check_output(f, pattern % value, pattern % output) # Check repeated values. self.check_output(f, value * 2, output * 2) # Verify it doesn't double replace &. self.check_output(f, '<&', '<&') def test_linebreaks(self): f = html.linebreaks items = ( ("para1\n\npara2\r\rpara3", "
para1
\n\npara2
\n\npara3
"), ("para1\nsub1\rsub2\n\npara2", "para1
sub1
sub2
para2
"), ("para1\r\n\r\npara2\rsub1\r\rpara4", "para1
\n\npara2
sub1
para4
"), ("para1\tmore\n\npara2", "para1\tmore
\n\npara2
"), ) for value, output in items: self.check_output(f, value, output) def test_strip_tags(self): f = html.strip_tags items = ( ('hello
\nworld
', 'hello
world
'), ('\n\t
\n\n', '\n\n'), ) for value, output in items: self.check_output(f, value, output) def test_strip_entities(self): f = html.strip_entities # Strings that should come out untouched. values = ("&", "&a", "&a", "aa") for value in values: self.check_output(f, value) # Valid entities that should be stripped from the patterns. entities = ("", "", "&a;", "&fdasdfasdfasdf;") patterns = ( ("asdf %(entity)s ", "asdf "), ("%(entity)s%(entity)s", ""), ("&%(entity)s%(entity)s", "&"), ("%(entity)s3", "3"), ) for entity in entities: for in_pattern, output in patterns: self.check_output(f, in_pattern % {'entity': entity}, output) def test_fix_ampersands(self): f = html.fix_ampersands # Strings without ampersands or with ampersands already encoded. values = ("a", "b", "&a;", "& &x; ", "asdf") patterns = ( ("%s", "%s"), ("&%s", "&%s"), ("&%s&", "&%s&"), ) for value in values: for in_pattern, out_pattern in patterns: self.check_output(f, in_pattern % value, out_pattern % value) # Strings with ampersands that need encoding. items = ( ("", "&#;"), ("ͫ ;", "ͫ ;"), ("abc;", "abc;"), ) for value, output in items: self.check_output(f, value, output) class TestUtilsChecksums(TestCase): def check_output(self, function, value, output=None): """ Check that function(value) equals output. If output is None, check that function(value) equals value. """ if output is None: output = value self.assertEqual(function(value), output) def test_luhn(self): f = checksums.luhn items = ( (4111111111111111, True), ('4111111111111111', True), (4222222222222, True), (378734493671000, True), (5424000000000015, True), (5555555555554444, True), (1008, True), ('0000001008', True), ('000000001008', True), (4012888888881881, True), (1234567890123456789012345678909, True), (4111111111211111, False), (42222222222224, False), (100, False), ('100', False), ('0000100', False), ('abc', False), (None, False), (object(), False), ) for value, output in items: self.check_output(f, value, output) class _ComplexObject(object): def __init__(self, name): self.name = name def __eq__(self, other): return self.name == other.name def __hash__(self): return hash(self.name) def __str__(self): return "I am _ComplexObject(%r)" % self.name def __unicode__(self): return unicode(self.name) def __repr__(self): return "_ComplexObject(%r)" % self.name complex_object = lambda: _ComplexObject("joe") class TestUtilsSimpleLazyObject(TestCase): """ Tests for SimpleLazyObject """ # Note that concrete use cases for SimpleLazyObject are also found in the # auth context processor tests (unless the implementation of that function # is changed). def test_equality(self): self.assertEqual(complex_object(), SimpleLazyObject(complex_object)) self.assertEqual(SimpleLazyObject(complex_object), complex_object()) def test_hash(self): # hash() equality would not be true for many objects, but it should be # for _ComplexObject self.assertEqual(hash(complex_object()), hash(SimpleLazyObject(complex_object))) def test_repr(self): # For debugging, it will really confuse things if there is no clue that # SimpleLazyObject is actually a proxy object. So we don't # proxy __repr__ self.assert_("SimpleLazyObject" in repr(SimpleLazyObject(complex_object))) def test_str(self): self.assertEqual("I am _ComplexObject('joe')", str(SimpleLazyObject(complex_object))) def test_unicode(self): self.assertEqual(u"joe", unicode(SimpleLazyObject(complex_object))) def test_class(self): # This is important for classes that use __class__ in things like # equality tests. self.assertEqual(_ComplexObject, SimpleLazyObject(complex_object).__class__) def test_deepcopy(self): import django.utils.copycompat as copy # Check that we *can* do deep copy, and that it returns the right # objects. # First, for an unevaluated SimpleLazyObject s = SimpleLazyObject(complex_object) assert s._wrapped is None s2 = copy.deepcopy(s) assert s._wrapped is None # something has gone wrong is s is evaluated self.assertEqual(s2, complex_object()) # Second, for an evaluated SimpleLazyObject name = s.name # evaluate assert s._wrapped is not None s3 = copy.deepcopy(s) self.assertEqual(s3, complex_object()) if __name__ == "__main__": import doctest doctest.testmod()