2012-07-15 04:52:24 +02:00
package net.osmand.router ;
2011-07-08 14:32:57 +02:00
2012-07-06 00:35:39 +02:00
import java.io.File ;
import java.io.FileInputStream ;
2011-07-08 14:32:57 +02:00
import java.io.IOException ;
import java.io.InputStream ;
import java.io.RandomAccessFile ;
2012-07-06 00:35:39 +02:00
import java.util.ArrayList ;
2011-07-08 14:32:57 +02:00
import java.util.List ;
import javax.xml.parsers.DocumentBuilderFactory ;
2012-07-13 09:51:00 +02:00
import net.osmand.NativeLibrary ;
2011-07-08 14:32:57 +02:00
import net.osmand.binary.BinaryMapIndexReader ;
import net.osmand.router.BinaryRoutePlanner ;
2012-07-06 00:35:39 +02:00
import net.osmand.router.BinaryRoutePlanner.RouteSegment ;
2011-07-08 14:32:57 +02:00
import net.osmand.router.RouteSegmentResult ;
2012-06-16 12:06:04 +02:00
import net.osmand.router.RoutingConfiguration ;
2012-09-28 00:40:00 +02:00
import net.osmand.router.RoutingConfiguration.Builder ;
2011-07-08 14:32:57 +02:00
import net.osmand.router.RoutingContext ;
2012-07-06 00:35:39 +02:00
import net.osmand.swing.DataExtractionSettings ;
2011-07-08 14:32:57 +02:00
import org.w3c.dom.Document ;
import org.w3c.dom.Element ;
import org.w3c.dom.NodeList ;
import org.xml.sax.InputSource ;
import org.xml.sax.SAXException ;
public class RouterTestsSuite {
2012-07-07 14:31:47 +02:00
2012-10-14 01:09:01 +02:00
public static int MEMORY_TEST_LIMIT = 800 ;
public static boolean TEST_WO_HEURISTIC = true ;
public static boolean TEST_BOTH_DIRECTION = true ;
2012-07-07 14:31:47 +02:00
private static class Parameters {
public File obfDir ;
public List < File > tests = new ArrayList < File > ( ) ;
public RoutingConfiguration . Builder configBuilder ;
public static Parameters init ( String [ ] args ) throws SAXException , IOException {
Parameters p = new Parameters ( ) ;
String routingXmlFile = null ;
String obfDirectory = null ;
BinaryRoutePlanner . PRINT_TO_CONSOLE_ROUTE_INFORMATION_TO_TEST = false ;
for ( String a : args ) {
if ( a . startsWith ( " -routingXmlPath= " ) ) {
routingXmlFile = a . substring ( " -routingXmlPath= " . length ( ) ) ;
} else if ( a . startsWith ( " -verbose " ) ) {
BinaryRoutePlanner . PRINT_TO_CONSOLE_ROUTE_INFORMATION_TO_TEST = true ;
} else if ( a . startsWith ( " -obfDir= " ) ) {
obfDirectory = a . substring ( " -obfDir= " . length ( ) ) ;
} else if ( a . startsWith ( " -testDir= " ) ) {
String testDirectory = a . substring ( " -testDir= " . length ( ) ) ;
for ( File f : new File ( testDirectory ) . listFiles ( ) ) {
if ( f . getName ( ) . endsWith ( " .test.xml " ) ) {
p . tests . add ( f ) ;
}
}
} else if ( ! a . startsWith ( " - " ) ) {
p . tests . add ( new File ( a ) ) ;
}
}
if ( obfDirectory = = null ) {
obfDirectory = DataExtractionSettings . getSettings ( ) . getBinaryFilesDir ( ) ;
}
if ( obfDirectory ! = null & & obfDirectory . length ( ) > 0 ) {
p . obfDir = new File ( obfDirectory ) ;
}
if ( routingXmlFile = = null ) {
routingXmlFile = DataExtractionSettings . getSettings ( ) . getRoutingXmlPath ( ) ;
}
if ( routingXmlFile . equals ( " routing.xml " ) ) {
p . configBuilder = RoutingConfiguration . getDefault ( ) ;
} else {
p . configBuilder = RoutingConfiguration . parseFromInputStream ( new FileInputStream ( routingXmlFile ) ) ;
}
return p ;
}
}
2012-09-28 09:31:36 +02:00
public static void main ( String [ ] args ) throws Exception {
2012-07-07 14:31:47 +02:00
Parameters params = Parameters . init ( args ) ;
if ( params . tests . isEmpty ( ) | | params . obfDir = = null ) {
println ( " Run router tests is console utility to test route calculation for osmand. " ) ;
println ( " \ nUsage for run tests : runTestsSuite [-routingXmlPath=PATH] [-verbose] [-obfDir=PATH] [-testDir=PATH] {individualTestPath} " ) ;
return ;
}
2012-07-06 00:35:39 +02:00
List < File > files = new ArrayList < File > ( ) ;
2012-07-07 14:31:47 +02:00
for ( File f : params . obfDir . listFiles ( ) ) {
2012-07-06 00:35:39 +02:00
if ( f . getName ( ) . endsWith ( " .obf " ) ) {
files . add ( f ) ;
}
}
BinaryMapIndexReader [ ] rs = new BinaryMapIndexReader [ files . size ( ) ] ;
int it = 0 ;
for ( File f : files ) {
RandomAccessFile raf = new RandomAccessFile ( f , " r " ) ; //$NON-NLS-1$ //$NON-NLS-2$
2012-08-25 20:39:45 +02:00
rs [ it + + ] = new BinaryMapIndexReader ( raf ) ;
2012-07-06 00:35:39 +02:00
}
2011-07-08 14:32:57 +02:00
boolean allSuccess = true ;
2012-07-07 14:31:47 +02:00
for ( File f : params . tests ) {
2012-07-13 09:51:00 +02:00
allSuccess & = test ( null , new FileInputStream ( f ) , rs , params . configBuilder ) ;
2012-07-06 00:35:39 +02:00
}
2011-07-08 14:32:57 +02:00
if ( allSuccess ) {
System . out . println ( " All is successfull " ) ;
}
}
2012-07-07 14:31:47 +02:00
private static void println ( String string ) {
System . out . println ( string ) ;
}
2012-09-28 09:31:36 +02:00
public static boolean test ( NativeLibrary lib , InputStream resource , BinaryMapIndexReader [ ] rs , RoutingConfiguration . Builder config ) throws Exception {
2011-07-08 14:32:57 +02:00
Document testSuite = DocumentBuilderFactory . newInstance ( ) . newDocumentBuilder ( ) . parse ( new InputSource ( resource ) ) ;
NodeList tests = testSuite . getElementsByTagName ( " test " ) ;
2012-07-07 14:31:47 +02:00
for ( int i = 0 ; i < tests . getLength ( ) ; i + + ) {
2011-07-08 14:32:57 +02:00
Element e = ( Element ) tests . item ( i ) ;
2012-09-28 00:40:00 +02:00
testRoute ( e , config , lib , rs ) ;
2011-07-08 14:32:57 +02:00
}
2012-07-07 14:31:47 +02:00
2011-07-08 14:32:57 +02:00
return true ;
2012-07-06 00:35:39 +02:00
}
private static float parseFloat ( Element e , String attr ) {
if ( e . getAttribute ( attr ) = = null | | e . getAttribute ( attr ) . length ( ) = = 0 ) {
return 0 ;
}
return Float . parseFloat ( e . getAttribute ( attr ) ) ;
}
2012-07-07 14:31:47 +02:00
private static boolean isInOrLess ( float expected , float value , float percent ) {
2012-10-14 01:09:01 +02:00
if ( equalPercent ( expected , value , percent ) ) {
2012-07-06 00:35:39 +02:00
return true ;
}
2012-07-07 14:31:47 +02:00
if ( value < expected ) {
System . err . println ( " Test could be adjusted value " + value + " is much less then expected " + expected ) ;
return true ;
}
2012-07-06 00:35:39 +02:00
return false ;
2011-07-08 14:32:57 +02:00
}
2012-10-14 01:09:01 +02:00
private static boolean equalPercent ( float expected , float value , float percent ) {
if ( Math . abs ( value / expected - 1 ) < percent / 100 ) {
return true ;
}
return false ;
}
2011-07-08 14:32:57 +02:00
2012-09-28 09:31:36 +02:00
private static void testRoute ( Element testCase , Builder config , NativeLibrary lib , BinaryMapIndexReader [ ] rs ) throws IOException , SAXException , InterruptedException {
2011-07-08 14:32:57 +02:00
String vehicle = testCase . getAttribute ( " vehicle " ) ;
2012-07-06 00:35:39 +02:00
int loadedTiles = ( int ) parseFloat ( testCase , " loadedTiles " ) ;
int visitedSegments = ( int ) parseFloat ( testCase , " visitedSegments " ) ;
int complete_time = ( int ) parseFloat ( testCase , " complete_time " ) ;
2012-10-14 01:09:01 +02:00
int routing_time = ( int ) parseFloat ( testCase , " routing_time " ) ;
2012-07-06 00:35:39 +02:00
int complete_distance = ( int ) parseFloat ( testCase , " complete_distance " ) ;
float percent = parseFloat ( testCase , " best_percent " ) ;
2011-07-08 14:32:57 +02:00
String testDescription = testCase . getAttribute ( " description " ) ;
2012-07-06 00:35:39 +02:00
if ( percent = = 0 ) {
System . err . println ( " \ n \ n!! Skipped test case ' " + testDescription + " ' because 'best_percent' attribute is not specified \ n \ n " ) ;
return ;
}
2012-10-14 01:09:01 +02:00
RoutingConfiguration rconfig = config . build ( vehicle , MEMORY_TEST_LIMIT ) ;
2012-09-28 00:40:00 +02:00
BinaryRoutePlanner router = new BinaryRoutePlanner ( ) ;
2012-10-14 01:09:01 +02:00
RoutingContext ctx = new RoutingContext ( rconfig ,
2012-09-28 00:40:00 +02:00
lib , rs ) ;
2011-08-14 18:41:25 +02:00
String skip = testCase . getAttribute ( " skip_comment " ) ;
if ( skip ! = null & & skip . length ( ) > 0 ) {
System . err . println ( " \ n \ n!! Skipped test case ' " + testDescription + " ' because ' " + skip + " ' \ n \ n " ) ;
return ;
}
2012-07-06 00:35:39 +02:00
System . out . println ( " Run test " + testDescription ) ;
2011-08-14 18:41:25 +02:00
2011-07-08 14:32:57 +02:00
double startLat = Double . parseDouble ( testCase . getAttribute ( " start_lat " ) ) ;
double startLon = Double . parseDouble ( testCase . getAttribute ( " start_lon " ) ) ;
2012-09-28 00:40:00 +02:00
RouteSegment startSegment = router . findRouteSegment ( startLat , startLon , ctx ) ;
2011-07-08 14:32:57 +02:00
double endLat = Double . parseDouble ( testCase . getAttribute ( " target_lat " ) ) ;
double endLon = Double . parseDouble ( testCase . getAttribute ( " target_lon " ) ) ;
2012-09-28 00:40:00 +02:00
RouteSegment endSegment = router . findRouteSegment ( endLat , endLon , ctx ) ;
2011-07-08 14:32:57 +02:00
if ( startSegment = = null ) {
throw new IllegalArgumentException ( " Start segment is not found for test : " + testDescription ) ;
}
if ( endSegment = = null ) {
throw new IllegalArgumentException ( " End segment is not found for test : " + testDescription ) ;
}
2012-09-28 00:40:00 +02:00
List < RouteSegmentResult > route = router . searchRoute ( ctx , startSegment , endSegment , false ) ;
2012-10-14 01:09:01 +02:00
final float calcRoutingTime = ctx . routingTime ;
2012-07-06 00:35:39 +02:00
float completeTime = 0 ;
float completeDistance = 0 ;
for ( int i = 0 ; i < route . size ( ) ; i + + ) {
completeTime + = route . get ( i ) . getSegmentTime ( ) ;
completeDistance + = route . get ( i ) . getDistance ( ) ;
}
2012-07-07 14:31:47 +02:00
if ( complete_time > 0 & & ! isInOrLess ( complete_time , completeTime , percent ) ) {
2012-07-06 00:35:39 +02:00
throw new IllegalArgumentException ( String . format ( " Complete time (expected) %s != %s (original) : %s " , complete_time , completeTime , testDescription ) ) ;
}
2012-07-07 14:31:47 +02:00
if ( complete_distance > 0 & & ! isInOrLess ( complete_distance , completeDistance , percent ) ) {
2012-07-06 00:35:39 +02:00
throw new IllegalArgumentException ( String . format ( " Complete distance (expected) %s != %s (original) : %s " , complete_distance , completeDistance , testDescription ) ) ;
}
2012-10-14 01:09:01 +02:00
if ( routing_time > 0 & & ! isInOrLess ( routing_time , calcRoutingTime , percent ) ) {
throw new IllegalArgumentException ( String . format ( " Complete routing time (expected) %s != %s (original) : %s " , routing_time , calcRoutingTime , testDescription ) ) ;
2012-07-06 00:35:39 +02:00
}
2012-10-14 01:09:01 +02:00
if ( visitedSegments > 0 & & ! isInOrLess ( visitedSegments , ctx . visitedSegments , percent ) ) {
throw new IllegalArgumentException ( String . format ( " Visited segments (expected) %s != %s (original) : %s " , visitedSegments ,
ctx . visitedSegments , testDescription ) ) ;
}
if ( loadedTiles > 0 & & ! isInOrLess ( loadedTiles , ctx . loadedTiles , percent ) ) {
throw new IllegalArgumentException ( String . format ( " Loaded tiles (expected) %s != %s (original) : %s " , loadedTiles ,
ctx . loadedTiles , testDescription ) ) ;
}
if ( TEST_BOTH_DIRECTION ) {
rconfig . planRoadDirection = - 1 ;
runTestSpecialTest ( lib , rs , rconfig , router , startSegment , endSegment , calcRoutingTime , " Calculated routing time in both direction %s != %s time in -1 direction " ) ;
rconfig . planRoadDirection = 1 ;
runTestSpecialTest ( lib , rs , rconfig , router , startSegment , endSegment , calcRoutingTime , " Calculated routing time in both direction %s != %s time in 1 direction " ) ;
2012-07-06 00:35:39 +02:00
}
2011-07-08 14:32:57 +02:00
2012-10-14 01:09:01 +02:00
if ( TEST_WO_HEURISTIC ) {
rconfig . planRoadDirection = 0 ;
rconfig . heuristicCoefficient = 0 . 5f ;
runTestSpecialTest ( lib , rs , rconfig , router , startSegment , endSegment , calcRoutingTime ,
" Calculated routing time with heuristic 1 %s != %s with heuristic 0.5 " ) ;
}
2011-07-08 14:32:57 +02:00
2012-10-14 01:09:01 +02:00
}
private static void runTestSpecialTest ( NativeLibrary lib , BinaryMapIndexReader [ ] rs , RoutingConfiguration rconfig , BinaryRoutePlanner router ,
RouteSegment startSegment , RouteSegment endSegment , final float calcRoutingTime , String msg ) throws IOException , InterruptedException {
RoutingContext ctx ;
RouteSegment frs ;
ctx = new RoutingContext ( rconfig , lib , rs ) ;
frs = router . searchRouteInternal ( ctx , startSegment , endSegment , false ) ;
if ( frs = = null | | ! equalPercent ( calcRoutingTime , frs . distanceFromStart , 0 . 5f ) ) {
throw new IllegalArgumentException ( String . format ( msg , calcRoutingTime + " " , frs = = null ? " 0 " : frs . distanceFromStart + " " ) ) ;
}
2012-07-06 00:35:39 +02:00
}
2012-07-07 14:31:47 +02:00
protected static NodeList compareBySegment ( Element testCase , String testDescription , List < RouteSegmentResult > route ) {
2011-07-08 14:32:57 +02:00
NodeList segments = testCase . getElementsByTagName ( " segment " ) ;
int i = 0 ;
while ( i < segments . getLength ( ) & & i < route . size ( ) ) {
Element segment = ( Element ) segments . item ( i ) ;
long expectedId = Long . parseLong ( segment . getAttribute ( " id " ) ) ;
int expectedStart = Integer . parseInt ( segment . getAttribute ( " start " ) ) ;
int expectedEnd = Integer . parseInt ( segment . getAttribute ( " end " ) ) ;
RouteSegmentResult segmentResult = route . get ( i ) ;
2012-06-11 22:28:57 +02:00
if ( expectedId ! = segmentResult . getObject ( ) . getId ( ) > > 1 ) {
2011-07-08 14:32:57 +02:00
throw new IllegalArgumentException ( " Test : ' " + testDescription + " ' on segment " + ( i + 1 ) + " : " + " \ n "
2012-06-11 22:28:57 +02:00
+ " (expected route id) " + expectedId + " != " + ( segmentResult . getObject ( ) . getId ( ) > > 1 ) + " (actual route id) " ) ;
2011-07-08 14:32:57 +02:00
}
2012-06-11 22:28:57 +02:00
if ( expectedStart ! = segmentResult . getStartPointIndex ( ) ) {
2011-07-08 14:32:57 +02:00
throw new IllegalArgumentException ( " Test : ' " + testDescription + " ' on segment " + ( i + 1 ) + " : " + " \ n "
2012-06-11 22:28:57 +02:00
+ " (expected start index) " + expectedStart + " != " + segmentResult . getStartPointIndex ( ) + " (actual start index) " ) ;
2011-07-08 14:32:57 +02:00
}
2012-06-11 22:28:57 +02:00
if ( expectedEnd ! = segmentResult . getEndPointIndex ( ) ) {
2011-07-08 14:32:57 +02:00
throw new IllegalArgumentException ( " Test : ' " + testDescription + " ' on segment " + ( i + 1 ) + " : " + " \ n "
2012-06-11 22:28:57 +02:00
+ " (expected end index) " + expectedEnd + " != " + segmentResult . getEndPointIndex ( ) + " (actual end index) " ) ;
2011-07-08 14:32:57 +02:00
}
i + + ;
}
2012-07-06 00:35:39 +02:00
return segments ;
2011-07-08 14:32:57 +02:00
}
}