aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/language/src/test
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2021-12-12 17:48:47 +0100
committerLibravatar Kristóf Marussy <kristof@marussy.com>2021-12-12 17:48:47 +0100
commitfc7e9312d00e60171ed77c477ed91231d3dbfff9 (patch)
treecc185dd088b5fa6e9357aab3c9062a70626d1953 /subprojects/language/src/test
parentbuild: refactor java-application conventions (diff)
downloadrefinery-fc7e9312d00e60171ed77c477ed91231d3dbfff9.tar.gz
refinery-fc7e9312d00e60171ed77c477ed91231d3dbfff9.tar.zst
refinery-fc7e9312d00e60171ed77c477ed91231d3dbfff9.zip
build: move modules into subproject directory
Diffstat (limited to 'subprojects/language/src/test')
-rw-r--r--subprojects/language/src/test/java/tools/refinery/language/tests/ProblemParsingTest.xtend64
-rw-r--r--subprojects/language/src/test/java/tools/refinery/language/tests/formatting2/ProblemFormatterTest.java235
-rw-r--r--subprojects/language/src/test/java/tools/refinery/language/tests/rules/DirectRuleParsingTest.xtend96
-rw-r--r--subprojects/language/src/test/java/tools/refinery/language/tests/scoping/NodeScopingTest.xtend322
-rw-r--r--subprojects/language/src/test/java/tools/refinery/language/tests/serializer/ProblemSerializerTest.java229
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 */
4package tools.refinery.language.tests
5
6import com.google.inject.Inject
7import org.eclipse.xtext.testing.InjectWith
8import org.eclipse.xtext.testing.extensions.InjectionExtension
9import org.eclipse.xtext.testing.util.ParseHelper
10import org.junit.jupiter.api.Test
11import org.junit.jupiter.api.^extension.ExtendWith
12import tools.refinery.language.model.problem.Problem
13import tools.refinery.language.model.tests.ProblemTestUtil
14
15import static org.hamcrest.MatcherAssert.assertThat
16import static org.hamcrest.Matchers.*
17
18@ExtendWith(InjectionExtension)
19@InjectWith(ProblemInjectorProvider)
20class 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 @@
1package tools.refinery.language.tests.formatting2;
2
3import static org.hamcrest.MatcherAssert.assertThat;
4import static org.hamcrest.Matchers.equalTo;
5
6import java.util.List;
7
8import org.eclipse.xtext.formatting2.FormatterRequest;
9import org.eclipse.xtext.formatting2.IFormatter2;
10import org.eclipse.xtext.formatting2.regionaccess.ITextRegionAccess;
11import org.eclipse.xtext.formatting2.regionaccess.ITextReplacement;
12import org.eclipse.xtext.formatting2.regionaccess.TextRegionAccessBuilder;
13import org.eclipse.xtext.resource.XtextResource;
14import org.eclipse.xtext.testing.InjectWith;
15import org.eclipse.xtext.testing.extensions.InjectionExtension;
16import org.eclipse.xtext.testing.util.ParseHelper;
17import org.junit.jupiter.api.Test;
18import org.junit.jupiter.api.extension.ExtendWith;
19
20import com.google.inject.Inject;
21import com.google.inject.Provider;
22
23import tools.refinery.language.model.problem.Problem;
24import tools.refinery.language.tests.ProblemInjectorProvider;
25
26@ExtendWith(InjectionExtension.class)
27@InjectWith(ProblemInjectorProvider.class)
28class 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 @@
1package tools.refinery.language.tests.rules
2
3import com.google.inject.Inject
4import org.eclipse.xtext.testing.InjectWith
5import org.eclipse.xtext.testing.extensions.InjectionExtension
6import org.eclipse.xtext.testing.util.ParseHelper
7import org.junit.jupiter.api.Test
8import org.junit.jupiter.api.^extension.ExtendWith
9import tools.refinery.language.model.problem.Problem
10import tools.refinery.language.tests.ProblemInjectorProvider
11import tools.refinery.language.model.tests.ProblemTestUtil
12
13import static org.hamcrest.MatcherAssert.assertThat
14import static org.hamcrest.Matchers.*
15
16@ExtendWith(InjectionExtension)
17@InjectWith(ProblemInjectorProvider)
18class 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 @@
1package tools.refinery.language.tests.scoping
2
3import com.google.inject.Inject
4import java.util.stream.Stream
5import org.eclipse.xtext.testing.InjectWith
6import org.eclipse.xtext.testing.extensions.InjectionExtension
7import org.eclipse.xtext.testing.util.ParseHelper
8import org.junit.jupiter.api.Test
9import org.junit.jupiter.api.^extension.ExtendWith
10import org.junit.jupiter.params.ParameterizedTest
11import org.junit.jupiter.params.provider.Arguments
12import org.junit.jupiter.params.provider.MethodSource
13import org.junit.jupiter.params.provider.ValueSource
14import tools.refinery.language.model.problem.Problem
15import tools.refinery.language.model.tests.ProblemTestUtil
16import tools.refinery.language.tests.ProblemInjectorProvider
17
18import static org.hamcrest.MatcherAssert.assertThat
19import static org.hamcrest.Matchers.*
20
21@ExtendWith(InjectionExtension)
22@InjectWith(ProblemInjectorProvider)
23class 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 @@
1package tools.refinery.language.tests.serializer;
2
3import static org.hamcrest.MatcherAssert.assertThat;
4import static org.hamcrest.Matchers.equalTo;
5
6import java.io.ByteArrayOutputStream;
7import java.io.IOException;
8import java.util.Map;
9import java.util.stream.Stream;
10
11import org.eclipse.emf.common.util.URI;
12import org.eclipse.emf.ecore.resource.Resource;
13import org.eclipse.emf.ecore.resource.ResourceSet;
14import org.eclipse.xtext.testing.InjectWith;
15import org.eclipse.xtext.testing.extensions.InjectionExtension;
16import org.junit.jupiter.api.BeforeEach;
17import org.junit.jupiter.api.Test;
18import org.junit.jupiter.api.extension.ExtendWith;
19import org.junit.jupiter.params.ParameterizedTest;
20import org.junit.jupiter.params.provider.Arguments;
21import org.junit.jupiter.params.provider.MethodSource;
22
23import com.google.inject.Inject;
24
25import tools.refinery.language.model.ProblemUtil;
26import tools.refinery.language.model.problem.Atom;
27import tools.refinery.language.model.problem.LogicValue;
28import tools.refinery.language.model.problem.Node;
29import tools.refinery.language.model.problem.PredicateDefinition;
30import tools.refinery.language.model.problem.Problem;
31import tools.refinery.language.model.problem.ProblemFactory;
32import tools.refinery.language.model.problem.Relation;
33import tools.refinery.language.model.problem.VariableOrNode;
34import tools.refinery.language.model.tests.ProblemTestUtil;
35import tools.refinery.language.tests.ProblemInjectorProvider;
36
37@ExtendWith(InjectionExtension.class)
38@InjectWith(ProblemInjectorProvider.class)
39class 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}