diff --git a/platform/ios/Integration Tests/MBShapeSourceTests.m b/platform/ios/Integration Tests/MBShapeSourceTests.m new file mode 100644 index 00000000000..20a325af460 --- /dev/null +++ b/platform/ios/Integration Tests/MBShapeSourceTests.m @@ -0,0 +1,74 @@ +// +// MBShapeSourceTests.m +// integration +// +// Created by Julian Rex on 4/5/18. +// Copyright © 2018 Mapbox. All rights reserved. +// + +#import "MGLMapViewIntegrationTest.h" + +@interface MBShapeSourceTests : MGLMapViewIntegrationTest +@end + +@implementation MBShapeSourceTests + +- (void)testRepeatedlyChangingShapeSourceToNil { + + NSMutableArray *features = [[NSMutableArray alloc] init]; + + for (NSUInteger i = 0; i <= 180; i+=5) { + CLLocationCoordinate2D coord[4] = { + CLLocationCoordinate2DMake(round(0), round(i)), + CLLocationCoordinate2DMake(round(20), round(i)), + CLLocationCoordinate2DMake(round(0), round(i / 2 )), + CLLocationCoordinate2DMake(round(20), round(i / 2))}; + + MGLPolygonFeature *feature = [MGLPolygonFeature polygonWithCoordinates:coord count:4]; + [features addObject:feature]; + } + + MGLShapeSource *shapeSource = [[MGLShapeSource alloc] initWithIdentifier:@"source" features:features options:nil]; + [self.style addSource:shapeSource]; + + MGLFillStyleLayer *layer = [[MGLFillStyleLayer alloc] initWithIdentifier:@"layer" source:shapeSource]; + layer.fillOpacity = [NSExpression expressionForConstantValue:@0.5]; + [self.style addLayer:layer]; + + XCTestExpectation *expectation = [self expectationWithDescription:@"regionDidChange expectation"]; + + __weak typeof(self) weakself = self; + __block NSInteger delegateCallCount; + + self.regionDidChange = ^(MGLMapView *mapView, BOOL animated) { + + MBShapeSourceTests *strongSelf = weakself; + + if (!strongSelf) + return; + + delegateCallCount++; + + // Setting the shapeSource.shape = nil, was causing an infinite loop, so here + // we check for a runaway call. 10 here is arbitrary. We could argue that this + // should check that the call count is only 1, however in this case we particularly + // want to check for the infinite loop. + // See https://github.com/mapbox/mapbox-gl-native/issues/11180 + + if (delegateCallCount > 10) { + XCTFail(); + } + else { + shapeSource.shape = nil; + } + + [NSObject cancelPreviousPerformRequestsWithTarget:expectation selector:@selector(fulfill) object:nil]; + [expectation performSelector:@selector(fulfill) withObject:nil afterDelay:5.0]; + }; + + [self.mapView setCenterCoordinate:CLLocationCoordinate2DMake(10.0, 10.0)]; + [self waitForExpectations:@[expectation] timeout:30.0]; +} + + +@end diff --git a/platform/ios/ios.xcodeproj/project.pbxproj b/platform/ios/ios.xcodeproj/project.pbxproj index 78cfff965cc..20da7659863 100644 --- a/platform/ios/ios.xcodeproj/project.pbxproj +++ b/platform/ios/ios.xcodeproj/project.pbxproj @@ -363,6 +363,7 @@ AC518E00201BB55A00EBC820 /* MGLTelemetryConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = AC518DFD201BB55A00EBC820 /* MGLTelemetryConfig.h */; }; AC518E03201BB56000EBC820 /* MGLTelemetryConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = AC518DFE201BB55A00EBC820 /* MGLTelemetryConfig.m */; }; AC518E04201BB56100EBC820 /* MGLTelemetryConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = AC518DFE201BB55A00EBC820 /* MGLTelemetryConfig.m */; }; + CA0C27922076C804001CE5B7 /* MBShapeSourceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CA0C27912076C804001CE5B7 /* MBShapeSourceTests.m */; }; CA0C27942076CA19001CE5B7 /* MGLMapViewIntegrationTest.m in Sources */ = {isa = PBXBuildFile; fileRef = CA0C27932076CA19001CE5B7 /* MGLMapViewIntegrationTest.m */; }; CA4EB8C720863487006AB465 /* MGLStyleLayerIntegrationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CA4EB8C620863487006AB465 /* MGLStyleLayerIntegrationTests.m */; }; CA55CD41202C16AA00CE7095 /* MGLCameraChangeReason.h in Headers */ = {isa = PBXBuildFile; fileRef = CA55CD3E202C16AA00CE7095 /* MGLCameraChangeReason.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -996,6 +997,7 @@ 96F3F73B1F5711F1003E2D2C /* MGLUserLocationHeadingIndicator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLUserLocationHeadingIndicator.h; sourceTree = ""; }; AC518DFD201BB55A00EBC820 /* MGLTelemetryConfig.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLTelemetryConfig.h; sourceTree = ""; }; AC518DFE201BB55A00EBC820 /* MGLTelemetryConfig.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MGLTelemetryConfig.m; sourceTree = ""; }; + CA0C27912076C804001CE5B7 /* MBShapeSourceTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MBShapeSourceTests.m; sourceTree = ""; }; CA0C27932076CA19001CE5B7 /* MGLMapViewIntegrationTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MGLMapViewIntegrationTest.m; sourceTree = ""; }; CA0C27952076CA50001CE5B7 /* MGLMapViewIntegrationTest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLMapViewIntegrationTest.h; sourceTree = ""; }; CA4EB8C620863487006AB465 /* MGLStyleLayerIntegrationTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MGLStyleLayerIntegrationTests.m; sourceTree = ""; }; @@ -1353,6 +1355,7 @@ children = ( 16376B091FFD9DAF0000563E /* MBGLIntegrationTests.m */, 16376B0B1FFD9DAF0000563E /* Info.plist */, + CA0C27912076C804001CE5B7 /* MBShapeSourceTests.m */, CA0C27932076CA19001CE5B7 /* MGLMapViewIntegrationTest.m */, CA0C27952076CA50001CE5B7 /* MGLMapViewIntegrationTest.h */, CA4EB8C620863487006AB465 /* MGLStyleLayerIntegrationTests.m */, @@ -2811,6 +2814,7 @@ CA4EB8C720863487006AB465 /* MGLStyleLayerIntegrationTests.m in Sources */, 16376B0A1FFD9DAF0000563E /* MBGLIntegrationTests.m in Sources */, CA0C27942076CA19001CE5B7 /* MGLMapViewIntegrationTest.m in Sources */, + CA0C27922076C804001CE5B7 /* MBShapeSourceTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; };