summaryrefslogtreecommitdiffstats
path: root/test/test_util.py
diff options
context:
space:
mode:
Diffstat (limited to 'test/test_util.py')
-rw-r--r--test/test_util.py395
1 files changed, 395 insertions, 0 deletions
diff --git a/test/test_util.py b/test/test_util.py
new file mode 100644
index 0000000..815b2d8
--- /dev/null
+++ b/test/test_util.py
@@ -0,0 +1,395 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+# Copyright 2015-2019 Mike Fährmann
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+
+import unittest
+import sys
+import random
+import string
+
+from gallery_dl import util, text, exception
+
+
+class TestRange(unittest.TestCase):
+
+ def test_parse_range(self, f=util.RangePredicate.parse_range):
+ self.assertEqual(
+ f(""),
+ [])
+ self.assertEqual(
+ f("1-2"),
+ [(1, 2)])
+ self.assertEqual(
+ f("-"),
+ [(1, sys.maxsize)])
+ self.assertEqual(
+ f("-2,4,6-8,10-"),
+ [(1, 2), (4, 4), (6, 8), (10, sys.maxsize)])
+ self.assertEqual(
+ f(" - 3 , 4- 4, 2-6"),
+ [(1, 3), (4, 4), (2, 6)])
+
+ def test_optimize_range(self, f=util.RangePredicate.optimize_range):
+ self.assertEqual(
+ f([]),
+ [])
+ self.assertEqual(
+ f([(2, 4)]),
+ [(2, 4)])
+ self.assertEqual(
+ f([(2, 4), (6, 8), (10, 12)]),
+ [(2, 4), (6, 8), (10, 12)])
+ self.assertEqual(
+ f([(2, 4), (4, 6), (5, 8)]),
+ [(2, 8)])
+ self.assertEqual(
+ f([(1, 1), (2, 2), (3, 6), (8, 9)]),
+ [(1, 6), (8, 9)])
+
+
+class TestPredicate(unittest.TestCase):
+
+ def test_range_predicate(self):
+ dummy = None
+
+ pred = util.RangePredicate(" - 3 , 4- 4, 2-6")
+ for i in range(6):
+ self.assertTrue(pred(dummy, dummy))
+ with self.assertRaises(exception.StopExtraction):
+ bool(pred(dummy, dummy))
+
+ pred = util.RangePredicate("1, 3, 5")
+ self.assertTrue(pred(dummy, dummy))
+ self.assertFalse(pred(dummy, dummy))
+ self.assertTrue(pred(dummy, dummy))
+ self.assertFalse(pred(dummy, dummy))
+ self.assertTrue(pred(dummy, dummy))
+ with self.assertRaises(exception.StopExtraction):
+ bool(pred(dummy, dummy))
+
+ pred = util.RangePredicate("")
+ with self.assertRaises(exception.StopExtraction):
+ bool(pred(dummy, dummy))
+
+ def test_unique_predicate(self):
+ dummy = None
+ pred = util.UniquePredicate()
+
+ # no duplicates
+ self.assertTrue(pred("1", dummy))
+ self.assertTrue(pred("2", dummy))
+ self.assertFalse(pred("1", dummy))
+ self.assertFalse(pred("2", dummy))
+ self.assertTrue(pred("3", dummy))
+ self.assertFalse(pred("3", dummy))
+
+ # duplicates for "text:"
+ self.assertTrue(pred("text:123", dummy))
+ self.assertTrue(pred("text:123", dummy))
+ self.assertTrue(pred("text:123", dummy))
+
+ def test_filter_predicate(self):
+ url = ""
+
+ pred = util.FilterPredicate("a < 3")
+ self.assertTrue(pred(url, {"a": 2}))
+ self.assertFalse(pred(url, {"a": 3}))
+
+ with self.assertRaises(SyntaxError):
+ util.FilterPredicate("(")
+
+ with self.assertRaises(exception.FilterError):
+ util.FilterPredicate("a > 1")(url, {"a": None})
+
+ with self.assertRaises(exception.FilterError):
+ util.FilterPredicate("b > 1")(url, {"a": 2})
+
+ def test_build_predicate(self):
+ pred = util.build_predicate([])
+ self.assertIsInstance(pred, type(lambda: True))
+
+ pred = util.build_predicate([util.UniquePredicate()])
+ self.assertIsInstance(pred, util.UniquePredicate)
+
+ pred = util.build_predicate([util.UniquePredicate(),
+ util.UniquePredicate()])
+ self.assertIsInstance(pred, util.ChainPredicate)
+
+
+class TestISO639_1(unittest.TestCase):
+
+ def test_code_to_language(self):
+ d = "default"
+ self._run_test(util.code_to_language, {
+ ("en",): "English",
+ ("FR",): "French",
+ ("xx",): None,
+ ("" ,): None,
+ (None,): None,
+ ("en", d): "English",
+ ("FR", d): "French",
+ ("xx", d): d,
+ ("" , d): d,
+ (None, d): d,
+ })
+
+ def test_language_to_code(self):
+ d = "default"
+ self._run_test(util.language_to_code, {
+ ("English",): "en",
+ ("fRENch",): "fr",
+ ("xx",): None,
+ ("" ,): None,
+ (None,): None,
+ ("English", d): "en",
+ ("fRENch", d): "fr",
+ ("xx", d): d,
+ ("" , d): d,
+ (None, d): d,
+ })
+
+ def _run_test(self, func, tests):
+ for args, result in tests.items():
+ self.assertEqual(func(*args), result)
+
+
+class TestFormatter(unittest.TestCase):
+
+ kwdict = {
+ "a": "hElLo wOrLd",
+ "b": "äöü",
+ "l": ["a", "b", "c"],
+ "n": None,
+ "u": "%27%3C%20/%20%3E%27",
+ "name": "Name",
+ "title1": "Title",
+ "title2": "",
+ "title3": None,
+ "title4": 0,
+ }
+
+ def test_conversions(self):
+ self._run_test("{a!l}", "hello world")
+ self._run_test("{a!u}", "HELLO WORLD")
+ self._run_test("{a!c}", "Hello world")
+ self._run_test("{a!C}", "Hello World")
+ self._run_test("{a!U}", self.kwdict["a"])
+ self._run_test("{u!U}", "'< / >'")
+ self._run_test("{a!s}", self.kwdict["a"])
+ self._run_test("{a!r}", "'" + self.kwdict["a"] + "'")
+ self._run_test("{a!a}", "'" + self.kwdict["a"] + "'")
+ self._run_test("{b!a}", "'\\xe4\\xf6\\xfc'")
+ self._run_test("{a!S}", self.kwdict["a"])
+ self._run_test("{l!S}", "a, b, c")
+ self._run_test("{n!S}", "")
+ with self.assertRaises(KeyError):
+ self._run_test("{a!q}", "hello world")
+
+ def test_optional(self):
+ self._run_test("{name}{title1}", "NameTitle")
+ self._run_test("{name}{title1:?//}", "NameTitle")
+ self._run_test("{name}{title1:? **/''/}", "Name **Title''")
+
+ self._run_test("{name}{title2}", "Name")
+ self._run_test("{name}{title2:?//}", "Name")
+ self._run_test("{name}{title2:? **/''/}", "Name")
+
+ self._run_test("{name}{title3}", "NameNone")
+ self._run_test("{name}{title3:?//}", "Name")
+ self._run_test("{name}{title3:? **/''/}", "Name")
+
+ self._run_test("{name}{title4}", "Name0")
+ self._run_test("{name}{title4:?//}", "Name")
+ self._run_test("{name}{title4:? **/''/}", "Name")
+
+ def test_missing(self):
+ replacement = "None"
+
+ self._run_test("{missing}", replacement)
+ self._run_test("{missing.attr}", replacement)
+ self._run_test("{missing[key]}", replacement)
+ self._run_test("{missing:?a//}", "")
+
+ self._run_test("{name[missing]}", replacement)
+ self._run_test("{name[missing].attr}", replacement)
+ self._run_test("{name[missing][key]}", replacement)
+ self._run_test("{name[missing]:?a//}", "")
+
+ def test_missing_custom_default(self):
+ replacement = default = "foobar"
+ self._run_test("{missing}" , replacement, default)
+ self._run_test("{missing.attr}", replacement, default)
+ self._run_test("{missing[key]}", replacement, default)
+ self._run_test("{missing:?a//}", "a" + default, default)
+
+ def test_slicing(self):
+ v = self.kwdict["a"]
+ self._run_test("{a[1:10]}" , v[1:10])
+ self._run_test("{a[-10:-1]}", v[-10:-1])
+ self._run_test("{a[5:]}" , v[5:])
+ self._run_test("{a[50:]}", v[50:])
+ self._run_test("{a[:5]}" , v[:5])
+ self._run_test("{a[:50]}", v[:50])
+ self._run_test("{a[:]}" , v)
+ self._run_test("{a[1:10:2]}" , v[1:10:2])
+ self._run_test("{a[-10:-1:2]}", v[-10:-1:2])
+ self._run_test("{a[5::2]}" , v[5::2])
+ self._run_test("{a[50::2]}", v[50::2])
+ self._run_test("{a[:5:2]}" , v[:5:2])
+ self._run_test("{a[:50:2]}", v[:50:2])
+ self._run_test("{a[::]}" , v)
+
+ def test_maxlen(self):
+ v = self.kwdict["a"]
+ self._run_test("{a:L5/foo/}" , "foo")
+ self._run_test("{a:L50/foo/}", v)
+ self._run_test("{a:L50/foo/>50}", " " * 39 + v)
+ self._run_test("{a:L50/foo/>51}", "foo")
+ self._run_test("{a:Lab/foo/}", "foo")
+
+ def test_join(self):
+ self._run_test("{l:J}" , "abc")
+ self._run_test("{l:J,}" , "a,b,c")
+ self._run_test("{l:J,/}" , "a,b,c")
+ self._run_test("{l:J,/>20}" , " a,b,c")
+ self._run_test("{l:J - }" , "a - b - c")
+ self._run_test("{l:J - /}" , "a - b - c")
+ self._run_test("{l:J - />20}", " a - b - c")
+
+ self._run_test("{a:J/}" , self.kwdict["a"])
+ self._run_test("{a:J, /}" , ", ".join(self.kwdict["a"]))
+
+ def test_replace(self):
+ self._run_test("{a:Rh/C/}" , "CElLo wOrLd")
+ self._run_test("{a!l:Rh/C/}", "Cello world")
+ self._run_test("{a!u:Rh/C/}", "HELLO WORLD")
+
+ self._run_test("{a!l:Rl/_/}", "he__o wor_d")
+ self._run_test("{a!l:Rl//}" , "heo word")
+ self._run_test("{name:Rame/othing/}", "Nothing")
+
+ def _run_test(self, format_string, result, default=None):
+ formatter = util.Formatter(format_string, default)
+ output = formatter.format_map(self.kwdict)
+ self.assertEqual(output, result, format_string)
+
+
+class TestOther(unittest.TestCase):
+
+ def test_bencode(self):
+ self.assertEqual(util.bencode(0), "")
+ self.assertEqual(util.bencode(123), "123")
+ self.assertEqual(util.bencode(123, "01"), "1111011")
+ self.assertEqual(util.bencode(123, "BA"), "AAAABAA")
+
+ def test_bdecode(self):
+ self.assertEqual(util.bdecode(""), 0)
+ self.assertEqual(util.bdecode("123"), 123)
+ self.assertEqual(util.bdecode("1111011", "01"), 123)
+ self.assertEqual(util.bdecode("AAAABAA", "BA"), 123)
+
+ def test_bencode_bdecode(self):
+ for _ in range(100):
+ value = random.randint(0, 1000000)
+ for alphabet in ("01", "0123456789", string.ascii_letters):
+ result = util.bdecode(util.bencode(value, alphabet), alphabet)
+ self.assertEqual(result, value)
+
+ def test_advance(self):
+ items = range(5)
+
+ self.assertCountEqual(
+ util.advance(items, 0), items)
+ self.assertCountEqual(
+ util.advance(items, 3), range(3, 5))
+ self.assertCountEqual(
+ util.advance(items, 9), [])
+ self.assertCountEqual(
+ util.advance(util.advance(items, 1), 2), range(3, 5))
+
+ def test_raises(self):
+ func = util.raises(Exception())
+ with self.assertRaises(Exception):
+ func()
+
+ func = util.raises(ValueError(1))
+ with self.assertRaises(ValueError):
+ func()
+ with self.assertRaises(ValueError):
+ func()
+ with self.assertRaises(ValueError):
+ func()
+
+ def test_combine_dict(self):
+ self.assertEqual(
+ util.combine_dict({}, {}),
+ {})
+ self.assertEqual(
+ util.combine_dict({1: 1, 2: 2}, {2: 4, 4: 8}),
+ {1: 1, 2: 4, 4: 8})
+ self.assertEqual(
+ util.combine_dict(
+ {1: {11: 22, 12: 24}, 2: {13: 26, 14: 28}},
+ {1: {11: 33, 13: 39}, 2: "str"}),
+ {1: {11: 33, 12: 24, 13: 39}, 2: "str"})
+ self.assertEqual(
+ util.combine_dict(
+ {1: {2: {3: {4: {"1": "a", "2": "b"}}}}},
+ {1: {2: {3: {4: {"1": "A", "3": "C"}}}}}),
+ {1: {2: {3: {4: {"1": "A", "2": "b", "3": "C"}}}}})
+
+ def test_transform_dict(self):
+ d = {}
+ util.transform_dict(d, str)
+ self.assertEqual(d, {})
+
+ d = {1: 123, 2: "123", 3: True, 4: None}
+ util.transform_dict(d, str)
+ self.assertEqual(
+ d, {1: "123", 2: "123", 3: "True", 4: "None"})
+
+ d = {1: 123, 2: "123", 3: "foo", 4: {11: 321, 12: "321", 13: "bar"}}
+ util.transform_dict(d, text.parse_int)
+ self.assertEqual(
+ d, {1: 123, 2: 123, 3: 0, 4: {11: 321, 12: 321, 13: 0}})
+
+ def test_number_to_string(self, f=util.number_to_string):
+ self.assertEqual(f(1) , "1")
+ self.assertEqual(f(1.0) , "1.0")
+ self.assertEqual(f("1.0") , "1.0")
+ self.assertEqual(f([1]) , [1])
+ self.assertEqual(f({1: 2}), {1: 2})
+ self.assertEqual(f(True) , True)
+ self.assertEqual(f(None) , None)
+
+ def test_to_string(self, f=util.to_string):
+ self.assertEqual(f(1) , "1")
+ self.assertEqual(f(1.0) , "1.0")
+ self.assertEqual(f("1.0"), "1.0")
+
+ self.assertEqual(f("") , "")
+ self.assertEqual(f(None) , "")
+ self.assertEqual(f(0) , "")
+
+ self.assertEqual(f(["a"]), "a")
+ self.assertEqual(f([1]) , "1")
+ self.assertEqual(f(["a", "b", "c"]), "a, b, c")
+ self.assertEqual(f([1, 2, 3]), "1, 2, 3")
+
+ def test_universal_none(self):
+ obj = util.NONE
+
+ self.assertFalse(obj)
+ self.assertEqual(str(obj), str(None))
+ self.assertEqual(repr(obj), repr(None))
+ self.assertIs(obj.attr, obj)
+ self.assertIs(obj["key"], obj)
+
+
+if __name__ == '__main__':
+ unittest.main()