/********************************************************************** * $Id: XMLTester.cpp,v 1.48.2.4.2.2 2006/03/06 14:54:19 strk Exp $ * * GEOS - Geometry Engine Open Source * http://geos.refractions.net * * Copyright (C) 2005-2006 Refractions Research Inc. * Copyright (C) 2001-2002 Vivid Solutions Inc. * * This is free software; you can redistribute and/or modify it under * the terms of the GNU Lesser General Public Licence as published * by the Free Software Foundation. * See the COPYING file for more information. * **********************************************************************/ //#define _CRTDBG_MAP_ALLOC //#include #ifdef _MSC_VER #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include <../io/markup/MarkupSTL.h> #include #include #include "XMLTester.h" //#include "util.h" //#include "geomgraph.h" //#include "io.h" //#include "opRelate.h" //#include "MarkupSTL.h" #ifdef _MSC_VER #include #include "Stackwalker.h" #endif using namespace geos; //using namespace geos::operation::polygonize; //using namespace geos::operation::linemerge; //using geos::Polygon; // for mingw providing a Polygon global function template unsigned char safe_ctype(unsigned char c) { return F(c); } void tolower(std::string& str) { std::transform(str.begin(), str.end(), str.begin(), safe_ctype); } XMLTester::XMLTester() : gA(0), gB(0), gT(0), pm(0), factory(0), r(0), w(0), br(0), test_predicates(0), failed(0), succeeded(0), caseCount(0), testCount(0), testFileCount(0), totalTestCount(0), curr_file(NULL), testValidOutput(false), testValidInput(false) { setVerbosityLevel(0); } int XMLTester::setVerbosityLevel(int value) { int old_value=verbose; verbose=value; return old_value; } void XMLTester::run(const std::string &source) { curr_file=&source; ++testFileCount; caseCount=0; xml.Load(source.c_str()); xml.ResetPos(); xml.FindElem("run"); xml.FindChildElem("precisionModel"); parsePrecisionModel(); while (xml.FindChildElem("case")) { try { parseCase(); } catch (GEOSException* exc) { std::cerr << exc->toString() << std::endl; delete exc; } } } void XMLTester::resultSummary(std::ostream &os) const { os<<"Files: "<toString() <getMessage(); //NOTICE_MESSAGE(err->getMessage().c_str()); std::cerr << *curr_file << ":" << " case" << caseCount << ":" << " test" << testCount << ": " << opSignature << ": " << " invalid geometry (" << label << "): " << err->getMessage() << std::endl; } } //return result; } /** * Parse WKT or HEXWKB */ Geometry * XMLTester::parseGeometry(const std::string &in) { Geometry* ret = r->read(in); if ( testValidInput ) testValid(ret, "parsed"); return ret; } std::string XMLTester::trimBlanks(const std::string &in) { std::string out; std::string::size_type pos = in.find_first_not_of(" \t\n\r"); if (pos!=std::string::npos) out=in.substr(pos); pos = out.find_last_not_of(" \t\n\r"); if (pos!=std::string::npos) out=out.substr(0, pos+1); return out; } void XMLTester::parseCase() { std::string geomAin; std::string geomBin; std::string thrownException; gA=NULL; gB=NULL; xml.IntoElem(); xml.FindChildElem("desc"); curr_case_desc=trimBlanks(xml.GetChildData()); try { xml.FindChildElem("a"); geomAin=xml.GetChildData(); geomAin=trimBlanks(geomAin); gA=parseGeometry(geomAin); if ( xml.FindChildElem("b") ) { geomBin=xml.GetChildData(); geomBin=trimBlanks(geomBin); gB=parseGeometry(geomBin); } } catch (GEOSException* ex) { thrownException = ex->toString(); delete ex; } catch (const std::exception &e) { thrownException = e.what(); } catch (...) { thrownException = "Unknown exception"; } if ( thrownException != "" ) { std::cout << *curr_file <<":"; std::cout << " case" << caseCount << ":"; std::cout << " skipped ("<relate(gB); assert(im); if (im->matches(opArg3)) actual_result="true"; else actual_result="false"; if (actual_result==opRes) success=1; delete im; } else if (opName=="isvalid") { Geometry *gT=gA; if ( ( opArg1 == "B" || opArg1 == "b" ) && gB ) { gT=gB; } if (gT->isValid()) actual_result="true"; else actual_result="false"; if (actual_result==opRes) success=1; } else if (opName=="intersection") { Geometry *gRes=NULL; Geometry *gRealRes=NULL; gRes=r->read(opRes); gRes->normalize(); try { gRealRes=gA->intersection(gB); gRealRes->normalize(); } catch (...) { delete gRealRes; delete gRes; throw; } if (gRes->compareTo(gRealRes)==0) success=1; if ( testValidOutput ) testValid(gRes, "result"); actual_result=gRealRes->toString(); expected_result=gRes->toString(); delete gRes; delete gRealRes; } else if (opName=="union") { Geometry *gRes=r->read(opRes); gRes->normalize(); Geometry *gRealRes=gA->Union(gB); gRealRes->normalize(); if (gRes->compareTo(gRealRes)==0) success=1; if ( testValidOutput ) testValid(gRes, "result"); actual_result=gRealRes->toString(); expected_result=gRes->toString(); delete gRes; delete gRealRes; } else if (opName=="difference") { Geometry *gRes=r->read(opRes); gRes->normalize(); Geometry *gRealRes=gA->difference(gB); gRealRes->normalize(); if (gRes->compareTo(gRealRes)==0) success=1; if ( testValidOutput ) testValid(gRes, "result"); actual_result=gRealRes->toString(); expected_result=gRes->toString(); delete gRes; delete gRealRes; } else if (opName=="symdifference") { Geometry *gRes=r->read(opRes); gRes->normalize(); Geometry *gRealRes=gA->symDifference(gB); gRealRes->normalize(); if (gRes->compareTo(gRealRes)==0) success=1; if ( testValidOutput ) testValid(gRes, "result"); actual_result=gRealRes->toString(); expected_result=gRes->toString(); delete gRes; delete gRealRes; } else if (opName=="intersects") { if (gA->intersects(gB)) actual_result="true"; else actual_result="false"; if (actual_result==opRes) success=1; } else if (opName=="getboundary") { Geometry *gT=gA; if ( ( opArg1 == "B" || opArg1 == "b" ) && gB ) gT=gB; Geometry *gRes=r->read(opRes); gRes->normalize(); Geometry *gRealRes=gT->getBoundary(); gRealRes->normalize(); if (gRes->compareTo(gRealRes)==0) success=1; if ( testValidOutput ) testValid(gRes, "result"); actual_result=gRealRes->toString(); expected_result=gRes->toString(); delete gRes; delete gRealRes; } else if (opName=="getcentroid") { Geometry *gT=gA; if ( ( opArg1 == "B" || opArg1 == "b" ) && gB ) gT=gB; Geometry *gRes=r->read(opRes); gRes->normalize(); Geometry *gRealRes=gT->getCentroid(); if ( gRealRes ) gRealRes->normalize(); else gRealRes = factory->createGeometryCollection(); gRealRes->normalize(); if (gRes->compareTo(gRealRes)==0) success=1; if ( testValidOutput ) testValid(gRes, "result"); actual_result=gRealRes->toString(); expected_result=gRes->toString(); delete gRes; delete gRealRes; } else if (opName=="issimple") { Geometry *gT=gA; if ( ( opArg1 == "B" || opArg1 == "b" ) && gB ) gT=gB; if (gT->isSimple()) actual_result="true"; else actual_result="false"; if (actual_result==opRes) success=1; } else if (opName=="convexhull") { Geometry *gT=gA; if ( ( opArg1 == "B" || opArg1 == "b" ) && gB ) gT=gB; Geometry *gRes=r->read(opRes); gRes->normalize(); Geometry *gRealRes=gT->convexHull(); gRealRes->normalize(); if (gRes->compareTo(gRealRes)==0) success=1; if ( testValidOutput ) testValid(gRes, "result"); actual_result=gRealRes->toString(); expected_result=gRes->toString(); delete gRes; delete gRealRes; } else if (opName=="buffer") { Geometry *gT=gA; if ( ( opArg1 == "B" || opArg1 == "b" ) && gB ) gT=gB; Geometry *gRes=r->read(opRes); gRes->normalize(); profile.start(); Geometry *gRealRes; if ( opArg2 != "" ) { gRealRes=gT->buffer(atof(opArg3.c_str()), atoi(opArg2.c_str())); } else { gRealRes=gT->buffer(atof(opArg3.c_str())); } profile.stop(); gRealRes->normalize(); /// Allow for slightly different representations if (gRes->equalsExact(gRealRes, 0.00000000000001)==true) success=1; //if (gRes->compareTo(gRealRes)==0) success=1; if ( testValidOutput ) testValid(gRes, "result"); actual_result=gRealRes->toString(); expected_result=gRes->toString(); delete gRealRes; delete gRes; } else if (opName=="getinteriorpoint") { Geometry *gT=gA; if ( ( opArg1 == "B" || opArg1 == "b" ) && gB ) gT=gB; Geometry *gRes=r->read(opRes); gRes->normalize(); Geometry *gRealRes=gT->getInteriorPoint(); if ( gRealRes ) gRealRes->normalize(); else gRealRes = factory->createGeometryCollection(); if (gRes->compareTo(gRealRes)==0) success=1; if ( testValidOutput ) testValid(gRes, "result"); actual_result=gRealRes->toString(); expected_result=gRes->toString(); delete gRes; delete gRealRes; } else if (opName=="iswithindistance") { float dist=atof(opArg3.c_str()); if (gA->isWithinDistance(gB, dist)) { actual_result="true"; } else { actual_result="false"; } if (actual_result==opRes) success=1; } else if (opName=="polygonize") { Geometry *gRes=NULL; Geometry *gRealRes=NULL; gRes=r->read(opRes); gRes->normalize(); try { Polygonizer plgnzr; plgnzr.add(gA); std::vector*polys = plgnzr.getPolygons(); std::vector*newgeoms = new std::vector; for (unsigned int i=0; isize(); i++) newgeoms->push_back((*polys)[i]); delete polys; gRealRes=factory->createGeometryCollection(newgeoms); gRealRes->normalize(); } catch (...) { delete gRealRes; delete gRes; throw; } if (gRes->compareTo(gRealRes)==0) success=1; if ( testValidOutput ) testValid(gRes, "result"); actual_result=gRealRes->toString(); expected_result=gRes->toString(); delete gRealRes; delete gRes; } else if (opName=="linemerge") { Geometry *gRes=NULL; Geometry *gRealRes=NULL; gRes=r->read(opRes); gRes->normalize(); Geometry *gT=gA; if ( ( opArg1 == "B" || opArg1 == "b" ) && gB ) gT=gB; try { LineMerger merger; merger.add(gT); std::vector*lines = merger.getMergedLineStrings(); std::vector*newgeoms = new std::vector(lines->begin(), lines->end()); delete lines; gRealRes=factory->createGeometryCollection(newgeoms); gRealRes->normalize(); } catch (...) { delete gRealRes; delete gRes; throw; } if (gRes->compareTo(gRealRes)==0) success=1; if ( testValidOutput ) testValid(gRes, "result"); actual_result=gRealRes->toString(); expected_result=gRes->toString(); delete gRealRes; delete gRes; } else { if ( 1 ) // verbose { std::cerr << *curr_file << ":"; std::cerr << " case" << caseCount << ":"; std::cerr << " test" << testCount << ": " << opName << "(" << opSig << ")"; std::cerr << ": skipped (unrecognized)." << std::endl; } return; } } catch (const std::exception &e) { std::cerr<<"EXCEPTION on case "< 1) { std::cout << *curr_file <<":"; std::cout << " case" << caseCount << ":"; std::cout << " test" << testCount << ": " << opName << "(" << opSig <<")"; std::cout << ": " << (success?"ok.":"failed.")<write(gA); std::cout << "\tGeometry A: " << geomOut << std::endl; } if ( gB ) { geomOut=w->write(gB); std::cout << "\tGeometry B: " << geomOut << std::endl; } std::cout << "\tExpected result: "< [ ...]" << std::endl; os << " Multiple -v increments verbosity" << std::endl; exit(exitcode); } int main(int argC, char* argV[]) { int verbose=0; #ifdef _MSC_VER InitAllocCheck(); { #endif if ( argC < 2 ) usage(argV[0], 1, std::cerr); XMLTester tester; tester.setVerbosityLevel(verbose); for (int i=1; i namespaces mapping for most GEOS internal code (uncomplete, but working). Dir-level libs for index/ subdirs. * * Revision 1.3 2006/02/14 13:28:26 strk * New SnapRounding code ported from JTS-1.7 (not complete yet). * Buffer op optimized by using new snaprounding code. * Leaks fixed in XMLTester. * * Revision 1.2 2006/02/09 15:52:47 strk * GEOSException derived from std::exception; always thrown and cought by const ref. * * Revision 1.1 2006/01/31 19:07:35 strk * - Renamed DefaultCoordinateSequence to CoordinateArraySequence. * - Moved GetNumGeometries() and GetGeometryN() interfaces * from GeometryCollection to Geometry class. * - Added getAt(int pos, Coordinate &to) funtion to CoordinateSequence class. * - Reworked automake scripts to produce a static lib for each subdir and * then link all subsystem's libs togheter * - Moved C-API in it's own top-level dir capi/ * - Moved source/bigtest and source/test to tests/bigtest and test/xmltester * - Fixed PointLocator handling of LinearRings * - Changed CoordinateArrayFilter to reduce memory copies * - Changed UniqueCoordinateArrayFilter to reduce memory copies * - Added CGAlgorithms::isPointInRing() version working with * Coordinate::ConstVect type (faster!) * - Ported JTS-1.7 version of ConvexHull with big attention to * memory usage optimizations. * - Improved XMLTester output and user interface * - geos::geom::util namespace used for geom/util stuff * - Improved memory use in geos::geom::util::PolygonExtractor * - New ShortCircuitedGeometryVisitor class * - New operation/predicate package * * Revision 1.60 2006/01/18 17:49:58 strk * Reworked XMLTester to be quiet by default. Use -v switch to make it verbose. * * Revision 1.59 2006/01/18 12:54:48 strk * Added HEXWKB support in XMLTester. Added a simple test in HEXWKB form * and a 'test' rule running the locally-available tests and showing * result summay. * * Revision 1.58 2005/11/25 12:22:42 strk * Made XMLTester able to run multiple test files and keep overall * counters. * * Revision 1.57 2005/06/28 16:52:09 strk * Added number of points count as a debugging aid * * Revision 1.56 2005/06/21 12:22:19 strk * XMLTester code cleanups * * Revision 1.55 2005/06/14 11:57:03 strk * Added workaround for mingw Polygon name clash * * Revision 1.54 2005/06/10 13:24:50 strk * Added use declaration to make MingW build work * * Revision 1.53 2005/02/18 08:20:24 strk * Added support for point-per-quadrant argument in buffer tests (using arg2). * * Revision 1.52 2005/01/03 16:06:27 strk * Changed polygonize op to return a GeometryCollection * * Revision 1.51 2005/01/03 15:56:21 strk * Fixed memory leaks just introduced for Polygonizer test case. * * Revision 1.50 2005/01/03 15:49:30 strk * Added Polygonize test handling * * Revision 1.49 2004/12/30 13:32:30 strk * Handled NULL result from getCentroid() * * Revision 1.48 2004/12/08 13:54:44 strk * gcc warnings checked and fixed, general cleanups. * * Revision 1.47 2004/11/04 19:08:07 strk * Cleanups, initializers list, profiling. * * Revision 1.46 2004/11/02 09:38:33 strk * Added timer for buffer test. * * Revision 1.45 2004/09/13 12:39:49 strk * Added missing newline at end of output * * Revision 1.44 2004/07/07 09:38:12 strk * Dropped WKTWriter::stringOfChars (implemented by std::string). * Dropped WKTWriter default constructor (internally created GeometryFactory). * Updated XMLTester to respect the changes. * Main documentation page made nicer. * * Revision 1.43 2004/07/02 13:28:29 strk * Fixed all #include lines to reflect headers layout change. * Added client application build tips in README. * * Revision 1.42 2004/05/27 08:40:13 strk * Fixed a memleak in buffer test. * * Revision 1.41 2004/05/18 13:49:18 strk * Output made more neat (geometry B is not printed if not existent). * Added support for buffer tests. * * Revision 1.40 2004/05/17 12:53:52 strk * Expected result string trimmed for blanks * * Revision 1.39 2004/05/14 07:19:59 strk * Changed the algorythm for finding precisionModel type (current way did * not work): now if you specify a scale precisionModel will be FIXED, * otherwise it will be FLOATING. * * Revision 1.38 2004/05/07 13:23:51 strk * Memory leaks fixed. * * Revision 1.37 2004/03/19 09:48:46 ybychkov * "geomgraph" and "geomgraph/indexl" upgraded to JTS 1.4 * * Revision 1.36 2003/11/12 17:10:01 strk * added missing initialization * * Revision 1.35 2003/11/12 15:02:12 strk * more cleanup on exception * * Revision 1.34 2003/11/07 01:23:43 pramsey * Add standard CVS headers licence notices and copyrights to all cpp and h * files. * * Revision 1.33 2003/10/17 05:51:21 ybychkov * Fixed a small memory leak. * * Revision 1.32 2003/10/16 13:01:31 strk * Added call to Unload::Release() * * Revision 1.31 2003/10/16 12:09:48 strk * bug fixed in exception handling * * Revision 1.30 2003/10/16 08:48:06 strk * Exceptions handled * **********************************************************************/