| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- # -*- coding: utf-8 -*-
- import gc
- import sys
- import unittest
- from markupsafe import Markup, escape, escape_silent
- from markupsafe._compat import text_type
- class MarkupTestCase(unittest.TestCase):
- def test_adding(self):
- # adding two strings should escape the unsafe one
- unsafe = '<script type="application/x-some-script">alert("foo");</script>'
- safe = Markup('<em>username</em>')
- assert unsafe + safe == text_type(escape(unsafe)) + text_type(safe)
- def test_string_interpolation(self):
- # string interpolations are safe to use too
- assert Markup('<em>%s</em>') % '<bad user>' == \
- '<em><bad user></em>'
- assert Markup('<em>%(username)s</em>') % {
- 'username': '<bad user>'
- } == '<em><bad user></em>'
- assert Markup('%i') % 3.14 == '3'
- assert Markup('%.2f') % 3.14 == '3.14'
- def test_type_behavior(self):
- # an escaped object is markup too
- assert type(Markup('foo') + 'bar') is Markup
- # and it implements __html__ by returning itself
- x = Markup("foo")
- assert x.__html__() is x
- def test_html_interop(self):
- # it also knows how to treat __html__ objects
- class Foo(object):
- def __html__(self):
- return '<em>awesome</em>'
- def __unicode__(self):
- return 'awesome'
- __str__ = __unicode__
- assert Markup(Foo()) == '<em>awesome</em>'
- assert Markup('<strong>%s</strong>') % Foo() == \
- '<strong><em>awesome</em></strong>'
- def test_tuple_interpol(self):
- self.assertEqual(Markup('<em>%s:%s</em>') % (
- '<foo>',
- '<bar>',
- ), Markup(u'<em><foo>:<bar></em>'))
- def test_dict_interpol(self):
- self.assertEqual(Markup('<em>%(foo)s</em>') % {
- 'foo': '<foo>',
- }, Markup(u'<em><foo></em>'))
- self.assertEqual(Markup('<em>%(foo)s:%(bar)s</em>') % {
- 'foo': '<foo>',
- 'bar': '<bar>',
- }, Markup(u'<em><foo>:<bar></em>'))
- def test_escaping(self):
- # escaping and unescaping
- assert escape('"<>&\'') == '"<>&''
- assert Markup("<em>Foo & Bar</em>").striptags() == "Foo & Bar"
- assert Markup("<test>").unescape() == "<test>"
- def test_formatting(self):
- for actual, expected in (
- (Markup('%i') % 3.14, '3'),
- (Markup('%.2f') % 3.14159, '3.14'),
- (Markup('%s %s %s') % ('<', 123, '>'), '< 123 >'),
- (Markup('<em>{awesome}</em>').format(awesome='<awesome>'),
- '<em><awesome></em>'),
- (Markup('{0[1][bar]}').format([0, {'bar': '<bar/>'}]),
- '<bar/>'),
- (Markup('{0[1][bar]}').format([0, {'bar': Markup('<bar/>')}]),
- '<bar/>')):
- assert actual == expected, "%r should be %r!" % (actual, expected)
- # This is new in 2.7
- if sys.version_info >= (2, 7):
- def test_formatting_empty(self):
- formatted = Markup('{}').format(0)
- assert formatted == Markup('0')
- def test_custom_formatting(self):
- class HasHTMLOnly(object):
- def __html__(self):
- return Markup('<foo>')
- class HasHTMLAndFormat(object):
- def __html__(self):
- return Markup('<foo>')
- def __html_format__(self, spec):
- return Markup('<FORMAT>')
- assert Markup('{0}').format(HasHTMLOnly()) == Markup('<foo>')
- assert Markup('{0}').format(HasHTMLAndFormat()) == Markup('<FORMAT>')
- def test_complex_custom_formatting(self):
- class User(object):
- def __init__(self, id, username):
- self.id = id
- self.username = username
- def __html_format__(self, format_spec):
- if format_spec == 'link':
- return Markup('<a href="/user/{0}">{1}</a>').format(
- self.id,
- self.__html__(),
- )
- elif format_spec:
- raise ValueError('Invalid format spec')
- return self.__html__()
- def __html__(self):
- return Markup('<span class=user>{0}</span>').format(self.username)
- user = User(1, 'foo')
- assert Markup('<p>User: {0:link}').format(user) == \
- Markup('<p>User: <a href="/user/1"><span class=user>foo</span></a>')
- def test_all_set(self):
- import markupsafe as markup
- for item in markup.__all__:
- getattr(markup, item)
- def test_escape_silent(self):
- assert escape_silent(None) == Markup()
- assert escape(None) == Markup(None)
- assert escape_silent('<foo>') == Markup(u'<foo>')
- def test_splitting(self):
- self.assertEqual(Markup('a b').split(), [
- Markup('a'),
- Markup('b')
- ])
- self.assertEqual(Markup('a b').rsplit(), [
- Markup('a'),
- Markup('b')
- ])
- self.assertEqual(Markup('a\nb').splitlines(), [
- Markup('a'),
- Markup('b')
- ])
- def test_mul(self):
- self.assertEqual(Markup('a') * 3, Markup('aaa'))
- class MarkupLeakTestCase(unittest.TestCase):
- def test_markup_leaks(self):
- counts = set()
- for count in range(20):
- for item in range(1000):
- escape("foo")
- escape("<foo>")
- escape(u"foo")
- escape(u"<foo>")
- counts.add(len(gc.get_objects()))
- assert len(counts) == 1, 'ouch, c extension seems to leak objects'
- def suite():
- suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(MarkupTestCase))
- # this test only tests the c extension
- if not hasattr(escape, 'func_code'):
- suite.addTest(unittest.makeSuite(MarkupLeakTestCase))
- return suite
- if __name__ == '__main__':
- unittest.main(defaultTest='suite')
- # vim:sts=4:sw=4:et:
|