/MapView/UnitTesting/RouteMeTests.m
Objective C | 409 lines | 338 code | 60 blank | 11 comment | 6 complexity | a7feb33e7225b89eac828cc4eaa11569 MD5 | raw file
1// 2// RouteMeTests.m 3// MapView 4// 5// Created by Hal Mueller on 4/6/09. 6// Copyright 2009 Route-Me Contributors. All rights reserved. 7// 8 9#import "RouteMeTests.h" 10#import "RMMapView.h" 11#import "RMCloudMadeMapSource.h" 12#import "RMGeoHash.h" 13#import "RMMarker.h" 14#import "RMMarkerManager.h" 15 16@implementation RouteMeTests 17#define kAccuracyThreshold .0001 18#define kAccuracyThresholdForGeographicCoordinates .00001 19#define kAccuracyThresholdForPixelCoordinates kAccuracyThreshold 20 21- (void)setUp { 22 [super setUp]; 23 24 CGRect appRect = [[UIScreen mainScreen] applicationFrame]; 25 contentView = [[UIView alloc] initWithFrame:appRect]; 26 contentView.backgroundColor = [UIColor greenColor]; 27 28 initialCenter.latitude = 66.44; 29 initialCenter.longitude = -178.0; 30 31 mapView = [[RMMapView alloc] initWithFrame:CGRectMake(10,20,200,300) 32 WithLocation:initialCenter]; 33 [contentView addSubview:mapView]; 34} 35 36-(void)tearDown { 37 [mapView release]; mapView = nil; 38 [super tearDown]; 39} 40 41- (void)testObjectCreation 42{ 43 44 STAssertNotNil((mapView = [[RMMapView alloc] init]), @"mapView alloc/init failed"); 45 STAssertNoThrow([mapView release], @"mapView release failed"); 46 mapView = nil; 47 48 id myTilesource; 49 STAssertNotNil((myTilesource = [[RMCloudMadeMapSource alloc] initWithAccessKey:@"0199bdee456e59ce950b0156029d6934" styleNumber:999]), 50 @"tilesource creation failed"); 51 STAssertNoThrow([myTilesource release], @"tilesource release failed"); 52 STAssertNil((myTilesource = [[RMCloudMadeMapSource alloc] initWithAccessKey:nil styleNumber:999]), 53 @"empty CloudMade key does not trigger error"); 54 STAssertNoThrow([myTilesource release], @"tilesource release failed"); 55 STAssertThrows((myTilesource = [[RMCloudMadeMapSource alloc] initWithAccessKey:@"0199bdee456e59ce950b0156029d693" styleNumber:999]), 56 @"bogus CloudMade key does not trigger error"); 57 STAssertNoThrow([myTilesource release], @"tilesource release failed"); 58} 59 60- (void)testGeohashing 61{ 62 CLLocationCoordinate2D location1, location2; 63 location1.latitude = 38.89; 64 location1.longitude = -77.0; 65 STAssertEqualStrings([RMGeoHash fromLocation:location1 withPrecision:6], @"dqcjr2", @"6-digit geohash location1 failed"); 66 STAssertEqualStrings([RMGeoHash fromLocation:location1 withPrecision:4], @"dqcj", @"4-digit geohash location1 failed"); 67 68 location2.latitude = 38.89; 69 location2.longitude = -77.1; 70 STAssertEqualStrings([RMGeoHash fromLocation:location2 withPrecision:6], @"dqcjjx", @"geohash location2 failed"); 71 STAssertEqualStrings([RMGeoHash fromLocation:location2 withPrecision:4], @"dqcj", @"4-digit geohash location1 failed"); 72 73} 74 75- (void)testProgrammaticViewCreation 76{ 77 STAssertNotNil(mapView, @"mapview creation failed"); 78 STAssertNotNil([mapView contents], @"mapView contents should not be nil"); 79} 80 81- (void)testMarkerCreation 82{ 83 // create markers from -183 to -169 longitude 84 initialCenter.longitude = -178.0; 85 86 CLLocationCoordinate2D markerPosition; 87 NSUInteger nRows = 1; 88 NSUInteger nColumns = 8; 89 double columnSpacing = 2.0; 90 91 UIImage *markerImage = [UIImage imageNamed:@"marker-red.png"]; 92 STAssertNotNil(markerImage, @"testMarkerCreation marker image did not load"); 93 markerPosition.latitude = initialCenter.latitude - ((nRows - 1)/2.0 * columnSpacing); 94 NSUInteger i, j; 95 for (i = 0; i < nRows; i++) { 96 markerPosition.longitude = initialCenter.longitude - ((nColumns - 1)/2.0 * columnSpacing); 97 for (j = 0; j < nColumns; j++) { 98 markerPosition.longitude += columnSpacing; 99 RMMarker *newMarker = [[RMMarker alloc] initWithUIImage:markerImage]; 100 STAssertNotNil(newMarker, @"testMarkerCreation marker creation failed"); 101 [newMarker setData:[NSArray arrayWithObjects:[NSNumber numberWithDouble:markerPosition.longitude],[NSNumber numberWithDouble:markerPosition.latitude],nil]]; 102 [mapView.contents.markerManager addMarker:newMarker 103 AtLatLong:markerPosition]; 104 } 105 markerPosition.latitude += columnSpacing; 106 } 107} 108 109- (void)testMarkerCoordinatesFarEast 110{ 111 [mapView.contents setZoom:3.0]; 112 113 // create markers from +177 to +191 longitude 114 initialCenter.longitude = +176.0; 115 CLLocationCoordinate2D markerPosition; 116 117 NSUInteger nColumns = 8; 118 double columnSpacing = 2.0; 119 120 UIImage *markerImage = [UIImage imageNamed:@"marker-red.png"]; 121 markerPosition.latitude = initialCenter.latitude; 122 markerPosition.longitude = initialCenter.longitude - ((nColumns - 1)/2.0 * columnSpacing); 123 NSUInteger j; 124 NSMutableArray *testMarkers = [NSMutableArray arrayWithCapacity:nColumns]; 125 for (j = 0; j < nColumns; j++) { 126 markerPosition.longitude += columnSpacing; 127 RMMarker *newMarker = [[RMMarker alloc] initWithUIImage:markerImage]; 128 [testMarkers addObject:newMarker]; 129 [newMarker setData:[NSArray arrayWithObjects:[NSNumber numberWithDouble:markerPosition.longitude],[NSNumber numberWithDouble:markerPosition.latitude],nil]]; 130 [mapView.contents.markerManager addMarker:newMarker 131 AtLatLong:markerPosition]; 132 } 133 STAssertGreaterThan(columnSpacing, 0.0, @"this test requires positive columnSpacing"); 134 135 RMMarkerManager *mangler = [[mapView contents] markerManager]; 136 137 [[mapView contents] moveBy:CGSizeMake(-5.0, 0.0)]; 138#ifdef DEBUG 139 RMSphericalTrapezium screenLimitsDegrees = [[mapView contents] latitudeLongitudeBoundingBoxForScreen]; 140 RMLog(@"screen limits west: %4.1f east %4.1f", screenLimitsDegrees.southwest.longitude, screenLimitsDegrees.northeast.longitude); 141 RMLog(@"screen limits south: %4.1f north %4.1f", screenLimitsDegrees.southwest.latitude, screenLimitsDegrees.northeast.latitude); 142#endif 143 144 for (j = 1; j < nColumns; j++) { 145 RMMarker *leftMarker = [testMarkers objectAtIndex:j - 1]; 146 RMMarker *rightMarker = [testMarkers objectAtIndex:j]; 147 CGPoint leftScreenPosition = [mangler screenCoordinatesForMarker:leftMarker]; 148 CGPoint rightScreenPosition = [mangler screenCoordinatesForMarker:rightMarker]; 149 RMLatLong leftMarkerCoordinate, rightMarkerCoordinate; 150 leftMarkerCoordinate.longitude = [[(NSArray *)leftMarker.data objectAtIndex:0] doubleValue]; 151 leftMarkerCoordinate.latitude = [[(NSArray *)leftMarker.data objectAtIndex:1] doubleValue]; 152 rightMarkerCoordinate.longitude = [[(NSArray *)rightMarker.data objectAtIndex:0] doubleValue]; 153 rightMarkerCoordinate.latitude = [[(NSArray *)rightMarker.data objectAtIndex:1] doubleValue]; 154 STAssertLessThan(leftScreenPosition.x, rightScreenPosition.x, 155 @"screen position calculation failed (markers %d, %d): left (%f, %f) right (%f, %f) mapped to left (%f, %f) right (%f, %f)", 156 j-1, j, 157// write these out as longitude/latitude instead of standard latitude/longitude to make comparisons easier 158 leftMarkerCoordinate.longitude, leftMarkerCoordinate.latitude, 159 rightMarkerCoordinate.longitude, rightMarkerCoordinate.latitude, 160 leftScreenPosition.x, leftScreenPosition.y, rightScreenPosition.x, rightScreenPosition.y); 161 CLLocationCoordinate2D computedLatitudeLongitude = 162 [mangler latitudeLongitudeForMarker:leftMarker]; 163 STAssertEqualsWithAccuracy(leftMarkerCoordinate.longitude, computedLatitudeLongitude.longitude, kAccuracyThresholdForGeographicCoordinates, 164 @"round-trip computation of longitude failed %f %f", 165 leftMarkerCoordinate.longitude, computedLatitudeLongitude.longitude); 166 STAssertEqualsWithAccuracy(leftMarkerCoordinate.latitude, computedLatitudeLongitude.latitude, kAccuracyThresholdForGeographicCoordinates, 167 @"round-trip computation of latitude failed %f %f", 168 leftMarkerCoordinate.latitude, computedLatitudeLongitude.latitude); 169 } 170 171} 172 173- (void)testMarkerCoordinatesFarWest 174{ 175 [mapView.contents setZoom:3.0]; 176 177 // create markers from -177 to -169 longitude 178 initialCenter.longitude = -178.0; 179 CLLocationCoordinate2D markerPosition; 180 181 NSUInteger nColumns = 8; 182 double columnSpacing = 2.0; 183 184 UIImage *markerImage = [UIImage imageNamed:@"marker-red.png"]; 185 markerPosition.latitude = initialCenter.latitude; 186 markerPosition.longitude = initialCenter.longitude - ((nColumns - 1)/2.0 * columnSpacing); 187 NSUInteger j; 188 NSMutableArray *testMarkers = [NSMutableArray arrayWithCapacity:nColumns]; 189 for (j = 0; j < nColumns; j++) { 190 markerPosition.longitude += columnSpacing; 191 RMMarker *newMarker = [[RMMarker alloc] initWithUIImage:markerImage]; 192 [testMarkers addObject:newMarker]; 193 [newMarker setData:[NSArray arrayWithObjects:[NSNumber numberWithDouble:markerPosition.longitude],[NSNumber numberWithDouble:markerPosition.latitude],nil]]; 194 [mapView.contents.markerManager addMarker:newMarker 195 AtLatLong:markerPosition]; 196 } 197 STAssertGreaterThan(columnSpacing, 0.0, @"this test requires positive columnSpacing"); 198 199 RMMarkerManager *mangler = [[mapView contents] markerManager]; 200 201 [[mapView contents] moveBy:CGSizeMake(-5.0, 0.0)]; 202#ifdef DEBUG 203 RMSphericalTrapezium screenLimitsDegrees = [[mapView contents] latitudeLongitudeBoundingBoxForScreen]; 204 RMLog(@"screen limits west: %4.1f east %4.1f", screenLimitsDegrees.southwest.longitude, screenLimitsDegrees.northeast.longitude); 205 RMLog(@"screen limits south: %4.1f north %4.1f", screenLimitsDegrees.southwest.latitude, screenLimitsDegrees.northeast.latitude); 206#endif 207 208 for (j = 1; j < nColumns; j++) { 209 RMMarker *leftMarker = [testMarkers objectAtIndex:j - 1]; 210 RMMarker *rightMarker = [testMarkers objectAtIndex:j]; 211 CGPoint leftScreenPosition = [mangler screenCoordinatesForMarker:leftMarker]; 212 CGPoint rightScreenPosition = [mangler screenCoordinatesForMarker:rightMarker]; 213 RMLatLong leftMarkerCoordinate, rightMarkerCoordinate; 214 leftMarkerCoordinate.longitude = [[(NSArray *)leftMarker.data objectAtIndex:0] doubleValue]; 215 leftMarkerCoordinate.latitude = [[(NSArray *)leftMarker.data objectAtIndex:1] doubleValue]; 216 rightMarkerCoordinate.longitude = [[(NSArray *)rightMarker.data objectAtIndex:0] doubleValue]; 217 rightMarkerCoordinate.latitude = [[(NSArray *)rightMarker.data objectAtIndex:1] doubleValue]; 218 STAssertLessThan(leftScreenPosition.x, rightScreenPosition.x, 219 @"screen position calculation failed (markers %d, %d): left (%f, %f) right (%f, %f) mapped to left (%f, %f) right (%f, %f)", 220 j-1, j, 221 leftMarkerCoordinate.longitude, leftMarkerCoordinate.latitude, 222 rightMarkerCoordinate.longitude, rightMarkerCoordinate.latitude, 223 leftScreenPosition.x, leftScreenPosition.y, rightScreenPosition.x, rightScreenPosition.y); 224 CLLocationCoordinate2D computedLatitudeLongitude = 225 [mangler latitudeLongitudeForMarker:leftMarker]; 226 STAssertEqualsWithAccuracy(leftMarkerCoordinate.longitude, computedLatitudeLongitude.longitude, kAccuracyThresholdForGeographicCoordinates, 227 @"round-trip computation of longitude failed %f %f", 228 leftMarkerCoordinate.longitude, computedLatitudeLongitude.longitude); 229 STAssertEqualsWithAccuracy(leftMarkerCoordinate.latitude, computedLatitudeLongitude.latitude, kAccuracyThresholdForGeographicCoordinates, 230 @"round-trip computation of latitude failed %f %f", 231 leftMarkerCoordinate.latitude, computedLatitudeLongitude.latitude); 232 } 233 234} 235 236- (void)testScreenCoordinatesPacificNorthwest 237{ 238 [[mapView contents] setZoom: 10]; 239 CLLocationCoordinate2D coord = {45.5,-121}; 240 [mapView moveToLatLong:coord]; 241 242 CGPoint point1 = [mapView latLongToPixel:coord]; 243 244 coord.longitude -= .125; 245 CGPoint point2 = [mapView latLongToPixel:coord]; 246 247 coord.longitude -= .125; 248 CGPoint point3 = [mapView latLongToPixel:coord]; 249 250 STAssertEqualsWithAccuracy(point1.y, point2.y, kAccuracyThresholdForPixelCoordinates, 251 @"Y pixel values should be equal"); 252 STAssertEqualsWithAccuracy(point2.y, point3.y, kAccuracyThresholdForPixelCoordinates, 253 @"Y pixel values should be equal"); 254 STAssertLessThan(point3.x, point2.x, 255 @"X pixel coordinates should be increasing left to right"); 256 STAssertLessThan(point2.x, point1.x, 257 @"X pixel coordinates should be increasing left to right"); 258} 259 260- (void)testScreenCoordinatesFarEast 261{ 262 [[mapView contents] setZoom: 10]; 263 CLLocationCoordinate2D coord = {45.5,179.9}; 264 [mapView moveToLatLong:coord]; 265 266 CGPoint point1 = [mapView latLongToPixel:coord]; 267 268 coord.longitude += .125; 269 CGPoint point2 = [mapView latLongToPixel:coord]; 270 271 coord.longitude += .125; 272 CGPoint point3 = [mapView latLongToPixel:coord]; 273 274 STAssertEqualsWithAccuracy(point1.y, point2.y, kAccuracyThresholdForPixelCoordinates, 275 @"Y pixel values should be equal"); 276 STAssertEqualsWithAccuracy(point2.y, point3.y, kAccuracyThresholdForPixelCoordinates, 277 @"Y pixel values should be equal"); 278 STAssertLessThan(point1.x, point2.x, 279 @"X pixel coordinates should be increasing left to right"); 280 STAssertLessThan(point2.x, point3.x, 281 @"X pixel coordinates should be increasing left to right"); 282} 283 284- (void)testScreenCoordinatesFarWest 285{ 286 [[mapView contents] setZoom: 10]; 287 CLLocationCoordinate2D coord = {45.5,-179.9}; 288 [mapView moveToLatLong:coord]; 289 290 CGPoint point1 = [mapView latLongToPixel:coord]; 291 292 coord.longitude -= .125; 293 CGPoint point2 = [mapView latLongToPixel:coord]; 294 295 coord.longitude -= .125; 296 CGPoint point3 = [mapView latLongToPixel:coord]; 297 298 STAssertEqualsWithAccuracy(point1.y, point2.y, kAccuracyThresholdForPixelCoordinates, 299 @"Y pixel values should be equal"); 300 STAssertEqualsWithAccuracy(point2.y, point3.y, kAccuracyThresholdForPixelCoordinates, 301 @"Y pixel values should be equal"); 302 STAssertLessThan(point3.x, point2.x, 303 @"X pixel coordinates should be increasing left to right"); 304 STAssertLessThan(point2.x, point1.x, 305 @"X pixel coordinates should be increasing left to right"); 306} 307 308- (void)testZoomBounds 309{ 310 double contentsMaxZoom, tilesourceMaxZoom, contentsZoom; 311 contentsMaxZoom = [[mapView contents] maxZoom]; 312 tilesourceMaxZoom = [[[mapView contents] tileSource] maxZoom]; 313 contentsZoom = [[mapView contents] zoom]; 314 STAssertLessThanOrEqual(contentsMaxZoom, tilesourceMaxZoom, @"map's maxZoom exceeds tilesource's maxZoom"); 315 STAssertLessThanOrEqual(contentsZoom, tilesourceMaxZoom, @"map's zoom exceeds tilesource's maxZoom"); 316 317 double targetZoom = tilesourceMaxZoom + 0.4; 318 [[mapView contents] setZoom:targetZoom]; // try to exceed tilesource limit 319 contentsZoom = [[mapView contents] zoom]; 320 STAssertEqualsWithAccuracy(contentsZoom, tilesourceMaxZoom, kAccuracyThreshold, @"map's zoom wrong after trying to exceed tilesource's maxZoom"); 321 322 targetZoom = tilesourceMaxZoom + 0.5; 323 [[mapView contents] setZoom:targetZoom]; // try to exceed tilesource limit 324 contentsZoom = [[mapView contents] zoom]; 325 STAssertEqualsWithAccuracy(contentsZoom, tilesourceMaxZoom, kAccuracyThreshold, @"map's zoom wrong after trying to exceed tilesource's maxZoom"); 326 327 targetZoom = tilesourceMaxZoom - 1.6; 328 [[mapView contents] setZoom:targetZoom]; 329 CGPoint pivotPoint = CGPointMake(5., 5.); 330 [[mapView contents] zoomInToNextNativeZoomAt:pivotPoint]; 331 contentsZoom = [[mapView contents] zoom]; 332 STAssertEqualsWithAccuracy(contentsZoom, tilesourceMaxZoom - 1.0, kAccuracyThreshold, 333 @"map's zoom %f wrong after zoomInToNextNativeZoomAt: for maxZoom-1 %f", 334 contentsZoom, tilesourceMaxZoom); 335 [[mapView contents] zoomInToNextNativeZoomAt:pivotPoint]; 336 contentsZoom = [[mapView contents] zoom]; 337 STAssertEqualsWithAccuracy(contentsZoom, tilesourceMaxZoom, kAccuracyThreshold, 338 @"map's zoom [%f] wrong after zoomInToNextNativeZoomAt: for maxZoom %f (first)", 339 contentsZoom, tilesourceMaxZoom); 340 [[mapView contents] zoomInToNextNativeZoomAt:pivotPoint]; 341 contentsZoom = [[mapView contents] zoom]; 342 STAssertEqualsWithAccuracy(contentsZoom, tilesourceMaxZoom, kAccuracyThreshold, 343 @"map's zoom %f wrong after zoomInToNextNativeZoomAt: for maxZoom %f (second)", 344 contentsZoom, tilesourceMaxZoom); 345 346 347 targetZoom = tilesourceMaxZoom - 1.5; 348 [[mapView contents] setZoom:targetZoom]; 349 pivotPoint = CGPointMake(5., 5.); 350 [[mapView contents] zoomInToNextNativeZoomAt:pivotPoint]; 351 contentsZoom = [[mapView contents] zoom]; 352 STAssertEqualsWithAccuracy(contentsZoom, tilesourceMaxZoom - 1.0, kAccuracyThreshold, 353 @"map's zoom %f wrong after zoomInToNextNativeZoomAt: for maxZoom-1 %f", 354 contentsZoom, tilesourceMaxZoom); 355 [[mapView contents] zoomInToNextNativeZoomAt:pivotPoint]; 356 contentsZoom = [[mapView contents] zoom]; 357 STAssertEqualsWithAccuracy(contentsZoom, tilesourceMaxZoom, kAccuracyThreshold, 358 @"map's zoom [%f] wrong after zoomInToNextNativeZoomAt: for maxZoom %f (first)", 359 contentsZoom, tilesourceMaxZoom); 360 [[mapView contents] zoomInToNextNativeZoomAt:pivotPoint]; 361 contentsZoom = [[mapView contents] zoom]; 362 STAssertEqualsWithAccuracy(contentsZoom, tilesourceMaxZoom, kAccuracyThreshold, 363 @"map's zoom %f wrong after zoomInToNextNativeZoomAt: for maxZoom %f (second)", 364 contentsZoom, tilesourceMaxZoom); 365 366 367 double contentsMinZoom = 3.0; 368 [[mapView contents] setMinZoom:contentsMinZoom]; 369 targetZoom = contentsMinZoom + 0.6; 370 [[mapView contents] setZoom:targetZoom]; 371 contentsZoom = [[mapView contents] zoom]; 372 NSLog(@"zoom: %f minZoom: %f", contentsZoom, [[mapView contents] minZoom]); 373 [[mapView contents] zoomOutToNextNativeZoomAt:pivotPoint]; 374 contentsZoom = [[mapView contents] zoom]; 375 STAssertEqualsWithAccuracy(contentsZoom, contentsMinZoom, kAccuracyThreshold, 376 @"map's zoom %f wrong after first zoomOutToNextNativeZoomAt: for minZoom %f", 377 contentsZoom, contentsMinZoom); 378 [[mapView contents] zoomOutToNextNativeZoomAt:pivotPoint]; 379 contentsZoom = [[mapView contents] zoom]; 380 STAssertEqualsWithAccuracy(contentsZoom, contentsMinZoom, kAccuracyThreshold, 381 @"map's zoom %f wrong after second zoomOutToNextNativeZoomAt: for minZoom %f", 382 contentsZoom, contentsMinZoom); 383 384 contentsMinZoom = 3.0; 385 [[mapView contents] setMinZoom:contentsMinZoom]; 386 targetZoom = contentsMinZoom + 1.6; 387 [[mapView contents] setZoom:targetZoom]; 388 contentsZoom = [[mapView contents] zoom]; 389 NSLog(@"zoom: %f minZoom: %f", contentsZoom, [[mapView contents] minZoom]); 390 [[mapView contents] zoomOutToNextNativeZoomAt:pivotPoint]; 391 contentsZoom = [[mapView contents] zoom]; 392 STAssertEqualsWithAccuracy(contentsZoom, contentsMinZoom+1.0, kAccuracyThreshold, 393 @"map's zoom %f wrong after first zoomOutToNextNativeZoomAt: for minZoom %f", 394 contentsZoom, contentsMinZoom); 395 [[mapView contents] zoomOutToNextNativeZoomAt:pivotPoint]; 396 contentsZoom = [[mapView contents] zoom]; 397 STAssertEqualsWithAccuracy(contentsZoom, contentsMinZoom, kAccuracyThreshold, 398 @"map's zoom %f wrong after second zoomOutToNextNativeZoomAt: for minZoom %f", 399 contentsZoom, contentsMinZoom); 400 [[mapView contents] zoomOutToNextNativeZoomAt:pivotPoint]; 401 contentsZoom = [[mapView contents] zoom]; 402 STAssertEqualsWithAccuracy(contentsZoom, contentsMinZoom, kAccuracyThreshold, 403 @"map's zoom %f wrong after second zoomOutToNextNativeZoomAt: for minZoom %f", 404 contentsZoom, contentsMinZoom); 405 406 407} 408 409@end