diff options
Diffstat (limited to 'subprojects/language/src/test')
5 files changed, 946 insertions, 0 deletions
diff --git a/subprojects/language/src/test/java/tools/refinery/language/tests/ProblemParsingTest.xtend b/subprojects/language/src/test/java/tools/refinery/language/tests/ProblemParsingTest.xtend new file mode 100644 index 00000000..53d31a6c --- /dev/null +++ b/subprojects/language/src/test/java/tools/refinery/language/tests/ProblemParsingTest.xtend | |||
@@ -0,0 +1,64 @@ | |||
1 | /* | ||
2 | * generated by Xtext 2.26.0.M1 | ||
3 | */ | ||
4 | package tools.refinery.language.tests | ||
5 | |||
6 | import com.google.inject.Inject | ||
7 | import org.eclipse.xtext.testing.InjectWith | ||
8 | import org.eclipse.xtext.testing.extensions.InjectionExtension | ||
9 | import org.eclipse.xtext.testing.util.ParseHelper | ||
10 | import org.junit.jupiter.api.Test | ||
11 | import org.junit.jupiter.api.^extension.ExtendWith | ||
12 | import tools.refinery.language.model.problem.Problem | ||
13 | import tools.refinery.language.model.tests.ProblemTestUtil | ||
14 | |||
15 | import static org.hamcrest.MatcherAssert.assertThat | ||
16 | import static org.hamcrest.Matchers.* | ||
17 | |||
18 | @ExtendWith(InjectionExtension) | ||
19 | @InjectWith(ProblemInjectorProvider) | ||
20 | class ProblemParsingTest { | ||
21 | @Inject | ||
22 | ParseHelper<Problem> parseHelper | ||
23 | |||
24 | @Inject | ||
25 | extension ProblemTestUtil | ||
26 | |||
27 | @Test | ||
28 | def void exampleTest() { | ||
29 | val it = parseHelper.parse(''' | ||
30 | class Family { | ||
31 | contains Person[] members | ||
32 | } | ||
33 | |||
34 | class Person { | ||
35 | Person[0..*] children opposite parent | ||
36 | Person[0..1] parent opposite children | ||
37 | int age | ||
38 | TaxStatus taxStatus | ||
39 | } | ||
40 | |||
41 | enum TaxStatus { | ||
42 | child, student, adult, retired | ||
43 | } | ||
44 | |||
45 | % A child cannot have any dependents. | ||
46 | error invalidTaxStatus(Person p) <-> | ||
47 | taxStatus(p, child), children(p, _q). | ||
48 | |||
49 | indiv family. | ||
50 | Family(family). | ||
51 | members(family, anne): true. | ||
52 | members(family, bob). | ||
53 | members(family, ciri). | ||
54 | children(anne, ciri). | ||
55 | ?children(bob, ciri). | ||
56 | taxStatus(anne, adult). | ||
57 | age(anne, 35). | ||
58 | bobAge: 27. | ||
59 | age(bob, bobAge). | ||
60 | !age(ciri, bobAge). | ||
61 | ''') | ||
62 | assertThat(errors, empty) | ||
63 | } | ||
64 | } | ||
diff --git a/subprojects/language/src/test/java/tools/refinery/language/tests/formatting2/ProblemFormatterTest.java b/subprojects/language/src/test/java/tools/refinery/language/tests/formatting2/ProblemFormatterTest.java new file mode 100644 index 00000000..41ad2d31 --- /dev/null +++ b/subprojects/language/src/test/java/tools/refinery/language/tests/formatting2/ProblemFormatterTest.java | |||
@@ -0,0 +1,235 @@ | |||
1 | package tools.refinery.language.tests.formatting2; | ||
2 | |||
3 | import static org.hamcrest.MatcherAssert.assertThat; | ||
4 | import static org.hamcrest.Matchers.equalTo; | ||
5 | |||
6 | import java.util.List; | ||
7 | |||
8 | import org.eclipse.xtext.formatting2.FormatterRequest; | ||
9 | import org.eclipse.xtext.formatting2.IFormatter2; | ||
10 | import org.eclipse.xtext.formatting2.regionaccess.ITextRegionAccess; | ||
11 | import org.eclipse.xtext.formatting2.regionaccess.ITextReplacement; | ||
12 | import org.eclipse.xtext.formatting2.regionaccess.TextRegionAccessBuilder; | ||
13 | import org.eclipse.xtext.resource.XtextResource; | ||
14 | import org.eclipse.xtext.testing.InjectWith; | ||
15 | import org.eclipse.xtext.testing.extensions.InjectionExtension; | ||
16 | import org.eclipse.xtext.testing.util.ParseHelper; | ||
17 | import org.junit.jupiter.api.Test; | ||
18 | import org.junit.jupiter.api.extension.ExtendWith; | ||
19 | |||
20 | import com.google.inject.Inject; | ||
21 | import com.google.inject.Provider; | ||
22 | |||
23 | import tools.refinery.language.model.problem.Problem; | ||
24 | import tools.refinery.language.tests.ProblemInjectorProvider; | ||
25 | |||
26 | @ExtendWith(InjectionExtension.class) | ||
27 | @InjectWith(ProblemInjectorProvider.class) | ||
28 | class ProblemFormatterTest { | ||
29 | @Inject | ||
30 | private ParseHelper<Problem> parseHelper; | ||
31 | |||
32 | @Inject | ||
33 | private Provider<FormatterRequest> formatterRequestProvider; | ||
34 | |||
35 | @Inject | ||
36 | private TextRegionAccessBuilder regionBuilder; | ||
37 | |||
38 | @Inject | ||
39 | private IFormatter2 formatter2; | ||
40 | |||
41 | @Test | ||
42 | void problemNameTest() { | ||
43 | testFormatter(" problem problem . ", "problem problem.\n"); | ||
44 | } | ||
45 | |||
46 | @Test | ||
47 | void assertionTest() { | ||
48 | testFormatter(" equals ( a , b , * ) : true . ", "equals(a, b, *): true.\n"); | ||
49 | } | ||
50 | |||
51 | @Test | ||
52 | void defaultAssertionTest() { | ||
53 | testFormatter(" default equals ( a , b , * ) : true . ", "default equals(a, b, *): true.\n"); | ||
54 | } | ||
55 | |||
56 | @Test | ||
57 | void assertionShortTrueTest() { | ||
58 | testFormatter(" equals ( a , b , * ) . ", "equals(a, b, *).\n"); | ||
59 | } | ||
60 | |||
61 | @Test | ||
62 | void defaultAssertionShortTrueTest() { | ||
63 | testFormatter(" default equals ( a , b , * ) . ", "default equals(a, b, *).\n"); | ||
64 | } | ||
65 | |||
66 | @Test | ||
67 | void assertionShortFalseTest() { | ||
68 | testFormatter(" ! equals ( a , b , * ) . ", "!equals(a, b, *).\n"); | ||
69 | } | ||
70 | |||
71 | @Test | ||
72 | void defaultAssertionShortFalseTest() { | ||
73 | testFormatter(" default ! equals ( a , b , * ) . ", "default !equals(a, b, *).\n"); | ||
74 | } | ||
75 | |||
76 | @Test | ||
77 | void assertionShortUnknownTest() { | ||
78 | testFormatter(" ? equals ( a , b , * ) . ", "?equals(a, b, *).\n"); | ||
79 | } | ||
80 | |||
81 | @Test | ||
82 | void defaultAssertionShortUnknownTest() { | ||
83 | testFormatter(" default ? equals ( a , b , * ) . ", "default ?equals(a, b, *).\n"); | ||
84 | } | ||
85 | |||
86 | @Test | ||
87 | void multipleAssertionsTest() { | ||
88 | testFormatter(" exists ( a ) . ? equals ( a , a ).", """ | ||
89 | exists(a). | ||
90 | ?equals(a, a). | ||
91 | """); | ||
92 | } | ||
93 | |||
94 | @Test | ||
95 | void multipleAssertionsNamedProblemTest() { | ||
96 | testFormatter(" problem foo . exists ( a ) . ? equals ( a , a ).", """ | ||
97 | problem foo. | ||
98 | |||
99 | exists(a). | ||
100 | ?equals(a, a). | ||
101 | """); | ||
102 | } | ||
103 | |||
104 | @Test | ||
105 | void classWithoutBodyTest() { | ||
106 | testFormatter(" class Foo . ", "class Foo.\n"); | ||
107 | } | ||
108 | |||
109 | @Test | ||
110 | void abstractClassWithoutBodyTest() { | ||
111 | testFormatter(" abstract class Foo . ", "abstract class Foo.\n"); | ||
112 | } | ||
113 | |||
114 | @Test | ||
115 | void classExtendsWithoutBodyTest() { | ||
116 | testFormatter(" class Foo. class Bar . class Quux extends Foo , Bar . ", """ | ||
117 | class Foo. | ||
118 | |||
119 | class Bar. | ||
120 | |||
121 | class Quux extends Foo, Bar. | ||
122 | """); | ||
123 | } | ||
124 | |||
125 | @Test | ||
126 | void classWithEmptyBodyTest() { | ||
127 | testFormatter(" class Foo { } ", """ | ||
128 | class Foo { | ||
129 | } | ||
130 | """); | ||
131 | } | ||
132 | |||
133 | @Test | ||
134 | void classExtendsWithBodyTest() { | ||
135 | testFormatter(" class Foo. class Bar . class Quux extends Foo , Bar { } ", """ | ||
136 | class Foo. | ||
137 | |||
138 | class Bar. | ||
139 | |||
140 | class Quux extends Foo, Bar { | ||
141 | } | ||
142 | """); | ||
143 | } | ||
144 | |||
145 | @Test | ||
146 | void predicateWithoutBodyTest() { | ||
147 | testFormatter(" pred foo ( node a , b ) . ", "pred foo(node a, b).\n"); | ||
148 | } | ||
149 | |||
150 | @Test | ||
151 | void predicateWithBodyTest() { | ||
152 | testFormatter( | ||
153 | " pred foo ( node a , b ) <-> equal (a , _c ) , ! equal ( a , b ) ; equal+( a , b ) . ", | ||
154 | "pred foo(node a, b) <-> equal(a, _c), !equal(a, b); equal+(a, b).\n"); | ||
155 | } | ||
156 | |||
157 | @Test | ||
158 | void predicatesWithoutBodyTest() { | ||
159 | testFormatter(" pred foo ( node a , b ) . pred bar ( node c ) . ", """ | ||
160 | pred foo(node a, b). | ||
161 | |||
162 | pred bar(node c). | ||
163 | """); | ||
164 | } | ||
165 | |||
166 | @Test | ||
167 | void predicateCommentsTest() { | ||
168 | testFormatter(""" | ||
169 | % Some foo | ||
170 | pred foo ( node a , b ) . | ||
171 | % Some bar | ||
172 | pred bar ( node c ) . | ||
173 | """, """ | ||
174 | % Some foo | ||
175 | pred foo(node a, b). | ||
176 | |||
177 | % Some bar | ||
178 | pred bar(node c). | ||
179 | """); | ||
180 | } | ||
181 | |||
182 | @Test | ||
183 | void individualDeclarationTest() { | ||
184 | testFormatter(" indiv a , b . ", "indiv a, b.\n"); | ||
185 | } | ||
186 | |||
187 | @Test | ||
188 | void mixedDeclarationsTest() { | ||
189 | testFormatter(""" | ||
190 | problem test. | ||
191 | pred foo(node a). | ||
192 | class Foo. | ||
193 | foo(n1, n2). | ||
194 | indiv i1. | ||
195 | !foo(i1, n1). | ||
196 | pred bar(node a, node b). | ||
197 | pred quux(). | ||
198 | default !bar(*, *). | ||
199 | """, """ | ||
200 | problem test. | ||
201 | |||
202 | pred foo(node a). | ||
203 | |||
204 | class Foo. | ||
205 | |||
206 | foo(n1, n2). | ||
207 | indiv i1. | ||
208 | !foo(i1, n1). | ||
209 | |||
210 | pred bar(node a, node b). | ||
211 | |||
212 | pred quux(). | ||
213 | |||
214 | default !bar(*, *). | ||
215 | """); | ||
216 | } | ||
217 | |||
218 | private void testFormatter(String toFormat, String expected) { | ||
219 | Problem problem; | ||
220 | try { | ||
221 | problem = parseHelper.parse(toFormat); | ||
222 | } catch (Exception e) { | ||
223 | throw new RuntimeException("Failed to parse document", e); | ||
224 | } | ||
225 | var resource = (XtextResource) problem.eResource(); | ||
226 | FormatterRequest request = formatterRequestProvider.get(); | ||
227 | request.setAllowIdentityEdits(false); | ||
228 | request.setFormatUndefinedHiddenRegionsOnly(false); | ||
229 | ITextRegionAccess regionAccess = regionBuilder.forNodeModel(resource).create(); | ||
230 | request.setTextRegionAccess(regionAccess); | ||
231 | List<ITextReplacement> replacements = formatter2.format(request); | ||
232 | var formattedString = regionAccess.getRewriter().renderToString(replacements); | ||
233 | assertThat(formattedString, equalTo(expected)); | ||
234 | } | ||
235 | } | ||
diff --git a/subprojects/language/src/test/java/tools/refinery/language/tests/rules/DirectRuleParsingTest.xtend b/subprojects/language/src/test/java/tools/refinery/language/tests/rules/DirectRuleParsingTest.xtend new file mode 100644 index 00000000..d60651a0 --- /dev/null +++ b/subprojects/language/src/test/java/tools/refinery/language/tests/rules/DirectRuleParsingTest.xtend | |||
@@ -0,0 +1,96 @@ | |||
1 | package tools.refinery.language.tests.rules | ||
2 | |||
3 | import com.google.inject.Inject | ||
4 | import org.eclipse.xtext.testing.InjectWith | ||
5 | import org.eclipse.xtext.testing.extensions.InjectionExtension | ||
6 | import org.eclipse.xtext.testing.util.ParseHelper | ||
7 | import org.junit.jupiter.api.Test | ||
8 | import org.junit.jupiter.api.^extension.ExtendWith | ||
9 | import tools.refinery.language.model.problem.Problem | ||
10 | import tools.refinery.language.tests.ProblemInjectorProvider | ||
11 | import tools.refinery.language.model.tests.ProblemTestUtil | ||
12 | |||
13 | import static org.hamcrest.MatcherAssert.assertThat | ||
14 | import static org.hamcrest.Matchers.* | ||
15 | |||
16 | @ExtendWith(InjectionExtension) | ||
17 | @InjectWith(ProblemInjectorProvider) | ||
18 | class DirectRuleParsingTest { | ||
19 | @Inject | ||
20 | ParseHelper<Problem> parseHelper | ||
21 | |||
22 | @Inject | ||
23 | extension ProblemTestUtil | ||
24 | |||
25 | @Test | ||
26 | def void relationValueRewriteTest() { | ||
27 | val it = parseHelper.parse(''' | ||
28 | pred Person(p). | ||
29 | direct rule r(p1): Person(p1) = true ~> Person(p1) = false. | ||
30 | ''') | ||
31 | assertThat(errors, empty) | ||
32 | } | ||
33 | |||
34 | @Test | ||
35 | def void relationValueMergeTest() { | ||
36 | val it = parseHelper.parse(''' | ||
37 | pred Person(p). | ||
38 | direct rule r(p1): Person(p1): true ~> Person(p1): false. | ||
39 | ''') | ||
40 | assertThat(errors, empty) | ||
41 | } | ||
42 | |||
43 | @Test | ||
44 | def void newNodeTest() { | ||
45 | val it = parseHelper.parse(''' | ||
46 | pred Person(p). | ||
47 | direct rule r(p1): Person(p1) = true ~> new p2, Person(p2) = unknown. | ||
48 | ''') | ||
49 | assertThat(errors, empty) | ||
50 | assertThat(rule("r").param(0), equalTo(rule("r").conj(0).lit(0).valueAtom.arg(0).variable)) | ||
51 | assertThat(rule("r").actionLit(0).newVar, | ||
52 | equalTo(rule("r").actionLit(1).valueAtom.arg(0).variable) | ||
53 | ) | ||
54 | } | ||
55 | |||
56 | @Test | ||
57 | def void differentScopeTest() { | ||
58 | val it = parseHelper.parse(''' | ||
59 | pred Friend(a, b). | ||
60 | direct rule r(p1): Friend(p1, p2) = false ~> new p2, Friend(p1, p2) = true. | ||
61 | ''') | ||
62 | assertThat(errors, empty) | ||
63 | assertThat(rule("r").conj(0).lit(0).valueAtom.arg(1).variable, | ||
64 | not(equalTo(rule("r").actionLit(1).valueAtom.arg(1).variable))) | ||
65 | } | ||
66 | |||
67 | @Test | ||
68 | def void parameterShadowingTest() { | ||
69 | val it = parseHelper.parse(''' | ||
70 | pred Friend(a, b). | ||
71 | direct rule r(p1, p2): Friend(p1, p2) = false ~> new p2, Friend(p1, p2) = true. | ||
72 | ''') | ||
73 | assertThat(errors, empty) | ||
74 | assertThat(rule("r").param(1), | ||
75 | not(equalTo(rule("r").actionLit(1).valueAtom.arg(1).variable))) | ||
76 | } | ||
77 | |||
78 | @Test | ||
79 | def void deleteParameterNodeTest() { | ||
80 | val it = parseHelper.parse(''' | ||
81 | pred Person(p). | ||
82 | direct rule r(p1): Person(p1): false ~> delete p1. | ||
83 | ''') | ||
84 | assertThat(errors, empty) | ||
85 | } | ||
86 | |||
87 | @Test | ||
88 | def void deleteDifferentScopeNodeTest() { | ||
89 | val it = parseHelper.parse(''' | ||
90 | pred Friend(p). | ||
91 | direct rule r(p1): Friend(p1, p2) = true ~> delete p2. | ||
92 | ''') | ||
93 | assertThat(errors, not(empty)) | ||
94 | } | ||
95 | |||
96 | } | ||
diff --git a/subprojects/language/src/test/java/tools/refinery/language/tests/scoping/NodeScopingTest.xtend b/subprojects/language/src/test/java/tools/refinery/language/tests/scoping/NodeScopingTest.xtend new file mode 100644 index 00000000..3a046341 --- /dev/null +++ b/subprojects/language/src/test/java/tools/refinery/language/tests/scoping/NodeScopingTest.xtend | |||
@@ -0,0 +1,322 @@ | |||
1 | package tools.refinery.language.tests.scoping | ||
2 | |||
3 | import com.google.inject.Inject | ||
4 | import java.util.stream.Stream | ||
5 | import org.eclipse.xtext.testing.InjectWith | ||
6 | import org.eclipse.xtext.testing.extensions.InjectionExtension | ||
7 | import org.eclipse.xtext.testing.util.ParseHelper | ||
8 | import org.junit.jupiter.api.Test | ||
9 | import org.junit.jupiter.api.^extension.ExtendWith | ||
10 | import org.junit.jupiter.params.ParameterizedTest | ||
11 | import org.junit.jupiter.params.provider.Arguments | ||
12 | import org.junit.jupiter.params.provider.MethodSource | ||
13 | import org.junit.jupiter.params.provider.ValueSource | ||
14 | import tools.refinery.language.model.problem.Problem | ||
15 | import tools.refinery.language.model.tests.ProblemTestUtil | ||
16 | import tools.refinery.language.tests.ProblemInjectorProvider | ||
17 | |||
18 | import static org.hamcrest.MatcherAssert.assertThat | ||
19 | import static org.hamcrest.Matchers.* | ||
20 | |||
21 | @ExtendWith(InjectionExtension) | ||
22 | @InjectWith(ProblemInjectorProvider) | ||
23 | class NodeScopingTest { | ||
24 | @Inject | ||
25 | ParseHelper<Problem> parseHelper | ||
26 | |||
27 | @Inject | ||
28 | extension ProblemTestUtil | ||
29 | |||
30 | @ParameterizedTest | ||
31 | @ValueSource(strings=#["", "builtin::"]) | ||
32 | def void builtInArgumentTypeTest(String prefix) { | ||
33 | val it = parseHelper.parse(''' | ||
34 | pred predicate(«prefix»node a, «prefix»data b, «prefix»int c). | ||
35 | ''') | ||
36 | assertThat(errors, empty) | ||
37 | assertThat(pred('predicate').param(0).parameterType, equalTo(builtin.findClass('node'))) | ||
38 | assertThat(pred('predicate').param(1).parameterType, equalTo(builtin.findClass('data'))) | ||
39 | assertThat(pred('predicate').param(2).parameterType, equalTo(builtin.findClass('int'))) | ||
40 | } | ||
41 | |||
42 | @Test | ||
43 | def void implicitNodeInAssertionTest() { | ||
44 | val it = parseHelper.parse(''' | ||
45 | pred predicate(node x, node y) <-> node(x). | ||
46 | predicate(a, a). | ||
47 | ?predicate(a, b). | ||
48 | ''') | ||
49 | assertThat(errors, empty) | ||
50 | assertThat(nodeNames, hasItems('a', 'b')) | ||
51 | assertThat(assertion(0).arg(0).node, equalTo(node('a'))) | ||
52 | assertThat(assertion(0).arg(1).node, equalTo(node('a'))) | ||
53 | assertThat(assertion(1).arg(0).node, equalTo(node('a'))) | ||
54 | assertThat(assertion(1).arg(1).node, equalTo(node('b'))) | ||
55 | } | ||
56 | |||
57 | @Test | ||
58 | def void implicitNodeInNodeValueAssertionTest() { | ||
59 | val it = parseHelper.parse(''' | ||
60 | a: 16. | ||
61 | ''') | ||
62 | assertThat(errors, empty) | ||
63 | assertThat(nodeNames, hasItems('a')) | ||
64 | assertThat(nodeValueAssertion(0).node, equalTo(node('a'))) | ||
65 | } | ||
66 | |||
67 | @Test | ||
68 | def void implicitNodeInPredicateTest() { | ||
69 | val it = parseHelper.parse(''' | ||
70 | pred predicate(node a) <-> node(b). | ||
71 | predicate(b). | ||
72 | ''') | ||
73 | assertThat(errors, empty) | ||
74 | assertThat(nodeNames, hasItem("b")) | ||
75 | assertThat(pred("predicate").conj(0).lit(0).arg(0).node, equalTo(node("b"))) | ||
76 | assertThat(assertion(0).arg(0).node, equalTo(node("b"))) | ||
77 | } | ||
78 | |||
79 | @ParameterizedTest | ||
80 | @MethodSource("individualNodeReferenceSource") | ||
81 | def void individualNodeInAssertionTest(String qualifiedNamePrefix, boolean namedProblem) { | ||
82 | val it = parseHelper.parse(''' | ||
83 | «IF namedProblem»problem test.«ENDIF» | ||
84 | indiv a, b. | ||
85 | pred predicate(node x, node y) <-> node(x). | ||
86 | predicate(«qualifiedNamePrefix»a, «qualifiedNamePrefix»a). | ||
87 | ?predicate(«qualifiedNamePrefix»a, «qualifiedNamePrefix»b). | ||
88 | ''') | ||
89 | assertThat(errors, empty) | ||
90 | assertThat(nodeNames, empty) | ||
91 | assertThat(assertion(0).arg(0).node, equalTo(individualNode('a'))) | ||
92 | assertThat(assertion(0).arg(1).node, equalTo(individualNode('a'))) | ||
93 | assertThat(assertion(1).arg(0).node, equalTo(individualNode('a'))) | ||
94 | assertThat(assertion(1).arg(1).node, equalTo(individualNode('b'))) | ||
95 | } | ||
96 | |||
97 | @ParameterizedTest | ||
98 | @MethodSource("individualNodeReferenceSource") | ||
99 | def void individualNodeInNodeValueAssertionTest(String qualifiedNamePrefix, boolean namedProblem) { | ||
100 | val it = parseHelper.parse(''' | ||
101 | «IF namedProblem»problem test.«ENDIF» | ||
102 | indiv a. | ||
103 | «qualifiedNamePrefix»a: 16. | ||
104 | ''') | ||
105 | assertThat(errors, empty) | ||
106 | assertThat(nodeNames, empty) | ||
107 | assertThat(nodeValueAssertion(0).node, equalTo(individualNode('a'))) | ||
108 | } | ||
109 | |||
110 | @ParameterizedTest | ||
111 | @MethodSource("individualNodeReferenceSource") | ||
112 | def void individualNodeInPredicateTest(String qualifiedNamePrefix, boolean namedProblem) { | ||
113 | val it = parseHelper.parse(''' | ||
114 | «IF namedProblem»problem test.«ENDIF» | ||
115 | indiv b. | ||
116 | pred predicate(node a) <-> node(«qualifiedNamePrefix»b). | ||
117 | ''') | ||
118 | assertThat(errors, empty) | ||
119 | assertThat(nodeNames, empty) | ||
120 | assertThat(pred("predicate").conj(0).lit(0).arg(0).node, equalTo(individualNode("b"))) | ||
121 | } | ||
122 | |||
123 | static def individualNodeReferenceSource() { | ||
124 | Stream.of( | ||
125 | Arguments.of("", false), | ||
126 | Arguments.of("", true), | ||
127 | Arguments.of("test::", true) | ||
128 | ) | ||
129 | } | ||
130 | |||
131 | @ParameterizedTest | ||
132 | @MethodSource("builtInNodeReferencesSource") | ||
133 | def void builtInNodeTest(String qualifiedName) { | ||
134 | val it = parseHelper.parse(''' | ||
135 | pred predicate(node x) <-> node(x). | ||
136 | predicate(«qualifiedName»). | ||
137 | ''') | ||
138 | assertThat(errors, empty) | ||
139 | assertThat(nodes, empty) | ||
140 | assertThat(assertion(0).arg(0).node, equalTo(builtin.findClass('int').newNode)) | ||
141 | } | ||
142 | |||
143 | @ParameterizedTest | ||
144 | @MethodSource("builtInNodeReferencesSource") | ||
145 | def void builtInNodeInNodeValueAssertionTest(String qualifiedName) { | ||
146 | val it = parseHelper.parse(''' | ||
147 | «qualifiedName»: 16. | ||
148 | ''') | ||
149 | assertThat(errors, empty) | ||
150 | assertThat(nodes, empty) | ||
151 | assertThat(nodeValueAssertion(0).node, equalTo(builtin.findClass('int').newNode)) | ||
152 | } | ||
153 | |||
154 | @ParameterizedTest | ||
155 | @MethodSource("builtInNodeReferencesSource") | ||
156 | def void builtInNodeInPredicateTest(String qualifiedName) { | ||
157 | val it = parseHelper.parse(''' | ||
158 | pred predicate(node x) <-> node(«qualifiedName»). | ||
159 | ''') | ||
160 | assertThat(errors, empty) | ||
161 | assertThat(pred("predicate").conj(0).lit(0).arg(0).node, equalTo(builtin.findClass('int').newNode)) | ||
162 | } | ||
163 | |||
164 | static def builtInNodeReferencesSource() { | ||
165 | Stream.of( | ||
166 | Arguments.of("int::new"), | ||
167 | Arguments.of("builtin::int::new") | ||
168 | ) | ||
169 | } | ||
170 | |||
171 | @ParameterizedTest(name="{0}, namedProblem={1}") | ||
172 | @MethodSource("classNewNodeReferencesSource") | ||
173 | def void classNewNodeTest(String qualifiedName, boolean namedProblem) { | ||
174 | val it = parseHelper.parse(''' | ||
175 | «IF namedProblem»problem test.«ENDIF» | ||
176 | class Foo. | ||
177 | pred predicate(node x) <-> node(x). | ||
178 | predicate(«qualifiedName»). | ||
179 | ''') | ||
180 | assertThat(errors, empty) | ||
181 | assertThat(nodes, empty) | ||
182 | assertThat(assertion(0).arg(0).node, equalTo(findClass('Foo').newNode)) | ||
183 | } | ||
184 | |||
185 | @ParameterizedTest(name="{0}, namedProblem={1}") | ||
186 | @MethodSource("classNewNodeReferencesSource") | ||
187 | def void classNewNodeInNodeValueAssertionTest(String qualifiedName, boolean namedProblem) { | ||
188 | val it = parseHelper.parse(''' | ||
189 | «IF namedProblem»problem test.«ENDIF» | ||
190 | class Foo. | ||
191 | «qualifiedName»: 16. | ||
192 | ''') | ||
193 | assertThat(errors, empty) | ||
194 | assertThat(nodes, empty) | ||
195 | assertThat(nodeValueAssertion(0).node, equalTo(findClass('Foo').newNode)) | ||
196 | } | ||
197 | |||
198 | @ParameterizedTest(name="{0}, namedProblem={1}") | ||
199 | @MethodSource("classNewNodeReferencesSource") | ||
200 | def void classNewNodeInPredicateTest(String qualifiedName, boolean namedProblem) { | ||
201 | val it = parseHelper.parse(''' | ||
202 | «IF namedProblem»problem test.«ENDIF» | ||
203 | class Foo. | ||
204 | pred predicate(node x) <-> node(«qualifiedName»). | ||
205 | ''') | ||
206 | assertThat(errors, empty) | ||
207 | assertThat(pred("predicate").conj(0).lit(0).arg(0).node, equalTo(findClass('Foo').newNode)) | ||
208 | } | ||
209 | |||
210 | static def classNewNodeReferencesSource() { | ||
211 | Stream.of( | ||
212 | Arguments.of("Foo::new", false), | ||
213 | Arguments.of("Foo::new", true), | ||
214 | Arguments.of("test::Foo::new", true) | ||
215 | ) | ||
216 | } | ||
217 | |||
218 | @Test | ||
219 | def void newNodeIsNotSpecial() { | ||
220 | val it = parseHelper.parse(''' | ||
221 | class Foo. | ||
222 | pred predicate(node x) <-> node(x). | ||
223 | predicate(new). | ||
224 | ''') | ||
225 | assertThat(errors, empty) | ||
226 | assertThat(nodeNames, hasItem('new')) | ||
227 | assertThat(assertion(0).arg(0).node, not(equalTo(findClass('Foo').newNode))) | ||
228 | } | ||
229 | |||
230 | @ParameterizedTest(name="{0}, namedProblem={1}") | ||
231 | @MethodSource("enumLiteralReferencesSource") | ||
232 | def void enumLiteralTest(String qualifiedName, boolean namedProblem) { | ||
233 | val it = parseHelper.parse(''' | ||
234 | «IF namedProblem»problem test.«ENDIF» | ||
235 | enum Foo { alpha, beta } | ||
236 | pred predicate(Foo a) <-> node(a). | ||
237 | predicate(«qualifiedName»). | ||
238 | ''') | ||
239 | assertThat(errors, empty) | ||
240 | assertThat(nodes, empty) | ||
241 | assertThat(assertion(0).arg(0).node, equalTo(findEnum("Foo").literal("alpha"))) | ||
242 | } | ||
243 | |||
244 | @ParameterizedTest(name="{0}, namedProblem={1}") | ||
245 | @MethodSource("enumLiteralReferencesSource") | ||
246 | def void enumLiteralInNodeValueAssertionTest(String qualifiedName, boolean namedProblem) { | ||
247 | val it = parseHelper.parse(''' | ||
248 | «IF namedProblem»problem test.«ENDIF» | ||
249 | enum Foo { alpha, beta } | ||
250 | «qualifiedName»: 16. | ||
251 | ''') | ||
252 | assertThat(errors, empty) | ||
253 | assertThat(nodes, empty) | ||
254 | assertThat(nodeValueAssertion(0).node, equalTo(findEnum("Foo").literal("alpha"))) | ||
255 | } | ||
256 | |||
257 | @ParameterizedTest(name="{0}, namedProblem={1}") | ||
258 | @MethodSource("enumLiteralReferencesSource") | ||
259 | def void enumLiteralInPredicateTest(String qualifiedName, boolean namedProblem) { | ||
260 | val it = parseHelper.parse(''' | ||
261 | «IF namedProblem»problem test.«ENDIF» | ||
262 | enum Foo { alpha, beta } | ||
263 | pred predicate(Foo a) <-> node(«qualifiedName»). | ||
264 | ''') | ||
265 | assertThat(errors, empty) | ||
266 | assertThat(nodes, empty) | ||
267 | assertThat(pred("predicate").conj(0).lit(0).arg(0).node, equalTo(findEnum("Foo").literal("alpha"))) | ||
268 | } | ||
269 | |||
270 | static def enumLiteralReferencesSource() { | ||
271 | Stream.of( | ||
272 | Arguments.of("alpha", false), | ||
273 | Arguments.of("alpha", true), | ||
274 | Arguments.of("Foo::alpha", false), | ||
275 | Arguments.of("Foo::alpha", true), | ||
276 | Arguments.of("test::alpha", true), | ||
277 | Arguments.of("test::Foo::alpha", true) | ||
278 | ) | ||
279 | } | ||
280 | |||
281 | @ParameterizedTest | ||
282 | @MethodSource("builtInEnumLiteralReferencesSource") | ||
283 | def void builtInEnumLiteralTest(String qualifiedName) { | ||
284 | val it = parseHelper.parse(''' | ||
285 | pred predicate(node a) <-> node(a). | ||
286 | predicate(«qualifiedName»). | ||
287 | ''') | ||
288 | assertThat(errors, empty) | ||
289 | assertThat(nodes, empty) | ||
290 | assertThat(assertion(0).arg(0).node, equalTo(builtin.findEnum("bool").literal("true"))) | ||
291 | } | ||
292 | |||
293 | @ParameterizedTest | ||
294 | @MethodSource("builtInEnumLiteralReferencesSource") | ||
295 | def void builtInEnumLiteralInNodeValueAssertionTest(String qualifiedName) { | ||
296 | val it = parseHelper.parse(''' | ||
297 | «qualifiedName»: 16. | ||
298 | ''') | ||
299 | assertThat(errors, empty) | ||
300 | assertThat(nodes, empty) | ||
301 | assertThat(nodeValueAssertion(0).node, equalTo(builtin.findEnum("bool").literal("true"))) | ||
302 | } | ||
303 | |||
304 | @ParameterizedTest | ||
305 | @MethodSource("builtInEnumLiteralReferencesSource") | ||
306 | def void bultInEnumLiteralInPredicateTest(String qualifiedName) { | ||
307 | val it = parseHelper.parse(''' | ||
308 | pred predicate() <-> node(«qualifiedName»). | ||
309 | ''') | ||
310 | assertThat(errors, empty) | ||
311 | assertThat(pred("predicate").conj(0).lit(0).arg(0).node, equalTo(builtin.findEnum("bool").literal("true"))) | ||
312 | } | ||
313 | |||
314 | static def builtInEnumLiteralReferencesSource() { | ||
315 | Stream.of( | ||
316 | Arguments.of("true"), | ||
317 | Arguments.of("bool::true"), | ||
318 | Arguments.of("builtin::true"), | ||
319 | Arguments.of("builtin::bool::true") | ||
320 | ) | ||
321 | } | ||
322 | } | ||
diff --git a/subprojects/language/src/test/java/tools/refinery/language/tests/serializer/ProblemSerializerTest.java b/subprojects/language/src/test/java/tools/refinery/language/tests/serializer/ProblemSerializerTest.java new file mode 100644 index 00000000..ba3aaeb7 --- /dev/null +++ b/subprojects/language/src/test/java/tools/refinery/language/tests/serializer/ProblemSerializerTest.java | |||
@@ -0,0 +1,229 @@ | |||
1 | package tools.refinery.language.tests.serializer; | ||
2 | |||
3 | import static org.hamcrest.MatcherAssert.assertThat; | ||
4 | import static org.hamcrest.Matchers.equalTo; | ||
5 | |||
6 | import java.io.ByteArrayOutputStream; | ||
7 | import java.io.IOException; | ||
8 | import java.util.Map; | ||
9 | import java.util.stream.Stream; | ||
10 | |||
11 | import org.eclipse.emf.common.util.URI; | ||
12 | import org.eclipse.emf.ecore.resource.Resource; | ||
13 | import org.eclipse.emf.ecore.resource.ResourceSet; | ||
14 | import org.eclipse.xtext.testing.InjectWith; | ||
15 | import org.eclipse.xtext.testing.extensions.InjectionExtension; | ||
16 | import org.junit.jupiter.api.BeforeEach; | ||
17 | import org.junit.jupiter.api.Test; | ||
18 | import org.junit.jupiter.api.extension.ExtendWith; | ||
19 | import org.junit.jupiter.params.ParameterizedTest; | ||
20 | import org.junit.jupiter.params.provider.Arguments; | ||
21 | import org.junit.jupiter.params.provider.MethodSource; | ||
22 | |||
23 | import com.google.inject.Inject; | ||
24 | |||
25 | import tools.refinery.language.model.ProblemUtil; | ||
26 | import tools.refinery.language.model.problem.Atom; | ||
27 | import tools.refinery.language.model.problem.LogicValue; | ||
28 | import tools.refinery.language.model.problem.Node; | ||
29 | import tools.refinery.language.model.problem.PredicateDefinition; | ||
30 | import tools.refinery.language.model.problem.Problem; | ||
31 | import tools.refinery.language.model.problem.ProblemFactory; | ||
32 | import tools.refinery.language.model.problem.Relation; | ||
33 | import tools.refinery.language.model.problem.VariableOrNode; | ||
34 | import tools.refinery.language.model.tests.ProblemTestUtil; | ||
35 | import tools.refinery.language.tests.ProblemInjectorProvider; | ||
36 | |||
37 | @ExtendWith(InjectionExtension.class) | ||
38 | @InjectWith(ProblemInjectorProvider.class) | ||
39 | class ProblemSerializerTest { | ||
40 | @Inject | ||
41 | private ResourceSet resourceSet; | ||
42 | |||
43 | @Inject | ||
44 | private ProblemTestUtil testUtil; | ||
45 | |||
46 | private Resource resource; | ||
47 | |||
48 | private Problem problem; | ||
49 | |||
50 | private Problem builtin; | ||
51 | |||
52 | @BeforeEach | ||
53 | void beforeEach() { | ||
54 | problem = ProblemFactory.eINSTANCE.createProblem(); | ||
55 | resource = resourceSet.createResource(URI.createFileURI("test.problem")); | ||
56 | resource.getContents().add(problem); | ||
57 | builtin = ProblemUtil.getBuiltInLibrary(problem).get(); | ||
58 | } | ||
59 | |||
60 | @ParameterizedTest | ||
61 | @MethodSource | ||
62 | void assertionTest(LogicValue value, String serializedAssertion) { | ||
63 | var pred = createPred(); | ||
64 | var node = ProblemFactory.eINSTANCE.createNode(); | ||
65 | node.setName("a"); | ||
66 | var individualDeclaration = ProblemFactory.eINSTANCE.createIndividualDeclaration(); | ||
67 | individualDeclaration.getNodes().add(node); | ||
68 | problem.getStatements().add(individualDeclaration); | ||
69 | createAssertion(pred, node, value); | ||
70 | |||
71 | assertSerializedResult(""" | ||
72 | pred foo(node p). | ||
73 | |||
74 | indiv a. | ||
75 | """ + serializedAssertion + "\n"); | ||
76 | } | ||
77 | |||
78 | static Stream<Arguments> assertionTest() { | ||
79 | return Stream.of(Arguments.of(LogicValue.TRUE, "foo(a)."), Arguments.of(LogicValue.FALSE, "!foo(a)."), | ||
80 | Arguments.of(LogicValue.UNKNOWN, "?foo(a)."), Arguments.of(LogicValue.ERROR, "foo(a): error.")); | ||
81 | } | ||
82 | |||
83 | @Test | ||
84 | void implicitNodeTest() { | ||
85 | var pred = createPred(); | ||
86 | var node = ProblemFactory.eINSTANCE.createNode(); | ||
87 | node.setName("a"); | ||
88 | problem.getNodes().add(node); | ||
89 | createAssertion(pred, node); | ||
90 | |||
91 | assertSerializedResult(""" | ||
92 | pred foo(node p). | ||
93 | |||
94 | foo(a). | ||
95 | """); | ||
96 | } | ||
97 | |||
98 | private PredicateDefinition createPred() { | ||
99 | var pred = ProblemFactory.eINSTANCE.createPredicateDefinition(); | ||
100 | pred.setName("foo"); | ||
101 | var parameter = ProblemFactory.eINSTANCE.createParameter(); | ||
102 | var nodeType = testUtil.findClass(builtin, "node"); | ||
103 | parameter.setParameterType(nodeType); | ||
104 | parameter.setName("p"); | ||
105 | pred.getParameters().add(parameter); | ||
106 | problem.getStatements().add(pred); | ||
107 | return pred; | ||
108 | } | ||
109 | |||
110 | @Test | ||
111 | void newNodeTest() { | ||
112 | var classDeclaration = ProblemFactory.eINSTANCE.createClassDeclaration(); | ||
113 | classDeclaration.setName("Foo"); | ||
114 | var newNode = ProblemFactory.eINSTANCE.createNode(); | ||
115 | newNode.setName("new"); | ||
116 | classDeclaration.setNewNode(newNode); | ||
117 | problem.getStatements().add(classDeclaration); | ||
118 | createAssertion(classDeclaration, newNode); | ||
119 | |||
120 | assertSerializedResult(""" | ||
121 | class Foo. | ||
122 | |||
123 | Foo(Foo::new). | ||
124 | """); | ||
125 | } | ||
126 | |||
127 | private void createAssertion(Relation relation, Node node) { | ||
128 | createAssertion(relation, node, LogicValue.TRUE); | ||
129 | } | ||
130 | |||
131 | private void createAssertion(Relation relation, Node node, LogicValue value) { | ||
132 | var assertion = ProblemFactory.eINSTANCE.createAssertion(); | ||
133 | assertion.setRelation(relation); | ||
134 | var argument = ProblemFactory.eINSTANCE.createNodeAssertionArgument(); | ||
135 | argument.setNode(node); | ||
136 | assertion.getArguments().add(argument); | ||
137 | assertion.setValue(value); | ||
138 | problem.getStatements().add(assertion); | ||
139 | } | ||
140 | |||
141 | @Test | ||
142 | void implicitVariableTest() { | ||
143 | var pred = ProblemFactory.eINSTANCE.createPredicateDefinition(); | ||
144 | pred.setName("foo"); | ||
145 | var nodeType = testUtil.findClass(builtin, "node"); | ||
146 | var parameter1 = ProblemFactory.eINSTANCE.createParameter(); | ||
147 | parameter1.setParameterType(nodeType); | ||
148 | parameter1.setName("p1"); | ||
149 | pred.getParameters().add(parameter1); | ||
150 | var parameter2 = ProblemFactory.eINSTANCE.createParameter(); | ||
151 | parameter2.setParameterType(nodeType); | ||
152 | parameter2.setName("p2"); | ||
153 | pred.getParameters().add(parameter2); | ||
154 | var conjunction = ProblemFactory.eINSTANCE.createConjunction(); | ||
155 | var variable = ProblemFactory.eINSTANCE.createImplicitVariable(); | ||
156 | variable.setName("q"); | ||
157 | conjunction.getImplicitVariables().add(variable); | ||
158 | var equals = testUtil.reference(nodeType, "equals"); | ||
159 | conjunction.getLiterals().add(createAtom(equals, parameter1, variable)); | ||
160 | conjunction.getLiterals().add(createAtom(equals, variable, parameter2)); | ||
161 | pred.getBodies().add(conjunction); | ||
162 | problem.getStatements().add(pred); | ||
163 | |||
164 | assertSerializedResult(""" | ||
165 | pred foo(node p1, node p2) <-> equals(p1, q), equals(q, p2). | ||
166 | """); | ||
167 | } | ||
168 | |||
169 | private Atom createAtom(Relation relation, VariableOrNode variable1, VariableOrNode variable2) { | ||
170 | var atom = ProblemFactory.eINSTANCE.createAtom(); | ||
171 | atom.setRelation(relation); | ||
172 | var arg1 = ProblemFactory.eINSTANCE.createVariableOrNodeArgument(); | ||
173 | arg1.setVariableOrNode(variable1); | ||
174 | atom.getArguments().add(arg1); | ||
175 | var arg2 = ProblemFactory.eINSTANCE.createVariableOrNodeArgument(); | ||
176 | arg2.setVariableOrNode(variable2); | ||
177 | atom.getArguments().add(arg2); | ||
178 | return atom; | ||
179 | } | ||
180 | |||
181 | @Test | ||
182 | void singletonVariableTest() { | ||
183 | var pred = ProblemFactory.eINSTANCE.createPredicateDefinition(); | ||
184 | pred.setName("foo"); | ||
185 | var nodeType = testUtil.findClass(builtin, "node"); | ||
186 | var parameter = ProblemFactory.eINSTANCE.createParameter(); | ||
187 | parameter.setParameterType(nodeType); | ||
188 | parameter.setName("p"); | ||
189 | pred.getParameters().add(parameter); | ||
190 | var conjunction = ProblemFactory.eINSTANCE.createConjunction(); | ||
191 | var atom = ProblemFactory.eINSTANCE.createAtom(); | ||
192 | var equals = testUtil.reference(nodeType, "equals"); | ||
193 | atom.setRelation(equals); | ||
194 | var arg1 = ProblemFactory.eINSTANCE.createVariableOrNodeArgument(); | ||
195 | arg1.setVariableOrNode(parameter); | ||
196 | atom.getArguments().add(arg1); | ||
197 | var arg2 = ProblemFactory.eINSTANCE.createVariableOrNodeArgument(); | ||
198 | var variable = ProblemFactory.eINSTANCE.createImplicitVariable(); | ||
199 | variable.setName("_q"); | ||
200 | arg2.setSingletonVariable(variable); | ||
201 | arg2.setVariableOrNode(variable); | ||
202 | atom.getArguments().add(arg2); | ||
203 | conjunction.getLiterals().add(atom); | ||
204 | pred.getBodies().add(conjunction); | ||
205 | problem.getStatements().add(pred); | ||
206 | |||
207 | assertSerializedResult(""" | ||
208 | pred foo(node p) <-> equals(p, _q). | ||
209 | """); | ||
210 | } | ||
211 | |||
212 | private void assertSerializedResult(String expected) { | ||
213 | var outputStream = new ByteArrayOutputStream(); | ||
214 | try { | ||
215 | resource.save(outputStream, Map.of()); | ||
216 | } catch (IOException e) { | ||
217 | throw new AssertionError("Failed to serialize problem", e); | ||
218 | } finally { | ||
219 | try { | ||
220 | outputStream.close(); | ||
221 | } catch (IOException e) { | ||
222 | // Nothing to handle in a test. | ||
223 | } | ||
224 | } | ||
225 | var problemString = outputStream.toString(); | ||
226 | |||
227 | assertThat(problemString, equalTo(expected)); | ||
228 | } | ||
229 | } | ||