aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/store-query/src/test/java/tools
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2023-02-24 20:21:15 +0100
committerLibravatar Kristóf Marussy <kristof@marussy.com>2023-02-24 23:29:49 +0100
commitf8a3c575e400259a4985233c07b7a50e5d4d82c5 (patch)
treef5975a19fcce28eba17b5af8adde5a37ddba83c6 /subprojects/store-query/src/test/java/tools
parentrefactor: split query and partial from store (diff)
downloadrefinery-f8a3c575e400259a4985233c07b7a50e5d4d82c5.tar.gz
refinery-f8a3c575e400259a4985233c07b7a50e5d4d82c5.tar.zst
refinery-f8a3c575e400259a4985233c07b7a50e5d4d82c5.zip
feat: Dnf reduction and structural equality
Diffstat (limited to 'subprojects/store-query/src/test/java/tools')
-rw-r--r--subprojects/store-query/src/test/java/tools/refinery/store/query/DnfBuilderTest.java218
-rw-r--r--subprojects/store-query/src/test/java/tools/refinery/store/query/DnfToStringTest.java172
-rw-r--r--subprojects/store-query/src/test/java/tools/refinery/store/query/tests/StructurallyEqualToTest.java77
3 files changed, 467 insertions, 0 deletions
diff --git a/subprojects/store-query/src/test/java/tools/refinery/store/query/DnfBuilderTest.java b/subprojects/store-query/src/test/java/tools/refinery/store/query/DnfBuilderTest.java
new file mode 100644
index 00000000..e6701fe3
--- /dev/null
+++ b/subprojects/store-query/src/test/java/tools/refinery/store/query/DnfBuilderTest.java
@@ -0,0 +1,218 @@
1package tools.refinery.store.query;
2
3import org.junit.jupiter.api.Test;
4import tools.refinery.store.query.literal.BooleanLiteral;
5import tools.refinery.store.query.view.KeyOnlyRelationView;
6import tools.refinery.store.representation.Symbol;
7
8import static org.hamcrest.MatcherAssert.assertThat;
9import static tools.refinery.store.query.literal.Literals.not;
10import static tools.refinery.store.query.tests.QueryMatchers.structurallyEqualTo;
11
12class DnfBuilderTest {
13 @Test
14 void eliminateTrueTest() {
15 var p = new Variable("p");
16 var q = new Variable("q");
17 var friend = new Symbol<>("friend", 2, Boolean.class, false);
18 var friendView = new KeyOnlyRelationView<>(friend);
19
20 var actual = Dnf.builder()
21 .parameters(p, q)
22 .clause(BooleanLiteral.TRUE, friendView.call(p, q))
23 .build();
24 var expected = Dnf.builder().parameters(p, q).clause(friendView.call(p, q)).build();
25
26 assertThat(actual, structurallyEqualTo(expected));
27 }
28
29 @Test
30 void eliminateFalseTest() {
31 var p = new Variable("p");
32 var q = new Variable("q");
33 var friend = new Symbol<>("friend", 2, Boolean.class, false);
34 var friendView = new KeyOnlyRelationView<>(friend);
35
36 var actual = Dnf.builder()
37 .parameters(p, q)
38 .clause(friendView.call(p, q))
39 .clause(friendView.call(q, p), BooleanLiteral.FALSE)
40 .build();
41 var expected = Dnf.builder().parameters(p, q).clause(friendView.call(p, q)).build();
42
43 assertThat(actual, structurallyEqualTo(expected));
44 }
45
46 @Test
47 void alwaysTrueTest() {
48 var p = new Variable("p");
49 var q = new Variable("q");
50 var friend = new Symbol<>("friend", 2, Boolean.class, false);
51 var friendView = new KeyOnlyRelationView<>(friend);
52
53 var actual = Dnf.builder()
54 .parameters(p, q)
55 .clause(friendView.call(p, q))
56 .clause(BooleanLiteral.TRUE)
57 .build();
58 var expected = Dnf.builder().parameters(p, q).clause().build();
59
60 assertThat(actual, structurallyEqualTo(expected));
61 }
62
63 @Test
64 void alwaysFalseTest() {
65 var p = new Variable("p");
66 var q = new Variable("q");
67 var friend = new Symbol<>("friend", 2, Boolean.class, false);
68 var friendView = new KeyOnlyRelationView<>(friend);
69
70 var actual = Dnf.builder()
71 .parameters(p, q)
72 .clause(friendView.call(p, q), BooleanLiteral.FALSE)
73 .build();
74 var expected = Dnf.builder().parameters(p, q).build();
75
76 assertThat(actual, structurallyEqualTo(expected));
77 }
78
79 @Test
80 void eliminateTrueDnfTest() {
81 var p = new Variable("p");
82 var q = new Variable("q");
83 var friend = new Symbol<>("friend", 2, Boolean.class, false);
84 var friendView = new KeyOnlyRelationView<>(friend);
85 var trueDnf = Dnf.builder().parameter(p).clause().build();
86
87 var actual = Dnf.builder()
88 .parameters(p, q)
89 .clause(trueDnf.call(q), friendView.call(p, q))
90 .build();
91 var expected = Dnf.builder().parameters(p, q).clause(friendView.call(p, q)).build();
92
93 assertThat(actual, structurallyEqualTo(expected));
94 }
95
96 @Test
97 void eliminateFalseDnfTest() {
98 var p = new Variable("p");
99 var q = new Variable("q");
100 var friend = new Symbol<>("friend", 2, Boolean.class, false);
101 var friendView = new KeyOnlyRelationView<>(friend);
102 var falseDnf = Dnf.builder().parameter(p).build();
103
104 var actual = Dnf.builder()
105 .parameters(p, q)
106 .clause(friendView.call(p, q))
107 .clause(friendView.call(q, p), falseDnf.call(q))
108 .build();
109 var expected = Dnf.builder().parameters(p, q).clause(friendView.call(p, q)).build();
110
111 assertThat(actual, structurallyEqualTo(expected));
112 }
113
114 @Test
115 void alwaysTrueDnfTest() {
116 var p = new Variable("p");
117 var q = new Variable("q");
118 var friend = new Symbol<>("friend", 2, Boolean.class, false);
119 var friendView = new KeyOnlyRelationView<>(friend);
120 var trueDnf = Dnf.builder().parameter(p).clause().build();
121
122 var actual = Dnf.builder()
123 .parameters(p, q)
124 .clause(friendView.call(p, q))
125 .clause(trueDnf.call(q))
126 .build();
127 var expected = Dnf.builder().parameters(p, q).clause().build();
128
129 assertThat(actual, structurallyEqualTo(expected));
130 }
131
132 @Test
133 void alwaysFalseDnfTest() {
134 var p = new Variable("p");
135 var q = new Variable("q");
136 var friend = new Symbol<>("friend", 2, Boolean.class, false);
137 var friendView = new KeyOnlyRelationView<>(friend);
138 var falseDnf = Dnf.builder().parameter(p).build();
139
140 var actual = Dnf.builder()
141 .parameters(p, q)
142 .clause(friendView.call(p, q), falseDnf.call(q))
143 .build();
144 var expected = Dnf.builder().parameters(p, q).build();
145
146 assertThat(actual, structurallyEqualTo(expected));
147 }
148
149 @Test
150 void eliminateNotFalseDnfTest() {
151 var p = new Variable("p");
152 var q = new Variable("q");
153 var friend = new Symbol<>("friend", 2, Boolean.class, false);
154 var friendView = new KeyOnlyRelationView<>(friend);
155 var falseDnf = Dnf.builder().parameter(p).build();
156
157 var actual = Dnf.builder()
158 .parameters(p, q)
159 .clause(not(falseDnf.call(q)), friendView.call(p, q))
160 .build();
161 var expected = Dnf.builder().parameters(p, q).clause(friendView.call(p, q)).build();
162
163 assertThat(actual, structurallyEqualTo(expected));
164 }
165
166 @Test
167 void eliminateNotTrueDnfTest() {
168 var p = new Variable("p");
169 var q = new Variable("q");
170 var friend = new Symbol<>("friend", 2, Boolean.class, false);
171 var friendView = new KeyOnlyRelationView<>(friend);
172 var trueDnf = Dnf.builder().parameter(p).clause().build();
173
174 var actual = Dnf.builder()
175 .parameters(p, q)
176 .clause(friendView.call(p, q))
177 .clause(friendView.call(q, p), not(trueDnf.call(q)))
178 .build();
179 var expected = Dnf.builder().parameters(p, q).clause(friendView.call(p, q)).build();
180
181 assertThat(actual, structurallyEqualTo(expected));
182 }
183
184 @Test
185 void alwaysNotFalseDnfTest() {
186 var p = new Variable("p");
187 var q = new Variable("q");
188 var friend = new Symbol<>("friend", 2, Boolean.class, false);
189 var friendView = new KeyOnlyRelationView<>(friend);
190 var falseDnf = Dnf.builder().parameter(p).build();
191
192 var actual = Dnf.builder()
193 .parameters(p, q)
194 .clause(friendView.call(p, q))
195 .clause(not(falseDnf.call(q)))
196 .build();
197 var expected = Dnf.builder().parameters(p, q).clause().build();
198
199 assertThat(actual, structurallyEqualTo(expected));
200 }
201
202 @Test
203 void alwaysNotTrueDnfTest() {
204 var p = new Variable("p");
205 var q = new Variable("q");
206 var friend = new Symbol<>("friend", 2, Boolean.class, false);
207 var friendView = new KeyOnlyRelationView<>(friend);
208 var trueDnf = Dnf.builder().parameter(p).clause().build();
209
210 var actual = Dnf.builder()
211 .parameters(p, q)
212 .clause(friendView.call(p, q), not(trueDnf.call(q)))
213 .build();
214 var expected = Dnf.builder().parameters(p, q).build();
215
216 assertThat(actual, structurallyEqualTo(expected));
217 }
218}
diff --git a/subprojects/store-query/src/test/java/tools/refinery/store/query/DnfToStringTest.java b/subprojects/store-query/src/test/java/tools/refinery/store/query/DnfToStringTest.java
new file mode 100644
index 00000000..e6e4bef3
--- /dev/null
+++ b/subprojects/store-query/src/test/java/tools/refinery/store/query/DnfToStringTest.java
@@ -0,0 +1,172 @@
1package tools.refinery.store.query;
2
3import org.junit.jupiter.api.Test;
4import tools.refinery.store.query.view.KeyOnlyRelationView;
5import tools.refinery.store.representation.Symbol;
6
7import static org.hamcrest.MatcherAssert.assertThat;
8import static org.hamcrest.Matchers.is;
9import static tools.refinery.store.query.literal.Literals.not;
10
11class DnfToStringTest {
12 @Test
13 void noClausesTest() {
14 var p = new Variable("p");
15 var dnf = Dnf.builder("Example").parameter(p).build();
16
17 assertThat(dnf.toString(), is("""
18 pred Example(p) <->
19 <no clauses>.
20 """));
21 }
22
23 @Test
24 void noParametersTest() {
25 var dnf = Dnf.builder("Example").build();
26
27 assertThat(dnf.toString(), is("""
28 pred Example() <->
29 <no clauses>.
30 """));
31 }
32
33 @Test
34 void emptyClauseTest() {
35 var p = new Variable("p");
36 var dnf = Dnf.builder("Example").parameter(p).clause().build();
37
38 assertThat(dnf.toString(), is("""
39 pred Example(p) <->
40 <empty>.
41 """));
42 }
43
44 @Test
45 void relationViewPositiveTest() {
46 var p = new Variable("p");
47 var q = new Variable("q");
48 var friend = new Symbol<>("friend", 2, Boolean.class, false);
49 var friendView = new KeyOnlyRelationView<>(friend);
50 var dnf = Dnf.builder("Example").parameter(p).clause(friendView.call(p, q)).build();
51
52 assertThat(dnf.toString(), is("""
53 pred Example(p) <->
54 @RelationView("key") friend(p, q).
55 """));
56 }
57
58 @Test
59 void relationViewNegativeTest() {
60 var p = new Variable("p");
61 var q = new Variable("q");
62 var friend = new Symbol<>("friend", 2, Boolean.class, false);
63 var friendView = new KeyOnlyRelationView<>(friend);
64 var dnf = Dnf.builder("Example").parameter(p).clause(not(friendView.call(p, q))).build();
65
66 assertThat(dnf.toString(), is("""
67 pred Example(p) <->
68 !(@RelationView("key") friend(p, q)).
69 """));
70 }
71
72 @Test
73 void relationViewTransitiveTest() {
74 var p = new Variable("p");
75 var q = new Variable("q");
76 var friend = new Symbol<>("friend", 2, Boolean.class, false);
77 var friendView = new KeyOnlyRelationView<>(friend);
78 var dnf = Dnf.builder("Example").parameter(p).clause(friendView.callTransitive(p, q)).build();
79
80 assertThat(dnf.toString(), is("""
81 pred Example(p) <->
82 @RelationView("key") friend+(p, q).
83 """));
84 }
85
86 @Test
87 void multipleParametersTest() {
88 var p = new Variable("p");
89 var q = new Variable("q");
90 var friend = new Symbol<>("friend", 2, Boolean.class, false);
91 var friendView = new KeyOnlyRelationView<>(friend);
92 var dnf = Dnf.builder("Example").parameters(p, q).clause(friendView.call(p, q)).build();
93
94 assertThat(dnf.toString(), is("""
95 pred Example(p, q) <->
96 @RelationView("key") friend(p, q).
97 """));
98 }
99
100 @Test
101 void multipleLiteralsTest() {
102 var p = new Variable("p");
103 var q = new Variable("q");
104 var person = new Symbol<>("person", 1, Boolean.class, false);
105 var personView = new KeyOnlyRelationView<>(person);
106 var friend = new Symbol<>("friend", 2, Boolean.class, false);
107 var friendView = new KeyOnlyRelationView<>(friend);
108 var dnf = Dnf.builder("Example")
109 .parameter(p)
110 .clause(
111 personView.call(p),
112 personView.call(q),
113 friendView.call(p, q)
114 )
115 .build();
116
117 assertThat(dnf.toString(), is("""
118 pred Example(p) <->
119 @RelationView("key") person(p),
120 @RelationView("key") person(q),
121 @RelationView("key") friend(p, q).
122 """));
123 }
124
125 @Test
126 void multipleClausesTest() {
127 var p = new Variable("p");
128 var q = new Variable("q");
129 var friend = new Symbol<>("friend", 2, Boolean.class, false);
130 var friendView = new KeyOnlyRelationView<>(friend);
131 var dnf = Dnf.builder("Example")
132 .parameter(p)
133 .clause(friendView.call(p, q))
134 .clause(friendView.call(q, p))
135 .build();
136
137 assertThat(dnf.toString(), is("""
138 pred Example(p) <->
139 @RelationView("key") friend(p, q)
140 ;
141 @RelationView("key") friend(q, p).
142 """));
143 }
144
145 @Test
146 void dnfTest() {
147 var p = new Variable("p");
148 var q = new Variable("q");
149 var r = new Variable("r");
150 var s = new Variable("s");
151 var person = new Symbol<>("person", 1, Boolean.class, false);
152 var personView = new KeyOnlyRelationView<>(person);
153 var friend = new Symbol<>("friend", 2, Boolean.class, false);
154 var friendView = new KeyOnlyRelationView<>(friend);
155 var called = Dnf.builder("Called").parameters(r, s).clause(friendView.call(r, s)).build();
156 var dnf = Dnf.builder("Example")
157 .parameter(p)
158 .clause(
159 personView.call(p),
160 personView.call(q),
161 not(called.call(p, q))
162 )
163 .build();
164
165 assertThat(dnf.toString(), is("""
166 pred Example(p) <->
167 @RelationView("key") person(p),
168 @RelationView("key") person(q),
169 !(@Dnf Called(p, q)).
170 """));
171 }
172}
diff --git a/subprojects/store-query/src/test/java/tools/refinery/store/query/tests/StructurallyEqualToTest.java b/subprojects/store-query/src/test/java/tools/refinery/store/query/tests/StructurallyEqualToTest.java
new file mode 100644
index 00000000..0cda22df
--- /dev/null
+++ b/subprojects/store-query/src/test/java/tools/refinery/store/query/tests/StructurallyEqualToTest.java
@@ -0,0 +1,77 @@
1package tools.refinery.store.query.tests;
2
3import org.junit.jupiter.api.Test;
4import tools.refinery.store.query.Dnf;
5import tools.refinery.store.query.Variable;
6import tools.refinery.store.query.view.KeyOnlyRelationView;
7import tools.refinery.store.representation.Symbol;
8
9import static org.hamcrest.CoreMatchers.containsString;
10import static org.hamcrest.MatcherAssert.assertThat;
11import static org.junit.jupiter.api.Assertions.assertThrows;
12import static tools.refinery.store.query.tests.QueryMatchers.structurallyEqualTo;
13
14class StructurallyEqualToTest {
15 @Test
16 void flatEqualsTest() {
17 var p = new Variable("p");
18 var q = new Variable("q");
19 var person = new Symbol<>("Person", 1, Boolean.class, false);
20 var personView = new KeyOnlyRelationView<>(person);
21
22 var expected = Dnf.builder("Expected").parameters(q).clause(personView.call(q)).build();
23 var actual = Dnf.builder("Actual").parameters(p).clause(personView.call(p)).build();
24
25 assertThat(actual, structurallyEqualTo(expected));
26 }
27
28 @Test
29 void flatNotEqualsTest() {
30 var p = new Variable("p");
31 var q = new Variable("q");
32 var person = new Symbol<>("Person", 1, Boolean.class, false);
33 var personView = new KeyOnlyRelationView<>(person);
34
35 var expected = Dnf.builder("Expected").parameters(q).clause(personView.call(q)).build();
36 var actual = Dnf.builder("Actual").parameters(p).clause(personView.call(q)).build();
37
38 var assertion = structurallyEqualTo(expected);
39 assertThrows(AssertionError.class, () -> assertThat(actual, assertion));
40 }
41
42 @Test
43 void deepEqualsTest() {
44 var p = new Variable("p");
45 var q = new Variable("q");
46 var person = new Symbol<>("Person", 1, Boolean.class, false);
47 var personView = new KeyOnlyRelationView<>(person);
48
49 var expected = Dnf.builder("Expected").parameters(q).clause(
50 Dnf.builder("Expected2").parameters(p).clause(personView.call(p)).build().call(q)
51 ).build();
52 var actual = Dnf.builder("Actual").parameters(q).clause(
53 Dnf.builder("Actual2").parameters(p).clause(personView.call(p)).build().call(q)
54 ).build();
55
56 assertThat(actual, structurallyEqualTo(expected));
57 }
58
59 @Test
60 void deepNotEqualsTest() {
61 var p = new Variable("p");
62 var q = new Variable("q");
63 var person = new Symbol<>("Person", 1, Boolean.class, false);
64 var personView = new KeyOnlyRelationView<>(person);
65
66 var expected = Dnf.builder("Expected").parameters(q).clause(
67 Dnf.builder("Expected2").parameters(p).clause(personView.call(p)).build().call(q)
68 ).build();
69 var actual = Dnf.builder("Actual").parameters(q).clause(
70 Dnf.builder("Actual2").parameters(p).clause(personView.call(q)).build().call(q)
71 ).build();
72
73 var assertion = structurallyEqualTo(expected);
74 var error = assertThrows(AssertionError.class, () -> assertThat(actual, assertion));
75 assertThat(error.getMessage(), containsString(" called from Expected "));
76 }
77}