summaryrefslogtreecommitdiff
path: root/platform/ios/Integration Tests
diff options
context:
space:
mode:
authorChris Loer <chris.loer@gmail.com>2018-06-01 15:23:41 -0700
committerChris Loer <chris.loer@mapbox.com>2018-06-04 11:32:20 -0700
commitaf4efd4fa7106a919f730127bdb8bade81fd8203 (patch)
tree18b50fa26a036d698d6179133d49766fd55708e7 /platform/ios/Integration Tests
parent552b982a33c087a83534bfc7d4e3829cd0d5af86 (diff)
downloadqtlocation-mapboxgl-af4efd4fa7106a919f730127bdb8bade81fd8203.tar.gz
[ios, test] Add MGLMapSnapshotter integration tests.
Diffstat (limited to 'platform/ios/Integration Tests')
-rw-r--r--platform/ios/Integration Tests/MGLMapViewIntegrationTest.h6
-rw-r--r--platform/ios/Integration Tests/Snapshotter Tests/MGLMapSnapshotterTest.m239
2 files changed, 245 insertions, 0 deletions
diff --git a/platform/ios/Integration Tests/MGLMapViewIntegrationTest.h b/platform/ios/Integration Tests/MGLMapViewIntegrationTest.h
index 3ceec8f04a..1b680f2b71 100644
--- a/platform/ios/Integration Tests/MGLMapViewIntegrationTest.h
+++ b/platform/ios/Integration Tests/MGLMapViewIntegrationTest.h
@@ -10,6 +10,12 @@
#define MGLTestAssertEqualWithAccuracy(myself, expression1, expression2, accuracy, ...) \
_XCTPrimitiveAssertEqualWithAccuracy(myself, expression1, @#expression1, expression2, @#expression2, accuracy, @#accuracy, __VA_ARGS__)
+#define MGLTestAssertNil(myself, expression, ...) \
+ _XCTPrimitiveAssertNil(myself, expression, @#expression, __VA_ARGS__)
+
+#define MGLTestAssertNotNil(myself, expression, ...) \
+ _XCTPrimitiveAssertNotNil(myself, expression, @#expression, __VA_ARGS__)
+
@interface MGLMapViewIntegrationTest : XCTestCase <MGLMapViewDelegate>
@property (nonatomic) MGLMapView *mapView;
diff --git a/platform/ios/Integration Tests/Snapshotter Tests/MGLMapSnapshotterTest.m b/platform/ios/Integration Tests/Snapshotter Tests/MGLMapSnapshotterTest.m
new file mode 100644
index 0000000000..f31f9cf787
--- /dev/null
+++ b/platform/ios/Integration Tests/Snapshotter Tests/MGLMapSnapshotterTest.m
@@ -0,0 +1,239 @@
+#import "MGLMapViewIntegrationTest.h"
+
+@interface MGLMapSnapshotterTest : MGLMapViewIntegrationTest
+@end
+
+// Convenience func to create snapshotter
+MGLMapSnapshotter* snapshotterWithCoordinates(CLLocationCoordinate2D coordinates, CGSize size) {
+ // Create snapshot options
+ MGLMapCamera* mapCamera = [[MGLMapCamera alloc] init];
+ mapCamera.pitch = 20;
+ mapCamera.centerCoordinate = coordinates;
+ MGLMapSnapshotOptions* options = [[MGLMapSnapshotOptions alloc] initWithStyleURL:[MGLStyle satelliteStreetsStyleURL]
+ camera:mapCamera
+ size:size];
+ options.zoomLevel = 10;
+
+ // Create and start the snapshotter
+ MGLMapSnapshotter* snapshotter = [[MGLMapSnapshotter alloc] initWithOptions:options];
+ return snapshotter;
+}
+
+NSString* validAccessToken() {
+ NSString *accessToken = [[NSProcessInfo processInfo] environment][@"MAPBOX_ACCESS_TOKEN"];
+ if (!accessToken) {
+ printf("warning: MAPBOX_ACCESS_TOKEN env var is required for this test - skipping.\n");
+ return nil;
+ }
+
+ [MGLAccountManager setAccessToken:accessToken];
+ return accessToken;
+}
+
+@implementation MGLMapSnapshotterTest
+
+- (void)testMultipleSnapshotsWithASingleSnapshotter {
+ if (!validAccessToken()) {
+ return;
+ }
+
+ CGSize size = self.mapView.bounds.size;
+
+ XCTestExpectation *expectation = [self expectationWithDescription:@"snapshots"];
+ expectation.expectedFulfillmentCount = 2;
+ expectation.assertForOverFulfill = YES;
+
+ CLLocationCoordinate2D coord = CLLocationCoordinate2DMake(30.0, 30.0);
+
+ MGLMapSnapshotter *snapshotter = snapshotterWithCoordinates(coord, size);
+ XCTAssertNotNil(snapshotter);
+
+ [snapshotter startWithCompletionHandler:^(MGLMapSnapshot * _Nullable snapshot, NSError * _Nullable error) {
+ [expectation fulfill];
+ }];
+
+ @try {
+ [snapshotter startWithCompletionHandler:^(MGLMapSnapshot * _Nullable snapshot, NSError * _Nullable error) {
+ XCTFail(@"Should not be called - but should it?");
+ }];
+ XCTFail(@"Should not be called");
+ }
+ @catch (NSException *exception) {
+ XCTAssert(exception.name == NSInternalInconsistencyException);
+ [expectation fulfill];
+ }
+
+ [self waitForExpectations:@[expectation] timeout:10.0];
+}
+
+- (void)testAllocatingSnapshotOnBackgroundQueue {
+ if (!validAccessToken()) {
+ return;
+ }
+
+ XCTestExpectation *expectation = [self expectationWithDescription:@"snapshots"];
+
+ CGSize size = self.mapView.bounds.size;
+ CLLocationCoordinate2D coord = CLLocationCoordinate2DMake(30.0, 30.0);
+
+ dispatch_queue_attr_t attr = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_USER_INITIATED, QOS_MIN_RELATIVE_PRIORITY);
+ dispatch_queue_t backgroundQueue = dispatch_queue_create(__PRETTY_FUNCTION__, attr);
+
+ // This crashes maybe 1 in 10 times.
+ dispatch_async(backgroundQueue, ^{
+
+ // Create the snapshotter - DO NOT START.
+ MGLMapSnapshotter* snapshotter = snapshotterWithCoordinates(coord, size);
+
+ dispatch_group_t group = dispatch_group_create();
+ dispatch_group_enter(group);
+
+ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
+ dispatch_group_leave(group);
+ });
+
+ dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
+
+ snapshotter = nil;
+
+ dispatch_sync(dispatch_get_main_queue(), ^{
+ [expectation fulfill];
+ });
+ });
+
+ [self waitForExpectations:@[expectation] timeout:2.0];
+}
+
+- (void)testMultipleSnapshottersFromBackgroundQueue {
+ if (!validAccessToken()) {
+ return;
+ }
+
+ // Crashes with only 1 snapshot
+ CGSize size = self.mapView.bounds.size;
+ CLLocationCoordinate2D coord = CLLocationCoordinate2DMake(30.0, 30.0);
+
+ XCTestExpectation *expectation = [self expectationWithDescription:@"snapshots"];
+ expectation.expectedFulfillmentCount = 1;
+ expectation.assertForOverFulfill = YES;
+
+ __weak __typeof__(self) weakself = self;
+
+ dispatch_queue_attr_t attr = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_USER_INITIATED, QOS_MIN_RELATIVE_PRIORITY); // also for concurrent
+ dispatch_queue_t backgroundQueue = dispatch_queue_create(__PRETTY_FUNCTION__, attr);
+
+
+ // Use dispatch_group to keep the backgroundQueue block around (and
+ // so also the MGLMapSnapshotter
+ dispatch_group_t group = dispatch_group_create();
+ dispatch_group_enter(group);
+
+
+ dispatch_async(backgroundQueue, ^{
+
+ MGLMapSnapshotter *snapshotter = snapshotterWithCoordinates(coord, size);
+ XCTAssertNotNil(snapshotter);
+
+ MGLMapSnapshotCompletionHandler completion = ^(MGLMapSnapshot * _Nullable snapshot, NSError * _Nullable error) {
+
+ // This should be the main queue
+ __typeof__(self) strongself = weakself;
+
+ MGLTestAssertNotNil(strongself, strongself);
+
+ MGLTestAssertNotNil(strongself, snapshot);
+ MGLTestAssertNotNil(strongself, snapshot.image);
+ MGLTestAssertNil(strongself, error, @"Snapshot should not error with: %@", error);
+
+ // Change this back to XCTAttachmentLifetimeDeleteOnSuccess when we're sure this
+ // test is passing.
+ XCTAttachment *attachment = [XCTAttachment attachmentWithImage:snapshot.image];
+ attachment.lifetime = XCTAttachmentLifetimeKeepAlways;
+ [strongself addAttachment:attachment];
+
+ dispatch_group_leave(group);
+ };
+
+ // untested
+ @try {
+ [snapshotter startWithCompletionHandler:completion];
+ MGLTestFail(weakself);
+ }
+ @catch (NSException *exception) {
+ MGLTestAssert(weakself, exception.name == NSInvalidArgumentException);
+ dispatch_group_leave(group);
+ }
+
+ // Wait for the snapshot to complete
+ dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
+
+ snapshotter = nil;
+
+ dispatch_sync(dispatch_get_main_queue(), ^{
+ [expectation fulfill];
+ });
+ });
+
+ [self waitForExpectations:@[expectation] timeout:10.0];
+}
+
+- (void)testMultipleSnapshotters {
+ if (!validAccessToken()) {
+ return;
+ }
+
+ NSUInteger numSnapshots = 8;
+ CGSize size = self.mapView.bounds.size;
+
+ XCTestExpectation *expectation = [self expectationWithDescription:@"snapshots"];
+ expectation.expectedFulfillmentCount = numSnapshots;
+ expectation.assertForOverFulfill = YES;
+
+ __weak __typeof__(self) weakself = self;
+
+ for (size_t run = 0; run < numSnapshots; run++) {
+
+ float ratio = (float)run/(float)numSnapshots;
+ float lon = (ratio*120.0) + ((1.0-ratio)*54.0);
+ CLLocationCoordinate2D coord = CLLocationCoordinate2DMake(57.0, lon);
+
+ __block MGLMapSnapshotter *snapshotter;
+
+ // Allocate from an autorelease pool here, to avoid having
+ // snapshotter retained for longer than we'd like to test.
+ @autoreleasepool {
+ snapshotter = snapshotterWithCoordinates(coord, size);
+ XCTAssertNotNil(snapshotter);
+ }
+
+ [snapshotter startWithCompletionHandler:^(MGLMapSnapshot * _Nullable snapshot, NSError * _Nullable error) {
+
+ // This should be the main queue
+ __typeof__(self) strongself = weakself;
+
+ MGLTestAssertNotNil(strongself, strongself);
+
+ MGLTestAssertNotNil(strongself, snapshot);
+ MGLTestAssertNotNil(strongself, snapshot.image);
+ MGLTestAssertNil(strongself, error, @"Snapshot should not error with: %@", error);
+
+ // Change this back to XCTAttachmentLifetimeDeleteOnSuccess when we're sure this
+ // test is passing.
+ XCTAttachment *attachment = [XCTAttachment attachmentWithImage:snapshot.image];
+ attachment.lifetime = XCTAttachmentLifetimeKeepAlways;
+ [strongself addAttachment:attachment];
+
+ // Dealloc the snapshotter (by having this line in the block, we
+ // also retained the snapshotter. Setting to nil should release, as
+ // this block should be the only thing retaining it (since it was
+ // allocated from the above autorelease pool)
+ snapshotter = nil;
+
+ [expectation fulfill];
+ }];
+ } // end for loop
+
+ [self waitForExpectations:@[expectation] timeout:20.0];
+}
+
+@end