1import pytest
2
3from stix2patterns.inspector import INDEX_STAR
4from stix2patterns.v20.pattern import Pattern
5
6
7@pytest.mark.parametrize(u"pattern,expected_qualifiers", [
8    (u"[foo:bar = 1]", set()),
9    (u"[foo:bar = 1] REPEATS 5 TIMES", set([u"REPEATS 5 TIMES"])),
10    (u"[foo:bar = 1] WITHIN 10.3 SECONDS", set([u"WITHIN 10.3 SECONDS"])),
11    (u"[foo:bar = 1] WITHIN 123 SECONDS", set([u"WITHIN 123 SECONDS"])),
12    (u"[foo:bar = 1] START '1932-11-12T15:42:15Z' STOP '1964-10-53T21:12:26Z'",
13        set([u"START '1932-11-12T15:42:15Z' STOP '1964-10-53T21:12:26Z'"])),
14    (u"[foo:bar = 1] REPEATS 1 TIMES REPEATS 2 TIMES",
15        set([u"REPEATS 1 TIMES", u"REPEATS 2 TIMES"])),
16    (u"[foo:bar = 1] REPEATS 1 TIMES AND [foo:baz = 2] WITHIN 1.23 SECONDS",
17        set([u"REPEATS 1 TIMES", u"WITHIN 1.23 SECONDS"])),
18    (u"([foo:bar = 1] START '1932-11-12T15:42:15Z' STOP '1964-10-53T21:12:26Z' AND [foo:abc < h'12ab']) WITHIN 22 SECONDS "
19     u"OR [frob:baz NOT IN (1,2,3)] REPEATS 31 TIMES",
20        set([u"START '1932-11-12T15:42:15Z' STOP '1964-10-53T21:12:26Z'",
21            u"WITHIN 22 SECONDS", u"REPEATS 31 TIMES"]))
22])
23def test_qualifiers(pattern, expected_qualifiers):
24    compiled_pattern = Pattern(pattern)
25    pattern_data = compiled_pattern.inspect()
26
27    assert pattern_data.qualifiers == expected_qualifiers
28
29
30@pytest.mark.parametrize(u"pattern,expected_obs_ops", [
31    (u"[foo:bar = 1]", set()),
32    (u"[foo:bar = 1] AND [foo:baz > 25.2]", set([u"AND"])),
33    (u"[foo:bar = 1] OR [foo:baz != 'hello']", set([u"OR"])),
34    (u"[foo:bar = 1] FOLLOWEDBY [foo:baz IN (1,2,3)]", set([u"FOLLOWEDBY"])),
35    (u"[foo:bar = 1] AND [foo:baz = 22] OR [foo:abc = '123']", set([u"AND", u"OR"])),
36    (u"[foo:bar = 1] OR ([foo:baz = false] FOLLOWEDBY [frob:abc LIKE '123']) WITHIN 46.1 SECONDS",
37        set([u"OR", u"FOLLOWEDBY"]))
38])
39def test_observation_ops(pattern, expected_obs_ops):
40    compiled_pattern = Pattern(pattern)
41    pattern_data = compiled_pattern.inspect()
42
43    assert pattern_data.observation_ops == expected_obs_ops
44
45
46@pytest.mark.parametrize(u"pattern,expected_comparisons", [
47    (u"[foo:bar = 1]", {u"foo": [([u"bar"], u"=", u"1")]}),
48    (u"[foo:bar=1 AND foo:baz=2]", {u"foo": [([u"bar"], u"=", u"1"), ([u"baz"], u"=", u"2")]}),
49    (u"[foo:bar NOT !=1 OR bar:foo<12.3]", {
50        u"foo": [([u"bar"], u"NOT !=", u"1")],
51        u"bar": [([u"foo"], u"<", u"12.3")]
52    }),
53    (u"[foo:bar=1] OR [foo:baz MATCHES '123\\\\d+']", {
54        u"foo": [([u"bar"], u"=", u"1"), ([u"baz"], u"MATCHES", u"'123\\\\d+'")]
55    }),
56    (u"[foo:bar=1 AND bar:foo NOT >33] REPEATS 12 TIMES OR "
57     u"  ([baz:bar ISSUBSET '1234'] FOLLOWEDBY [baz:quux NOT LIKE 'a_cd'])",
58     {
59         u"foo": [([u"bar"], u"=", u"1")],
60         u"bar": [([u"foo"], u"NOT >", u"33")],
61         u"baz": [([u"bar"], u"ISSUBSET", u"'1234'"), ([u"quux"], u"NOT LIKE", u"'a_cd'")]
62     }),
63    (u"[obj-type:a.b[*][1].'c-d' NOT ISSUPERSET '1.2.3.4/16']", {
64        u"obj-type": [([u"a", u"b", INDEX_STAR, 1, u"c-d"], u"NOT ISSUPERSET", u"'1.2.3.4/16'")]
65    }),
66])
67def test_comparisons(pattern, expected_comparisons):
68    compiled_pattern = Pattern(pattern)
69    pattern_data = compiled_pattern.inspect()
70
71    assert pattern_data.comparisons == expected_comparisons
72