aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/language/src/test
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2022-09-19 21:33:55 +0200
committerLibravatar Kristóf Marussy <kristof@marussy.com>2022-09-19 21:42:05 +0200
commit7fb99f0225911a8962aaf3493b89f41e791df359 (patch)
treef289ac1433f91e2b1c9e1a5eab92ae6b52aa9d83 /subprojects/language/src/test
parentrefactor(language): clarify containment hierarchy (diff)
downloadrefinery-7fb99f0225911a8962aaf3493b89f41e791df359.tar.gz
refinery-7fb99f0225911a8962aaf3493b89f41e791df359.tar.zst
refinery-7fb99f0225911a8962aaf3493b89f41e791df359.zip
feat(language): problem desugaring
Diffstat (limited to 'subprojects/language/src/test')
-rw-r--r--subprojects/language/src/test/java/tools/refinery/language/tests/utils/SymbolCollectorTest.java276
1 files changed, 276 insertions, 0 deletions
diff --git a/subprojects/language/src/test/java/tools/refinery/language/tests/utils/SymbolCollectorTest.java b/subprojects/language/src/test/java/tools/refinery/language/tests/utils/SymbolCollectorTest.java
new file mode 100644
index 00000000..e2e3218c
--- /dev/null
+++ b/subprojects/language/src/test/java/tools/refinery/language/tests/utils/SymbolCollectorTest.java
@@ -0,0 +1,276 @@
1package tools.refinery.language.tests.utils;
2
3import com.google.inject.Inject;
4import org.eclipse.xtext.testing.InjectWith;
5import org.eclipse.xtext.testing.extensions.InjectionExtension;
6import org.hamcrest.Matcher;
7import org.junit.jupiter.api.Test;
8import org.junit.jupiter.api.extension.ExtendWith;
9import org.junit.jupiter.params.ParameterizedTest;
10import org.junit.jupiter.params.provider.Arguments;
11import org.junit.jupiter.params.provider.MethodSource;
12import tools.refinery.language.model.problem.*;
13import tools.refinery.language.model.tests.utils.ProblemParseHelper;
14import tools.refinery.language.tests.ProblemInjectorProvider;
15import tools.refinery.language.utils.ProblemDesugarer;
16
17import java.util.stream.Stream;
18
19import static org.hamcrest.MatcherAssert.assertThat;
20import static org.hamcrest.Matchers.*;
21import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
22
23@ExtendWith(InjectionExtension.class)
24@InjectWith(ProblemInjectorProvider.class)
25class SymbolCollectorTest {
26 @Inject
27 private ProblemParseHelper parseHelper;
28
29 @Inject
30 private ProblemDesugarer desugarer;
31
32 @Test
33 void implicitNodeTest() {
34 var problem = parseHelper.parse("""
35 exists(a).
36 """);
37 var collectedSymbols = desugarer.collectSymbols(problem.get());
38 var node = problem.node("a");
39 assertThat(collectedSymbols.nodes(), hasKey(node));
40 assertThat(collectedSymbols.nodes().get(node).individual(), is(false));
41 }
42
43 @Test
44 void individualNodeTest() {
45 var problem = parseHelper.parse("""
46 indiv a.
47 """);
48 var collectedSymbols = desugarer.collectSymbols(problem.get());
49 var node = problem.individualNode("a");
50 assertThat(collectedSymbols.nodes(), hasKey(node));
51 assertThat(collectedSymbols.nodes().get(node).individual(), is(true));
52 }
53
54 @Test
55 void classTest() {
56 var problem = parseHelper.parse("""
57 class Foo.
58 """);
59 var collectedSymbols = desugarer.collectSymbols(problem.get());
60 var classDeclaration = problem.findClass("Foo").get();
61 assertThat(collectedSymbols.relations(), hasKey(classDeclaration));
62 var classInfo = collectedSymbols.relations().get(classDeclaration);
63 assertThat(classInfo.parameters(), hasSize(1));
64 assertThat(classInfo.kind(), is(PredicateKind.CONTAINED));
65 assertThat(classInfo.hasDefinition(), is(false));
66 var newNode = classDeclaration.getNewNode();
67 assertThat(collectedSymbols.nodes(), hasKey(newNode));
68 assertThat(collectedSymbols.nodes().get(newNode).individual(), is(false));
69 assertThat(classInfo.assertions(), assertsNode(newNode, LogicValue.TRUE));
70 assertThat(collectedSymbols.relations().get(problem.builtinSymbols().exists()).assertions(),
71 assertsNode(newNode, LogicValue.UNKNOWN));
72 assertThat(collectedSymbols.relations().get(problem.builtinSymbols().equals()).assertions(),
73 assertsNode(newNode, LogicValue.UNKNOWN));
74 }
75
76 @Test
77 void abstractClassTest() {
78 var problem = parseHelper.parse("""
79 abstract class Foo.
80 """);
81 var collectedSymbols = desugarer.collectSymbols(problem.get());
82 assertThat(collectedSymbols.relations().get(problem.findClass("Foo").get()).assertions(), hasSize(0));
83 }
84
85 @Test
86 void referenceTest() {
87 var problem = parseHelper.parse("""
88 class Foo {
89 Foo[] bar opposite quux
90 Foo quux opposite bar
91 }
92 """);
93 var collectedSymbols = desugarer.collectSymbols(problem.get());
94 var fooClass = problem.findClass("Foo");
95 var barReference = fooClass.reference("bar");
96 var barInfo = collectedSymbols.relations().get(barReference);
97 var quuxReference = fooClass.reference("quux");
98 var quuxInfo = collectedSymbols.relations().get(quuxReference);
99 assertThat(barInfo.kind(), is(PredicateKind.DEFAULT));
100 assertThat(barInfo.opposite(), is(quuxReference));
101 assertThat(barInfo.multiplicity(), is(instanceOf(UnboundedMultiplicity.class)));
102 assertThat(barInfo.hasDefinition(), is(false));
103 assertThat(quuxInfo.kind(), is(PredicateKind.DEFAULT));
104 assertThat(quuxInfo.opposite(), is(barReference));
105 assertThat(quuxInfo.multiplicity(), is(instanceOf(ExactMultiplicity.class)));
106 assertThat(quuxInfo.multiplicity(), hasProperty("exactValue", is(1)));
107 assertThat(quuxInfo.hasDefinition(), is(false));
108 }
109
110 @Test
111 void containmentReferenceTest() {
112 var problem = parseHelper.parse("""
113 class Foo {
114 contains Foo[] bar
115 }
116 """);
117 var collectedSymbols = desugarer.collectSymbols(problem.get());
118 assertThat(collectedSymbols.relations().get(problem.findClass("Foo").reference("bar")).kind(),
119 is(PredicateKind.CONTAINMENT));
120 }
121
122 @Test
123 void dataReferenceTest() {
124 var problem = parseHelper.parse("""
125 class Foo {
126 int bar
127 }
128 """);
129 var collectedSymbols = desugarer.collectSymbols(problem.get());
130 assertThat(collectedSymbols.relations().get(problem.findClass("Foo").reference("bar")).kind(),
131 is(PredicateKind.CONTAINMENT));
132 }
133
134 @Test
135 void enumTest() {
136 var problem = parseHelper.parse("""
137 enum Foo {
138 bar, quux
139 }
140 """);
141 var collectedSymbols = desugarer.collectSymbols(problem.get());
142 var enumDeclaration = problem.findEnum("Foo");
143 var enumInfo = collectedSymbols.relations().get(enumDeclaration.get());
144 assertThat(enumInfo.kind(), is(PredicateKind.DEFAULT));
145 assertThat(enumInfo.assertions(), assertsNode(enumDeclaration.literal("bar"), LogicValue.TRUE));
146 assertThat(enumInfo.assertions(), assertsNode(enumDeclaration.literal("quux"), LogicValue.TRUE));
147 }
148
149 @ParameterizedTest
150 @MethodSource
151 void predicateTest(String keyword, PredicateKind kind) {
152 var problem = parseHelper.parse(keyword + " foo(node x) <-> domain(x); data(x).");
153 var collectedSymbols = desugarer.collectSymbols(problem.get());
154 var predicateInfo = collectedSymbols.relations().get(problem.pred("foo").get());
155 assertThat(predicateInfo.kind(), is(kind));
156 assertThat(predicateInfo.parameters(), hasSize(1));
157 assertThat(predicateInfo.bodies(), hasSize(2));
158 assertThat(predicateInfo.hasDefinition(), is(true));
159 }
160
161 static Stream<Arguments> predicateTest() {
162 return Stream.of(Arguments.of("pred", PredicateKind.DEFAULT), Arguments.of("error", PredicateKind.ERROR),
163 Arguments.of("contained", PredicateKind.CONTAINED), Arguments.of("containment",
164 PredicateKind.CONTAINMENT));
165 }
166
167 @ParameterizedTest
168 @MethodSource("logicValues")
169 void assertionTest(String keyword, LogicValue value) {
170 var problem = parseHelper.parse("""
171 pred foo(node x).
172 foo(a): %s.
173 """.formatted(keyword));
174 var collectedSymbols = desugarer.collectSymbols(problem.get());
175 assertThat(collectedSymbols.relations().get(problem.pred("foo").get()).assertions(),
176 assertsNode(problem.node("a"), value));
177 }
178
179 @ParameterizedTest
180 @MethodSource("logicValues")
181 void defaultAssertionTest(String keyword, LogicValue value) {
182 var problem = parseHelper.parse("""
183 pred foo(node x).
184 default foo(a): %s.
185 """.formatted(keyword));
186 var collectedSymbols = desugarer.collectSymbols(problem.get());
187 assertThat(collectedSymbols.relations().get(problem.pred("foo").get()).defaultAssertions(),
188 assertsNode(problem.node("a"), value));
189 }
190
191 static Stream<Arguments> logicValues() {
192 return Stream.of(Arguments.of("true", LogicValue.TRUE), Arguments.of("false", LogicValue.FALSE),
193 Arguments.of("unknown", LogicValue.UNKNOWN), Arguments.of("error", LogicValue.ERROR));
194 }
195
196 @Test
197 void invalidAssertionArityTest() {
198 var problem = parseHelper.parse("""
199 pred foo(node x).
200 foo(a, b).
201 """);
202 var collectedSymbols = desugarer.collectSymbols(problem.get());
203 assertThat(collectedSymbols.relations().get(problem.pred("foo").get()).assertions(), hasSize(0));
204 }
205
206 @ParameterizedTest
207 @MethodSource("valueTypes")
208 void nodeValueAssertionTest(String value, String typeName) {
209 var problem = parseHelper.parse("a: %s.".formatted(value));
210 var collectedSymbols = desugarer.collectSymbols(problem.get());
211 var node = problem.node("a");
212 var nodeInfo = collectedSymbols.nodes().get(node);
213 assertThat(nodeInfo.individual(), is(false));
214 assertThat(nodeInfo.valueAssertions(), hasSize(1));
215 assertThat(collectedSymbols.relations().get(problem.builtin().findClass(typeName).get()).assertions(),
216 assertsNode(node, LogicValue.TRUE));
217 }
218
219 @ParameterizedTest
220 @MethodSource("valueTypes")
221 void constantInAssertionTest(String value, String typeName) {
222 var problem = parseHelper.parse("""
223 containment pred foo(node x, data y).
224 foo(a, %s).
225 """.formatted(value));
226 var collectedSymbols = desugarer.collectSymbols(problem.get());
227 var node = problem.assertion(0).arg(1).constantNode();
228 var nodeInfo = collectedSymbols.nodes().get(node);
229 assertThat(nodeInfo.individual(), is(false));
230 assertThat(nodeInfo.valueAssertions(), hasSize(1));
231 assertThat(collectedSymbols.relations().get(problem.pred("foo").get()).assertions(), assertsNode(node,
232 LogicValue.TRUE));
233 assertThat(collectedSymbols.relations().get(problem.builtin().findClass(typeName).get()).assertions(),
234 assertsNode(node, LogicValue.TRUE));
235 }
236
237 @ParameterizedTest
238 @MethodSource("valueTypes")
239 void constantInUnknownAssertionTest(String value, String typeName) {
240 var problem = parseHelper.parse("""
241 containment pred foo(node x, data y).
242 foo(a, %s): unknown.
243 """.formatted(value));
244 var collectedSymbols = desugarer.collectSymbols(problem.get());
245 var node = problem.assertion(0).arg(1).constantNode();
246 var nodeInfo = collectedSymbols.nodes().get(node);
247 assertThat(nodeInfo.individual(), is(false));
248 assertThat(nodeInfo.valueAssertions(), hasSize(1));
249 assertThat(collectedSymbols.relations().get(problem.pred("foo").get()).assertions(), assertsNode(node,
250 LogicValue.UNKNOWN));
251 assertThat(collectedSymbols.relations().get(problem.builtin().findClass(typeName).get()).assertions(),
252 assertsNode(node, LogicValue.TRUE));
253 assertThat(collectedSymbols.relations().get(problem.builtinSymbols().exists()).assertions(), assertsNode(node,
254 LogicValue.UNKNOWN));
255 }
256
257 @Test
258 void invalidProblemTest() {
259 var problem = parseHelper.parse("""
260 class Foo {
261 bar[] opposite quux
262 Foo quux opposite bar
263 }
264 """).get();
265 assertDoesNotThrow(() -> desugarer.collectSymbols(problem));
266 }
267
268 static Stream<Arguments> valueTypes() {
269 return Stream.of(Arguments.of("3", "int"), Arguments.of("3.14", "real"), Arguments.of("\"foo\"", "string"));
270 }
271
272 private static Matcher<Iterable<? super Assertion>> assertsNode(Node node, LogicValue value) {
273 return hasItem(allOf(hasProperty("arguments", hasItem(hasProperty("node", is(node)))), hasProperty("value",
274 is(value))));
275 }
276}