Exemple #1
0
def test_dict_specializers(polar, qvar, qeval, query):
    class Animal:
        def __init__(self, species=None, genus=None, family=None):
            self.genus = genus
            self.species = species

    polar.register_class(Animal)

    rules = """
    what_is(_: {genus: "canis"}, res) if res = "canine";
    what_is(_: {species: "canis lupus", genus: "canis"}, res) if res = "wolf";
    what_is(_: {species: "canis familiaris", genus: "canis"}, res) if res = "dog";
    """
    polar.load_str(rules)

    wolf = 'new Animal(species: "canis lupus", genus: "canis", family: "canidae")'
    dog = 'new Animal(species: "canis familiaris", genus: "canis", family: "canidae")'
    canine = 'new Animal(genus: "canis", family: "canidae")'

    assert len(query(f"what_is({wolf}, res)")) == 2
    assert len(query(f"what_is({dog}, res)")) == 2
    assert len(query(f"what_is({canine}, res)")) == 1

    assert qvar(f"what_is({wolf}, res)", "res") == ["wolf", "canine"]
    assert qvar(f"what_is({dog}, res)", "res") == ["dog", "canine"]
    assert qvar(f"what_is({canine}, res)", "res") == ["canine"]
Exemple #2
0
def test_anything_works(polar, query):
    polar.load_str("f(1);")
    results = query("f(x)")
    assert results[0]["x"] == 1

    results = query("f(y)")
    assert results[0]["y"] == 1
Exemple #3
0
def test_instance_from_external_call(polar, load_policy, query):
    user = Actor(name="guest")
    resource = Widget(id="1", name="name")
    assert query(Predicate(name="allow", args=[user, "frob", resource]))

    resource = Widget(id="2", name="name")
    assert not query(Predicate(name="allow", args=[user, "frob", resource]))
Exemple #4
0
def test_class_specializers(polar, qvar, qeval, query):
    class A:
        def a(self):
            return "A"

        def x(self):
            return "A"

    class B(A):
        def b(self):
            return "B"

        def x(self):
            return "B"

    class C(B):
        def c(self):
            return "C"

        def x(self):
            return "C"

    class X:
        def x(self):
            return "X"

    polar.register_class(A)
    polar.register_class(B)
    polar.register_class(C)
    polar.register_class(X)

    rules = """
    test(_: A);
    test(_: B);

    try(_: B, res) if res = 2;
    try(_: C, res) if res = 3;
    try(_: A, res) if res = 1;
    """
    polar.load_str(rules)

    assert qvar("new A().a() = x", "x", one=True) == "A"
    assert qvar("new A().x() = x", "x", one=True) == "A"
    assert qvar("new B().a() = x", "x", one=True) == "A"
    assert qvar("new B().b() = x", "x", one=True) == "B"
    assert qvar("new B().x() = x", "x", one=True) == "B"
    assert qvar("new C().a() = x", "x", one=True) == "A"
    assert qvar("new C().b() = x", "x", one=True) == "B"
    assert qvar("new C().c() = x", "x", one=True) == "C"
    assert qvar("new C().x() = x", "x", one=True) == "C"
    assert qvar("new X().x() = x", "x", one=True) == "X"

    assert len(query("test(new A())")) == 1
    assert len(query("test(new B())")) == 2

    assert qvar("try(new A(), x)", "x") == [1]
    assert qvar("try(new B(), x)", "x") == [2, 1]
    assert qvar("try(new C(), x)", "x") == [3, 2, 1]
    assert qvar("try(new X(), x)", "x") == []
Exemple #5
0
def test_class_specializers(polar, qvar, qeval, query):
    class A:
        def a(self):
            return "A"

        def x(self):
            return "A"

    class B(A):
        def b(self):
            return "B"

        def x(self):
            return "B"

    class C(B):
        def c(self):
            return "C"

        def x(self):
            return "C"

    class X:
        def x(self):
            return "X"

    polar.register_class(A)
    polar.register_class(B)
    polar.register_class(C)
    polar.register_class(X)

    rules = """
    test(_: A{});
    test(_: B{});

    try(_: B{}, res) if res = 2;
    try(_: C{}, res) if res = 3;
    try(_: A{}, res) if res = 1;
    """
    polar.load_str(rules)

    assert qvar("new A{}.a = x", "x", one=True) == "A"
    assert qvar("new A{}.x = x", "x", one=True) == "A"
    assert qvar("new B{}.a = x", "x", one=True) == "A"
    assert qvar("new B{}.b = x", "x", one=True) == "B"
    assert qvar("new B{}.x = x", "x", one=True) == "B"
    assert qvar("new C{}.a = x", "x", one=True) == "A"
    assert qvar("new C{}.b = x", "x", one=True) == "B"
    assert qvar("new C{}.c = x", "x", one=True) == "C"
    assert qvar("new C{}.x = x", "x", one=True) == "C"
    assert qvar("new X{}.x = x", "x", one=True) == "X"

    assert len(query("test(new A{})")) == 1
    assert len(query("test(new B{})")) == 2

    assert qvar("try(new A{}, x)", "x") == [1]
    assert qvar("try(new B{}, x)", "x") == [2, 1]
    assert qvar("try(new C{}, x)", "x") == [3, 2, 1]
    assert qvar("try(new X{}, x)", "x") == []
Exemple #6
0
def test_instance_initialization(polar, query, qvar):
    # test round trip through kb query
    user = Actor("sam")
    env = query('new Actor{name:"sam"} = returned_user')[0]
    assert polar.host.to_python(env["returned_user"]) == user

    env = query('new Actor(name:"sam") = returned_user')[0]
    assert polar.host.to_python(env["returned_user"]) == user
Exemple #7
0
def test_is_allowed(polar, load_policy, query):
    actor = Actor(name="guest")
    resource = Widget(id="1")
    action = "get"
    assert query(Predicate(name="allow", args=[actor, action, resource]))
    actor = Actor(name="president")
    assert query(Predicate(name="actorInRole", args=[actor, "admin", resource]))
    assert query(Predicate(name="allowRole", args=["admin", "create", resource]))
Exemple #8
0
def test_cut(polar, load_policy, query):
    set_frobbed([])
    actor = Actor(name="guest")
    resource = Widget(id="1")
    action = "get"
    assert query(Predicate(name="allow_with_cut", args=[actor, action, resource]))
    assert get_frobbed() == ["Widget"]
    set_frobbed([])
    resource = DooDad(id="2")
    assert query(Predicate(name="allow_with_cut", args=[actor, action, resource]))
    assert get_frobbed() == ["DooDad"]
Exemple #9
0
def test_clear_rules(polar, query):
    class Test:
        pass

    polar.register_class(Test)
    polar.load_str("f(x) if x = 1;")
    assert len(query("f(1)")) == 1
    assert len(query("x = new Test()")) == 1
    polar.clear_rules()
    assert len(query("f(1)")) == 0
    assert len(query("x = new Test()")) == 1
Exemple #10
0
def test_lookup_errors(polar, query):
    class Foo:
        def foo(self):
            return "foo"

    polar.register_class(Foo)

    # Unify with an invalid field doesn't error.
    assert query('new Foo() = {bar: "bar"}') == []
    # Dot op with an invalid field does error.
    with pytest.raises(exceptions.PolarRuntimeError) as e:
        query('new Foo().bar = "bar"') == []
    assert "Application error: 'Foo' object has no attribute 'bar'" in str(e.value)
Exemple #11
0
def test_method_resolution_order(polar, load_policy, query):
    set_frobbed([])
    actor = Actor(name="guest")
    resource = Widget(id="1")
    action = "get"
    assert query(Predicate(name="allow", args=[actor, action, resource]))
    assert get_frobbed() == ["Widget"]

    # DooDad is a Widget
    set_frobbed([])
    resource = DooDad(id="2")
    assert query(Predicate(name="allow", args=[actor, action, resource]))
    assert get_frobbed() == ["DooDad", "Widget"]
Exemple #12
0
def test_patching(polar, widget_in_company, actor_in_role, load_policy, query):
    user = Actor("test")
    assert not query(
        Predicate(name="actorInRole", args=[user, "admin",
                                            Widget(id="1")]))
    with widget_in_company:
        with actor_in_role("admin"):
            assert query(
                Predicate(name="actorInRole",
                          args=[user, "admin", Widget(id="1")]))
    assert not query(
        Predicate(name="actorInRole", args=[user, "admin",
                                            Widget(id="1")]))
Exemple #13
0
def test_querystring_resource_map(polar, load_policy, query):
    assert query(
        Predicate(
            name="allow",
            args=[
                Actor(name="sam"),
                "what",
                Http(path="/widget/12", query={"param": "foo"}),
            ],
        ))
    assert not query(
        Predicate(name="allow",
                  args=[Actor(name="sam"), "what",
                        Http(path="/widget/12")]))
Exemple #14
0
def test_runtime_errors(polar, query):
    rules = """
    foo(a,b) if a in b;
    """
    polar.load_str(rules)
    with pytest.raises(exceptions.PolarRuntimeException) as e:
        query("foo(1,2)")
    assert (str(e.value) == """trace (most recent evaluation last):
  in query at line 1, column 1
    foo(1,2)
  in rule foo at line 2, column 17
    a in b
Type error: can only use `in` on a list, this is Variable(Symbol("_a_3")) at line 2, column 17"""
            )
Exemple #15
0
def test_clear(polar, load_policy, query):
    old = Path(__file__).parent / "policies" / "load.pol"
    fails = Path(__file__).parent / "policies" / "reload_fail.pol"
    new = Path(__file__).parent / "policies" / "reload.pol"

    polar.clear()
    polar.load_file(old)

    actor = Actor(name="milton", id=1)
    resource = Widget(id=1, name="thingy")
    assert query(Predicate(name="allow", args=[actor, "make", resource]))
    assert query(Predicate(name="allow", args=[actor, "get", resource]))
    assert query(Predicate(name="allow", args=[actor, "edit", resource]))
    assert query(Predicate(name="allow", args=[actor, "delete", resource]))

    # raises exception because new policy file specifies on a class defined in the old file,
    # but not in the new file
    polar.clear()
    with pytest.raises(PolarRuntimeException):
        polar.load_file(fails)

    polar.clear()
    polar.load_file(new)
    assert query(Predicate(name="allow", args=[actor, "make", resource]))
    assert not query(Predicate(name="allow", args=[actor, "get", resource]))
    assert not query(Predicate(name="allow", args=[actor, "edit", resource]))
    assert not query(Predicate(name="allow", args=[actor, "delete", resource]))
Exemple #16
0
def test_class_field_specializers(polar, qvar, qeval, query):
    class Animal:
        def __init__(self, species=None, genus=None, family=None):
            self.genus = genus
            self.species = species
            self.family = family

    polar.register_class(Animal)

    rules = """
    what_is(_: Animal, res) if res = "animal";
    what_is(_: Animal{genus: "canis"}, res) if res = "canine";
    what_is(_: Animal{family: "canidae"}, res) if res = "canid";
    what_is(_: Animal{species: "canis lupus", genus: "canis"}, res) if res = "wolf";
    what_is(_: Animal{species: "canis familiaris", genus: "canis"}, res) if res = "dog";
    what_is(_: Animal{species: s, genus: "canis"}, res) if res = s;
    """
    polar.load_str(rules)

    wolf = 'new Animal(species: "canis lupus", genus: "canis", family: "canidae")'
    dog = 'new Animal(species: "canis familiaris", genus: "canis", family: "canidae")'
    canine = 'new Animal(genus: "canis", family: "canidae")'
    canid = 'new Animal(family: "canidae")'
    animal = "new Animal()"

    assert len(query(f"what_is({wolf}, res)")) == 5
    assert len(query(f"what_is({dog}, res)")) == 5
    assert len(query(f"what_is({canine}, res)")) == 4
    assert len(query(f"what_is({canid}, res)")) == 2
    assert len(query(f"what_is({animal}, res)")) == 1

    assert qvar(f"what_is({wolf}, res)", "res") == [
        "wolf",
        "canis lupus",
        "canine",
        "canid",
        "animal",
    ]
    assert qvar(f"what_is({dog}, res)", "res") == [
        "dog",
        "canis familiaris",
        "canine",
        "canid",
        "animal",
    ]
    assert qvar(f"what_is({canine}, res)",
                "res") == [None, "canine", "canid", "animal"]
    assert qvar(f"what_is({canid}, res)", "res") == ["canid", "animal"]
    assert qvar(f"what_is({animal}, res)", "res") == ["animal"]
Exemple #17
0
def test_runtime_errors(polar, query):
    rules = """
    foo(a,b) if a in b;
    """
    polar.load_str(rules)
    with pytest.raises(exceptions.PolarRuntimeError) as e:
        query("foo(1,2)")
    assert (
        str(e.value)
        == """trace (most recent evaluation last):
  in query at line 1, column 1
    foo(1,2)
  in rule foo at line 2, column 17
    a in b
Type error: can only use `in` on an iterable value, this is Number(Integer(2)) at line 1, column 7"""
    )
Exemple #18
0
 def create_widget():
     if not query(
         Predicate(
             name="allow",
             args=[g.user, request.method.lower(), Http(path=request.path)],
         )
     ):
         return Response("Denied", status=403)
     return Response("Ok", status=204)
Exemple #19
0
def test_unbound_variable(polar, query):
    """Test that unbound variable is returned."""
    polar.load_str("rule(x, y) if y = 1;")

    first = query("rule(x, y)")[0]

    # y will be bound to 1
    first["y"] = 1

    # x should be unbound
    assert isinstance(first["x"], Variable)
Exemple #20
0
def test_query(load_file, polar, query):
    """Test that queries work with variable arguments"""

    load_file(Path(__file__).parent / "test_file.polar")
    # plaintext polar query: query("f(x)") == [{"x": 1}, {"x": 2}, {"x": 3}]

    assert query(Predicate(name="f", args=[Variable("a")])) == [
        {"a": 1},
        {"a": 2},
        {"a": 3},
    ]
Exemple #21
0
def test_return_list(polar, query):
    class User:
        def groups(self):
            return ["engineering", "social", "admin"]

    polar.register_class(User)

    # for testing lists
    polar.load_str('allow(actor: User, "join", "party") if "social" in actor.groups();')

    assert query(Predicate(name="allow", args=[User(), "join", "party"]))
Exemple #22
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]
Exemple #23
0
def test_datetime(polar, query):
    # test datetime comparison
    t1 = datetime(2020, 5, 25)
    t2 = datetime.now()
    t3 = datetime(2030, 5, 25)
    t4 = datetime(2020, 5, 26)

    polar.load_str("lt(a, b) if a < b;")
    assert query(Predicate("lt", [t1, t2]))
    assert not query(Predicate("lt", [t2, t1]))

    # test creating datetime from polar
    polar.load_str("dt(x) if x = new Datetime(year: 2020, month: 5, day: 25);")
    assert query(Predicate("dt", [Variable("x")])) == [{
        "x":
        datetime(2020, 5, 25)
    }]
    polar.load_str("ltnow(x) if x < Datetime.now();")
    assert query(Predicate("ltnow", [t1]))
    assert not query(Predicate("ltnow", [t3]))

    polar.load_str(
        "timedelta(a: Datetime, b: Datetime) if a.__sub__(b) == new Timedelta(days: 1);"
    )
    assert query(Predicate("timedelta", [t4, t1]))
Exemple #24
0
def test_external_op(polar, query):
    class A:
        def __init__(self, a):
            self.a = a

        def __gt__(self, other):
            return self.a > other.a

        def __lt__(self, other):
            return self.a < other.a

        def __eq__(self, other):
            return self.a == other.a

    polar.register_class(A)

    a1 = A(1)
    a2 = A(2)

    polar.load_str("lt(a, b) if a < b;")
    polar.load_str("gt(a, b) if a > b;")
    assert query(Predicate("lt", [a1, a2]))
    assert not query(Predicate("lt", [a2, a1]))
    assert query(Predicate("gt", [a2, a1]))
Exemple #25
0
def test_load_function(polar, query, qvar):
    """Make sure the load function works."""
    # Loading the same file twice doesn't mess stuff up.
    polar.load_file(Path(__file__).parent / "test_file.polar")
    with pytest.raises(exceptions.PolarRuntimeException) as e:
        polar.load_file(Path(__file__).parent / "test_file.polar")
    assert (
        str(e.value) ==
        f"Problem loading file: File {Path(__file__).parent}/test_file.polar has already been loaded."
    )
    with pytest.raises(exceptions.PolarRuntimeException) as e:
        polar.load_file(Path(__file__).parent / "test_file_renamed.polar")
    assert (
        str(e.value) ==
        f"Problem loading file: A file with the same contents as {Path(__file__).parent}/test_file_renamed.polar named {Path(__file__).parent}/test_file.polar has already been loaded."
    )
    assert query("f(x)") == [{"x": 1}, {"x": 2}, {"x": 3}]
    assert qvar("f(x)", "x") == [1, 2, 3]

    polar.clear()
    polar.load_file(Path(__file__).parent / "test_file.polar")
    polar.load_file(Path(__file__).parent / "test_file_gx.polar")
    assert query("f(x)") == [{"x": 1}, {"x": 2}, {"x": 3}]
    assert query("g(x)") == [{"x": 1}, {"x": 2}, {"x": 3}]
Exemple #26
0
def test_instance_cache(polar, qeval, query):
    class Counter:
        count = 0

        def __init__(self):
            self.__class__.count += 1

    polar.register_class(Counter)
    polar.load_str("f(c: Counter) if c.count > 0;")

    assert Counter.count == 0
    c = Counter()
    assert Counter.count == 1
    assert query(Predicate(name="f", args=[c]))
    assert Counter.count == 1
    assert c not in polar.host.instances.values()
Exemple #27
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")
Exemple #28
0
def test_register_class(polar, load_policy, query):
    actor = Actor(name="guest")
    resource = Widget(id="1")
    action = "get"
    assert query(Predicate(name="allow", args=(actor, action, resource)))
Exemple #29
0
def test_iter_fields(polar, load_policy, query):
    resource = Widget(id=1, name="stapler")
    actor = Actor(name="milton", id=1)
    assert query(Predicate(name="allow", args=[actor, "can_have", resource]))
Exemple #30
0
def test_type_fields(polar, load_policy, query):
    resource = Widget(id=1, name="goldfish")
    actor = Actor(name="elmo", id=1, widget=resource)
    assert query(Predicate(name="allow", args=[actor, "keep", resource]))