diff --git a/.github/workflows/ios-ci.yml b/.github/workflows/ios-ci.yml index 49cf35292..c5e7b298a 100644 --- a/.github/workflows/ios-ci.yml +++ b/.github/workflows/ios-ci.yml @@ -97,6 +97,9 @@ jobs: - name: Running ios unit tests run: make ios-test + - name: Running ios UI tests + run: make ios-uitest + - name: Build and run SDK unit tests with thread and undefined behavior sanitizers run: make ios-sanitize diff --git a/README.md b/README.md index be0e5523b..e101275af 100644 --- a/README.md +++ b/README.md @@ -87,9 +87,26 @@ Please refer to [Mapbox Maps SDK for Android](platform/android/) for detailed in #### iOS +You can run automated test on a Simulator or Device by changing to the Scheme `iosapp` and choosing `Product` > `Test` (or use `⌘-U`). Use `⌘-9` to navigate to `Reports` to see results and browse through screenshots. This method of testing should work well with CI tools such as GitHub Actions, Xcode Server Bots, & AWS Device Farm. + ```bash cd platform/ios + +# make and open the Xcode workspace +make iproj + +# make Xcode workspace, but run in headless mode +make iproj CI=1 + +# Make Frameworks make xcframework BUILDTYPE=Release + +# test +make ios-test + +# UITests +# You can review uitest results: $(IOS_OUTPUT_PATH)/Logs/Test + make ios-uitest ``` The packaging script will produce a `platform/ios/build/ios/pkg/dynamic` diff --git a/platform/ios/Makefile b/platform/ios/Makefile index 1486b19d3..6da1d126d 100644 --- a/platform/ios/Makefile +++ b/platform/ios/Makefile @@ -1,6 +1,7 @@ export BUILDTYPE ?= Debug export IS_LOCAL_DEVELOPMENT ?= true export TARGET_BRANCH ?= master +export CI ?= 0 CMAKE ?= cmake @@ -146,9 +147,14 @@ $(IOS_USER_DATA_PATH)/WorkspaceSettings.xcsettings: platform/ios/WorkspaceSettin ios: $(IOS_PROJ_PATH) set -o pipefail && $(IOS_XCODEBUILD_SIM) -scheme 'CI' build $(XCPRETTY) +# make iproj .PHONY: iproj iproj: $(IOS_PROJ_PATH) - xed $(IOS_WORK_PATH) + # Check if Xcode should run in headless mode + if [ $(CI) == 1 ]; then echo "CI=1. Running in headless mode, skipping $(IOS_WORK_PATH)"; \ + else \ + echo "Opening MapLibre in Xcode 'xed $(IOS_WORK_PATH)'. To skip opening Xcode, use 'make iproj CI=1'"; \ + xed $(IOS_WORK_PATH); fi; .PHONY: ios-lint-plist ios-lint-plist: @@ -164,6 +170,12 @@ ios-lint: ios-pod-lint ios-pod-lint: ./platform/ios/scripts/lint-podspecs.js +# make ios-uitest +.PHONY: ios-uitest +ios-uitest: $(IOS_PROJ_PATH) + set -o pipefail && $(IOS_XCODEBUILD_SIM) -scheme 'iosapp' test $(XCPRETTY) + echo "You can review uitest results: open $(IOS_OUTPUT_PATH)/Logs/Test" + .PHONY: ios-test ios-test: $(IOS_PROJ_PATH) set -o pipefail && $(IOS_XCODEBUILD_SIM) -scheme 'CI' test $(XCPRETTY) @@ -200,6 +212,7 @@ iframework: $(IOS_PROJ_PATH) FORMAT=$(FORMAT) BUILD_DEVICE=$(BUILD_DEVICE) SYMBOLS=$(SYMBOLS) BUILD_DOCS=$(BUILD_DOCS) \ ./platform/ios/scripts/package.sh +# make xcframework .PHONY: xcframework xcframework: $(IOS_PROJ_PATH) FORMAT=$(FORMAT) SYMBOLS=$(SYMBOLS) BUILD_DOCS=$(BUILD_DOCS) \ @@ -307,6 +320,7 @@ style-code: codestyle: scripts/codestyle.sh +# make clean .PHONY: clean clean: -rm -rf ./build \ diff --git a/platform/ios/platform/ios/app/MBXViewController.m b/platform/ios/platform/ios/app/MBXViewController.m index 678736a4d..47766d893 100644 --- a/platform/ios/platform/ios/app/MBXViewController.m +++ b/platform/ios/platform/ios/app/MBXViewController.m @@ -203,6 +203,8 @@ CLLocationCoordinate2D randomWorldCoordinate() { @property (weak, nonatomic) IBOutlet UIButton *hudLabel; @property (weak, nonatomic) IBOutlet MBXFrameTimeGraphView *frameTimeGraphView; @property (nonatomic) NSInteger styleIndex; +@property (nonatomic) NSMutableArray* styleNames; +@property (nonatomic) NSMutableArray* styleURLs; @property (nonatomic) BOOL customUserLocationAnnnotationEnabled; @property (nonatomic, getter=isLocalizingLabels) BOOL localizingLabels; @property (nonatomic) BOOL reuseQueueStatsEnabled; @@ -255,11 +257,9 @@ CLLocationCoordinate2D randomWorldCoordinate() { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(restoreMapState:) name:UIApplicationWillEnterForegroundNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(saveCurrentMapState:) name:UIApplicationWillTerminateNotification object:nil]; - if ([MGLAccountManager accessToken].length) - { - self.styleIndex = -1; - [self cycleStyles:self]; - } + self.styleIndex = -1; + [self setStyles]; + [self cycleStyles:self]; self.mapView.experimental_enableFrameRateMeasurement = YES; self.hudLabel.titleLabel.font = [UIFont monospacedDigitSystemFontOfSize:10 weight:UIFontWeightRegular]; @@ -1898,56 +1898,53 @@ CLLocationCoordinate2D randomWorldCoordinate() { } } +// MARK: - User defined Styles +- (void)setStyles +{ + self.styleNames = [NSMutableArray array]; + self.styleURLs = [NSMutableArray array]; + + /// Style that does not require an `accessToken` nor any further configuration + [self.styleNames addObject:@"Zeroconf Style"]; + [self.styleURLs addObject:[NSURL URLWithString:@"https://raw.githubusercontent.com/roblabs/openmaptiles-ios-demo/master/OSM2VectorTiles/styles/geography-class.GitHub.json"]]; + + /// Add Mapbox Styles if an `accessToken` exists + if ([MGLAccountManager accessToken].length) + { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + + [self.styleNames addObject:@"Streets"]; + [self.styleURLs addObject:[MGLStyle streetsStyleURL]]; + + [self.styleNames addObject:@"Outdoors"]; + [self.styleURLs addObject:[MGLStyle outdoorsStyleURL]]; + + [self.styleNames addObject:@"Light"]; + [self.styleURLs addObject:[MGLStyle lightStyleURL]]; + + [self.styleNames addObject:@"Dark"]; + [self.styleURLs addObject:[MGLStyle darkStyleURL]]; + + [self.styleNames addObject:@"Satellite"]; + [self.styleURLs addObject:[MGLStyle satelliteStyleURL]]; + + [self.styleNames addObject:@"Satellite Streets"]; + [self.styleURLs addObject:[MGLStyle satelliteStreetsStyleURL]]; + }); + } + + NSAssert(self.styleNames.count == self.styleURLs.count, @"Style names and URLs don’t match."); +} + - (IBAction)cycleStyles:(__unused id)sender { - static NSArray *styleNames; - static NSArray *styleURLs; + self.styleIndex = (self.styleIndex + 1) % self.styleNames.count; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - styleNames = @[ - @"Streets", - @"Outdoors", - @"Light", - @"Dark", - @"Satellite", - @"Satellite Streets", - ]; - styleURLs = @[ - [MGLStyle streetsStyleURL], - [MGLStyle outdoorsStyleURL], - [MGLStyle lightStyleURL], - [MGLStyle darkStyleURL], - [MGLStyle satelliteStyleURL], - [MGLStyle satelliteStreetsStyleURL] - ]; - NSAssert(styleNames.count == styleURLs.count, @"Style names and URLs don’t match."); - - // Make sure defaultStyleURLs is up-to-date. - unsigned numMethods = 0; - Method *methods = class_copyMethodList(object_getClass([MGLStyle class]), &numMethods); - unsigned numStyleURLMethods = 0; - for (NSUInteger i = 0; i < numMethods; i++) { - Method method = methods[i]; - if (method_getNumberOfArguments(method) == 3 /* _cmd, self, version */) { - SEL selector = method_getName(method); - NSString *name = @(sel_getName(selector)); - if ([name hasSuffix:@"StyleURLWithVersion:"]) { - numStyleURLMethods += 1; - } - } - } - NSAssert(numStyleURLMethods == styleNames.count, - @"MGLStyle provides %u default styles but iosapp only knows about %lu of them.", - numStyleURLMethods, (unsigned long)styleNames.count); - }); - - self.styleIndex = (self.styleIndex + 1) % styleNames.count; - - self.mapView.styleURL = styleURLs[self.styleIndex]; + self.mapView.styleURL = self.styleURLs[self.styleIndex]; UIButton *titleButton = (UIButton *)self.navigationItem.titleView; - [titleButton setTitle:styleNames[self.styleIndex] forState:UIControlStateNormal]; + [titleButton setTitle:self.styleNames[self.styleIndex] forState:UIControlStateNormal]; } - (IBAction)locateUser:(id)sender diff --git a/platform/ios/platform/ios/app/insert_access_token.sh b/platform/ios/platform/ios/app/insert_access_token.sh index 3a3a77644..28b5818e9 100755 --- a/platform/ios/platform/ios/app/insert_access_token.sh +++ b/platform/ios/platform/ios/app/insert_access_token.sh @@ -10,8 +10,7 @@ else plutil -replace MGLMapboxAccessToken -string $token "$TARGET_BUILD_DIR/$INFOPLIST_PATH" echo "Token insertion successful" else - echo \'error: Missing Mapbox access token\' - echo "error: Get an access token from , then create a new file at $token_file that contains the access token." - exit 1 + echo \'Warning: Missing Mapbox access token. You can optionally use MapLibre with Mapbox Styles\' + echo "Warning: Get an access token from , then create a new file at $token_file that contains the access token." fi fi diff --git a/platform/ios/platform/ios/bench UITests/Info.plist b/platform/ios/platform/ios/bench UITests/Info.plist new file mode 100644 index 000000000..64d65ca49 --- /dev/null +++ b/platform/ios/platform/ios/bench UITests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/platform/ios/platform/ios/bench UITests/bench_UITests.swift b/platform/ios/platform/ios/bench UITests/bench_UITests.swift new file mode 100644 index 000000000..2a2b5cca6 --- /dev/null +++ b/platform/ios/platform/ios/bench UITests/bench_UITests.swift @@ -0,0 +1,36 @@ +// +// bench_UITests.swift +// bench UITests +// +// Copyright © 2021 MapLibre. All rights reserved. +// + +import XCTest + +class bench_UITests: XCTestCase { + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + + // In UI tests it is usually best to stop immediately when a failure occurs. + continueAfterFailure = false + + // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func test_benchScheme() throws { + // UI tests must launch the application that they test. + let app = XCUIApplication() + app.launch() + + // Give the app enough time to run + sleep(100) + + // Use recording to get started writing UI tests. + // Use XCTAssert and related functions to verify your tests produce the correct results. + } +} diff --git a/platform/ios/platform/ios/benchmark/MBXBenchViewController.mm b/platform/ios/platform/ios/benchmark/MBXBenchViewController.mm index 9bd47f7ba..174696d6c 100644 --- a/platform/ios/platform/ios/benchmark/MBXBenchViewController.mm +++ b/platform/ios/platform/ios/benchmark/MBXBenchViewController.mm @@ -51,10 +51,54 @@ - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; + + #ifdef LOG_TO_DOCUMENTS_DIR + [self setAndRedirectLogFileToDocuments]; + #endif [self startBenchmarkIteration]; } +// For setting the filename +NSDate* const currentDate = [NSDate date]; + +/*! + \description + Write the Benchmark log to the Documents Directory. For the device or simulator, fetch the Documents Directory, and make a friendly name for the benchmarking output file. In Build Settings > Other C Flags add the compiler flag. `-DLOG_TO_DOCUMENTS_DIR` + */ +- (void)setAndRedirectLogFileToDocuments +{ + NSString* const name = UIDevice.currentDevice.name; + #if TARGET_IPHONE_SIMULATOR + NSString* const DeviceMode = @"Simulator"; + #else + NSString* const DeviceMode = @"Device"; + #endif + + // Set log file name date + NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; + [formatter setDateFormat:@"yyyy-MM-dd-HHmm"]; + NSString *dateString = [formatter stringFromDate:currentDate]; + + // Set the log file name + NSString* filename = [NSString stringWithFormat: @"MapLibre-bench-%@-%@-%@.log", name, DeviceMode, dateString]; + + // Set log file path + NSArray *allPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *documentsDirectory = [allPaths objectAtIndex:0]; + NSString *pathForLog = [documentsDirectory stringByAppendingPathComponent: filename]; + NSLog(@"Writing MapLibre Bench log. To open in Console, use the CLI command"); + NSLog(@" open \"%@\"", pathForLog); + + [self redirectLogToDocuments :pathForLog]; +} + +- (void)redirectLogToDocuments: (NSString*) fileName +{ + // write to file in append "a+" mode + freopen([fileName cStringUsingEncoding:NSASCIIStringEncoding], "a+", stderr); +} + size_t idx = 0; enum class State { None, WaitingForAssets, WarmingUp, Benchmarking } state = State::None; int frames = 0; diff --git a/platform/ios/platform/ios/ios.xcodeproj/project.pbxproj b/platform/ios/platform/ios/ios.xcodeproj/project.pbxproj index 5da4776e4..c6f899dbb 100644 --- a/platform/ios/platform/ios/ios.xcodeproj/project.pbxproj +++ b/platform/ios/platform/ios/ios.xcodeproj/project.pbxproj @@ -406,6 +406,9 @@ CAFB3C15234505D500399265 /* MGLMapSnapshotter_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = CAFB3C13234505D500399265 /* MGLMapSnapshotter_Private.h */; }; CF75A91522D85E860058A5C4 /* MGLLoggingConfiguration.mm in Sources */ = {isa = PBXBuildFile; fileRef = CF75A91422D85E860058A5C4 /* MGLLoggingConfiguration.mm */; }; CF75A91622D85E860058A5C4 /* MGLLoggingConfiguration.mm in Sources */ = {isa = PBXBuildFile; fileRef = CF75A91422D85E860058A5C4 /* MGLLoggingConfiguration.mm */; }; + D717FE7A25F1955A0054E06E /* iosapp_UITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D717FE7925F1955A0054E06E /* iosapp_UITests.swift */; }; + D717FECB25F19F520054E06E /* XCTestCase+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D717FECA25F19F520054E06E /* XCTestCase+Extensions.swift */; }; + D7E7CE8825F2EF6A00C175FC /* bench_UITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7E7CE8725F2EF6A00C175FC /* bench_UITests.swift */; }; DA00FC8E1D5EEB0D009AABC8 /* MGLAttributionInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = DA00FC8C1D5EEB0D009AABC8 /* MGLAttributionInfo.h */; settings = {ATTRIBUTES = (Public, ); }; }; DA00FC8F1D5EEB0D009AABC8 /* MGLAttributionInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = DA00FC8C1D5EEB0D009AABC8 /* MGLAttributionInfo.h */; settings = {ATTRIBUTES = (Public, ); }; }; DA00FC901D5EEB0D009AABC8 /* MGLAttributionInfo.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA00FC8D1D5EEB0D009AABC8 /* MGLAttributionInfo.mm */; }; @@ -682,6 +685,20 @@ remoteGlobalIDString = 16376B2E1FFDB4B40000563E; remoteInfo = "Integration Test Harness"; }; + D717FE7C25F1955A0054E06E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DA1DC9421CB6C1C2006E619F /* Project object */; + proxyType = 1; + remoteGlobalIDString = DA1DC9491CB6C1C2006E619F; + remoteInfo = iosapp; + }; + D7E7CE8A25F2EF6A00C175FC /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DA1DC9421CB6C1C2006E619F /* Project object */; + proxyType = 1; + remoteGlobalIDString = DABCABA71CB80692000A7C39; + remoteInfo = bench; + }; DA25D5C91CCDA0CC00607828 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DA1DC9421CB6C1C2006E619F /* Project object */; @@ -1038,6 +1055,14 @@ CAE7AD5420F46EF5003B6782 /* MGLMapSnapshotterSwiftTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MGLMapSnapshotterSwiftTests.swift; sourceTree = ""; }; CAFB3C13234505D500399265 /* MGLMapSnapshotter_Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLMapSnapshotter_Private.h; sourceTree = ""; }; CF75A91422D85E860058A5C4 /* MGLLoggingConfiguration.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLLoggingConfiguration.mm; sourceTree = ""; }; + D717FE7725F1955A0054E06E /* iosapp UITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "iosapp UITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + D717FE7925F1955A0054E06E /* iosapp_UITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iosapp_UITests.swift; sourceTree = ""; }; + D717FE7B25F1955A0054E06E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + D717FECA25F19F520054E06E /* XCTestCase+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "XCTestCase+Extensions.swift"; sourceTree = ""; }; + D7E1154C25F4A8B50064246D /* iosapp_TestPlan.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = iosapp_TestPlan.xctestplan; sourceTree = ""; }; + D7E7CE8525F2EF6A00C175FC /* bench UITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "bench UITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + D7E7CE8725F2EF6A00C175FC /* bench_UITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = bench_UITests.swift; sourceTree = ""; }; + D7E7CE8925F2EF6A00C175FC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; DA00FC8C1D5EEB0D009AABC8 /* MGLAttributionInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLAttributionInfo.h; sourceTree = ""; }; DA00FC8D1D5EEB0D009AABC8 /* MGLAttributionInfo.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLAttributionInfo.mm; sourceTree = ""; }; DA0CD58F1CF56F6A00A5F5A5 /* MGLFeatureTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLFeatureTests.mm; path = ../../darwin/test/MGLFeatureTests.mm; sourceTree = ""; }; @@ -1317,6 +1342,20 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + D717FE7425F1955A0054E06E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D7E7CE8225F2EF6A00C175FC /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; DA1DC9471CB6C1C2006E619F /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -1683,6 +1722,26 @@ name = Annotations; sourceTree = ""; }; + D717FE7825F1955A0054E06E /* iosapp UITests */ = { + isa = PBXGroup; + children = ( + D7E1154C25F4A8B50064246D /* iosapp_TestPlan.xctestplan */, + D717FE7925F1955A0054E06E /* iosapp_UITests.swift */, + D717FE7B25F1955A0054E06E /* Info.plist */, + D717FECA25F19F520054E06E /* XCTestCase+Extensions.swift */, + ); + path = "iosapp UITests"; + sourceTree = ""; + }; + D7E7CE8625F2EF6A00C175FC /* bench UITests */ = { + isa = PBXGroup; + children = ( + D7E7CE8725F2EF6A00C175FC /* bench_UITests.swift */, + D7E7CE8925F2EF6A00C175FC /* Info.plist */, + ); + path = "bench UITests"; + sourceTree = ""; + }; DA1DC9411CB6C1C2006E619F = { isa = PBXGroup; children = ( @@ -1694,6 +1753,8 @@ DA2E88521CC036F400F24E7B /* SDK Tests */, 16376B301FFDB4B40000563E /* Integration Test Harness */, 16376B081FFD9DAF0000563E /* Integration Tests */, + D717FE7825F1955A0054E06E /* iosapp UITests */, + D7E7CE8625F2EF6A00C175FC /* bench UITests */, DA1DC9921CB6DF24006E619F /* Frameworks */, DAC07C951CBB2CAD000CB309 /* Configuration */, DA1DC94B1CB6C1C2006E619F /* Products */, @@ -1712,6 +1773,8 @@ DA8933D51CCD306400E68420 /* Mapbox.bundle */, 16376B071FFD9DAF0000563E /* integration.xctest */, 16376B2F1FFDB4B40000563E /* Integration Test Harness.app */, + D717FE7725F1955A0054E06E /* iosapp UITests.xctest */, + D7E7CE8525F2EF6A00C175FC /* bench UITests.xctest */, ); name = Products; sourceTree = ""; @@ -2522,6 +2585,42 @@ productReference = 16376B2F1FFDB4B40000563E /* Integration Test Harness.app */; productType = "com.apple.product-type.application"; }; + D717FE7625F1955A0054E06E /* iosapp UITests */ = { + isa = PBXNativeTarget; + buildConfigurationList = D717FE8125F1955A0054E06E /* Build configuration list for PBXNativeTarget "iosapp UITests" */; + buildPhases = ( + D717FE7325F1955A0054E06E /* Sources */, + D717FE7425F1955A0054E06E /* Frameworks */, + D717FE7525F1955A0054E06E /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + D717FE7D25F1955A0054E06E /* PBXTargetDependency */, + ); + name = "iosapp UITests"; + productName = "iosapp UITests"; + productReference = D717FE7725F1955A0054E06E /* iosapp UITests.xctest */; + productType = "com.apple.product-type.bundle.ui-testing"; + }; + D7E7CE8425F2EF6A00C175FC /* bench UITests */ = { + isa = PBXNativeTarget; + buildConfigurationList = D7E7CE8F25F2EF6A00C175FC /* Build configuration list for PBXNativeTarget "bench UITests" */; + buildPhases = ( + D7E7CE8125F2EF6A00C175FC /* Sources */, + D7E7CE8225F2EF6A00C175FC /* Frameworks */, + D7E7CE8325F2EF6A00C175FC /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + D7E7CE8B25F2EF6A00C175FC /* PBXTargetDependency */, + ); + name = "bench UITests"; + productName = "bench UITests"; + productReference = D7E7CE8525F2EF6A00C175FC /* bench UITests.xctest */; + productType = "com.apple.product-type.bundle.ui-testing"; + }; DA1DC9491CB6C1C2006E619F /* iosapp */ = { isa = PBXNativeTarget; buildConfigurationList = DA1DC9611CB6C1C2006E619F /* Build configuration list for PBXNativeTarget "iosapp" */; @@ -2639,6 +2738,7 @@ isa = PBXProject; attributes = { CLASSPREFIX = MBX; + LastSwiftUpdateCheck = 1240; LastUpgradeCheck = 1120; ORGANIZATIONNAME = Mapbox; TargetAttributes = { @@ -2653,6 +2753,16 @@ DevelopmentTeam = GJZR2MEM28; ProvisioningStyle = Automatic; }; + D717FE7625F1955A0054E06E = { + CreatedOnToolsVersion = 12.4; + ProvisioningStyle = Automatic; + TestTargetID = DA1DC9491CB6C1C2006E619F; + }; + D7E7CE8425F2EF6A00C175FC = { + CreatedOnToolsVersion = 12.4; + ProvisioningStyle = Automatic; + TestTargetID = DABCABA71CB80692000A7C39; + }; DA1DC9491CB6C1C2006E619F = { CreatedOnToolsVersion = 7.3; DevelopmentTeam = KBDAWM7T4E; @@ -2727,6 +2837,8 @@ DA2E88501CC036F400F24E7B /* test */, 16376B061FFD9DAF0000563E /* integration */, 16376B2E1FFDB4B40000563E /* Integration Test Harness */, + D717FE7625F1955A0054E06E /* iosapp UITests */, + D7E7CE8425F2EF6A00C175FC /* bench UITests */, ); }; /* End PBXProject section */ @@ -2750,6 +2862,20 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + D717FE7525F1955A0054E06E /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D7E7CE8325F2EF6A00C175FC /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; DA1DC9481CB6C1C2006E619F /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -2901,6 +3027,23 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + D717FE7325F1955A0054E06E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D717FE7A25F1955A0054E06E /* iosapp_UITests.swift in Sources */, + D717FECB25F19F520054E06E /* XCTestCase+Extensions.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D7E7CE8125F2EF6A00C175FC /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D7E7CE8825F2EF6A00C175FC /* bench_UITests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; DA1DC9461CB6C1C2006E619F /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -3213,6 +3356,16 @@ target = 16376B2E1FFDB4B40000563E /* Integration Test Harness */; targetProxy = CABE5DAB2072FA660003AF3C /* PBXContainerItemProxy */; }; + D717FE7D25F1955A0054E06E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DA1DC9491CB6C1C2006E619F /* iosapp */; + targetProxy = D717FE7C25F1955A0054E06E /* PBXContainerItemProxy */; + }; + D7E7CE8B25F2EF6A00C175FC /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DABCABA71CB80692000A7C39 /* bench */; + targetProxy = D7E7CE8A25F2EF6A00C175FC /* PBXContainerItemProxy */; + }; DA25D5CA1CCDA0CC00607828 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = DA8933D41CCD306400E68420 /* bundle */; @@ -3731,6 +3884,334 @@ }; name = RelWithDebInfo; }; + D717FE7E25F1955A0054E06E /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_STYLE = Automatic; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = "iosapp UITests/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "org.maplibre.iosapp-UITests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = iosapp; + }; + name = Debug; + }; + D717FE7F25F1955A0054E06E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_STYLE = Automatic; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = "iosapp UITests/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "org.maplibre.iosapp-UITests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = iosapp; + }; + name = Release; + }; + D717FE8025F1955A0054E06E /* RelWithDebInfo */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_STYLE = Automatic; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = "iosapp UITests/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "org.maplibre.iosapp-UITests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = iosapp; + }; + name = RelWithDebInfo; + }; + D7E7CE8C25F2EF6A00C175FC /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_STYLE = Automatic; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = "bench UITests/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 14.4; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "org.maplibre.bench-UITests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = bench; + }; + name = Debug; + }; + D7E7CE8D25F2EF6A00C175FC /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_STYLE = Automatic; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = "bench UITests/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 14.4; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "org.maplibre.bench-UITests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = bench; + }; + name = Release; + }; + D7E7CE8E25F2EF6A00C175FC /* RelWithDebInfo */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_STYLE = Automatic; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = "bench UITests/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 14.4; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "org.maplibre.bench-UITests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = bench; + }; + name = RelWithDebInfo; + }; DA1DC95F1CB6C1C2006E619F /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -4106,6 +4587,26 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = RelWithDebInfo; }; + D717FE8125F1955A0054E06E /* Build configuration list for PBXNativeTarget "iosapp UITests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D717FE7E25F1955A0054E06E /* Debug */, + D717FE7F25F1955A0054E06E /* Release */, + D717FE8025F1955A0054E06E /* RelWithDebInfo */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = RelWithDebInfo; + }; + D7E7CE8F25F2EF6A00C175FC /* Build configuration list for PBXNativeTarget "bench UITests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D7E7CE8C25F2EF6A00C175FC /* Debug */, + D7E7CE8D25F2EF6A00C175FC /* Release */, + D7E7CE8E25F2EF6A00C175FC /* RelWithDebInfo */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = RelWithDebInfo; + }; DA1DC9451CB6C1C2006E619F /* Build configuration list for PBXProject "ios" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/platform/ios/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/bench.xcscheme b/platform/ios/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/bench.xcscheme index b548020b5..e41c6f24c 100644 --- a/platform/ios/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/bench.xcscheme +++ b/platform/ios/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/bench.xcscheme @@ -37,6 +37,16 @@ + + + + + + + + + + + + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 5.9.0 + CFBundleVersion + 15256 + + diff --git a/platform/ios/platform/ios/iosapp UITests/XCTestCase+Extensions.swift b/platform/ios/platform/ios/iosapp UITests/XCTestCase+Extensions.swift new file mode 100644 index 000000000..33ff09cab --- /dev/null +++ b/platform/ios/platform/ios/iosapp UITests/XCTestCase+Extensions.swift @@ -0,0 +1,36 @@ +// +// XCTestCase+Extensions.swift +// iosapp UITests +// +// Copyright © 2021 MapLibre. All rights reserved. +// + +import XCTest + +extension XCTestCase { + + /// `screenshot` — Save a PNG screenshot to the UITest results + /// - Parameter name: friendly name to include. + /// Associate an image with the Activity - See [add()](https://developer.apple.com/documentation/xctest/xctactivity/2887222-add) + /// - returns: XCTAttachment, which will need to be `add`ed to the `XCTActivity` +/** +``` +/// rely on the calling test functions name +add(screenshot()) + +/// Add by name +add(screenshot(name: "Example")) +``` +*/ + func screenshot(name: String = #function) -> XCTAttachment { + let attachmentName = "MapLibre-Screenshot-\(name)-\(UIDevice.current.name)-\(UIDevice.current.systemVersion).png" + let screenshot = XCUIScreen.main.screenshot() + let attachment = XCTAttachment(uniformTypeIdentifier: "public.png", + name: attachmentName, + payload: screenshot.pngRepresentation, + userInfo: nil) + attachment.lifetime = .keepAlways + + return attachment + } +} diff --git a/platform/ios/platform/ios/iosapp UITests/iosapp_TestPlan.xctestplan b/platform/ios/platform/ios/iosapp UITests/iosapp_TestPlan.xctestplan new file mode 100644 index 000000000..1d2083c40 --- /dev/null +++ b/platform/ios/platform/ios/iosapp UITests/iosapp_TestPlan.xctestplan @@ -0,0 +1,35 @@ +{ + "configurations" : [ + { + "id" : "703F9AFF-A843-44C5-AB1D-E7A0406B2FAB", + "name" : "Configuration 1", + "options" : { + + } + } + ], + "defaultOptions" : { + "commandLineArgumentEntries" : [ + { + "argument" : "-DLOG_TO_DOCUMENTS_DIR" + } + ] + }, + "testTargets" : [ + { + "target" : { + "containerPath" : "container:ios.xcodeproj", + "identifier" : "D7E7CE8425F2EF6A00C175FC", + "name" : "bench UITests" + } + }, + { + "target" : { + "containerPath" : "container:ios.xcodeproj", + "identifier" : "D717FE7625F1955A0054E06E", + "name" : "iosapp UITests" + } + } + ], + "version" : 1 +} diff --git a/platform/ios/platform/ios/iosapp UITests/iosapp_UITests.swift b/platform/ios/platform/ios/iosapp UITests/iosapp_UITests.swift new file mode 100644 index 000000000..e559717f2 --- /dev/null +++ b/platform/ios/platform/ios/iosapp UITests/iosapp_UITests.swift @@ -0,0 +1,83 @@ +// +// iosapp_UITests.swift +// iosapp UITests +// +// Copyright © 2021 MapLibre. All rights reserved. +// + +import XCTest + +class iosapp_UITests: XCTestCase { + + let app = XCUIApplication() + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + // UI tests must launch the application that they test. + app.launch() + + // In UI tests it is usually best to stop immediately when a failure occurs. + continueAfterFailure = false + + // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + /// Launch `iosapp`, reset to XYZ = (0, 0, 0) and take a screenshot + func test_iosappScheme() throws { + /// Launch and take a screenshot + app.navigationBars["Zeroconf Style"].buttons["Map settings"].tap() + app.tables/*@START_MENU_TOKEN@*/.staticTexts["Reset position"]/*[[".cells.staticTexts[\"Reset position\"]",".staticTexts[\"Reset position\"]"],[[[-1,1],[-1,0]]],[0]]@END_MENU_TOKEN@*/.tap() + sleep(1) + add(screenshot()) + } + + /// Turn on Debug tile boundaries, tile info and FPS ornaments + /// Demonstrates how the Tile Boundaries look when rendered + func testDebugBoundaryTiles() { + + app.windows.children(matching: .other).element.children(matching: .other).element.children(matching: .other).element.doubleTap() + + let mapSettingsButton = app.navigationBars["Zeroconf Style"].buttons["Map settings"] + mapSettingsButton.tap() + + /// setup initial conditions for position (0,0) and debug settings + let tablesQuery = app.tables + tablesQuery/*@START_MENU_TOKEN@*/.staticTexts["Show zoom level ornament"]/*[[".cells.staticTexts[\"Show zoom level ornament\"]",".staticTexts[\"Show zoom level ornament\"]"],[[[-1,1],[-1,0]]],[0]]@END_MENU_TOKEN@*/.tap() + mapSettingsButton.tap() + tablesQuery/*@START_MENU_TOKEN@*/.staticTexts["Show tile boundaries"]/*[[".cells.staticTexts[\"Show tile boundaries\"]",".staticTexts[\"Show tile boundaries\"]"],[[[-1,1],[-1,0]]],[0]]@END_MENU_TOKEN@*/.tap() + mapSettingsButton.tap() + tablesQuery/*@START_MENU_TOKEN@*/.staticTexts["Show tile info"]/*[[".cells.staticTexts[\"Show tile info\"]",".staticTexts[\"Show tile info\"]"],[[[-1,1],[-1,0]]],[0]]@END_MENU_TOKEN@*/.tap() + mapSettingsButton.tap() + tablesQuery/*@START_MENU_TOKEN@*/.staticTexts["Show tile timestamps"]/*[[".cells.staticTexts[\"Show tile timestamps\"]",".staticTexts[\"Show tile timestamps\"]"],[[[-1,1],[-1,0]]],[0]]@END_MENU_TOKEN@*/.tap() + mapSettingsButton.tap() + tablesQuery.staticTexts["Add Test Shapes"].tap() + + sleep(1) + add(screenshot(name: "Add Test Shapes")) + + mapSettingsButton.tap() + tablesQuery.staticTexts["Reset position"].tap() + + sleep(1) + add(screenshot(name: "Null Island, Zoom=0")) + } + + func testRecord() { + /// Use recording to get started writing UI tests. + /// Use `Editor` > `Start Recording UI Test` while your cursor is in this `func` + /// Use XCTAssert and related functions to verify your tests produce the correct results. + } + + func testLaunchPerformance() throws { + if #available(macOS 10.15, iOS 13.0, tvOS 13.0, *) { + // This measures how long it takes to launch your application. + measure(metrics: [XCTApplicationLaunchMetric()]) { + XCUIApplication().launch() + } + } + } +}