diff options
author | Tim Harder <radhermit@gmail.com> | 2021-03-04 13:41:41 -0700 |
---|---|---|
committer | Tim Harder <radhermit@gmail.com> | 2021-03-04 13:44:52 -0700 |
commit | 00684d51abf632310b58e5ed56b0ed61d9eeeb3d (patch) | |
tree | 19e965b2eb1ba5bc87ee5227dbb571a243a0ac56 /tests/restrictions | |
parent | coverage: minor config update (diff) | |
download | pkgcore-00684d51abf632310b58e5ed56b0ed61d9eeeb3d.tar.gz pkgcore-00684d51abf632310b58e5ed56b0ed61d9eeeb3d.tar.bz2 pkgcore-00684d51abf632310b58e5ed56b0ed61d9eeeb3d.zip |
tests: move to repo root dir
Diffstat (limited to 'tests/restrictions')
-rw-r--r-- | tests/restrictions/__init__.py | 0 | ||||
-rw-r--r-- | tests/restrictions/test_boolean.py | 165 | ||||
-rw-r--r-- | tests/restrictions/test_delegated.py | 40 | ||||
-rw-r--r-- | tests/restrictions/test_packages.py | 198 | ||||
-rw-r--r-- | tests/restrictions/test_restriction.py | 100 | ||||
-rw-r--r-- | tests/restrictions/test_util.py | 32 | ||||
-rw-r--r-- | tests/restrictions/test_values.py | 334 |
7 files changed, 869 insertions, 0 deletions
diff --git a/tests/restrictions/__init__.py b/tests/restrictions/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/restrictions/__init__.py diff --git a/tests/restrictions/test_boolean.py b/tests/restrictions/test_boolean.py new file mode 100644 index 000000000..5f998f048 --- /dev/null +++ b/tests/restrictions/test_boolean.py @@ -0,0 +1,165 @@ +from snakeoil.test import TestCase + +from pkgcore.restrictions import boolean, restriction + +true = restriction.AlwaysBool(node_type='foo', negate=True) +false = restriction.AlwaysBool(node_type='foo', negate=False) + + +class AlwaysForcableBool(boolean.base): + + __slots__ = () + + def force_True(self, action, *args): + yield True + + match = force_False = force_True + + +class base: + + kls = None + + def test_invalid_restrictions(self): + self.assertRaises(TypeError, self.kls, 42, node_type='foo') + base = self.kls(node_type='foo') + self.assertRaises(TypeError, base.add_restriction, 42) + self.assertRaises(TypeError, base.add_restriction) + + def test_init_finalize(self): + final = self.kls(true, node_type='foo', finalize=True) + # since it becomes a tuple, throws a AttributeError + self.assertRaises(TypeError, final.add_restriction, false) + + final = self.kls(true, node_type='foo') + # since it becomes a tuple, throws a AttributeError + self.assertRaises(TypeError, final.add_restriction, false) + + def test_finalize(self): + base = self.kls(true, node_type='foo', finalize=False) + base.add_restriction(false) + base.finalize() + self.assertRaises(TypeError, base.add_restriction, true) + + def test_change_restrictions(self): + base = self.kls(true, false) + assert self.kls(false, true) == base.change_restrictions(false, true) + assert self.kls(false, true) != base.change_restrictions(false, true, negate=True) + assert self.kls(false, true, negate=True) == base.change_restrictions(false, true, negate=True) + + def test_add_restriction(self): + self.assertRaises(TypeError, + self.kls(true, finalize=True).add_restriction, false) + self.assertRaises(TypeError, + self.kls(node_type='foon').add_restriction, false) + k = self.kls(finalize=False) + k.add_restriction(false) + assert k.restrictions == [false] + + # TODO total_len? what does it do? + +class BaseTest(base, TestCase): + + kls = boolean.base + + def test_base(self): + base = self.kls(true, false, node_type='foo') + assert len(base) == 2 + assert list(base) == [true, false] + self.assertRaises(NotImplementedError, base.match, false) + # TODO is the signature for these correct? + self.assertRaises(NotImplementedError, base.force_False, false) + self.assertRaises(NotImplementedError, base.force_True, false) + self.assertIdentical(base[1], false) + + +# TODO these tests are way too limited +class AndRestrictionTest(base, TestCase): + + kls = boolean.AndRestriction + + def test_match(self): + assert self.kls(true, true, node_type='foo').match(None) + assert not self.kls(false, true, true, node_type='foo').match(None) + assert not self.kls(true, false, true, node_type='foo').match(None) + + def test_negate_match(self): + assert self.kls(false, true, node_type='foo', negate=True).match(None) + assert self.kls(true, false, node_type='foo', negate=True).match(None) + assert self.kls(false, false, node_type='foo', negate=True).match(None) + assert not self.kls(true, true, node_type='foo', negate=True).match(None) + + def test_dnf_solutions(self): + assert self.kls(true, true).dnf_solutions() == [[true, true]] + assert self.kls(self.kls(true, true), true).dnf_solutions() == [[true, true, true]] + assert (list(map(set, self.kls( + true, true, + boolean.OrRestriction(false, true)).dnf_solutions())) == + [set([true, true, false]), set([true, true, true])]) + assert self.kls().dnf_solutions() == [[]] + + def test_cnf_solutions(self): + assert self.kls(true, true).cnf_solutions() == [[true], [true]] + assert self.kls(self.kls(true, true), true).cnf_solutions() == [[true], [true], [true]] + assert (list(self.kls( + true, true, + boolean.OrRestriction(false, true)).cnf_solutions()) == + list([[true], [true], [false, true]])) + assert self.kls().cnf_solutions() == [] + + +class OrRestrictionTest(base, TestCase): + + kls = boolean.OrRestriction + + def test_match(self): + assert self.kls(true, true, node_type='foo').match(None) + assert self.kls(false, true, false, node_type='foo').match(None) + assert self.kls(true, false, false, node_type='foo').match(None) + assert self.kls(false, false, true, node_type='foo').match(None) + assert not self.kls(false, false, node_type='foo').match(None) + + def test_negate_match(self): + for x in ((true, false), (false, true), (true, true)): + assert not self.kls(node_type='foo', negate=True, *x).match(None) + assert self.kls(false, false, node_type='foo', negate=True).match(None) + + def test_dnf_solutions(self): + assert self.kls(true, true).dnf_solutions() == [[true], [true]] + assert (list(map(set, self.kls( + true, true, + boolean.AndRestriction(false, true)).dnf_solutions())) == + list(map(set, [[true], [true], [false, true]]))) + assert self.kls(self.kls(true, false), true).dnf_solutions() == [[true], [false], [true]] + assert self.kls().dnf_solutions() == [[]] + + def test_cnf_solutions(self): + assert self.kls(true, true).cnf_solutions() == [[true, true]] + assert ([set(x) for x in self.kls( + true, true, + boolean.AndRestriction(false, true)).cnf_solutions()] == + [set(x) for x in [[true, false], [true, true]]]) + + assert ([set(x) for x in self.kls(self.kls( + true, true, + boolean.AndRestriction(false, true))).cnf_solutions()] == + [set(x) for x in [[true, false], [true, true]]]) + + assert (set(self.kls( + self.kls(true, false), + true).cnf_solutions()[0]) == + set([true, false, true])) + + assert self.kls().cnf_solutions() == [] + + +class JustOneRestrictionTest(base, TestCase): + + kls = boolean.JustOneRestriction + + def test_match(self): + assert self.kls(true, false, node_type='foo').match(None) + assert self.kls(false, true, false, node_type='foo').match(None) + assert not self.kls(false, false, node_type='foo').match(None) + assert not self.kls(true, false, true, node_type='foo').match(None) + assert not self.kls(true, true, true, node_type='foo').match(None) diff --git a/tests/restrictions/test_delegated.py b/tests/restrictions/test_delegated.py new file mode 100644 index 000000000..e392707ec --- /dev/null +++ b/tests/restrictions/test_delegated.py @@ -0,0 +1,40 @@ +from pkgcore.restrictions.delegated import delegate +from pkgcore.test import TestRestriction + + +class Test_delegate(TestRestriction): + + kls = delegate + + def test_it(self): + self.assertRaises(TypeError, self.kls, None, None) + y = True + l = [] + def f(x, mode): + l.append(mode) + if mode == 'force_False': + return not y + return y + + for negated in (False, True): + def assertIt(got, expected): + self.assertEqual( + got, expected, + msg=f"got={got!r}, expected={expected!r}, negate={negated!r}") + y = True + l[:] = [] + o = self.kls(f, negate=negated) + self.assertMatches(o, [None], negated=negated) + + y = False + self.assertNotMatches(o, [None], negated=negated) + + if negated: + assertIt(l, ['match', 'force_False', 'force_True', + 'match', 'force_False', 'force_True']) + else: + assertIt(l, ['match', 'force_True', 'force_False', + 'match', 'force_True', 'force_False']) + + def test_caching(self): + self.assertFalse(self.kls.inst_caching, False) diff --git a/tests/restrictions/test_packages.py b/tests/restrictions/test_packages.py new file mode 100644 index 000000000..b716073e1 --- /dev/null +++ b/tests/restrictions/test_packages.py @@ -0,0 +1,198 @@ +from snakeoil.mappings import AttrAccessible + +from pkgcore import log +from pkgcore.restrictions import packages, values +from pkgcore.test import (TestCase, TestRestriction, callback_logger, + malleable_obj, silence_logging) + + +class AlwaysSelfIntersect(values.base): + def intersect(self, other): + return self + + __hash__ = object.__hash__ + + +class TestPackageRestriction(TestRestriction): + + if packages.PackageRestriction is packages.PackageRestriction: + kls = packages.PackageRestriction + else: + class kls(packages.PackageRestriction, + packages.PackageRestriction_mixin): + __slots__ = () + __inst_caching__ = packages.PackageRestriction.__inst_caching__ + + kls = staticmethod(kls) + + @silence_logging(log.logging.root) + def test_matching(self): + strexact = values.StrExactMatch + + args = malleable_obj(category="foon", package="dar") + self.assertMatches(self.kls("category", strexact("foon")), args) + self.assertMatches(self.kls("package", strexact("dar")), args) + self.assertNotMatches(self.kls("package", strexact("dar"), negate=True), + args) + self.assertNotMatches(self.kls("package", strexact("foon")), args) + + self.assertMatches(self.kls("package", strexact("foon"), negate=True), + args) + excepts = [] + # no msg should be thrown, it wasn't an unexpected exception + + log.logging.root.addHandler(callback_logger(excepts.append)) + self.assertNotMatches(self.kls("foon", AlwaysSelfIntersect), args) + self.assertFalse(excepts) + + self.assertMatches(self.kls("foon", AlwaysSelfIntersect, negate=True), + args) + self.assertFalse(excepts) + + class foo: + def __getattr__(self, attr): + if attr.startswith("exc"): + raise exceptions_d.get(attr[4:], None)() + raise AttributeError("monkey lover") + + exceptions_d = {"KeyboardInterrupt":KeyboardInterrupt, + "RuntimeError":RuntimeError, "SystemExit":SystemExit} + + for mode in ("match", "force_True", "force_False"): + excepts[:] = [] + self.assertRaises(AttributeError, + getattr(self.kls("foon", AlwaysSelfIntersect), mode), + foo()) + self.assertEqual( + len(excepts), 1, + msg=f"expected one exception, got {excepts!r}") + + # ensure various exceptions are passed through + for k in (KeyboardInterrupt, RuntimeError, SystemExit): + self.assertRaises( + k, + getattr(self.kls(f"exc_{k.__name__}", AlwaysSelfIntersect), mode), + foo()) + + # check that it only does string comparison in exception catching. + class foo: + def __cmp__(self, other): + raise TypeError + + def __getattr__(self, attr): + raise AttributeError(self, attr) + + self.assertFalse(self.kls("foon", AlwaysSelfIntersect).match(foo())) + + def test_attr(self): + self.assertEqual(self.kls('val', values.AlwaysTrue).attr, + 'val') + self.assertEqual(self.kls('val.dar', values.AlwaysTrue).attr, + 'val.dar') + self.assertEqual(self.kls('val', values.AlwaysTrue).attrs, + ('val',)) + self.assertEqual(self.kls('val.dar', values.AlwaysTrue).attrs, + ('val.dar',)) + + def test_eq(self): + self.assertEqual( + self.kls('one', values.AlwaysTrue), + self.kls('one', values.AlwaysTrue)) + self.assertNotEqual( + self.kls('one', values.AlwaysTrue), + self.kls('one', values.AlwaysTrue, negate=True)) + self.assertNotEqual( + self.kls('one', values.AlwaysTrue), + self.kls('two', values.AlwaysTrue)) + self.assertNotEqual( + self.kls('one', values.AlwaysTrue, negate=True), + self.kls('one', values.AlwaysFalse, negate=True)) + + def test_hash(self): + inst = self.kls('one.dar', AlwaysSelfIntersect()) + hash(inst) + + +class values_callback(values.base): + + __slots__ = ("callback",) + + def __init__(self, callback): + object.__setattr__(self, 'callback', callback) + + def match(self, val): + return self.callback((None, val)) + + def force_True(self, pkg, attr, val): + return self.callback((True, pkg, attr, val)) + + def force_False(self, pkg, attr, val): + return self.callback((False, pkg, attr, val)) + + +class TestPackageRestrictionMulti(TestCase): + + if packages.PackageRestriction is packages.PackageRestriction: + kls = packages.PackageRestrictionMulti + else: + class kls(packages.PackageRestrictionMulti, + packages.PackageRestrictionMulti_mixin): + __slots__ = () + __inst_caching__ = packages.PackageRestrictionMulti.__inst_caching__ + + kls = staticmethod(kls) + + def test_attr(self): + o = self.kls(("asdf.far", "repo"), values.AlwaysTrue) + self.assertEqual(o.attrs, ("asdf.far", "repo")) + self.assertEqual(o.attr, None) + + def test_values(self): + l = [] + def f(*args): + self.assertLen(args, 1) + l.append(args[0]) + return True + + o = self.kls(("asdf.far", "repo"), values_callback(f)) + + pkg = AttrAccessible() + o.match(pkg) + self.assertFalse(l) + + pkg['repo'] = 1 + o.match(pkg) + self.assertFalse(l) + + pkg['asdf'] = AttrAccessible(far=2) + o.match(pkg) + self.assertEqual(l, [(None, [2,1],)]) + + l[:] = [] + o.force_True(pkg) + self.assertEqual(l, [(True, pkg, ('asdf.far', 'repo'), [2,1],)]) + + l[:] = [] + o.force_False(pkg) + self.assertEqual(l, [(False, pkg, ('asdf.far', 'repo'), [2,1],)]) + + +class ConditionalTest(TestCase): + + def test_eq(self): + p = (packages.PackageRestriction('one', values.AlwaysTrue),) + p2 = (packages.PackageRestriction('one', values.AlwaysFalse),) + v = values.AlwaysTrue + v2 = values.AlwaysFalse + self.assertEqual( + packages.Conditional('use', v, p), + packages.Conditional('use', v, p)) + self.assertNotEqual( + packages.Conditional('use', v2, p), + packages.Conditional('use', v, p)) + self.assertNotEqual( + packages.Conditional('use', v, p), + packages.Conditional('use', v, p2)) + self.assertNotEqual( + packages.Conditional('use1', v, p), + packages.Conditional('use', v, p)) diff --git a/tests/restrictions/test_restriction.py b/tests/restrictions/test_restriction.py new file mode 100644 index 000000000..03305bc77 --- /dev/null +++ b/tests/restrictions/test_restriction.py @@ -0,0 +1,100 @@ +from functools import partial + +from pkgcore.restrictions import restriction +from pkgcore.test import TestRestriction + + +class SillyBool(restriction.base): + """Extra stupid version of AlwaysBool to test base.force_{True,False}.""" + + __slots__ = ('negate',) + + def __init__(self, negate=False): + object.__setattr__(self, 'negate', negate) + + def match(self, *args, **kwargs): + return not self.negate + + +class BaseTest(TestRestriction): + + bool_kls = SillyBool + + def test_base(self): + base = restriction.base() + self.assertEqual(len(base), 1) + # Just check repr and str do not raise + self.assertTrue(str(base)) + self.assertTrue(repr(base)) + self.assertTrue(hash(base)) + self.assertRaises(NotImplementedError, base.match) + + def test_it(self): + true = self.bool_kls(negate=False) + false = self.bool_kls(negate=True) + args = [None] + + self.assertMatch(true, args[0]) + self.assertForceTrue(true, args) + self.assertNotForceFalse(true, args) + + self.assertNotMatch(false, args[0]) + self.assertNotForceTrue(false, args) + self.assertForceFalse(false, args) + + +class AlwaysBoolTest(TestRestriction): + + bool_kls = partial(restriction.AlwaysBool, 'foo') + + def test_true(self): + true_r = self.bool_kls(True) + false_r = self.bool_kls(False) + self.assertMatch(true_r, false_r) + self.assertForceTrue(true_r, false_r) + self.assertNotForceFalse(true_r, false_r) + + self.assertNotMatch(false_r, true_r) + self.assertNotForceTrue(false_r, true_r) + self.assertForceFalse(false_r, true_r) + + self.assertEqual(str(true_r), "always 'True'") + self.assertEqual(str(false_r), "always 'False'") + self.assertNotEqual(hash(true_r), hash(false_r)) + self.assertEqual(hash(true_r), + hash(self.bool_kls(True))) + self.assertEqual(hash(false_r), + hash(self.bool_kls(False))) + self.assertEqual(true_r, self.bool_kls(True)) + self.assertEqual(false_r, self.bool_kls(False)) + self.assertNotEqual(true_r, false_r) + + +class NoneMatch(restriction.base): + + """Only matches None.""" + + __slots__ = () + + def match(self, val): + return val is None + + def __repr__(self): + return '<NoneMatch>' + + def __str__(self): + return 'NoneMatch' + + +class AnyMatchTest(TestRestriction): + + def test_basic(self): + for negate in (False, True): + inst = restriction.AnyMatch(NoneMatch(), 'spork', negate=negate) + self.assertMatch(inst, ['spork', None], negated=negate) + self.assertNotMatch(inst, ['spork'], negated=negate) + self.assertNotMatch(inst, (), negated=negate) + + # just test these do not traceback + self.assertTrue(repr(inst)) + self.assertTrue(str(inst)) diff --git a/tests/restrictions/test_util.py b/tests/restrictions/test_util.py new file mode 100644 index 000000000..5e125d7e2 --- /dev/null +++ b/tests/restrictions/test_util.py @@ -0,0 +1,32 @@ +from snakeoil.test import TestCase + +from pkgcore.restrictions import packages, util, values + + +class Test_collect_package_restrictions(TestCase): + + def test_collect_all(self): + prs = [packages.PackageRestriction("category", values.AlwaysTrue)] * 10 + self.assertEqual( + list(util.collect_package_restrictions(packages.AndRestriction( + packages.OrRestriction(), packages.AndRestriction(), + *prs))), + prs) + + def test_collect_specific(self): + prs = {} + for x in ("category", "package", "version", "iuse"): + prs[x] = packages.PackageRestriction(x, values.AlwaysTrue) + + r = packages.AndRestriction( + packages.OrRestriction(*prs.values()), packages.AlwaysTrue) + for k, v in prs.items(): + self.assertEqual( + list(util.collect_package_restrictions(r, attrs=[k])), + [v]) + r = packages.AndRestriction(packages.OrRestriction( + *prs.values()), *prs.values()) + for k, v in prs.items(): + self.assertEqual( + list(util.collect_package_restrictions(r, attrs=[k])), + [v] * 2) diff --git a/tests/restrictions/test_values.py b/tests/restrictions/test_values.py new file mode 100644 index 000000000..2571f45de --- /dev/null +++ b/tests/restrictions/test_values.py @@ -0,0 +1,334 @@ +from snakeoil.test import TestCase + +from pkgcore.restrictions import values +from pkgcore.test import TestRestriction + + +class SillyBool(values.base): + """Extra stupid version of AlwaysBool to test base.force_{True,False}.""" + def __init__(self, negate=False): + object.__setattr__(self, "negate", negate) + + def match(self, something): + return not self.negate + + +class BaseTest(TestRestriction): + + def test_force(self): + self.assertMatches(SillyBool(negate=False), None, [None]*3) + self.assertNotMatches(SillyBool(negate=True), None, [None]*3) + + +class GetAttrTest(TestRestriction): + + """Test bits of GetAttrRestriction that differ from PackageRestriction.""" + + def test_force(self): + # TODO we could do with both more tests and a more powerful + # force_* implementation. This just tests if the function + # takes the right number of arguments. + + # TODO test negate handling + succeeds = values.GetAttrRestriction('test', values.AlwaysTrue) + fails = values.GetAttrRestriction('test', values.AlwaysFalse) + + class Dummy: + test = True + + dummy = Dummy() + + class FakePackage: + """XXX this is vastly too minimal.""" + value = dummy + + pkg = FakePackage() + + args = [pkg, 'value', dummy] + self.assertForceTrue(succeeds, args) + self.assertNotForceFalse(succeeds, args) + self.assertNotForceTrue(fails, args) + self.assertForceFalse(fails, args) + + +class StrRegexTest(TestRestriction): + + kls = values.StrRegex + + def test_match(self): + for negated in (False, True): + self.assertMatches(self.kls('foo.*r', match=True, + negate=negated), + 'foobar', [None, None, 'foobar'], negated=negated) + self.assertNotMatches(self.kls('foo.*r', match=True, + negate=negated), + 'afoobar', [None, None, 'afoobar'], negated=negated) + + def test_search(self): + for negated in (False, True): + self.assertMatches(self.kls('foo.*r', negate=negated), + 'asdfoobar', [None, None, 'asdfoobar'], negated=negated) + self.assertNotMatches(self.kls('foo.*r', negate=negated), + 'afobar', [None, None, 'afobar'], negated=negated) + + def test_case_sensitivity(self): + self.assertNotMatches(self.kls('foo'), 'FoO', ['FOo']*3) + self.assertMatches(self.kls('foo', False), 'FoO', ['fOo']*3) + + def test_str(self): + assert 'search spork' == str(self.kls('spork')) + assert 'not search spork' == str(self.kls('spork', negate=True)) + assert 'match spork' == str(self.kls('spork', match=True)) + assert 'not match spork' == str(self.kls('spork', match=True, negate=True)) + + def test_repr(self): + for restr, string in [ + (self.kls('spork'), "<StrRegex 'spork' search @"), + (self.kls('spork', match=True), + "<StrRegex 'spork' match @"), + (self.kls('spork', negate=True), + "<StrRegex 'spork' negated search @"), + ]: + self.assertTrue(repr(restr).startswith(string), (restr, string)) + + + +class TestStrExactMatch(TestRestriction): + + if values.StrExactMatch is values.StrExactMatch: + kls = values.StrExactMatch + else: + class kls(values.StrExactMatch, values.base): + __slots__ = () + __inst_caching__ = True + + intersect = values._StrExact_intersect + __repr__ = values._StrExact__repr__ + __str__ = values._StrExact__str__ + + kls = staticmethod(kls) + + def test_case_sensitive(self): + for negated in (False, True): + self.assertMatches(self.kls('package', negate=negated), + 'package', ['package']*3, negated=negated) + self.assertNotMatches(self.kls('Package', negate=negated), + 'package', ['package']*3, negated=negated) + + def test_case_insensitive(self): + for negated in (False, True): + # note that we explicitly test True/1, and False/0 + # we test 1/0, since bool protocol is supported for those kwds- + # thus we verify it, more specifically we verify the cpy + # support. + self.assertMatches(self.kls('package', case_sensitive=True, + negate=negated), + 'package', ['package']*3, negated=negated) + self.assertMatches(self.kls('package', case_sensitive=1, + negate=negated), + 'package', ['package']*3, negated=negated) + self.assertMatches(self.kls('Package', case_sensitive=False, + negate=negated), + 'package', ['package']*3, negated=negated) + self.assertMatches(self.kls('Package', case_sensitive=0, + negate=negated), + 'package', ['package']*3, negated=negated) + + def test__eq__(self): + for negate in (True, False): + assert self.kls("rsync", negate=negate) == self.kls("rsync", negate=negate) + for x in "Ca": + assert self.kls("rsync", negate=negate) != self.kls("rsyn"+x, negate=negate) + assert ( + self.kls("Rsync", case_sensitive=False, negate=negate) == + self.kls("rsync", case_sensitive=False, negate=negate)) + + +class TestStrGlobMatch(TestRestriction): + + kls = values.StrGlobMatch + + def test_matching(self): + for negated in (True, False): + self.assertMatches(self.kls('pack', negate=negated), + 'package', ['package']*3, negated=negated) + self.assertNotMatches(self.kls('pack', negate=negated), + 'apack', ['apack']*3, negated=negated) + # case sensitive... + self.assertMatches(self.kls('pAcK', case_sensitive=False, + negate=negated), + 'pack', ['pack']*3, negated=negated) + self.assertNotMatches(self.kls('pAcK', + case_sensitive=True, negate=negated), + 'pack', ['pack']*3, negated=negated) + + # check prefix. + self.assertMatches(self.kls('pAck', case_sensitive=False, + prefix=True, negate=negated), + 'packa', ['packa']*3, negated=negated) + + self.assertNotMatches(self.kls('pack', prefix=False, + negate=negated), + 'apacka', ['apacka']*3, negated=negated) + + self.assertMatches(self.kls('pack', prefix=False, + negate=negated), + 'apack', ['apack']*3, negated=negated) + + # daft, but verifies it's not doing contains. + self.assertNotMatches(self.kls('pack', prefix=False, + negate=negated), + 'apacka', ['apacka']*3, negated=negated) + + self.assertNotMatches(self.kls('pack', prefix=False, + case_sensitive=False, negate=negated), + 'aPacka', ['aPacka']*3, negated=negated) + + def test__eq__(self): + self.assertFalse( + self.kls("rsync", prefix=False) == + self.kls("rsync", prefix=True)) + for negate in (True, False): + assert self.kls("rsync", negate=negate) == self.kls("rsync", negate=negate) + for x in "Ca": + self.assertNotEqual( + self.kls("rsync", negate=negate), + self.kls("rsyn"+x, negate=negate)) + self.assertNotEqual( + self.kls("Rsync", case_sensitive=False, negate=negate), + self.kls("rsync", case_sensitive=True, negate=negate)) + self.assertNotEqual( + self.kls("rsync", case_sensitive=False, negate=negate), + self.kls("rsync", case_sensitive=True, negate=negate)) + self.assertNotEqual( + self.kls("rsync", case_sensitive=False, negate=negate), + self.kls("rsync", case_sensitive=True, negate=not negate)) + self.assertNotEqual( + self.kls("rsync", negate=True), + self.kls("rsync", negate=False)) + + +class TestEqualityMatch(TestRestriction): + + kls = staticmethod(values.EqualityMatch) + + def test_match(self): + for x, y, ret in (("asdf", "asdf", True), ("asdf", "fdsa", False), + (1, 1, True), (1,2, False), + (list(range(2)), list(range(2)), True), + (list(range(2)), reversed(list(range(2))), False), + (True, True, True), + (True, False, False), + (False, True, False)): + for negated in (True, False): + self.assertMatches(self.kls(x, negate=negated), + y, [y]*3, negated=(ret ^ (not negated))) + + def test__eq__(self): + for negate in (True, False): + assert self.kls("asdf", negate=negate) == self.kls("asdf", negate=negate) + self.assertNotEqual( + self.kls(1, negate=negate), + self.kls(2, negate=negate)) + self.assertNotEqual( + self.kls("asdf", negate=True), + self.kls("asdf", negate=False)) + + def test__hash__(self): + def f(*args, **kwds): + return hash(self.kls(*args, **kwds)) + assert f("dar") == f("dar") + assert f("dar") == f("dar", negate=False) + assert f("dar", negate=True) != f("dar", negate=False) + assert f("dar", negate=True) == f("dar", negate=True) + assert f("dar") != f("dar2") + assert f("dar", negate=True) != f("dar2") + + +class TestContainmentMatch(TestRestriction): + + kls = values.ContainmentMatch + + def test_match(self): + for x, y, ret in ( + (list(range(10)), list(range(10)), True), + (list(range(10)), [], False), + (list(range(10)), set(range(10)), True), + (set(range(10)), list(range(10)), True)): + + for negated in (False, True): + self.assertMatches(self.kls(negate=negated, + disable_inst_caching=True, *x), + y, [y]*3, negated=(ret == negated)) + + for negated in (False, True): + # intentionally differing for the force_* args; slips in + # an extra data set for testing. + self.assertMatches(self.kls(all=True, negate=negated, *range(10)), + list(range(20)), [list(range(10))]*3, negated=negated) + self.assertNotMatches(self.kls(all=True, negate=negated, *range(10)), + list(range(5)), [list(range(5))]*3, negated=negated) + + self.assertNotMatches(self.kls("asdf"), "fdsa", ["fdas"]*3) + self.assertMatches(self.kls("asdf"), "asdf", ["asdf"]*3) + self.assertMatches(self.kls("asdf"), "asdffdsa", ["asdffdsa"]*3) + self.assertMatches(self.kls("b"), "aba", ["aba"]*3) + + def test__eq__(self): + for negate in (True, False): + assert self.kls(negate=negate, *range(100)) == self.kls(negate=negate, *range(100)), \ + f"range(100), negate={negate}" + assert self.kls(1, negate=not negate) != self.kls(1, negate=negate) + assert ( + self.kls(1, 2, 3, all=True, negate=negate) == + self.kls(1, 2, 3, all=True, negate=negate)) + assert ( + self.kls(1, 2, all=True, negate=negate) != + self.kls(1, 2, 3, all=True, negate=negate)) + assert ( + self.kls(1, 2, 3, all=False, negate=negate) != + self.kls(1, 2, 3, all=True, negate=negate)) + + +class FlatteningRestrictionTest(TestCase): + + def test_basic(self): + for negate in (False, True): + inst = values.FlatteningRestriction( + tuple, values.AnyMatch(values.EqualityMatch(None)), + negate=negate) + assert not negate == inst.match([7, 8, [9, None]]) + assert negate == inst.match([7, 8, (9, None)]) + # Just check this does not raise + self.assertTrue(str(inst)) + self.assertTrue(repr(inst)) + + +class FunctionRestrictionTest(TestCase): + + def test_basic(self): + + def yes(val): + return True + def no(val): + return False + + for negate in (False, True): + yes_restrict = values.FunctionRestriction(yes, negate=negate) + no_restrict = values.FunctionRestriction(no, negate=negate) + assert not negate == yes_restrict.match(7) + assert negate == no_restrict.match(7) + for restrict in yes_restrict, no_restrict: + # Just check this does not raise + assert str(restrict) + assert repr(restrict) + + +class AnyMatchTest(TestCase): + + # Most of AnyMatch is tested through test_restriction. + + def test_force(self): + restrict = values.AnyMatch(values.AlwaysTrue) + assert restrict.force_True(None, None, list(range(2))) + assert not restrict.force_False(None, None, list(range(2))) |