mirror of https://github.com/CGAL/cgal
Fixed audit parsing in Linux
Fixed testsuite to handle unstable ordering of edges with equal collapse cost
This commit is contained in:
parent
6cdcb5d22e
commit
99a482f86e
|
|
@ -24,6 +24,8 @@
|
|||
#include <string>
|
||||
#include <fstream>
|
||||
|
||||
#include <boost/format.hpp>
|
||||
|
||||
#define CGAL_CHECK_EXPENSIVE
|
||||
|
||||
//#define TRACE
|
||||
|
|
@ -78,12 +80,15 @@ void error_handler ( char const* what, char const* expr, char const* file, int l
|
|||
|
||||
namespace SMS = CGAL::Surface_mesh_simplification ;
|
||||
|
||||
|
||||
template<class T>
|
||||
ostream& operator << ( ostream& os, optional<T> const& o )
|
||||
string opt2str ( optional<T> const& o )
|
||||
{
|
||||
ostringstream ss ;
|
||||
if ( o )
|
||||
return os << *o ;
|
||||
else return os << "<null>" ;
|
||||
ss << *o ;
|
||||
else ss << "<none>" ;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
template<class P>
|
||||
|
|
@ -110,20 +115,47 @@ string edge2str ( E const& e )
|
|||
return ss.str();
|
||||
}
|
||||
|
||||
#define SHOW_ERROR(msg) \
|
||||
{ \
|
||||
cerr << "\nError: " << msg << endl \
|
||||
<< " File:" << __FILE__ << endl \
|
||||
<< " Line:" << __LINE__ << endl ; \
|
||||
throw runtime_error("test error"); \
|
||||
}
|
||||
template<class D>
|
||||
string audit2str ( shared_ptr<D> const& d )
|
||||
{
|
||||
ostringstream ss ;
|
||||
ss << "[id:" << d->id ;
|
||||
if ( d->selected )
|
||||
{
|
||||
ss << " (S" << " at step " << d->order ;
|
||||
if ( d->cost )
|
||||
ss << " <" << *(d->cost) << ">" ;
|
||||
else ss << " <no-cost>" ;
|
||||
ss << ")";
|
||||
|
||||
if ( d->is_collapsable )
|
||||
{
|
||||
ss << " (C " ;
|
||||
if ( d->placement )
|
||||
ss << " <" << *(d->placement) << "> ";
|
||||
else ss << " <no-new-placement>" ;
|
||||
ss << ")";
|
||||
}
|
||||
else ss << " (not collapsed)" ;
|
||||
}
|
||||
else ss << " (not selected)" ;
|
||||
|
||||
ss << "]" ;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
template<class T> ostream& operator << ( ostream& os, optional<T> const& o ) { return os << opt2str(o); }
|
||||
|
||||
#define REPORT_ERROR(msg) error(__FILE__,__LINE__,0,msg);
|
||||
|
||||
#define REPORT_ERROR2(pred,msg) REPORT_ERROR(msg)
|
||||
|
||||
#define CHECK_MSG(pred,msg) if (!(pred)) SHOW_ERROR(msg)
|
||||
#define CHECK_MSG(pred,msg) if (!(pred)) REPORT_ERROR2(#pred,msg)
|
||||
|
||||
#define CHECK(pred) CHECK_MSG(pred,#pred)
|
||||
#define CHECK(pred) CHECK_MSG(pred,string(""))
|
||||
|
||||
#define CHECK_EQUAL(x,y) CHECK_MSG(((x)==(y)),"assertion " << #x << ":(" << x << ")==" << #y << ":(" << y << ") FAILED")
|
||||
#define CHECK_NOT_EQUAL(x,y) CHECK_MSG(((x)!=(y)),"assertion " << #x << ":(" << x << ")!=" << #y << ":(" << y << ") FAILED")
|
||||
#define CHECK_EQUAL(x,y) CHECK_MSG(((x)==(y)), str(format("Assertion failed: %1%(=%2%)==%3%(=%4%)") % (#x) % (x) % (#y) % (y) ) )
|
||||
#define CHECK_NOT_EQUAL(x,y) CHECK_MSG(((x)!=(y)), str(format("Assertion failed: %1%(=%2%)!=%3%(=%4%)") % (#x) % (x) % (#y) % (y) ) )
|
||||
|
||||
#include VISITOR
|
||||
|
||||
|
|
@ -189,7 +221,9 @@ bool Test ( string aName )
|
|||
}
|
||||
catch ( exception const& x )
|
||||
{
|
||||
cerr << "Exception caught: " << x.what() << endl ;
|
||||
string what(x.what());
|
||||
if ( what.length() > 0 )
|
||||
cerr << "Exception caught: " << what << endl ;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -239,4 +273,22 @@ int aux_main( int argc, char** argv )
|
|||
}
|
||||
}
|
||||
|
||||
namespace CGAL
|
||||
{
|
||||
|
||||
void assertion_fail( const char* expr, const char* file, int line )
|
||||
{
|
||||
assertion_fail(expr,file,line,"");
|
||||
}
|
||||
void precondition_fail( const char* expr, const char* file, int line )
|
||||
{
|
||||
precondition_fail(expr,file,line,"");
|
||||
}
|
||||
void postcondition_fail( const char* expr, const char* file, int line )
|
||||
{
|
||||
postcondition_fail(expr,file,line,"");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// EOF //
|
||||
|
|
|
|||
|
|
@ -8,13 +8,33 @@ private :
|
|||
|
||||
struct Data
|
||||
{
|
||||
Data ()
|
||||
Data ( size_t i )
|
||||
:
|
||||
selected(false)
|
||||
id(i)
|
||||
,selected(false)
|
||||
,is_collapsable(false)
|
||||
,order( size_t(-1) )
|
||||
{}
|
||||
|
||||
static bool match ( Data const& x, Data const& y )
|
||||
{
|
||||
bool r = false ;
|
||||
if ( x.selected == y.selected )
|
||||
{
|
||||
if ( x.selected )
|
||||
{
|
||||
if ( ( x.is_collapsable == y.is_collapsable )
|
||||
&& ( !x.cost == !y.cost )
|
||||
&& ( !x.placement == !y.placement )
|
||||
)
|
||||
r = true ;
|
||||
}
|
||||
else r = true ;
|
||||
}
|
||||
return r ;
|
||||
}
|
||||
|
||||
size_t id ;
|
||||
bool selected ;
|
||||
bool is_collapsable ;
|
||||
size_t order ;
|
||||
|
|
@ -24,12 +44,21 @@ private :
|
|||
typedef shared_ptr<Data> Data_ptr ;
|
||||
|
||||
typedef map<int,Data_ptr> Table ;
|
||||
|
||||
|
||||
|
||||
private :
|
||||
|
||||
typedef char_separator<char> Separator ;
|
||||
typedef tokenizer<Separator> Tokenizer ;
|
||||
|
||||
// The audit files are generated in a Windows machine, so if this runs on Linux there is a trailing CR that would mess up the tokenizer.
|
||||
string normalize_EOL ( string line )
|
||||
{
|
||||
string::size_type l = line.length();
|
||||
string::size_type d = ( l > 0 && line[l-1] == '\r' ) ? 1 : 0 ;
|
||||
return line.substr(0, l-d ) ;
|
||||
}
|
||||
|
||||
void ReadAudit( istream& in )
|
||||
{
|
||||
size_t order = 0 ;
|
||||
|
|
@ -38,34 +67,48 @@ private :
|
|||
{
|
||||
if ( line.length() > 1 )
|
||||
{
|
||||
line = normalize_EOL(line);
|
||||
|
||||
string h = str ( format("AUDIT: %1%") % line ) ;
|
||||
history.push_back(h);
|
||||
#ifdef TRACE
|
||||
std::cerr << "AUDIT: " << line << " (order=" << order << ")" << std::endl ;
|
||||
std::cerr << h << std::endl ;
|
||||
#endif
|
||||
|
||||
Tokenizer tk(line,Separator(" "));
|
||||
vector<string> tokens(tk.begin(),tk.end());
|
||||
CHECK( tokens.size() > 1 ) ;
|
||||
|
||||
CHECK_MSG( tokens.size() > 1, str(format("Invalid audit line, not enough tokens: %1%") % line) ) ;
|
||||
char c = tokens[0][0] ;
|
||||
switch ( c )
|
||||
{
|
||||
case 'I' :
|
||||
{
|
||||
CHECK( tokens.size() > 1 ) ;
|
||||
size_t id = lexical_cast<size_t>(tokens[1]);
|
||||
CHECK(audit_table.find(id)==audit_table.end());
|
||||
audit_table.insert(make_pair(id, Data_ptr( new Data() ) ) ) ;
|
||||
CHECK_MSG( tokens.size() > 1, str(format("Invalid audit line of type I, id field missing: %1%") % line) ) ;
|
||||
size_t id = lexical_cast<size_t>(tokens[1]);
|
||||
|
||||
CHECK_MSG(audit_table.find(id)==audit_table.end()
|
||||
,str(format("Invalid audit line of type I, id field with duplicate value: %1%") % line)
|
||||
);
|
||||
|
||||
audit_table.insert(make_pair(id, Data_ptr( new Data(id) ) ) ) ;
|
||||
}
|
||||
break ;
|
||||
|
||||
case 'S' :
|
||||
{
|
||||
CHECK_MSG( tokens.size() > 1, str(format("Invalid audit line of type S, id field missing: %1%") % line) ) ;
|
||||
size_t id = lexical_cast<size_t>(tokens[1]);
|
||||
Data_ptr data = audit_table[id];
|
||||
CHECK(data);
|
||||
|
||||
CHECK_MSG(data
|
||||
,str(format("Invalid audit line of type S, incorrect id field (doesn't match any previous I line): %1%") % line)
|
||||
);
|
||||
|
||||
optional<double> cost ;
|
||||
if ( tokens.size() > 2 )
|
||||
cost = lexical_cast<double>(tokens[2]);
|
||||
|
||||
data->selected = true ;
|
||||
data->cost = cost ;
|
||||
data->order = order++;
|
||||
|
|
@ -74,10 +117,14 @@ private :
|
|||
|
||||
case 'C' :
|
||||
{
|
||||
CHECK_MSG( tokens.size() > 1, str(format("Invalid audit line of type C, id field missing: %1%") % line) ) ;
|
||||
size_t id = lexical_cast<size_t>(tokens[1]);
|
||||
Data_ptr data = audit_table[id];
|
||||
CHECK(data);
|
||||
|
||||
CHECK_MSG(data
|
||||
,str(format("Invalid audit line of type C, incorrect id field (doesn't match any previous I line): %1%") % line)
|
||||
);
|
||||
|
||||
optional<Point> placement ;
|
||||
if ( tokens.size() > 4 )
|
||||
{
|
||||
|
|
@ -94,16 +141,20 @@ private :
|
|||
|
||||
case 'N' :
|
||||
{
|
||||
CHECK_MSG( tokens.size() > 1, str(format("Invalid audit line of type N, id field missing: %1%") % line) ) ;
|
||||
size_t id = lexical_cast<size_t>(tokens[1]);
|
||||
Data_ptr data = audit_table[id];
|
||||
CHECK(data);
|
||||
|
||||
CHECK_MSG(data
|
||||
,str(format("Invalid audit line of type N, incorrect id field (doesn't match any previous I line): %1%") % line)
|
||||
);
|
||||
|
||||
data->is_collapsable = false ;
|
||||
}
|
||||
break ;
|
||||
|
||||
default :
|
||||
SHOW_ERROR("Invalid audit line: " << line );
|
||||
REPORT_ERROR( str(format("Invalid audit line: %1%") % line) ) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -113,35 +164,48 @@ public :
|
|||
|
||||
Visitor ( string audit_name )
|
||||
{
|
||||
string h = str ( format("AUDIT FILE: %1%") % audit_name ) ;
|
||||
history.push_back(h);
|
||||
#ifdef TRACE
|
||||
std::cerr << "audit_name: " << audit_name << std::endl ;
|
||||
std::cerr << h << std::endl ;
|
||||
#endif
|
||||
ifstream in(audit_name.c_str());
|
||||
if ( in )
|
||||
ReadAudit(in);
|
||||
else SHOW_ERROR("Unable to open audit file: " << audit_name);
|
||||
else REPORT_ERROR( str(format("Unable to open audit file: %1%") % audit_name) ) ;
|
||||
}
|
||||
|
||||
void OnStarted( Surface& ) { order = 0 ; }
|
||||
|
||||
void OnFinished ( Surface& )
|
||||
{
|
||||
CHECK( audit_table.size() == actual_table.size() );
|
||||
CHECK_EQUAL( audit_table.size(), actual_table.size() ) ;
|
||||
|
||||
for ( size_t i = 0, ei = audit_table.size() ; i != ei ; ++ i )
|
||||
size_t total = audit_table.size() ;
|
||||
size_t wrong = 0 ;
|
||||
for ( size_t i = 0, ei = total ; i != ei ; ++ i )
|
||||
{
|
||||
size_t idx = i * 2 ;
|
||||
Data_ptr audit_data = audit_table[idx];
|
||||
Data_ptr audit_data = audit_table[idx];
|
||||
Data_ptr actual_data = actual_table[idx];
|
||||
|
||||
CHECK(audit_data);
|
||||
CHECK(actual_data);
|
||||
CHECK_EQUAL(audit_data->selected,actual_data->selected);
|
||||
if ( audit_data->selected )
|
||||
|
||||
if ( !Data::match(*audit_data,*actual_data) )
|
||||
{
|
||||
//CHECK_EQUAL(audit_data->order ,actual_data->order);
|
||||
CHECK_EQUAL(audit_data->is_collapsable ,actual_data->is_collapsable);
|
||||
CHECK_EQUAL(!audit_data->cost ,!actual_data->cost);
|
||||
CHECK_EQUAL(!audit_data->placement ,!actual_data->placement);
|
||||
cerr << "Mismatch detected.\n Expected: " << audit2str(audit_data) << "\n Got: " << audit2str(actual_data) << endl ;
|
||||
++ wrong ;
|
||||
}
|
||||
}
|
||||
|
||||
if ( wrong > 0 )
|
||||
{
|
||||
cerr << wrong << " mismatches out of " << total << " collapses" << endl ;
|
||||
if ( wrong > 20 )
|
||||
{
|
||||
cerr << "TEST FAILED. Too many mismatched collapses." << endl ;
|
||||
throw runtime_error("");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -152,16 +216,20 @@ public :
|
|||
|
||||
void OnCollected( Halfedge_handle const& aEdge, Surface& )
|
||||
{
|
||||
string h = str ( format("I %1% # %2%") % aEdge->id() % edge2str(aEdge) ) ;
|
||||
history.push_back(h);
|
||||
#ifdef TRACE
|
||||
std::cerr << "ACTUAL: I " << edge2str(aEdge) << std::endl ;
|
||||
std::cerr << h << std::endl ;
|
||||
#endif
|
||||
actual_table.insert(make_pair(aEdge->id(), Data_ptr( new Data() ) ) ) ;
|
||||
actual_table.insert(make_pair(aEdge->id(), Data_ptr( new Data(aEdge->id()) ) ) ) ;
|
||||
}
|
||||
|
||||
void OnSelected( Halfedge_handle const& aEdge, Surface&, optional<double> const& aCost, size_t, size_t )
|
||||
{
|
||||
string h = str ( format("S %1% %2%") % aEdge->id() % opt2str(aCost) ) ;
|
||||
history.push_back(h);
|
||||
#ifdef TRACE
|
||||
std::cerr << "ACTUAL: S " << edge2str(aEdge) << " cost:" << aCost << " (order=" << order << ")" << std::endl ;
|
||||
std::cerr << h << std::endl ;
|
||||
#endif
|
||||
actual_table[aEdge->id()]->selected = true ;
|
||||
actual_table[aEdge->id()]->cost = aCost ;
|
||||
|
|
@ -170,8 +238,10 @@ public :
|
|||
|
||||
void OnCollapsing(Halfedge_handle const& aEdge, Surface&, optional<Point> const& aPlacement )
|
||||
{
|
||||
string h = str ( format("C %1%") % aEdge->id() ) ;
|
||||
history.push_back(h);
|
||||
#ifdef TRACE
|
||||
std::cerr << "ACTUAL: C" << aEdge->id() << std::endl ;
|
||||
std::cerr << h << std::endl ;
|
||||
#endif
|
||||
actual_table[aEdge->id()]->placement = aPlacement ;
|
||||
actual_table[aEdge->id()]->is_collapsable = true ;
|
||||
|
|
@ -179,15 +249,29 @@ public :
|
|||
|
||||
void OnNonCollapsable(Halfedge_handle const& aEdge, Surface& )
|
||||
{
|
||||
string h = str ( format("N %1%") % aEdge->id() ) ;
|
||||
history.push_back(h);
|
||||
#ifdef TRACE
|
||||
std::cerr << "ACTUAL: N" << aEdge->id() << std::endl ;
|
||||
std::cerr << h << std::endl ;
|
||||
#endif
|
||||
actual_table[aEdge->id()]->is_collapsable = false ;
|
||||
}
|
||||
|
||||
void error ( char const* file, int line, char const* pred, string msg )
|
||||
{
|
||||
cerr << "ERROR in " << file << " at " << line << endl ;
|
||||
if ( pred )
|
||||
cerr << " Assertion failed: " << pred << endl ;
|
||||
cerr << " " << msg << endl ;
|
||||
|
||||
|
||||
throw runtime_error("");
|
||||
}
|
||||
|
||||
private :
|
||||
|
||||
Table audit_table ;
|
||||
Table actual_table ;
|
||||
size_t order ;
|
||||
Table audit_table ;
|
||||
Table actual_table ;
|
||||
size_t order ;
|
||||
vector<string> history ;
|
||||
} ;
|
||||
|
|
|
|||
|
|
@ -1,19 +1,4 @@
|
|||
data/triangle_open.off
|
||||
data/square_open.off
|
||||
data/cube_open.off
|
||||
data/hedra_open.off
|
||||
data/tetra.off
|
||||
data/cube.off
|
||||
data/hedra.off
|
||||
data/tetra_12f.off
|
||||
data/tetra_6f.off
|
||||
data/triangle_7f_open.off
|
||||
data/triangle_open_with_hole.off
|
||||
data/hexagon_open.off
|
||||
data/genus1.off
|
||||
data/eight.off
|
||||
data/head_open_with_holes.off
|
||||
data/oct.off
|
||||
data/oni.off
|
||||
data/star.off
|
||||
data/helmet.off
|
||||
|
|
|
|||
|
|
@ -1,19 +1,4 @@
|
|||
data/triangle_open.off
|
||||
data/square_open.off
|
||||
data/cube_open.off
|
||||
data/hedra_open.off
|
||||
data/tetra.off
|
||||
data/cube.off
|
||||
data/hedra.off
|
||||
data/tetra_12f.off
|
||||
data/tetra_6f.off
|
||||
data/triangle_7f_open.off
|
||||
data/triangle_open_with_hole.off
|
||||
data/hexagon_open.off
|
||||
data/genus1.off
|
||||
data/eight.off
|
||||
data/head_open_with_holes.off
|
||||
data/oct.off
|
||||
data/oni.off
|
||||
data/star.off
|
||||
data/helmet.off
|
||||
|
|
|
|||
Loading…
Reference in New Issue