souffle  2.0.2-371-g6315b36
ast_program_test.cpp
Go to the documentation of this file.
1 /*
2  * Souffle - A Datalog Compiler
3  * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved
4  * Licensed under the Universal Permissive License v 1.0 as shown at:
5  * - https://opensource.org/licenses/UPL
6  * - <souffle root>/licenses/SOUFFLE-UPL.txt
7  */
8 
9 /************************************************************************
10  *
11  * @file ast_program_test.cpp
12  *
13  * Tests souffle's AST program.
14  *
15  ***********************************************************************/
16 
17 #include "tests/test.h"
18 
19 #include "AggregateOp.h"
20 #include "ast/Aggregator.h"
21 #include "ast/Argument.h"
22 #include "ast/Atom.h"
23 #include "ast/Attribute.h"
24 #include "ast/Clause.h"
25 #include "ast/Literal.h"
26 #include "ast/Node.h"
27 #include "ast/Program.h"
28 #include "ast/Relation.h"
29 #include "ast/TranslationUnit.h"
30 #include "ast/Variable.h"
31 #include "ast/utility/Utils.h"
32 #include "parser/ParserDriver.h"
33 #include "reports/DebugReport.h"
34 #include "reports/ErrorReport.h"
35 #include <algorithm>
36 #include <iostream>
37 #include <memory>
38 #include <string>
39 #include <utility>
40 #include <vector>
41 
42 namespace souffle::ast::test {
43 
44 inline Own<TranslationUnit> makeATU(std::string program) {
45  ErrorReport e;
46  DebugReport d;
47  return ParserDriver::parseTranslationUnit(program, e, d);
48 }
49 
50 inline Own<Clause> makeClause(std::string name, Own<Argument> headArgument) {
51  auto headAtom = mk<Atom>(name);
52  headAtom->addArgument(std::move(headArgument));
53  auto clause = mk<Clause>();
54  clause->setHead(std::move(headAtom));
55  return clause;
56 }
57 
58 TEST(Program, Parse) {
59  ErrorReport e;
60  DebugReport d;
61  // check the empty program
63 
64  EXPECT_TRUE(empty->getProgram().getTypes().empty());
65  EXPECT_TRUE(empty->getProgram().getRelations().empty());
66 
67  // check something simple
69  R"(
70  .type Node <: symbol
71  .decl e ( a : Node , b : Node )
72  .decl r ( from : Node , to : Node )
73 
74  r(X,Y) :- e(X,Y).
75  r(X,Z) :- r(X,Y), r(Y,Z).
76  )",
77  e, d);
78 
79  auto& prog = tu->getProgram();
80  std::cout << prog << "\n";
81 
82  EXPECT_EQ(1, prog.getTypes().size());
83  EXPECT_EQ(2, prog.getRelations().size());
84 
85  EXPECT_TRUE(getRelation(prog, "e"));
86  EXPECT_TRUE(getRelation(prog, "r"));
87  EXPECT_FALSE(getRelation(prog, "n"));
88 }
89 
90 #define TESTASTCLONEANDEQUAL(SUBTYPE, DL) \
91  TEST(Ast, CloneAndEqual##SUBTYPE) { \
92  ErrorReport e; \
93  DebugReport d; \
94  Own<TranslationUnit> tu = ParserDriver::parseTranslationUnit(DL, e, d); \
95  Program& program = tu->getProgram(); \
96  EXPECT_EQ(program, program); \
97  Own<Program> clone(program.clone()); \
98  EXPECT_NE(clone.get(), &program); \
99  EXPECT_EQ(*clone, program); \
100  }
101 
102 TESTASTCLONEANDEQUAL(Program,
103  R"(
104  .decl r(a:number,b:number,c:number,d:number)
105  .decl s(x:symbol)
106  .decl a(x:number)
107  s("xxx").
108  r(X,Y,Z,W) :- a(X), 10 = Y, Y = Z, 8 + W = 12 + 14.
109  r(z + 2, x, y, a) :- s(b), b = to_string(a), z = x, a = y, x = 2, a = 2 + x.
110  )");
111 
112 TESTASTCLONEANDEQUAL(Record,
113  R"(
114  .type N <: symbol
115  .type R = [ a : N, B : N ]
116 
117  .decl r ( r : R )
118  .decl s ( r : N )
119 
120  s(x) :- r([x,y]).
121 
122  )");
123 
124 TESTASTCLONEANDEQUAL(SimpleTypes,
125  R"(
126  .type A <: symbol
127  .type B <: symbol
128  .type U = A | B
129 
130  .decl a ( x : A )
131  .decl b ( x : B )
132  .decl u ( x : U )
133 
134  a(X) :- u(X).
135  b(X) :- u(X).
136  u(X) :- u(X).
137 
138  a(X) :- b(X).
139  a(X) :- b(Y).
140 
141  )");
142 
143 TESTASTCLONEANDEQUAL(ComplexTypes,
144  R"(
145  .type A <: symbol
146  .type B <: number
147  .type U = B
148 
149  .decl a ( x : A )
150  .decl b ( x : B )
151  .decl u ( x : U )
152 
153  a(X) :- X < 10.
154  b(X) :- X < 10.
155  u(X) :- X < 10.
156 
157  )");
158 
159 TESTASTCLONEANDEQUAL(ChainedTypes,
160  R"(
161  .type D <: symbol
162  .type C = D
163  .type B = C
164  .type A = B
165 
166  .decl R1(x:A,y:B)
167  .decl R2(x:C,y:D)
168  .decl R4(x:A) output
169 
170  R4(x) :- R2(x,x),R1(x,x).
171  )");
172 
173 TESTASTCLONEANDEQUAL(NestedAggregates,
174  R"(
175  .type D <: symbol
176  .decl r(x:D)
177 
178  r(x) :- r(y), x=cat(cat(x,x),x).
179  )");
180 
181 TESTASTCLONEANDEQUAL(RelationCopies,
182  R"(
183  .type D = number
184  .decl a(a:D,b:D)
185  .decl b(a:D,b:D)
186  .decl c(a:D,b:D)
187  .decl d(a:D,b:D)
188 
189  a(1,2).
190  b(x,y) :- a(x,y).
191  c(x,y) :- b(x,y).
192 
193  d(x,y) :- b(x,y), c(y,x).
194 
195  )");
196 
197 /** test removeClause, addRelation and removeRelation */
198 TEST(Program, RemoveClause) {
199  auto atom = mk<Atom>("B");
200  atom->addArgument(mk<Variable>("x"));
201  auto sum = mk<Aggregator>(AggregateOp::SUM, mk<Variable>("x"));
202  VecOwn<Literal> body;
203  body.push_back(std::move(atom));
204  sum->setBody(std::move(body));
205 
206  auto tu1 = makeATU(".decl A,B(x:number) \n A(sum x : B(x)).");
207  auto clause = makeClause("A", std::move(sum));
208 
209  tu1->getProgram().removeClause(clause.get());
210  auto tu2 = makeATU(".decl A,B(x:number)");
211  EXPECT_EQ(tu1->getProgram(), tu2->getProgram());
212 }
213 
214 TEST(Program, AppendRelation) {
215  auto tu1 = makeATU(".decl A,B,C(x:number)");
216  auto& prog1 = tu1->getProgram();
217  auto rel = mk<Relation>();
218  rel->setQualifiedName("D");
219  rel->addAttribute(mk<Attribute>("x", "number"));
220  prog1.addRelation(std::move(rel));
221  auto tu2 = makeATU(".decl A,B,C,D(x:number)");
222  EXPECT_EQ(tu1->getProgram(), tu2->getProgram());
223 }
224 
225 TEST(Program, RemoveRelation) {
226  auto tu1 = makeATU(".decl A,B,C(x:number)");
227  removeRelation(*tu1, "B");
228  auto tu2 = makeATU(".decl A,C(x:number)");
229  EXPECT_EQ(tu1->getProgram(), tu2->getProgram());
230 }
231 
232 } // namespace souffle::ast::test
souffle::ast::test
Definition: ast_parser_utils_test.cpp:38
souffle::ParserDriver::parseTranslationUnit
static Own< ast::TranslationUnit > parseTranslationUnit(const std::string &filename, FILE *in, ErrorReport &errorReport, DebugReport &debugReport)
Definition: ParserDriver.cpp:84
souffle::ast::test::TESTASTCLONEANDEQUAL
TESTASTCLONEANDEQUAL(Program, R"( .decl r(a:number,b:number,c:number,d:number) .decl s(x:symbol) .decl a(x:number) s("xxx"). r(X,Y,Z,W) :- a(X), 10 = Y, Y = Z, 8 + W = 12 + 14. r(z + 2, x, y, a) :- s(b), b = to_string(a), z = x, a = y, x = 2, a = 2 + x. )")
EXPECT_TRUE
#define EXPECT_TRUE(a)
Definition: test.h:189
TranslationUnit.h
souffle::ast::removeRelation
void removeRelation(TranslationUnit &tu, const QualifiedName &name)
Remove relation and all its clauses from the program.
Definition: Utils.cpp:105
DebugReport.h
AggregateOp.h
souffle::ast::test::TEST
TEST(RuleBody, Basic)
Definition: ast_parser_utils_test.cpp:46
souffle::ast::test::makeATU
Own< TranslationUnit > makeATU(std::string program=".decl A,B,C(x:number)")
Definition: ast_print_test.cpp:52
EXPECT_EQ
#define EXPECT_EQ(a, b)
Definition: test.h:191
e
l j a showGridBackground &&c b raw series this eventEmitter e
Definition: htmlJsChartistMin.h:15
souffle::Own
std::unique_ptr< A > Own
Definition: ContainerUtil.h:42
Relation.h
Utils.h
Attribute.h
Argument.h
souffle::ast::Program
The program class consists of relations, clauses and types.
Definition: Program.h:52
souffle::ast::getRelation
Relation * getRelation(const Program &program, const QualifiedName &name)
Returns the relation with the given name in the program.
Definition: Utils.cpp:101
souffle::DebugReport
Class representing a HTML report, consisting of a list of sections.
Definition: DebugReport.h:87
Atom.h
Literal.h
souffle::ast::test::makeClause
Own< Clause > makeClause(std::string name, Own< Argument > headArgument)
Definition: ast_program_test.cpp:56
test.h
Node.h
souffle::AggregateOp::SUM
@ SUM
Aggregator.h
Program.h
Clause.h
d
else d
Definition: htmlJsChartistMin.h:15
ParserDriver.h
rel
void rel(size_t limit, bool showLimit=true)
Definition: Tui.h:1086
souffle::ErrorReport
Definition: ErrorReport.h:152
souffle::VecOwn
std::vector< Own< A > > VecOwn
Definition: ContainerUtil.h:45
ErrorReport.h
EXPECT_FALSE
#define EXPECT_FALSE(a)
Definition: test.h:190
Variable.h