1import pickle 2import random 3from collections import deque 4from copy import copy as shallow_copy 5 6import pytest 7from markupsafe import Markup 8 9from jinja2.utils import consume 10from jinja2.utils import generate_lorem_ipsum 11from jinja2.utils import LRUCache 12from jinja2.utils import missing 13from jinja2.utils import object_type_repr 14from jinja2.utils import select_autoescape 15from jinja2.utils import urlize 16 17 18class TestLRUCache: 19 def test_simple(self): 20 d = LRUCache(3) 21 d["a"] = 1 22 d["b"] = 2 23 d["c"] = 3 24 d["a"] 25 d["d"] = 4 26 assert len(d) == 3 27 assert "a" in d and "c" in d and "d" in d and "b" not in d 28 29 def test_itervalues(self): 30 cache = LRUCache(3) 31 cache["b"] = 1 32 cache["a"] = 2 33 values = [v for v in cache.values()] 34 assert len(values) == 2 35 assert 1 in values 36 assert 2 in values 37 38 def test_itervalues_empty(self): 39 cache = LRUCache(2) 40 values = [v for v in cache.values()] 41 assert len(values) == 0 42 43 def test_pickleable(self): 44 cache = LRUCache(2) 45 cache["foo"] = 42 46 cache["bar"] = 23 47 cache["foo"] 48 49 for protocol in range(3): 50 copy = pickle.loads(pickle.dumps(cache, protocol)) 51 assert copy.capacity == cache.capacity 52 assert copy._mapping == cache._mapping 53 assert copy._queue == cache._queue 54 55 @pytest.mark.parametrize("copy_func", [LRUCache.copy, shallow_copy]) 56 def test_copy(self, copy_func): 57 cache = LRUCache(2) 58 cache["a"] = 1 59 cache["b"] = 2 60 copy = copy_func(cache) 61 assert copy._queue == cache._queue 62 copy["c"] = 3 63 assert copy._queue != cache._queue 64 assert "a" not in copy and "b" in copy and "c" in copy 65 66 def test_clear(self): 67 d = LRUCache(3) 68 d["a"] = 1 69 d["b"] = 2 70 d["c"] = 3 71 d.clear() 72 assert d.__getstate__() == {"capacity": 3, "_mapping": {}, "_queue": deque([])} 73 74 def test_repr(self): 75 d = LRUCache(3) 76 d["a"] = 1 77 d["b"] = 2 78 d["c"] = 3 79 # Sort the strings - mapping is unordered 80 assert sorted(repr(d)) == sorted("<LRUCache {'a': 1, 'b': 2, 'c': 3}>") 81 82 def test_items(self): 83 """Test various items, keys, values and iterators of LRUCache.""" 84 d = LRUCache(3) 85 d["a"] = 1 86 d["b"] = 2 87 d["c"] = 3 88 assert d.items() == [("c", 3), ("b", 2), ("a", 1)] 89 assert d.keys() == ["c", "b", "a"] 90 assert d.values() == [3, 2, 1] 91 assert list(reversed(d)) == ["a", "b", "c"] 92 93 # Change the cache a little 94 d["b"] 95 d["a"] = 4 96 assert d.items() == [("a", 4), ("b", 2), ("c", 3)] 97 assert d.keys() == ["a", "b", "c"] 98 assert d.values() == [4, 2, 3] 99 assert list(reversed(d)) == ["c", "b", "a"] 100 101 def test_setdefault(self): 102 d = LRUCache(3) 103 assert len(d) == 0 104 assert d.setdefault("a") is None 105 assert d.setdefault("a", 1) is None 106 assert len(d) == 1 107 assert d.setdefault("b", 2) == 2 108 assert len(d) == 2 109 110 111class TestHelpers: 112 def test_object_type_repr(self): 113 class X: 114 pass 115 116 assert object_type_repr(42) == "int object" 117 assert object_type_repr([]) == "list object" 118 assert object_type_repr(X()) == "test_utils.X object" 119 assert object_type_repr(None) == "None" 120 assert object_type_repr(Ellipsis) == "Ellipsis" 121 122 def test_autoescape_select(self): 123 func = select_autoescape( 124 enabled_extensions=("html", ".htm"), 125 disabled_extensions=("txt",), 126 default_for_string="STRING", 127 default="NONE", 128 ) 129 130 assert func(None) == "STRING" 131 assert func("unknown.foo") == "NONE" 132 assert func("foo.html") 133 assert func("foo.htm") 134 assert not func("foo.txt") 135 assert func("FOO.HTML") 136 assert not func("FOO.TXT") 137 138 139class TestEscapeUrlizeTarget: 140 def test_escape_urlize_target(self): 141 url = "http://example.org" 142 target = "<script>" 143 assert urlize(url, target=target) == ( 144 '<a href="http://example.org"' 145 ' target="<script>">' 146 "http://example.org</a>" 147 ) 148 149 150class TestLoremIpsum: 151 def test_lorem_ipsum_markup(self): 152 """Test that output of lorem_ipsum is Markup by default.""" 153 assert isinstance(generate_lorem_ipsum(), Markup) 154 155 def test_lorem_ipsum_html(self): 156 """Test that output of lorem_ipsum is a string_type when not html.""" 157 assert isinstance(generate_lorem_ipsum(html=False), str) 158 159 def test_lorem_ipsum_n(self): 160 """Test that the n (number of lines) works as expected.""" 161 assert generate_lorem_ipsum(n=0, html=False) == "" 162 for n in range(1, 50): 163 assert generate_lorem_ipsum(n=n, html=False).count("\n") == (n - 1) * 2 164 165 def test_lorem_ipsum_min(self): 166 """Test that at least min words are in the output of each line""" 167 for _ in range(5): 168 m = random.randrange(20, 99) 169 for _ in range(10): 170 assert generate_lorem_ipsum(n=1, min=m, html=False).count(" ") >= m - 1 171 172 def test_lorem_ipsum_max(self): 173 """Test that at least max words are in the output of each line""" 174 for _ in range(5): 175 m = random.randrange(21, 100) 176 for _ in range(10): 177 assert generate_lorem_ipsum(n=1, max=m, html=False).count(" ") < m - 1 178 179 180def test_missing(): 181 """Test the repr of missing.""" 182 assert repr(missing) == "missing" 183 184 185def test_consume(): 186 """Test that consume consumes an iterator.""" 187 x = iter([1, 2, 3, 4, 5]) 188 consume(x) 189 with pytest.raises(StopIteration): 190 next(x) 191