dlvhex
2.5.0
|
00001 /* dlvhex -- Answer-Set Programming with external interfaces. 00002 * Copyright (C) 2005, 2006, 2007 Roman Schindlauer 00003 * Copyright (C) 2006, 2007, 2008, 2009, 2010 Thomas Krennwallner 00004 * Copyright (C) 2009, 2010 Peter Schüller 00005 * 00006 * This file is part of dlvhex. 00007 * 00008 * dlvhex is free software; you can redistribute it and/or modify it 00009 * under the terms of the GNU Lesser General Public License as 00010 * published by the Free Software Foundation; either version 2.1 of 00011 * the License, or (at your option) any later version. 00012 * 00013 * dlvhex is distributed in the hope that it will be useful, but 00014 * WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public 00019 * License along with dlvhex; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 00021 * 02110-1301 USA. 00022 */ 00023 00031 #ifdef HAVE_CONFIG_H 00032 #include "config.h" 00033 #endif // HAVE_CONFIG_H 00034 00035 #include <boost/cstdint.hpp> 00036 #include "dlvhex2/HexParser.h" 00037 #include "dlvhex2/InputProvider.h" 00038 #include "dlvhex2/ProgramCtx.h" 00039 #include "dlvhex2/Printer.h" 00040 #include "dlvhex2/Registry.h" 00041 #include "dlvhex2/Interpretation.h" 00042 #include "dlvhex2/MLPSyntaxChecker.h" 00043 //#include "dlvhex2/MLPSolver.hpp" 00044 00045 #define BOOST_TEST_MODULE "TestHexParserModule" 00046 #include <boost/test/unit_test.hpp> 00047 00048 #include <iostream> 00049 #include <fstream> 00050 00051 #define LOG_REGISTRY_PROGRAM(ctx) \ 00052 LOG(INFO, *ctx.registry()); \ 00053 RawPrinter printer(std::cerr, ctx.registry()); \ 00054 std::cerr << "first edb = " << *ctx.edbList.front() << std::endl; \ 00055 LOG(DBG, "first idb"); \ 00056 printer.printmany(ctx.idbList.front(),"\n"); \ 00057 std::cerr << std::endl; \ 00058 LOG(DBG, "idb end"); 00059 00060 /* 00061 #define LOG_REGISTRY_PROGRAM(ctx) \ 00062 LOG(*ctx.registry); \ 00063 RawPrinter printer(std::cerr, ctx.registry); \ 00064 std::cerr << "edb = " << *ctx.edb << std::endl; \ 00065 LOG("idb"); \ 00066 printer.printmany(ctx.idb,"\n"); \ 00067 std::cerr << std::endl; \ 00068 LOG("idb end");*/ 00069 00070 00071 LOG_INIT(Logger::ERROR | Logger::WARNING) 00072 00073 DLVHEX_NAMESPACE_USE 00074 00075 00076 BOOST_AUTO_TEST_CASE(testHexParserModuleAtoms) 00077 { 00078 ProgramCtx ctx; 00079 ctx.setupRegistry(RegistryPtr(new Registry)); 00080 00081 //.. put into different files 00082 00083 char *TOP_SRCDIR = getenv("TOP_SRCDIR"); 00084 assert(TOP_SRCDIR != 0); 00085 00086 std::string filename1(TOP_SRCDIR); 00087 std::string filename2(TOP_SRCDIR); 00088 std::string filename3(TOP_SRCDIR); 00089 00090 filename1 += "/examples/module1.mlp"; 00091 filename2 += "/examples/module2.mlp"; 00092 filename3 += "/examples/module3.mlp"; 00093 std::ifstream ifs; 00094 std::ostringstream buf; 00095 00096 ifs.open(filename1.c_str()); 00097 BOOST_REQUIRE(ifs.is_open()); 00098 buf << ifs.rdbuf(); 00099 ifs.close(); 00100 00101 ifs.open(filename2.c_str()); 00102 BOOST_REQUIRE(ifs.is_open()); 00103 buf << ifs.rdbuf(); 00104 ifs.close(); 00105 00106 ifs.open(filename3.c_str()); 00107 BOOST_REQUIRE(ifs.is_open()); 00108 buf << ifs.rdbuf(); 00109 ifs.close(); 00110 00111 std::stringstream ss; 00112 ss << buf.str(); 00113 std::cout << ss.str() << std::endl; 00114 00115 /* 00116 std::stringstream ss; 00117 ss << 00118 "#module(p1,[q1/1])." << std::endl << 00119 "q1(a)." << std::endl << 00120 "q1(b)." << std::endl << 00121 "ok :- @p2[q1]::even(c)." << std::endl << 00122 "#module(p2,[q2/1])." << std::endl << 00123 "q2i(X) v q2i(Y) :- q2(X), q2(Y), X!=Y." << std::endl << 00124 "skip2 :- q2(X), not q2i(X)." << std::endl << 00125 "even(c) :- not skip2." << std::endl << 00126 "even(c) :- skip2, @p3[q2i]::odd." << std::endl << 00127 std::endl << 00128 "#module(p3,[q3/1])." << std::endl << 00129 "q3i(X) v q3i(Y) :- q3(X), q3(Y), X!=Y." << std::endl << 00130 "skip3 :- q3(X), not q3i(X)." << std::endl << 00131 "odd :- skip3, @p2[q3i]::even(c)."; 00132 */ 00133 00134 InputProviderPtr ip(new InputProvider); 00135 ip->addStreamInput(ss, "testinput"); 00136 ModuleHexParser parser; 00137 BOOST_REQUIRE_NO_THROW(parser.parse(ip, ctx)); 00138 00139 // after parser, print ctx 00140 LOG_REGISTRY_PROGRAM(ctx); 00141 00142 // check some atoms (got the idea from TestHexParser.cpp) 00143 ID idp = ctx.registry()->preds.getIDByString("p1__q1"); 00144 ID idq = ctx.registry()->preds.getIDByString("p2__q2"); 00145 ID idr = ctx.registry()->preds.getIDByString("p3__q3"); 00146 ID idb = ctx.registry()->preds.getIDByString("p1__ok"); 00147 ID idc = ctx.registry()->preds.getIDByString("p2__even"); 00148 ID idmymod = ctx.registry()->preds.getIDByString("p3__p2"); 00149 00150 // the id should not fail 00151 BOOST_REQUIRE((idp) != ID_FAIL); 00152 BOOST_REQUIRE((idq) != ID_FAIL); 00153 BOOST_REQUIRE((idr) != ID_FAIL); 00154 BOOST_REQUIRE((idb) != ID_FAIL); 00155 BOOST_REQUIRE((idc) != ID_FAIL); 00156 BOOST_REQUIRE((idmymod) != ID_FAIL); 00157 ID mod1(ID::MAINKIND_ATOM | ID::SUBKIND_ATOM_MODULE, 0); 00158 BOOST_REQUIRE( ctx.registry()->matoms.getByID(mod1).actualModuleName == "p2" ); 00159 ID mod2(ID::MAINKIND_ATOM | ID::SUBKIND_ATOM_MODULE, 1); 00160 BOOST_REQUIRE( ctx.registry()->matoms.getByID(mod2).actualModuleName == "p3" ); 00161 ID mod3(ID::MAINKIND_ATOM | ID::SUBKIND_ATOM_MODULE, 2); 00162 BOOST_REQUIRE( ctx.registry()->matoms.getByID(mod3).actualModuleName == "p2" ); 00163 // BOOST_REQUIRE(ctx.edb != 0); 00164 // BOOST_REQUIRE(ctx.idb.size() == 3); 00165 { 00166 const Rule& r = ctx.registry()->rules.getByID(ctx.idbList.back()[2]); 00167 BOOST_CHECK(r.kind == (ID::MAINKIND_RULE | ID::SUBKIND_RULE_REGULAR | ID::PROPERTY_RULE_MODATOMS)); 00168 BOOST_CHECK(r.weight == ID_FAIL); 00169 BOOST_CHECK(r.level == ID_FAIL); 00170 BOOST_CHECK(r.head.size() == 1); 00171 BOOST_REQUIRE(r.body.size() == 2); 00172 { 00173 ID idlit = r.body[1]; 00174 BOOST_CHECK(idlit.isLiteral()); 00175 BOOST_CHECK(idlit.isModuleAtom()); 00176 } 00177 } 00178 00179 // syntax verifying: 00180 MLPSyntaxChecker sC(ctx); 00181 BOOST_REQUIRE( sC.verifySyntax() == true ); 00182 00183 } 00184 00185 00186 00187 // test case if we call a module that is not exist 00188 BOOST_AUTO_TEST_CASE(testCallNotExistModule) 00189 { 00190 ProgramCtx ctx; 00191 ctx.setupRegistry(RegistryPtr(new Registry)); 00192 00193 //.. put into different files 00194 char *TOP_SRCDIR = getenv("TOP_SRCDIR"); 00195 assert(TOP_SRCDIR != 0); 00196 00197 std::string filename1(TOP_SRCDIR); 00198 filename1 += "/examples/module1.mlp"; 00199 std::ifstream ifs; 00200 std::ostringstream buf; 00201 00202 ifs.open(filename1.c_str()); 00203 BOOST_REQUIRE(ifs.is_open()); 00204 buf << ifs.rdbuf(); 00205 std::string input1 = buf.str(); 00206 ifs.close(); 00207 00208 std::stringstream ss; 00209 ss << input1; 00210 00211 InputProviderPtr ip(new InputProvider); 00212 ip->addStreamInput(ss, "testinput"); 00213 ModuleHexParser parser; 00214 BOOST_REQUIRE_NO_THROW(parser.parse(ip, ctx)); 00215 00216 LOG_REGISTRY_PROGRAM(ctx); 00217 00218 MLPSyntaxChecker sC(ctx); 00219 // BOOST_REQUIRE( sC.verifySyntax() == false ); 00220 BOOST_REQUIRE_THROW(sC.verifySyntax(), FatalError); 00221 } 00222 00223 00224 // test case if there is a predicate input in module header (is okay) 00225 // that is not exist in module body 00226 BOOST_AUTO_TEST_CASE(testPredInputsNotExistModuleHeader) 00227 { 00228 ProgramCtx ctx; 00229 ctx.setupRegistry(RegistryPtr(new Registry)); 00230 00231 char *TOP_SRCDIR = getenv("TOP_SRCDIR"); 00232 assert(TOP_SRCDIR != 0); 00233 00234 std::string filename1(TOP_SRCDIR); 00235 filename1 += "/examples/module1-NotExist.mlp"; 00236 std::ifstream ifs; 00237 std::ostringstream buf; 00238 00239 ifs.open(filename1.c_str()); 00240 BOOST_REQUIRE(ifs.is_open()); 00241 buf << ifs.rdbuf(); 00242 ifs.close(); 00243 00244 std::stringstream ss; 00245 ss << buf.str(); 00246 00247 InputProviderPtr ip(new InputProvider); 00248 ip->addStreamInput(ss, "testinput"); 00249 ModuleHexParser parser; 00250 BOOST_REQUIRE_NO_THROW(parser.parse(ip, ctx)); 00251 00252 LOG_REGISTRY_PROGRAM(ctx); 00253 00254 MLPSyntaxChecker sC(ctx); 00255 BOOST_REQUIRE( sC.verifySyntax() == true ); 00256 } 00257 00258 00259 00260 // test case if there are too many predicate inputs in module calls 00261 // for example: call p2[p,q,r]::q(a) but actually module p2 need only 2 predicate inputs 00262 BOOST_AUTO_TEST_CASE(testTooManyPredInputsModuleCalls) 00263 { 00264 ProgramCtx ctx; 00265 ctx.setupRegistry(RegistryPtr(new Registry)); 00266 00267 std::ifstream ifs; 00268 std::ostringstream buf; 00269 00270 char *TOP_SRCDIR = getenv("TOP_SRCDIR"); 00271 assert(TOP_SRCDIR != 0); 00272 00273 std::string filename1(TOP_SRCDIR); 00274 filename1 += "/examples/module2-TooMany.mlp"; 00275 00276 ifs.open(filename1.c_str()); 00277 BOOST_REQUIRE(ifs.is_open()); 00278 buf << ifs.rdbuf(); 00279 ifs.close(); 00280 00281 std::string filename2(TOP_SRCDIR); 00282 filename2 += "/examples/module3.mlp"; 00283 ifs.open(filename2.c_str()); 00284 BOOST_REQUIRE(ifs.is_open()); 00285 buf << ifs.rdbuf(); 00286 ifs.close(); 00287 00288 std::stringstream ss; 00289 ss << buf.str(); 00290 00291 InputProviderPtr ip(new InputProvider); 00292 ip->addStreamInput(ss, "testinput"); 00293 ModuleHexParser parser; 00294 BOOST_REQUIRE_NO_THROW(parser.parse(ip, ctx)); 00295 00296 LOG_REGISTRY_PROGRAM(ctx); 00297 00298 MLPSyntaxChecker sC(ctx); 00299 //rmv. BOOST_REQUIRE( sC.verifySyntax() == false ); 00300 BOOST_REQUIRE_THROW(sC.verifySyntax(), FatalError); 00301 } 00302 00303 00304 // test case if there are too few predicate inputs in module calls 00305 // for example: call p2[p]::q(a) but actually module p2 need 2 predicate inputs 00306 BOOST_AUTO_TEST_CASE(testTooFewPredInputsModuleCalls) 00307 { 00308 ProgramCtx ctx; 00309 ctx.setupRegistry(RegistryPtr(new Registry)); 00310 00311 char *TOP_SRCDIR = getenv("TOP_SRCDIR"); 00312 assert(TOP_SRCDIR != 0); 00313 00314 std::string filename1(TOP_SRCDIR); 00315 std::ifstream ifs; 00316 std::ostringstream buf; 00317 filename1 += "/examples/module2-TooFew.mlp"; 00318 00319 ifs.open(filename1.c_str()); 00320 BOOST_REQUIRE(ifs.is_open()); 00321 buf << ifs.rdbuf(); 00322 ifs.close(); 00323 00324 std::string filename2(TOP_SRCDIR); 00325 filename2 += "/examples/module3.mlp"; 00326 ifs.open(filename2.c_str()); 00327 BOOST_REQUIRE(ifs.is_open()); 00328 buf << ifs.rdbuf(); 00329 ifs.close(); 00330 00331 std::stringstream ss; 00332 ss << buf.str(); 00333 00334 InputProviderPtr ip(new InputProvider); 00335 ip->addStreamInput(ss, "testinput"); 00336 ModuleHexParser parser; 00337 BOOST_REQUIRE_NO_THROW(parser.parse(ip, ctx)); 00338 00339 LOG_REGISTRY_PROGRAM(ctx); 00340 00341 MLPSyntaxChecker sC(ctx); 00342 //rmv. BOOST_REQUIRE( sC.verifySyntax() == false ); 00343 BOOST_REQUIRE_THROW(sC.verifySyntax(), FatalError); 00344 } 00345 00346 00347 // test case if the arity of predicate inputs in module calls are different 00348 // from the one specified in the module header 00349 // for example: p2[p]::q(a,c) where p is a predicate with arity 2 00350 // but actually we have #module(p2, p/1). 00351 BOOST_AUTO_TEST_CASE(testDifferentArityPredInputsModuleCalls) 00352 { 00353 ProgramCtx ctx; 00354 ctx.setupRegistry(RegistryPtr(new Registry)); 00355 00356 char *TOP_SRCDIR = getenv("TOP_SRCDIR"); 00357 assert(TOP_SRCDIR != 0); 00358 00359 std::string filename1(TOP_SRCDIR); 00360 std::ifstream ifs; 00361 std::ostringstream buf; 00362 filename1 += "/examples/module2-DiffArity.mlp"; 00363 00364 ifs.open(filename1.c_str()); 00365 BOOST_REQUIRE(ifs.is_open()); 00366 buf << ifs.rdbuf(); 00367 ifs.close(); 00368 00369 std::string filename2(TOP_SRCDIR); 00370 filename2 += "/examples/module3.mlp"; 00371 ifs.open(filename2.c_str()); 00372 BOOST_REQUIRE(ifs.is_open()); 00373 buf << ifs.rdbuf(); 00374 ifs.close(); 00375 00376 std::stringstream ss; 00377 ss << buf.str(); 00378 00379 InputProviderPtr ip(new InputProvider); 00380 ip->addStreamInput(ss, "testinput"); 00381 ModuleHexParser parser; 00382 BOOST_REQUIRE_NO_THROW(parser.parse(ip, ctx)); 00383 00384 LOG_REGISTRY_PROGRAM(ctx); 00385 00386 MLPSyntaxChecker sC(ctx); 00387 //rmv. BOOST_REQUIRE( sC.verifySyntax() == false ); 00388 BOOST_REQUIRE_THROW(sC.verifySyntax(), FatalError); 00389 } 00390 00391 00392 // test case if the predicate output in the module call 00393 // not exist in the module that being called 00394 BOOST_AUTO_TEST_CASE(testPredOutputsModuleCallsNotExist) 00395 { 00396 ProgramCtx ctx; 00397 ctx.setupRegistry(RegistryPtr(new Registry)); 00398 00399 char *TOP_SRCDIR = getenv("TOP_SRCDIR"); 00400 assert(TOP_SRCDIR != 0); 00401 00402 std::string filename1(TOP_SRCDIR); 00403 std::ifstream ifs; 00404 std::ostringstream buf; 00405 filename1 += "/examples/module3-NotExist.mlp"; 00406 00407 ifs.open(filename1.c_str()); 00408 BOOST_REQUIRE(ifs.is_open()); 00409 buf << ifs.rdbuf(); 00410 ifs.close(); 00411 00412 std::string filename2(TOP_SRCDIR); 00413 filename2 += "/examples/module2.mlp"; 00414 ifs.open(filename2.c_str()); 00415 BOOST_REQUIRE(ifs.is_open()); 00416 buf << ifs.rdbuf(); 00417 ifs.close(); 00418 00419 std::stringstream ss; 00420 ss << buf.str(); 00421 00422 InputProviderPtr ip(new InputProvider); 00423 ip->addStreamInput(ss, "testinput"); 00424 ModuleHexParser parser; 00425 BOOST_REQUIRE_NO_THROW(parser.parse(ip, ctx)); 00426 00427 LOG_REGISTRY_PROGRAM(ctx); 00428 00429 MLPSyntaxChecker sC(ctx); 00430 //rmv. BOOST_REQUIRE( sC.verifySyntax() == false ); 00431 BOOST_REQUIRE_THROW(sC.verifySyntax(), FatalError); 00432 } 00433 00434 00435 // test case if predicate output in the module call have a different arity 00436 // with the one inside the module that being called 00437 BOOST_AUTO_TEST_CASE(testDifferentArityPredOutputsModuleCalls) 00438 { 00439 ProgramCtx ctx; 00440 ctx.setupRegistry(RegistryPtr(new Registry)); 00441 00442 char *TOP_SRCDIR = getenv("TOP_SRCDIR"); 00443 assert(TOP_SRCDIR != 0); 00444 00445 std::string filename1(TOP_SRCDIR); 00446 std::ifstream ifs; 00447 std::ostringstream buf; 00448 filename1 += "/examples/module3-DiffArity.mlp"; 00449 00450 ifs.open(filename1.c_str()); 00451 BOOST_REQUIRE(ifs.is_open()); 00452 buf << ifs.rdbuf(); 00453 ifs.close(); 00454 00455 std::string filename2(TOP_SRCDIR); 00456 filename2 += "/examples/module2.mlp"; 00457 ifs.open(filename2.c_str()); 00458 BOOST_REQUIRE(ifs.is_open()); 00459 buf << ifs.rdbuf(); 00460 ifs.close(); 00461 00462 std::stringstream ss; 00463 ss << buf.str(); 00464 00465 InputProviderPtr ip(new InputProvider); 00466 ip->addStreamInput(ss, "testinput"); 00467 ModuleHexParser parser; 00468 BOOST_REQUIRE_NO_THROW(parser.parse(ip, ctx)); 00469 00470 LOG_REGISTRY_PROGRAM(ctx); 00471 00472 MLPSyntaxChecker sC(ctx); 00473 //rmv. BOOST_REQUIRE( sC.verifySyntax() == false ); 00474 BOOST_REQUIRE_THROW(sC.verifySyntax(), FatalError); 00475 } 00476 00477 00478 // test case for module call with different order of arity 00479 // for example: @p3[q, r]::even, where q is predicate with arity 1 and r is a predicate with arity 0 00480 // but we have #module(p3, [s/0, t/1]). 00481 BOOST_AUTO_TEST_CASE(testSwapArityPredInputsModuleCalls) 00482 { 00483 ProgramCtx ctx; 00484 ctx.setupRegistry(RegistryPtr(new Registry)); 00485 00486 char *TOP_SRCDIR = getenv("TOP_SRCDIR"); 00487 assert(TOP_SRCDIR != 0); 00488 00489 std::string filename1(TOP_SRCDIR); 00490 std::ifstream ifs; 00491 std::ostringstream buf; 00492 filename1 += "/examples/module3-SwapArity.mlp"; 00493 00494 ifs.open(filename1.c_str()); 00495 BOOST_REQUIRE(ifs.is_open()); 00496 buf << ifs.rdbuf(); 00497 ifs.close(); 00498 00499 std::string filename2(TOP_SRCDIR); 00500 filename2 += "/examples/module2-SwapArity.mlp"; 00501 ifs.open(filename2.c_str()); 00502 BOOST_REQUIRE(ifs.is_open()); 00503 buf << ifs.rdbuf(); 00504 ifs.close(); 00505 00506 std::stringstream ss; 00507 ss << buf.str(); 00508 00509 InputProviderPtr ip(new InputProvider); 00510 ip->addStreamInput(ss, "testinput"); 00511 ModuleHexParser parser; 00512 BOOST_REQUIRE_NO_THROW(parser.parse(ip, ctx)); 00513 00514 LOG_REGISTRY_PROGRAM(ctx); 00515 00516 MLPSyntaxChecker sC(ctx); 00517 //rmv. BOOST_REQUIRE( sC.verifySyntax() == false ); 00518 BOOST_REQUIRE_THROW(sC.verifySyntax(), FatalError); 00519 } 00520 00521 00522 00523 00524 /* TODO handle this? 00525 // test case if the predicate inputs specified in the module header have a different arity 00526 // with the one in the module body 00527 BOOST_AUTO_TEST_CASE(testDifferentArityModuleHeader) 00528 { 00529 ProgramCtx ctx; 00530 ctx.registry = RegistryPtr(new Registry); 00531 00532 std::string filename1 = "../../examples/module1-DiffArity.mlp"; 00533 std::ifstream ifs; 00534 std::ostringstream buf; 00535 00536 ifs.open(filename1.c_str()); 00537 BOOST_REQUIRE(ifs.is_open()); 00538 buf << ifs.rdbuf(); 00539 ifs.close(); 00540 00541 std::stringstream ss; 00542 ss << buf.str(); 00543 00544 HexParser parser(ctx); 00545 BOOST_REQUIRE_NO_THROW(parser.parse(ss)); 00546 LOG_REGISTRY_PROGRAM(ctx); 00547 00548 MLPSyntaxChecker sC(ctx); 00549 BOOST_REQUIRE( sC.verifySyntax() == false ); 00550 } 00551 */ 00552 00553 /* 00554 BOOST_AUTO_TEST_CASE(testDuplicateModuleHeader) 00555 { 00556 ProgramCtx ctx; 00557 ctx.setupRegistry(RegistryPtr(new Registry)); 00558 00559 std::string filename1 = "../../examples/module1.mlp"; 00560 std::ifstream ifs; 00561 std::ostringstream buf; 00562 00563 ifs.open(filename1.c_str()); 00564 BOOST_REQUIRE(ifs.is_open()); 00565 buf << ifs.rdbuf(); 00566 buf << ifs.rdbuf(); 00567 ifs.close(); 00568 00569 std::stringstream ss; 00570 ss << buf.str(); 00571 00572 HexParser parser(ctx); 00573 BOOST_CHECK_THROW(parser.parse(ss), SyntaxError); 00574 } 00575 00576 BOOST_AUTO_TEST_CASE(EndMessage) 00577 { 00578 std::cout << "[TestHexParserModule::BOOST_AUTO_TEST_CASE(EndMessage)] *** 1 failure ( from BOOST_AUTO_TEST_CASE(testDuplicateModuleHeader) ) is expected *** " <<std::endl; 00579 } 00580 */ 00581