<?php
require_once ('lib/simpletest/unit_tester.php');
require_once ('lib/simpletest/reporter.php');
require_once ('USGeocoder.inc');
require_once ('WorldGeocoder.inc');
require_once ('GoogleGeocoder.inc');
require_once ('MathUtils.inc');
class GeocoderTest extends UnitTestCase {
protected function testResult ($actual, $expect, $label='')
{
//print_array($expect, 'expect');
//print_array($actual, 'actual');
$lat = $actual["latitude"] ;
$lon = $actual["longitude"] ;
$err = $actual["error"] ;
list($expectLat,$expectLon,$expectErr) = $expect ;
$this->assertTrue (abs($lat - $expect[0]) < 0.05, $label." with $lat != $expectLat") ; // we should check that difference < delta..
$this->assertTrue (abs($lon - $expect[1]) < 0.05, $label." with $lon != $expectLon") ;
$this->assertEqual ($err, $expect[2], $label." with $err != $expectErr") ;
}
}
class USGeoCoderTest extends GeocoderTest {
//
// Validate US Geocoder
//
public function testZIP ()
{
// The zipcode of Sunnyvale, headquarters of Yahoo...
$test = new USGeocoder ("US", "94089-1019") ;
$result = $test->submit() ;
$this->testResult($result, array("37.402414", "-122.008017", null)) ;
$test = new USGeocoder ("US", "89883") ;
$result = $test->submit() ;
$this->testResult($result, array("40.735472", "-114.065667", null)) ;
}
public function testCityState ()
{
// headquarters of Yahoo...
$test = new USGeocoder ("US", null, "Sunnyvale", "CA") ;
$result = $test->submit() ;
$this->testResult($result, array("37.371612", "-122.038258", null)) ;
}
public function testInvalidZip ()
{
$test = new USGeocoder ("US", "99999") ;
$result = $test->submit() ;
$this->testResult($result, array(null, null, "Could not geocode ,US")) ;
}
public function testCityWithSpace ()
{
$test = new USGeocoder ("US", null, "san francisco", "ca") ;
$result = $test->submit() ;
$this->testResult($result, array("37.779160", "-122.420049", null)) ;
}
public function testNulls ()
{
$test = new USGeocoder ("US", null, null, null) ;
$result = $test->submit() ;
$this->testResult($result, array(null, null, "Could not geocode ,US")) ;
}
//
// Validate the US Geocoder parser
//
public function testLimitReached ()
{
$input = <<<TESTXML
<Error xmlns="urn:yahoo:api"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://api.yahoo.com/Api/V1/error.xsd">
The following errors were detected:
<Message>limit exceeded</Message>
</Error>
TESTXML;
$test = new USGeocoder (null, null, null) ;
$result = $test->parseResult ($input) ;
$this->assertNull ($result) ;
}
public function testDoubleInfo ()
{
$input = <<<TESTXML
<?xml version="1.0" encoding="UTF-8"?>
<ResultSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:yahoo:maps" xsi:schemaLocation="urn:yahoo:maps http://api.local.yahoo.com/MapsService/V1/GeocodeResponse.xsd">
<Result precision="address">
<Latitude>37.416384</Latitude>
<Latitude>99</Latitude>
<Longitude>-122.024853</Longitude>
<Address>701 FIRST AVE</Address>
<City>SUNNYVALE</City>
<State>CA</State>
<Zip>94089-1019</Zip>
<Country>US</Country>
</Result>
</ResultSet>
TESTXML;
$test = new USGeocoder (null, null, null) ;
$result = $test->parseResult (trim($input)) ;
$this->assertNull ($result) ;
}
public function testDoubleInfo2 ()
{
$input = <<<TESTXML
<?xml version="1.0" encoding="UTF-8"?>
<ResultSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:yahoo:maps" xsi:schemaLocation="urn:yahoo:maps http://api.local.yahoo.com/MapsService/V1/GeocodeResponse.xsd">
<Result precision="address">
<Latitude>37.416384</Latitude>
<Longitude>-122.024853</Longitude>
<Longitude>99</Longitude>
<Address>701 FIRST AVE</Address>
<City>SUNNYVALE</City>
<State>CA</State>
<Zip>94089-1019</Zip>
<Country>US</Country>
</Result>
</ResultSet>
TESTXML;
$test = new USGeocoder (null, null, null) ;
$result = $test->parseResult (trim($input)) ;
$this->assertNull ($result) ;
}
public function testNoInfo ()
{
$input = <<<TESTXML
<?xml version="1.0" encoding="UTF-8"?>
<ResultSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:yahoo:maps" xsi:schemaLocation="urn:yahoo:maps http://api.local.yahoo.com/MapsService/V1/GeocodeResponse.xsd">
<Result precision="address">
<Longitude>-122.024853</Longitude>
<Address>701 FIRST AVE</Address>
<City>SUNNYVALE</City>
<State>CA</State>
<Zip>94089-1019</Zip>
<Country>US</Country>
</Result>
</ResultSet>
TESTXML;
$test = new USGeocoder (null, null, null) ;
$result = $test->parseResult (trim($input)) ;
$this->assertNull ($result) ;
}
public function testNoInfo2 ()
{
$input = <<<TESTXML
<?xml version="1.0" encoding="UTF-8"?>
<ResultSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:yahoo:maps" xsi:schemaLocation="urn:yahoo:maps http://api.local.yahoo.com/MapsService/V1/GeocodeResponse.xsd">
<Result precision="address">
<Latitude>37.416384</Latitude>
<Address>701 FIRST AVE</Address>
<City>SUNNYVALE</City>
<State>CA</State>
<Zip>94089-1019</Zip>
<Country>US</Country>
</Result>
</ResultSet>
TESTXML;
$test = new USGeocoder (null, null, null) ;
$result = $test->parseResult (trim($input)) ;
$this->assertNull ($result) ;
}
}
class WorldGeoCoderTest extends GeocoderTest {
// Validate World Geocoder
public function testWorldZIP ()
{
// The zipcode of Sunnyvale, headquarters of Yahoo...
$test = new WorldGeocoder ("US", "94089-1019") ;
$result = $test->submit() ;
$this->testResult($result, array("37.189396", "-121.705327", null)) ;
}
public function testWorldZIP2 ()
{
// The zipcode of Sunnyvale, headquarters of Yahoo...
// idem, but with 5 char zipcode
$test = new WorldGeocoder ("US", "94089") ;
$result = $test->submit() ;
$this->testResult($result, array("37.189396", "-121.705327", null)) ;
}
public function testWorldCity ()
{
$test = new WorldGeocoder ("US", NULL, "San Francisco", "CA") ;
$result = $test->submit() ;
$this->testResult($result, array("37.784827", "-122.727802", null)) ;
// put the state inside the city
$test = new WorldGeocoder ("US", NULL, "San Francisco, ca") ;
$result = $test->submit() ;
$this->testResult($result, array("37.784827", "-122.727802", null)) ;
// canada cities can also have a state
$test = new WorldGeocoder ("CA", NULL, "Toronto, ON") ;
$result = $test->submit() ;
//print_array($result);
//$this->testResult($result, array("37.784827", "-122.727802", null)) ;
}
public function testGeoCode () {
$result = WorldGeocoder::geoCode('US', "94089", "Sunnyvale, ca") ;
$this->testResult($result, array("37.189396", "-121.705327", null)) ;
$result = WorldGeocoder::geoCode('US', '99999', "Sunnyvale, ca") ;
$this->testResult($result, array("37.189396", "-121.705327", null)) ;
}
public function testWorldCity2 ()
{
$test = new WorldGeocoder ("BE", NULL, "Mechelen", NULL) ;
$result = $test->submit() ;
$this->testResult($result, array("51.0333333", "4.4666667", null)) ;
}
public function testWorldCity3 ()
{// test with accented characters
$test = new WorldGeocoder ("BE", NULL, html_entity_decode("La Louvière", NULL, 'UTF-8'), NULL) ;
$result = $test->submit() ;
$this->testResult($result, array("50.4666667", "4.1833333", null)) ;
}
public function testWorldInvalidCity ()
{
// invalid city no zip
$test = new WorldGeocoder ("BE", NULL, "Tiznoland", NULL) ;
$result = $test->submit() ;
//print_array ($result) ;
$this->testResult($result, array(NULL, NULL, "no_geocode")) ;
// valid zip invalid city
$test = new WorldGeocoder ("BE", "2800", "Tiznoland", NULL) ;
$result = $test->submit() ;
//print_array ($result) ;
$this->testResult($result, array(NULL, NULL, "no_geocode")) ;
$test = new WorldGeocoder ("UK", NULL, "PRESCOTT, MERSEYSIDE", NULL) ;
$result = $test->submit() ;
//print_array ($result) ;
$this->testResult($result, array(NULL, NULL, "no_geocode")) ;
}
public function testWorldInvalidZIP ()
{
$test = new WorldGeocoder ("US", "99999", NULL, NULL) ;
$result = $test->submit() ;
$this->testResult($result, array(NULL, NULL, "no_geocode")) ;
// cityname has precedence over invalid zip...
$test = new WorldGeocoder ("BE", "28888", "Mechelen", NULL) ;
$result = $test->submit() ;
$this->testResult($result, array("51.0333333", "4.4666667", NULL)) ;
}
public function testWorldAllNull ()
{
$test = new WorldGeocoder (NULL, NULL, NULL, NULL) ;
$result = $test->submit() ;
$this->testResult($result, array(NULL, NULL, 'Could not geocode ,')) ;
}
public function testWorldBad () {
// the input is wrong because of input error, hence all input shifts...
$test = new WorldGeocoder ("BEAUMONT,TX", "www.artstudio.org", 77701) ;
$result = $test->submit() ;
//print_array($result);
$this->testResult($result, array(NULL, NULL, 'no_geocode')) ;
}
//
// Validate the World Geocoder parser
//
public function testWorldParser ()
{
$input = <<<TESTXML
<rdf:RDF>
<geo:Point>
<geo:long>-0.15</geo:long>
<geo:lat>50.8333333</geo:lat>
</geo:Point>
</rdf:RDF>
TESTXML;
$test = new WorldGeocoder (null, null, null, null) ;
$result = $test->parseResult ($input) ;
$this->testResult($result, array("50.8333333", "-0.15", null)) ;
}
}
class GoogleGeoCoderTest extends GeocoderTest {
public function testGoogleCity ()
{
$testList = array (
array ('US', 'San Francisco', "37.775000", "-122.418333"),
array ('US', 'San Francisco, ca', "37.775000", "-122.418333"),
array ('US', 'West Wendover,NV', "40.739167", "-114.072500"),
array ('US', ' Molena,ga', "33.011944", "-84.500278"),
array ('CA', 'Toronto,ON', "43.670233", "-79.392486"),
array ('BE', 'Mechelen', "51.029998", "4.469999"),
array ('GM', 'Koln', "50.940664", "6.959911"),
array ('BE', 'La Louvière', "50.490001", "4.230000")
) ;
foreach ($testList as $oneTest) {
list ($country,$city,$lat,$lon) = $oneTest ;
$city = html_entity_decode($city, NULL, 'UTF-8') ;
$test = new GoogleGeocoder ($country, NULL, $city) ;
$result = $test->submit() ;
//print_array($result);
$this->testResult($result, array($lat, $lon, null)) ;
}
}
public function testGoogleZipCode () {
$testList = array (
array ('94089', "Sunnyvale, ca", "37.398255", "-122.000637", null),
//array ('99999', "Sunnyvale, ca", NULL, NULL, 'no_geocode'),
array ('94089', NULL, "37.398255", "-122.000637", null),
array ('94089', "Sunnyvale", "37.398255", "-122.000637", null),
array ('89883', NULL, "40.878962", "-114.154526", null),
) ;
foreach ($testList as $oneTest) {
list($zip, $city, $expectLat, $expectLon, $expectErr) = $oneTest ;
sleep(1) ;
$test = new GoogleGeocoder('US', $zip, $city) ;
$result = $test->submit() ;
//print_array($result);
$this->testResult($result, array($expectLat, $expectLon, $expectErr)) ;
}
}
public function testGoogleZipCode2 () {
$testList = array (
array ('2018', 'Antwerpen', 'BE', 0, 0),
array ('2030', 'Antwerpen', 'BE', 0, 0),
// array ('NW1 8AB', 'London', 'UK', 0, 0), UK not yet supported in Google
array ('75020', 'Paris', 'FR', 0, 0),
array ('75009', 'Paris', 'FR', 0, 0),
array (NULL, 'Köln', 'GM', 0, 0), // '51063'
array ('50674', 'Köln', 'GM', 0, 0),
array ('28914', 'Madrid', 'SP', 0, 0),
array ('1030', 'Wien', 'AU', 0, 0),
array ('1110', 'Wien', 'AU', 0, 0),
array (NULL, 'Zürich', 'SZ', 0, 0), // '8050'
array ('8022', 'Zürich', 'SZ', 0, 0),
array (NULL, 'Montréal,QC', 'CA', 0, 0), // 'H2R2W1'
array ('H2X 3K2', 'Montréal,QC', 'CA', 0, 0),
array ('1101 DS', 'Amsterdam', 'NL', 0, 0),
array ('1071 LN', 'Amsterdam', 'NL', 0, 0),
array ('1000', 'København', 'DA', 0, 0),
array ('1369', 'København', 'DA', 0, 0),
array ('2300', 'København', 'DA', 0, 0),
) ;
foreach ($testList as $oneTest) {
sleep (1) ;
list ($zip,$city,$country,$lon,$lat) = $oneTest ;
$city = html_entity_decode($city, NULL, 'UTF-8');
$test = new GoogleGeocoder($country, $zip, $city) ;
$result = $test->submit() ;
//print_array($result);
$verify = new GoogleGeocoder($country, NULL, $city) ;
$expect = $verify->submit() ;
//echo("<hr>$city");
//print_array($result); print_array($expect);
$distance = distance($result['latitude'], $result['longitude'], $expect['latitude'], $expect['longitude'], 'km') ;
//echo("$distance<br>");
$this->assertTrue ($distance < 15, "Distance $distance with $city, $country") ;
}
}
public function testGoogleInvalidCity ()
{
// invalid city no zip
$test = new GoogleGeocoder ("BE", NULL, "Tiznoland", NULL) ;
$result = $test->submit() ;
//print_array ($result) ;
$this->testResult($result, array(NULL, NULL, "no_geocode")) ;
// valid zip invalid city
$test = new GoogleGeocoder ("BE", "2800", "Tiznoland", NULL) ;
$result = $test->submit() ;
//print_array ($result) ;
$this->testResult($result, array(NULL, NULL, "no_geocode")) ;
}
public function testGoogleAllNull ()
{
$test = new GoogleGeocoder (NULL, NULL, NULL, NULL) ;
$result = $test->submit() ;
$this->testResult($result, array(NULL, NULL, 'no_geocode')) ;
}
public function testGeocoderGeocode () {
$testList = array (
array ('US', 'San Francisco', '94115', "37.775000", "-122.418333"), // no WorldGeocoder as no state
array ('BE', 'La Louvière', '7100', "50.4666667", "4.1833333"),
array ("FI", "Jyväskylä", '40100', "62.2333333", "25.7333333"),
array ("SP", "Bergara", NULL, "43.118217", "-2.413358"), // WorldGeo doesn't know city
array ("GM", "Köln", '51063', "50.9333333", "6.95"),
array ('NZ', 'Motueka', NULL, "-41.110107", "173.011121"),
array ('NL', 'Amsterdam', '1017 PH', "52.35", "4.9166667"),
array ('NL', 'Amsterdam', '9999XX', "52.35", "4.9166667"), // illegal zip, fall back on city+country..
) ;
foreach ($testList as $oneTest) {
list ($country,$city,$zip, $lat,$lon) = $oneTest ;
$city = html_entity_decode($city, NULL, 'UTF-8');
$result = Geocoder::geoCode($country, NULL, $city) ;
//print_array($result);
$this->testResult($result, array($lat, $lon, null)) ;
// now try again with zip code. Distance from old geocode should be less than 10km..
$result1 = Geocoder::geoCode($country, $zip, $city) ;
$distance = distance($result['latitude'], $result['longitude'], $result1['latitude'], $result1['longitude'], 'km') ;
//print_array($result1, $city.$zip);
$this->assertTrue ($distance < 10.0) ;
}
$result = Geocoder::geoCode('BE', NULL, 'Tiznoland') ;
$this->testResult($result, array(NULL, NULL, 'no_geocode')) ;
}
public function testCheckValidPlace () {
$this->assertTrue (Geocoder::checkValidPlace('Nijmegen', 'NL')) ;
$this->assertTrue (Geocoder::checkValidPlace('Jena', 'GM')) ;
$this->assertTrue (Geocoder::checkValidPlace('London', 'UK')) ;
$this->assertFalse (Geocoder::checkValidPlace('Nijmegen', 'DK')) ;
$this->assertFalse (Geocoder::checkValidPlace('Kiekeboe', 'BE')) ;
// not-strict: there seems to be an Antwerpen in NL according to Google
$this->assertTrue (Geocoder::checkValidPlace('Antwerpen', 'NL')) ;
// but if we believe only WorldGeocoder, then not
$this->assertFalse (Geocoder::checkValidPlace('Antwerpen', 'NL', true)) ;
}
}
//--------------------------------------------------------------------------------
$testList = array (
'GeocoderTest' => new GeocoderTest(),
'USGeoCoderTest' => new USGeoCoderTest(),
'GoogleGeoCoderTest' => new GoogleGeoCoderTest(),
) ;
foreach ($testList as $oneName => $oneTest) {
$tester = new GroupTest($oneName) ;
$tester->addTestCase ($oneTest) ;
$tester->run(new HtmlReporter("UTF-8")) ;
}
?>
|