summaryrefslogtreecommitdiff
path: root/platform/ios
diff options
context:
space:
mode:
authorAsheem Mamoowala <asheem.mamoowala@mapbox.com>2018-04-02 16:15:25 -0700
committerGitHub <noreply@github.com>2018-04-02 16:15:25 -0700
commit099fcc3b3c72b117e93d4da39ee6f70c6c5a2bc8 (patch)
tree523c8c884404f82075702b6ea707e2b2b8015089 /platform/ios
parentc3079c6155d7ba2a0c8dd36571f17d7652a2092e (diff)
downloadqtlocation-mapboxgl-099fcc3b3c72b117e93d4da39ee6f70c6c5a2bc8.tar.gz
Use a host interface for CustomLayer instead of function pointers (#11553)
Use a host interface for CustomLayer instead of function pointers Co-authored-by: Julian Rex <julian.rex@mapbox.com>
Diffstat (limited to 'platform/ios')
-rw-r--r--platform/ios/Integration Tests/MBGLIntegrationTests.m217
1 files changed, 201 insertions, 16 deletions
diff --git a/platform/ios/Integration Tests/MBGLIntegrationTests.m b/platform/ios/Integration Tests/MBGLIntegrationTests.m
index db6cc13930..7b82f41b57 100644
--- a/platform/ios/Integration Tests/MBGLIntegrationTests.m
+++ b/platform/ios/Integration Tests/MBGLIntegrationTests.m
@@ -1,6 +1,6 @@
#import <XCTest/XCTest.h>
-
-@import Mapbox;
+#import <objc/message.h>
+#import <Mapbox/Mapbox.h>
@interface MBGLIntegrationTests : XCTestCase <MGLMapViewDelegate>
@@ -11,8 +11,11 @@
@implementation MBGLIntegrationTests {
XCTestExpectation *_styleLoadingExpectation;
+ XCTestExpectation *_renderFinishedExpectation;
}
+#pragma mark - Setup/Teardown
+
- (void)setUp {
[super setUp];
@@ -32,6 +35,16 @@
[window makeKeyAndVisible];
}
+- (void)tearDown {
+ _styleLoadingExpectation = nil;
+ self.mapView = nil;
+ self.style = nil;
+
+ [super tearDown];
+}
+
+#pragma mark - MGLMapViewDelegate
+
- (void)mapView:(MGLMapView *)mapView didFinishLoadingStyle:(MGLStyle *)style {
XCTAssertNotNil(mapView.style);
XCTAssertEqual(mapView.style, style);
@@ -39,30 +52,112 @@
[_styleLoadingExpectation fulfill];
}
-- (void)tearDown {
- _styleLoadingExpectation = nil;
- self.mapView = nil;
+- (void)mapViewDidFinishRenderingFrame:(MGLMapView *)mapView fullyRendered:(__unused BOOL)fullyRendered {
+ [_renderFinishedExpectation fulfill];
+ _renderFinishedExpectation = nil;
+}
- [super tearDown];
+#pragma mark - Utilities
+
+- (void)waitForMapViewToBeRendered {
+ [self.mapView setNeedsDisplay];
+ _renderFinishedExpectation = [self expectationWithDescription:@"Map view should be rendered"];
+ [self waitForExpectations:@[_renderFinishedExpectation] timeout:1];
}
- (MGLStyle *)style {
return self.mapView.style;
}
+#pragma mark - Tests
+
+// This test does not strictly need to be in this test file/target. Including here for convenience.
+- (void)testOpenGLLayerDoesNotLeakWhenCreatedAndDestroyedWithoutAddingToStyle {
+ MGLOpenGLStyleLayer *layer = [[MGLOpenGLStyleLayer alloc] initWithIdentifier:@"gl-layer"];
+ __weak id weakLayer = layer;
+ layer = nil;
+
+ XCTAssertNil(weakLayer);
+}
+
+- (void)testAddingRemovingOpenGLLayerWithoutRendering {
+ XCTAssertNotNil(self.style);
+
+ void(^addRemoveGLLayer)(void) = ^{
+ __weak id weakLayer = nil;
+
+ @autoreleasepool {
+ MGLOpenGLStyleLayer *layer = [[MGLOpenGLStyleLayer alloc] initWithIdentifier:@"gl-layer"];
+ [self.style insertLayer:layer atIndex:0];
+ weakLayer = layer;
+
+ // Nil the layer prior to remove to ensure it's being retained
+ layer = nil;
+ [self.style removeLayer:weakLayer];
+ }
+
+ XCTAssertNil(weakLayer);
+ };
+
+ addRemoveGLLayer();
+ addRemoveGLLayer();
+ addRemoveGLLayer();
+}
+
+- (void)testReusingOpenGLLayerIdentifier {
+ __weak MGLOpenGLStyleLayer *weakLayer2;
+
+ @autoreleasepool {
+ MGLOpenGLStyleLayer *layer1 = [[MGLOpenGLStyleLayer alloc] initWithIdentifier:@"gl-layer"];
+ [self.style insertLayer:layer1 atIndex:0];
+ [self waitForMapViewToBeRendered];
+ [self.style removeLayer:layer1];
+
+ MGLOpenGLStyleLayer *layer2 = [[MGLOpenGLStyleLayer alloc] initWithIdentifier:@"gl-layer"];
+ weakLayer2 = layer2;
+
+ XCTAssertNotNil(layer2);
+ XCTAssert(layer1 != layer2);
+
+ [self.style insertLayer:layer2 atIndex:0];
+ [self waitForMapViewToBeRendered];
+ [self.style removeLayer:layer2];
+
+ XCTAssertNil([layer1 style]);
+ XCTAssertNil([layer2 style]);
+ }
+
+ // At this point, layer2 (and layer1) should still be around,
+ // since the render process needs to keep a reference to them.
+ XCTAssertNotNil(weakLayer2);
+
+ // Let render loop run enough to release the layers
+ [self waitForMapViewToBeRendered];
+ XCTAssertNil(weakLayer2);
+}
+
- (void)testAddingRemovingOpenGLLayer {
XCTAssertNotNil(self.style);
void(^addRemoveGLLayer)(void) = ^{
- MGLOpenGLStyleLayer *layer = [[MGLOpenGLStyleLayer alloc] initWithIdentifier:@"gl-layer"];
- [self.style insertLayer:layer atIndex:0];
- layer = nil;
- [[NSRunLoop currentRunLoop] runUntilDate:[NSDate date]];
+ __weak id retrievedLayer = nil;
+
+ @autoreleasepool {
+ MGLOpenGLStyleLayer *layer = [[MGLOpenGLStyleLayer alloc] initWithIdentifier:@"gl-layer"];
+ [self.style insertLayer:layer atIndex:0];
+ layer = nil;
+
+ [self waitForMapViewToBeRendered];
- id retrievedLayer = [self.style layerWithIdentifier:@"gl-layer"];
- XCTAssertNotNil(retrievedLayer);
- [self.style removeLayer:retrievedLayer];
+ retrievedLayer = [self.style layerWithIdentifier:@"gl-layer"];
+ XCTAssertNotNil(retrievedLayer);
+
+ [self.style removeLayer:retrievedLayer];
+ [self waitForMapViewToBeRendered];
+ }
+
+ XCTAssertNil(retrievedLayer);
};
addRemoveGLLayer();
@@ -70,8 +165,98 @@
addRemoveGLLayer();
}
-//- (void)testOpenGLLayerDoesNotLeakWhenCreatedAndDestroyedWithoutAddingToStyle {
-// XCTFail(@"Not yet implemented");
-//}
+- (void)testReusingOpenGLLayer {
+ MGLOpenGLStyleLayer *layer = [[MGLOpenGLStyleLayer alloc] initWithIdentifier:@"gl-layer"];
+ [self.style insertLayer:layer atIndex:0];
+ [self waitForMapViewToBeRendered];
+
+ [self.style removeLayer:layer];
+ [self waitForMapViewToBeRendered];
+
+ [self.style insertLayer:layer atIndex:0];
+ [self waitForMapViewToBeRendered];
+
+ [self.style removeLayer:layer];
+ [self waitForMapViewToBeRendered];
+}
+
+- (void)testOpenGLLayerDoesNotLeakWhenRemovedFromStyle {
+ __weak id weakLayer;
+ @autoreleasepool {
+ MGLOpenGLStyleLayer *layer = [[MGLOpenGLStyleLayer alloc] initWithIdentifier:@"gl-layer"];
+ weakLayer = layer;
+ [self.style insertLayer:layer atIndex:0];
+ layer = nil;
+
+ [self waitForMapViewToBeRendered];
+ [self.style removeLayer:[self.style layerWithIdentifier:@"gl-layer"]];
+ }
+
+ MGLStyleLayer *layer2 = weakLayer;
+
+ XCTAssertNotNil(weakLayer);
+ [self waitForMapViewToBeRendered];
+
+ layer2 = nil;
+ XCTAssertNil(weakLayer);
+}
+
+- (void)testOpenGLLayerDoesNotLeakWhenStyleChanged {
+ __weak MGLOpenGLStyleLayer *weakLayer;
+
+ @autoreleasepool {
+ {
+ MGLOpenGLStyleLayer *layer = [[MGLOpenGLStyleLayer alloc] initWithIdentifier:@"gl-layer"];
+ weakLayer = layer;
+ [self.style insertLayer:layer atIndex:0];
+ layer = nil;
+ }
+ }
+
+ XCTAssertNotNil(weakLayer);
+
+ [self waitForMapViewToBeRendered];
+
+ MGLStyleLayer *layer2 = [self.mapView.style layerWithIdentifier:@"gl-layer"];
+
+ NSURL *styleURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"one-liner" withExtension:@"json"];
+ _styleLoadingExpectation = [self expectationWithDescription:@"Map view should finish loading style."];
+ [self.mapView setStyleURL:styleURL];
+ [self waitForExpectations:@[_styleLoadingExpectation] timeout:10];
+
+ // At this point the C++ CustomLayer will have been destroyed, and the rawLayer pointer has been NULLed
+ XCTAssert(weakLayer == layer2);
+ XCTAssertNotNil(weakLayer);
+
+ // Asking the style for the layer should return nil
+ MGLStyleLayer *layer3 = [self.mapView.style layerWithIdentifier:@"gl-layer"];
+ XCTAssertNil(layer3);
+}
+
+
+- (void)testOpenGLLayerDoesNotLeakWhenMapViewDeallocs {
+ __weak id weakLayer;
+
+ @autoreleasepool {
+
+ NSURL *styleURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"one-liner" withExtension:@"json"];
+ MGLMapView *mapView2 = [[MGLMapView alloc] initWithFrame:UIScreen.mainScreen.bounds styleURL:styleURL];
+ mapView2.delegate = self;
+
+ XCTAssertNil(mapView2.style);
+
+ _styleLoadingExpectation = [self expectationWithDescription:@"Map view should finish loading style."];
+ [self waitForExpectationsWithTimeout:1 handler:nil];
+
+ MGLOpenGLStyleLayer *layer = [[MGLOpenGLStyleLayer alloc] initWithIdentifier:@"gl-layer"];
+ weakLayer = layer;
+ [mapView2.style insertLayer:layer atIndex:0];
+ layer = nil;
+
+ [self waitForMapViewToBeRendered];
+ }
+ XCTAssertNil(weakLayer);
+}
@end
+