예제 #1
0
def test_combine() -> None:
    query1 = Query.by(P("test") == True).traverse_out().combine(
        Query.by("foo")).combine(Query.by("bla"))
    assert str(query1) == 'test == true -default-> (is("foo") and is("bla"))'
    query2 = (Query.by(P("test") == True).traverse_out().combine(
        Query.by("foo").traverse_out()).combine(
            Query.by("bla").traverse_out()))
    assert str(
        query2
    ) == 'test == true -default-> is("foo") -default-> is("bla") -default->'
    query3 = (Query.by(P("test") == True).traverse_out().filter(
        "boo").traverse_out().filter("bar").combine(Query.by("foo")).combine(
            Query.by("bla")))
    assert str(
        query3
    ) == 'test == true -default-> is("boo") -default-> ((is("bar") and is("foo")) and is("bla"))'
    query4 = Query.by("a").with_limit(10).combine(Query.by("b").with_limit(2))
    assert query4.current_part.limit == Limit(0, 2)  # minimum is taken
    with pytest.raises(AttributeError):
        # can not combine 2 aggregations
        parse_query("aggregate(sum(1)): is(a)").combine(
            parse_query("aggregate(sum(1)): is(a)"))
    with pytest.raises(AttributeError):
        # can not combine 2 with statements
        parse_query("is(foo) with(empty, -default->)").combine(
            parse_query("is(bla) with(empty, -default->)"))
예제 #2
0
def test_not() -> None:
    assert_round_trip(not_term,
                      (P.with_id("foo") | P.of_kind("bla")).not_term())
    assert_round_trip(not_term, P.of_kind("bla").not_term())
    assert_round_trip(
        not_term,
        term_parser.parse(
            "not(is(a) or not is(b) and not a>1 or not b<2 or not(a>1))"))
예제 #3
0
def test_not() -> None:
    assert_round_trip(not_term,
                      (P.with_id("foo") | P.of_kind("bla")).not_term())
    assert_round_trip(not_term, P.of_kind("bla").not_term())
    assert_round_trip(
        not_term,
        term_parser.parse(
            "not(is(a) or not is(b) and not a>1 or not b<2 or not(a>1))"))
    # make sure not only negates the simple term, not the combined term
    assert term_parser.parse("not a==b and b==c") == CombinedTerm(
        NotTerm(P("a") == "b"), "and",
        P("b") == "c")
예제 #4
0
def test_filter_term() -> None:
    assert_round_trip(term_parser, P("mem") < 23)
    assert_round_trip(term_parser, P.with_id("foo"))
    assert_round_trip(term_parser, P.of_kind("foo"))
    assert_round_trip(term_parser, P.of_kind("foo") | P.of_kind("bla"))
    assert_round_trip(
        term_parser,
        ((P.of_kind("foo") | P.of_kind("bla")) & (P("a") > 23)) &
        (P("b").is_in([1, 2, 3])) & (P("c") == {
            "a": 123
        }),
    )
예제 #5
0
def test_function() -> None:
    assert_round_trip(function_term,
                      P.function("in_subnet").on("foo.bla.bar", 1, "2", True))
    assert_round_trip(function_term,
                      P.function("in_subnet").on("foo.bla.bar", "in_subnet"))
    assert_round_trip(
        function_term,
        P.function("in_subnet").on("foo.bla.bar", "in_subnet", "1000"))
    assert_round_trip(function_term,
                      P.function("has_key").on("foo.bla.bar", "a", "b", "c"))
    assert_round_trip(function_term,
                      P.function("has_key").on("foo.bla.bar", "a"))
예제 #6
0
async def test_query_list(filled_graph_db: ArangoGraphDB,
                          foo_model: Model) -> None:
    blas = Query.by("foo",
                    P("identifier") == "9").traverse_out().filter(
                        "bla",
                        P("f") == 23)
    async with await filled_graph_db.search_list(
            QueryModel(blas.on_section("reported"), foo_model)) as gen:
        result = [from_js(x["reported"], Bla) async for x in gen]
        assert len(result) == 10

    foos_or_blas = parse_query("is([foo, bla])")
    async with await filled_graph_db.search_list(
            QueryModel(foos_or_blas.on_section("reported"), foo_model)) as gen:
        result = [x async for x in gen]
        assert len(result) == 111  # 113 minus 1 graph_root, minus one cloud
예제 #7
0
async def load_graph(db: GraphDB,
                     model: Model,
                     base_id: str = "sub_root") -> MultiDiGraph:
    blas = Query.by("foo",
                    P("identifier") == base_id).traverse_out(
                        0, Navigation.Max)
    return await db.search_graph(QueryModel(blas.on_section("reported"),
                                            model))
예제 #8
0
def test_simplify() -> None:
    # some_criteria | all => all
    assert str((IsTerm(["test"]) | AllTerm())) == "all"
    # some_criteria & all => some_criteria
    assert str((IsTerm(["test"]) & AllTerm())) == 'is("test")'
    # also works in nested setup
    q = Query.by(AllTerm() & ((P("test") == True) & (IsTerm(["test"]) | AllTerm())))
    assert (str(q)) == "test == true"
예제 #9
0
def test_query() -> None:
    query = (Query.by(
        "ec2",
        P("cpu") > 4, (P("mem") < 23) | (P("mem") < 59)).merge_with(
            "cloud", Navigation(1, Navigation.Max,
                                direction=Direction.inbound),
            Query.mk_term("cloud")).traverse_out().filter(
                P("some.int.value") < 1,
                P("some.other") == 23).traverse_out().filter(
                    P("active") == 12,
                    P.function("in_subnet").on(
                        "ip", "1.2.3.4/96")).filter_with(
                            WithClause(WithClauseFilter(
                                "==", 0), Navigation())).group_by([
                                    AggregateVariable(
                                        AggregateVariableName("foo"))
                                ], [AggregateFunction("sum", "cpu")]).add_sort(
                                    Sort("test", "asc")).with_limit(10))
    assert str(query) == (
        'aggregate(foo: sum(cpu)):((is("ec2") and cpu > 4) and (mem < 23 or mem < 59)) '
        '{cloud: all <-default[1:]- is("cloud")} -default-> '
        "(some.int.value < 1 and some.other == 23) -default-> "
        '(active == 12 and in_subnet(ip, "1.2.3.4/96")) '
        "with(empty, -default->) sort test asc limit 10")
    assert_round_trip(query_parser, query)
예제 #10
0
def test_part() -> None:
    assert_round_trip(part_parser, Part(P.of_kind("test")))
    assert_round_trip(
        part_parser,
        Part(P.of_kind("test"),
             navigation=Navigation(1, 10, [EdgeType.delete])))
    assert_round_trip(
        part_parser,
        Part(P.of_kind("test"),
             "red",
             navigation=Navigation(1, 10, [EdgeType.delete])))
    with_clause = WithClause(WithClauseFilter("==", 0),
                             Navigation(maybe_edge_types=[EdgeType.delete]))
    assert_round_trip(
        part_parser,
        Part(P.of_kind("test"),
             "green",
             with_clause,
             navigation=Navigation(1, 10, [EdgeType.delete])))
예제 #11
0
def test_simple_query() -> None:
    a = (Query.by("ec2",
                  P("cpu") > 4,
                  (P("mem") < 23) | (P("mem") < 59)).traverse_out().filter(
                      P("some.int.value") < 1,
                      P("some.other") == 23).traverse_out().filter(
                          P("active") == 12,
                          P.function("in_subnet").on("ip", "1.2.3.4/32")))

    assert (str(a) ==
            '((is("ec2") and cpu > 4) and (mem < 23 or mem < 59)) -default-> '
            "(some.int.value < 1 and some.other == 23) -default-> "
            '(active == 12 and in_subnet(ip, "1.2.3.4/32"))')
예제 #12
0
async def test_query_graph(filled_graph_db: ArangoGraphDB,
                           foo_model: Model) -> None:
    graph = await load_graph(filled_graph_db, foo_model)
    assert len(graph.edges) == 110
    assert len(graph.nodes.values()) == 111

    # filter data and tag result, and then traverse to the end of the graph in both directions
    around_me = Query.by(
        "foo",
        P("identifier") == "9").tag("red").traverse_inout(start=0)
    graph = await filled_graph_db.search_graph(
        QueryModel(around_me.on_section("reported"), foo_model))
    assert len({x for x in graph.nodes}) == 12
    assert GraphAccess.root_id(graph) == "sub_root"
    assert list(graph.successors("sub_root"))[0] == "9"
    assert set(graph.successors("9")) == {f"9_{x}" for x in range(0, 10)}
    for from_node, to_node, data in graph.edges.data(True):
        assert from_node == "9" or to_node == "9"
        assert data == {"edge_type": "default"}

    for node_id, node in graph.nodes.data(True):
        if node_id == "9":
            assert node["metadata"]["query_tag"] == "red"
        else:
            assert "tag" not in node["metadata"]

    async def assert_result(query: str, nodes: int, edges: int) -> None:
        q = parse_query(query)
        graph = await filled_graph_db.search_graph(QueryModel(q, foo_model))
        assert len(graph.nodes) == nodes
        assert len(graph.edges) == edges

    await assert_result(
        "is(foo) and reported.identifier==9 <-delete[0:]default->", 11, 20)
    await assert_result(
        "is(foo) and reported.identifier==9 <-default[0:]delete->", 4, 3)
    await assert_result("is(foo) and reported.identifier==9 <-default[0:]->",
                        14, 13)
    await assert_result("is(foo) and reported.identifier==9 <-delete[0:]->",
                        11, 10)
    await assert_result("is(foo) and reported.identifier==9 -default[0:]->",
                        11, 10)
    await assert_result("is(foo) and reported.identifier==9 <-delete[0:]-", 11,
                        10)
    await assert_result("is(foo) and reported.identifier==9 <-default[0:]-", 4,
                        3)
    await assert_result("is(foo) and reported.identifier==9 -delete[0:]->", 1,
                        0)
예제 #13
0
def test_parse_predicate_array() -> None:
    assert_round_trip(predicate_term, P.array("mem").for_any() < 23)
    assert_round_trip(predicate_term, P.array("mem").for_all() >= 23)
    assert_round_trip(predicate_term,
                      P.array("mem").for_none().matches("foo.*"))
    assert_round_trip(predicate_term,
                      P.array("num").for_any().is_in([1, 2, 5]))
    assert_round_trip(predicate_term,
                      P.array("num").for_all().is_in([1, 2, 5]))
    assert_round_trip(predicate_term,
                      P.array("num").for_none().is_in([1, 2, 5]))
예제 #14
0
def test_with_clause() -> None:
    predicate_term.parse("foo == bla")
    wc: WithClause = with_clause_parser.parse(
        "with(empty, -delete-> foo == bla and test > 23 with(any, -delete->))")
    assert wc.with_filter == WithClauseFilter("==", 0)
    assert wc.navigation == Navigation(maybe_edge_types=["delete"])
    assert str(wc.term) == '(foo == "bla" and test > 23)'
    assert str(wc.with_clause) == "with(any, -delete->)"
    term = Query.mk_term("foo", P("test") == 23)
    clause_filter = WithClauseFilter(">", 23)
    nav = Navigation()

    def edge(wc: WithClause) -> WithClause:
        wcr = replace(wc, with_clause=edge(
            wc.with_clause)) if wc.with_clause else wc
        return replace(wcr,
                       navigation=replace(wcr.navigation,
                                          maybe_edge_types=[EdgeType.default]))

    assert_round_trip(
        with_clause_parser,
        WithClause(clause_filter, nav, term, WithClause(clause_filter, nav)),
        edge)
    assert_round_trip(with_clause_parser, WithClause(clause_filter, nav), edge)
예제 #15
0
def test_query() -> None:
    query = (Query.by(
        "ec2",
        P("cpu") > 4, (P("mem") < 23) | (P("mem") < 59),
        preamble={
            "merge_with_ancestors": "cloud"
        }).traverse_out().filter(
            P("some.int.value") < 1,
            P("some.other") == 23).traverse_out().filter(
                P("active") == 12,
                P.function("in_subnet").on("ip", "1.2.3.4/96")).filter_with(
                    WithClause(WithClauseFilter(
                        "==", 0), Navigation())).group_by(
                            [AggregateVariable(AggregateVariableName("foo"))],
                            [AggregateFunction("sum", "cpu")]).add_sort(
                                "test", "asc").with_limit(10))
    assert (
        str(query) == 'aggregate(foo: sum(cpu))(merge_with_ancestors="cloud"):'
        + '((is("ec2") and cpu > 4) and (mem < 23 or mem < 59)) -default-> ' +
        "(some.int.value < 1 and some.other == 23) -default-> " +
        '(active == 12 and in_subnet(ip, "1.2.3.4/96")) ' +
        "with(empty, -default->) sort test asc limit 10")
    assert_round_trip(query_parser, query)
예제 #16
0
def test_marshal_query() -> None:
    q = Query.by("ec2", P("foo") > 23, P("test") >= "bummer", P("das") < "set")
    again = parse_query(str(q))
    assert str(q) == str(again)
예제 #17
0
def test_kind() -> None:
    assert_round_trip(is_term, P.of_kind("foo"))
예제 #18
0
def test_combined() -> None:
    assert_round_trip(combined_term, P.of_kind("foo") | P.of_kind("bla"))
예제 #19
0
def simple_reference() -> None:
    # only kind
    Query.by("ec2")

    # equality
    Query.by(P.of_kind("ec2") & (P("simple") == "hallo"))
    Query.by(P.of_kind("ec2") & (P("simple") != "hallo"))

    # regex
    Query.by(P.of_kind("ec2") & P("simple").matches("^some.regex[a-d]+$"))
    Query.by(P.of_kind("ec2") & P("simple").not_matches("^some.regex[a-d]+$"))

    # comparator
    Query.by(P.of_kind("ec2") & (P("num") > 23))
    Query.by(P.of_kind("ec2") & (P("num") >= 23))
    Query.by(P.of_kind("ec2") & (P("num") == 23))
    Query.by(P.of_kind("ec2") & (P("num") <= 23))
    Query.by(P.of_kind("ec2") & (P("num") < 23))

    # in set
    Query.by(P.of_kind("ec2") & P("num").is_in([1, 2, 5]))
    Query.by(P.of_kind("ec2") & P("num").is_not_in([1, 2, 5]))

    # array: all above operators are available
    Query.by(P.of_kind("ec2") & (P.array("some.array").for_all() > 12.23))
    Query.by(
        P.of_kind("ec2") & (P.array("some.array").for_any().is_in([1, 2, 3])))
    Query.by(P.of_kind("ec2") & (P.array("some.array").for_none() == 5))

    # call a function
    Query.by(P.function("in_subnet").on("ip", "1.2.3.4/16"))

    # refine with multiple predicates (all predicates have to match)
    Query.by(
        P.of_kind("ec2") & P("a").ge(1),
        P("b") == 2,
        P("c").matches("aaa"))
예제 #20
0
def test_parse_predicate() -> None:
    assert_round_trip(predicate_term, P("mem") < 23)
    assert_round_trip(predicate_term, P("simple") == "hallo")
    assert_round_trip(predicate_term, P("simple") != "hallo")
    assert_round_trip(predicate_term,
                      P("simple").matches("^some.regex[a-d]+$"))
    assert_round_trip(predicate_term,
                      P("simple").not_matches("^some.regex[a-d]+$"))
    assert_round_trip(predicate_term, P("num") > 23)
    assert_round_trip(predicate_term, P("num") >= 23)
    assert_round_trip(predicate_term, P("num") == 23)
    assert_round_trip(predicate_term, P("num") <= 23)
    assert_round_trip(predicate_term, P("num") < 23)
    assert_round_trip(predicate_term, P("num").is_in([1, 2, 5]))
    assert_round_trip(predicate_term, P("num").is_not_in([1, 2, 5]))