예제 #1
0
def test_nested_matches(qeval, qvar, externals):
    assert qeval(
        "new MyClass(x: new MyClass(x: 1, y: 2), y: 2) matches MyClass{x: MyClass{x: 1}}"
    )
    assert not qeval(
        "new MyClass(x: new MyClass(x: 1), y: 2) matches MyClass{x: MyClass{y: 2}}"
    )
예제 #2
0
def test_argument_patterns(tell, qeval, qvar, externals):
    tell("matchesFoo(name, foo: Foo) if name = foo.name")

    assert qeval('matchesFoo(sam, new Foo(name: "sam"))')
    assert qeval('matchesFoo(sam, new Bar(name: "sam"))')
    assert not qeval('matchesFoo("alex", new Foo(name: "sam"))')
    assert not qeval('matchesFoo("alex", new Bar(name: "sam"))')
    assert not qeval('matchesFoo("alex", new Qux())')
예제 #3
0
def test_rule_ordering(tell, qeval, externals):
    tell("f(_: Foo{}) if cut and 1 = 2;")
    tell('f(_: Foo{name: "test"});')

    assert qeval('f(new Foo( name: "test" )) ')
    assert qeval('x = new Foo( name: "test" ) and f(x) ')
    assert not qeval('f(new Foo( name: "nope" )) ')
    assert not qeval('x = new Foo( name: "nope" ) and f(x) ')
예제 #4
0
def test_groups(load_file, qeval, query):
    # Contains test queries.
    load_file(Path(__file__).parent / "policies/groups.pol")

    # Check that we can't instantiate groups.
    with pytest.raises(PolarRuntimeException):
        qeval("G{}")

    # Test rule ordering with groups.
    results = query("check_order(A{}, action)")
    expected = ["A", "G", "H"]
    assert expected == [result["action"] for result in results]
예제 #5
0
def test_comparisons(tell, qeval, qvar, query):
    assert qeval("3 == 3")
    assert qeval("3 != 2")
    assert qeval("2 <= 2")
    assert qeval("2 <= 3")
    assert qeval("2 < 3")
    assert qeval("3 >= 3")
    assert qeval("3 >= 2")
    assert qeval("3 > 2")
    assert qeval("x = 1 and x == 1")
예제 #6
0
def test_iterators(polar, qeval, qvar):
    class Foo:
        pass

    polar.register_class(Foo)
    with pytest.raises(exceptions.InvalidIteratorError) as e:
        qeval("x in new Foo()")

    class Bar(list):
        def sum(self):
            return sum(x for x in self)

    polar.register_class(Bar)
    assert qvar("x in new Bar([1, 2, 3])", "x") == [1, 2, 3]
    assert qvar("x = new Bar([1, 2, 3]).sum()", "x", one=True) == 6
예제 #7
0
def test_numbers_from_external_call(polar, qeval, qvar, query):
    class Numberer:
        def give_me_an_int(self):
            yield 1

        def give_me_a_float(self):
            yield 1.234

    polar.register_class(Numberer)

    result = qvar("new Numberer().give_me_an_int() = var", "var", one=True)
    assert result == 1
    assert qeval("new Numberer().give_me_an_int() = 1")

    result = qvar("new Numberer().give_me_a_float() = var", "var", one=True)
    assert result == 1.234
    assert qeval("new Numberer().give_me_a_float() = 1.234")
예제 #8
0
def test_inf_nan(polar, qeval, query):
    polar.register_constant("inf", inf)
    polar.register_constant("neg_inf", -inf)
    polar.register_constant("nan", nan)

    assert isnan(query("x = nan")[0]["x"])
    assert not query("nan = nan")

    assert query("x = inf")[0]["x"] == inf
    assert qeval("inf = inf")

    assert query("x = neg_inf")[0]["x"] == -inf
    assert qeval("neg_inf = neg_inf")

    assert not query("inf = neg_inf")
    assert not query("inf < neg_inf")
    assert qeval("neg_inf < inf")
예제 #9
0
def test_bool_from_external_call(polar, qeval, qvar, query):
    class Booler:
        def whats_up(self):
            yield True

    polar.register_class(Booler)

    result = qvar("new Booler().whats_up() = var", "var", one=True)
    assert qeval("new Booler().whats_up()")
예제 #10
0
def test_external(polar, qvar, qeval):
    class Bar:
        def y(self):
            return "y"

    class Foo:
        def __init__(self, a="a"):
            self.a = a

        def b(self):
            yield "b"

        @classmethod
        def c(cls):
            assert issubclass(cls, Foo)
            return "c"

        def d(self, x):
            return x

        def bar(self):
            return Bar()

        def e(self):
            return [1, 2, 3]

        def f(self):
            yield [1, 2, 3]
            yield [4, 5, 6]
            yield 7

        def g(self):
            return {"hello": "world"}

        def h(self):
            return True

    def capital_foo():
        return Foo(a="A")

    polar.register_class(Foo, from_polar=capital_foo)
    assert qvar("new Foo().a = x", "x", one=True) == "A"
    with pytest.raises(RuntimeError,
                       match="tried to call 'a' but it is not callable"):
        assert not qeval("new Foo().a() = x")
    assert not qvar("new Foo().b = x", "x", one=True) == "b"
    assert qvar("new Foo().b() = x", "x", one=True) == "b"
    assert not qvar("Foo.c = x", "x", one=True) == "c"
    assert qvar("Foo.c() = x", "x", one=True) == "c"
    assert qvar("new Foo() = f and f.a = x", "x", one=True) == "A"
    assert qvar("new Foo().bar().y() = x", "x", one=True) == "y"
    assert qvar("new Foo().e() = x", "x", one=True) == [1, 2, 3]
    assert qvar("new Foo().f() = x", "x") == [[1, 2, 3], [4, 5, 6], 7]
    assert qvar("new Foo().g().hello = x", "x", one=True) == "world"
    assert qvar("new Foo().h() = x", "x", one=True) is True
예제 #11
0
def test_class_definitions(tell, qeval, load_file):
    # Contains test queries.
    load_file(Path(__file__).parent / "policies/classes.pol")

    # Test instantiation errors.
    with pytest.raises(PolarRuntimeException):
        qeval("NotADefinedClassName{foo: 1}")
    with pytest.raises(PolarRuntimeException):
        qeval("Three{foo: One{}}")
    with pytest.raises(PolarRuntimeException):
        qeval("Three{unit: Two{}}")
    with pytest.raises(PolarRuntimeException):
        qeval("Three{unit: One{}, pair: One{}}")
예제 #12
0
def test_recursive_rule(tell, qeval, qvar):
    tell('derive("apple", "orange")')
    tell('derive("orange", "avacado")')
    tell('derive("avacado", "juniper_berry")')
    results = qvar('derive("apple", x)', "x")
    assert results == ["orange"]
    tell("derives(a, b) if derive(a, b);")
    tell("derives(a, b) if derive(a, z) and derives(z, b);")
    assert qeval('derives("apple", "juniper_berry")')
    results = qvar('derives("apple", x)', "x")
    assert results == ["orange", "avacado", "juniper_berry"]
예제 #13
0
def test_disjunctive_rule(tell, qeval):
    tell("or_eq(a, b) if 1 = 0 or a = b;")
    assert qeval("or_eq(1, 1)")

    tell("and_or_eq(a, b, c) if (a = b and b = c) or 1 = 0")
    assert not qeval("and_or_eq(1, 1, 0)")
    assert qeval("and_or_eq(1, 1, 1)")

    assert qeval("1=0 or (1=1 and 1=1)")
    assert not qeval("1=0 or (1=0 and 1=1)")

    # not sure if these test anything but :)
    assert qeval("1=0 or (1=0 or 1=1)")
    assert not qeval("1=0 or (1=0 or 1=0)")

    assert qeval("1=1 and (1=0 or 1=1)")
    assert not qeval("1=0 and (1=0 or 1=1)")
예제 #14
0
def test_keys_are_confusing(tell, qeval, qvar, externals):
    assert qeval("new MyClass(x: 1, y: 2) = new MyClass(y: 2, x: 1)")
    assert qeval("new MyClass(x: 1, y: 2) = new MyClass(x: 1, y: 2)")
    assert not qeval("new MyClass(x: 1, y: 2) = new MyClass(x: 2, y: 1)")
    assert not qeval("new MyClass(x: 1, y: 2) = new MyClass(y: 1, x: 2)")
    assert not qeval("new MyClass(x: 1) = new MyClass(x: 1, y: 2)")
    assert not qeval("new MyClass(x: 1, y: 2) = new MyClass(y: 2)")
예제 #15
0
def test_defining_things(tell, qeval):
    facts = [
        'apple("orange")',
        'thing("with", "two")',
        'thing("with", "a", "lot", "of", "arguments", 1, 2, 3, 4, 5)',
        'thing(with("nested"), "stuff")',
        "dream(within(a(dream(within(a(dream(within(a(_dream)))))))))",
        'embedded("strings")',
    ]
    for f in facts:
        tell(f)
    for f in facts:
        assert qeval(f)
예제 #16
0
def test_field_unification(qeval):
    # test dictionary field unification
    assert qeval("{} = {}")
    assert qeval("{x: 1} = {x: 1}")
    assert not qeval("{x: 1} = {x: 2}")
    assert not qeval("{x: 1} = {y: 1}")
    assert not qeval("{x: 1, y: 2} = {y: 1, x: 2}")
    assert qeval("{x: 1, y: 2} = {y: 2, x: 1}")
예제 #17
0
def test_unify(polar, qeval):
    class Foo:
        def __init__(self, foo):
            self.foo = foo

        def __eq__(self, other):
            if isinstance(other, Foo):
                return self.foo == other.foo
            return False

    polar.register_class(Foo)

    polar.load_str("foo() if new Foo(foo: 1) = new Foo(foo: 1);")
    assert qeval("foo()")
예제 #18
0
파일: test_polar.py 프로젝트: zmilan/oso
def test_dictionaries(tell, qeval, qvar):
    # basic dictionary lookup
    tell('dict({hello: "world", foo: "bar"})')
    assert qeval('dict(d) and d.hello = "world"')

    ### dictionary lookups with variable fields ###
    tell("attr(d, k, d.(k))")

    # k = "hello", {hello: "steve"}.(k) = "steve"
    assert qeval('attr({hello: "steve"}, "hello", "steve")')

    # k = "hello", {hello: "steve"}.(k) = value, value = "steve"
    assert qvar('attr({hello: "steve"}, "hello", value)', "value",
                one=True) == "steve"

    # k = key, {hello: "steve"}.(k) = "steve", key = "hello"
    assert qvar('attr({hello: "steve"}, key, "steve")', "key",
                one=True) == "hello"

    ### nested lookups ###
    assert qeval(
        'attr({hello: {this: {is: "nested"}}}, "hello", {this: {is: "nested"}})'
    )

    tell("deepget(d, d.hello.this.is)")
    assert qeval('deepget({hello: {this: {is: "nested"}}}, "nested")')

    tell("myget(d, d.get.inner)")
    assert qeval('myget({get: {inner: "nested"}}, "nested")')

    tell("x({a: {b:{c:123}}})")
    tell("x({a: {y:{c:456}}})")
    assert qvar("x(d) and d.a.(k).c = value", "value") == [123, 456]

    tell("lookup(dict, result) if result = dict.a.b.c;")
    assert qeval('lookup({a: {b: {c: "nested"}}}, "nested")')

    ### more basic lookup tests ###
    tell('user({name: "steve", job: "programmer", state: "NY"})')
    tell('user({name: "alex", job: "programmer", state: "CO"})')
    tell('user({name: "graham", job: "business", state: "NY"})')
    assert qeval('user(d) and d.name = "steve"')
    assert qvar('user({job: "programmer", name: name, state: state})',
                "name") == [
                    "steve",
                    "alex",
                ]
예제 #19
0
def test_load_file(load_file, tell, qeval, qvar):
    load_file(Path(__file__).parent / "policies/test.polar")
    assert qeval('test("true")')
    tell('b("foo")')
    assert qvar("a(x)", "x", one=True) == "foo"
예제 #20
0
def test_matches(qeval, qvar, externals):
    assert qeval("{} matches {}")
    assert qeval("{x: 1} matches {}")
    assert qeval("{x: 1} matches {x: 1}")
    assert qeval("{x: 1, y: 2} matches {x: 1}")
    assert qeval("{x: 1, y: 2} matches {x: 1, y: 2}")
    assert qeval("{a: {x: 1, y: 2}} matches {a: {y: 2}}")
    assert not qeval("{a: {x: 1, y: 2}} matches {b: {y: 2}}")
    assert not qeval("{x: 1} matches {x: 1, y: 2}")
    assert not qeval("{y: 2} matches {x: 1, y: 2}")
    assert not qeval("{} matches {x: 1, y: 2}")
    assert not qeval("{} matches {x: 1}")

    assert qeval("new MyClass(x: 1, y: 2) matches {}")
    assert qeval("new MyClass(x: 1, y: 2) matches {x: 1, y: 2}")
    assert not qeval("{x: 1, y: 2} matches MyClass{x: 1, y: 2}")

    assert qeval("new MyClass(x: 1, y: 2) matches MyClass{x: 1}")
    assert not qeval("new MyClass(y: 2) matches MyClass{x: 1, y: 2}")

    assert qeval("new OurClass(x: 1, y: 2) matches YourClass")
    assert qeval("new OurClass(x: 1, y: 2) matches MyClass{x: 1}")
    assert qeval("new OurClass(x: 1, y: 2) matches MyClass{x: 1, y: 2}")
    assert not qeval("new MyClass(x: 1, y: 2) matches OurClass{x: 1}")
    assert not qeval("new MyClass(x: 1, y: 2) matches YourClass")
    assert not qeval("new MyClass(x: 1, y: 2) matches YourClass{}")
예제 #21
0
def test_host_methods(qeval):
    assert qeval('x = "abc" and x.startswith("a") = true and x.find("bc") = 1')
    assert qeval("i = 4095 and i.bit_length() = 12")
    assert qeval('f = 3.14159 and f.hex() = "0x1.921f9f01b866ep+1"')
    assert qeval("l = [1, 2, 3] and l.index(3) = 2 and l.copy() = [1, 2, 3]")
    assert qeval('d = {a: 1} and d.get("a") = 1 and d.get("b", 2) = 2')
예제 #22
0
def test_in(polar, qeval):
    polar.load_str("g(x, y) if not x in y;")
    polar.load_str("f(x) if not (x=1 or x=2);")
    assert not qeval("f(1)")
    assert qeval("g(4, [1,2,3])")
    assert not qeval("g(1, [1,1,1])")
예제 #23
0
def test_booleans(qeval):
    assert qeval("true = true")
    assert qeval("false = false")
    assert not qeval("true = false")
예제 #24
0
def test_missing_rule(tell, qeval):
    tell("a(x) if b(x) and c(x);")
    tell('b("apple")')
    tell('c("apple")')
    assert not qeval('d("apple")')
예제 #25
0
def test_negation(tell, qeval):
    tell('b("apple")')
    assert qeval('b("apple")')
    assert not qeval('not (b("apple"))')
    assert qeval('not (b("notanapple"))')
예제 #26
0
def test_define_rule(tell, qeval):
    tell("a(x) if b(x) and c(x);")
    tell('b("apple")')
    tell('c("apple")')
    assert qeval('a("apple")')
예제 #27
0
def test_field_unification_external(qeval, externals):
    # test instance field unification
    assert qeval("new MyClass(x: 1, y: 2) = new MyClass(y: 2, x: 1)")
    assert not qeval("new MyClass(x: 1, y: 2) = {y: 2, x: 1}")
    assert qeval("new MyClass(x: 1, y: 2) = new OurClass(y: 2, x: 1)")
예제 #28
0
def test_external_classes(tell, qeval, qvar, externals):
    assert qeval("new Bar() matches Foo")
    assert not qeval("new Qux() matches Foo")
    assert qeval('new Foo().foo() = "Foo!"')
    assert qeval('new Bar().foo() = "Bar!"')
예제 #29
0
def test_arities(tell, qeval):
    tell("f(1);")
    tell("f(x, y);")
    assert qeval("f(1)")
    assert not qeval("f(2)")
    assert qeval("f(2, 3)")
예제 #30
0
def test_unify_class_fields(tell, qeval, qvar, externals):
    tell("check(name, new Foo(name: name))")

    assert qeval('check("sam", new Foo(name: "sam"))')
    assert not qeval('check("alex", new Foo(name: "sam"))')