iOS C++ Unit Tests Bazel target & running on CI (#1534)
This commit is contained in:
@@ -10,12 +10,13 @@ cc_library(
|
||||
".",
|
||||
],
|
||||
visibility = [
|
||||
"//platform/ios/test/core:__pkg__",
|
||||
"//render-test/ios:__pkg__",
|
||||
],
|
||||
)
|
||||
|
||||
objc_library(
|
||||
name = "render_test_app_srcs",
|
||||
name = "test_app_srcs",
|
||||
srcs = [
|
||||
"AppDelegate.h",
|
||||
"AppDelegate.m",
|
||||
@@ -25,6 +26,9 @@ objc_library(
|
||||
"LaunchScreen.storyboard",
|
||||
"Main.storyboard",
|
||||
],
|
||||
visibility = [
|
||||
"//platform/ios/test/core:__pkg__",
|
||||
],
|
||||
deps = [
|
||||
"ios_test_runner_lib",
|
||||
],
|
||||
@@ -43,7 +47,7 @@ ios_application(
|
||||
"//visibility:public",
|
||||
],
|
||||
deps = [
|
||||
"render_test_app_srcs",
|
||||
"test_app_srcs",
|
||||
"//render-test/ios:render_test_ios_src",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
#import "iosTestRunner.h"
|
||||
|
||||
#include <ios_test_runner.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
@interface IosTestRunner ()
|
||||
|
||||
@property (nullable) TestRunner *runner;
|
||||
|
||||
@property (copy, nullable) NSString *resultPath;
|
||||
|
||||
@property BOOL testStatus;
|
||||
|
||||
@end
|
||||
|
||||
@implementation IosTestRunner
|
||||
|
||||
-(instancetype)init
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.testStatus = NO;
|
||||
self.runner = new TestRunner();
|
||||
NSError *error;
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
NSString *bundleRoot = [[NSBundle mainBundle] bundlePath];
|
||||
|
||||
NSArray *bundleContents = [fileManager contentsOfDirectoryAtPath: bundleRoot error: &error];
|
||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
|
||||
NSString *documentsDir = [paths objectAtIndex: 0];
|
||||
|
||||
for (uint32_t i = 0; i < bundleContents.count; i++) {
|
||||
NSString *dirName = [bundleContents objectAtIndex: i];
|
||||
if ([dirName isEqualToString: dataDir]) {
|
||||
NSString *destinationPath = [documentsDir stringByAppendingPathComponent: dirName];
|
||||
BOOL success = [fileManager fileExistsAtPath: destinationPath];
|
||||
if (success) {
|
||||
[fileManager removeItemAtPath:destinationPath error:NULL];
|
||||
}
|
||||
|
||||
success = [fileManager fileExistsAtPath: destinationPath];
|
||||
if (!success) {
|
||||
NSString *copyDirPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent: dirName];
|
||||
success = [fileManager copyItemAtPath: copyDirPath toPath: destinationPath error: &error];
|
||||
|
||||
if (!success) {
|
||||
NSLog(@"Failed to copy file '%@'", dirName);
|
||||
NSAssert1(0, @"Failed to copy file, error '%@'", [error localizedDescription]);
|
||||
} else {
|
||||
NSLog(@"File '%@' copied OK", dirName);
|
||||
}
|
||||
} else {
|
||||
NSLog(@"Failed to remove file '%@'", dirName);
|
||||
NSAssert1(0, @"Failed to remove file, error '%@'", [error localizedDescription]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
NSString *baseDir = [documentsDir stringByAppendingPathComponent: dataDir];
|
||||
std::string basePath = std::string([baseDir UTF8String]);
|
||||
self.testStatus = self.runner->startTest(basePath) ? YES : NO;
|
||||
self.resultPath = [baseDir stringByAppendingPathComponent: resultFilePath];
|
||||
|
||||
BOOL fileFound = [fileManager fileExistsAtPath: self.resultPath];
|
||||
if (fileFound == NO) {
|
||||
NSLog(@"Test result file '%@' does not exist", self.resultPath);
|
||||
self.testStatus = NO;
|
||||
}
|
||||
|
||||
delete self.runner;
|
||||
self.runner = nullptr;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSString*) getResultPath {
|
||||
return self.resultPath;
|
||||
}
|
||||
|
||||
- (BOOL) getTestStatus {
|
||||
return self.testStatus;
|
||||
}
|
||||
@end
|
||||
68
platform/ios/test/core/BUILD.bazel
Normal file
68
platform/ios/test/core/BUILD.bazel
Normal file
@@ -0,0 +1,68 @@
|
||||
load("@build_bazel_rules_apple//apple:ios.bzl", "ios_application", "ios_unit_test")
|
||||
load("//platform/ios/bazel:config.bzl", "BUNDLE_ID_PREFIX")
|
||||
load("//bazel:flags.bzl", "CPP_FLAGS", "MAPLIBRE_FLAGS")
|
||||
load("@build_bazel_rules_apple//apple:resources.bzl", "apple_resource_bundle")
|
||||
|
||||
cc_library(
|
||||
name = "test_cpp_srcs",
|
||||
srcs = [
|
||||
"ios_test_runner.cpp",
|
||||
],
|
||||
copts = CPP_FLAGS + MAPLIBRE_FLAGS,
|
||||
deps = [
|
||||
"//platform:ios-sdk",
|
||||
"//platform/ios/test/common:ios_test_runner_lib",
|
||||
"//test:testlib",
|
||||
"//test:tests",
|
||||
],
|
||||
)
|
||||
|
||||
apple_resource_bundle(
|
||||
name = "TestData",
|
||||
infoplists = [
|
||||
"//render-test/ios:Empty.plist",
|
||||
],
|
||||
structured_resources = [
|
||||
"//test:fixtures",
|
||||
"//:scripts/style-spec-reference/v8.json",
|
||||
],
|
||||
)
|
||||
|
||||
objc_library(
|
||||
name = "test_objc_srcs",
|
||||
srcs = [
|
||||
"Tests.m",
|
||||
"iosTestRunner.h",
|
||||
"iosTestRunner.mm",
|
||||
],
|
||||
deps = [
|
||||
"TestData",
|
||||
"test_cpp_srcs",
|
||||
"//platform/ios/test/common:ios_test_runner_lib",
|
||||
],
|
||||
)
|
||||
|
||||
ios_application(
|
||||
name = "CppUnitTestsApp",
|
||||
bundle_id = "{}.maplibre.UnitTestsApp".format(BUNDLE_ID_PREFIX),
|
||||
families = ["iphone"],
|
||||
infoplists = [
|
||||
"Info.plist",
|
||||
],
|
||||
minimum_os_version = "12.0",
|
||||
provisioning_profile = "//platform/ios:xcode_profile",
|
||||
deps = [
|
||||
"//platform/ios/test/common:test_app_srcs",
|
||||
],
|
||||
)
|
||||
|
||||
ios_unit_test(
|
||||
name = "CppUnitTests",
|
||||
minimum_os_version = "12.0",
|
||||
provisioning_profile = "//platform/ios:xcode_profile",
|
||||
test_host = "CppUnitTestsApp",
|
||||
visibility = ["@rules_xcodeproj//xcodeproj:generated"],
|
||||
deps = [
|
||||
"test_objc_srcs",
|
||||
],
|
||||
)
|
||||
56
platform/ios/test/core/Info.plist
Normal file
56
platform/ios/test/core/Info.plist
Normal file
@@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>${PRODUCT_NAME}</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>UnitTestsApp</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string>com.mapbox.UnitTestsApp</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleLongVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>MBGL</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>7877</string>
|
||||
<key>CSResourcesFileMapped</key>
|
||||
<true/>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>© 2014–2020 Mapbox</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>fetch</string>
|
||||
<string>remote-notification</string>
|
||||
</array>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
11
platform/ios/test/core/iosTestRunner.h
Normal file
11
platform/ios/test/core/iosTestRunner.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
__attribute__((visibility ("default")))
|
||||
@interface IosTestRunner : NSObject
|
||||
|
||||
- (NSString*) getResultPath;
|
||||
- (BOOL) getTestStatus;
|
||||
|
||||
@end
|
||||
92
platform/ios/test/core/iosTestRunner.mm
Normal file
92
platform/ios/test/core/iosTestRunner.mm
Normal file
@@ -0,0 +1,92 @@
|
||||
#import "iosTestRunner.h"
|
||||
|
||||
#include <ios_test_runner.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
@interface IosTestRunner ()
|
||||
|
||||
@property (nullable) TestRunner *runner;
|
||||
|
||||
@property (copy, nullable) NSString *resultPath;
|
||||
|
||||
@property BOOL testStatus;
|
||||
|
||||
@end
|
||||
|
||||
@implementation IosTestRunner
|
||||
|
||||
-(instancetype)init
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.testStatus = NO;
|
||||
self.runner = new TestRunner();
|
||||
|
||||
NSError *error;
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
|
||||
NSString *xcTestBundleRoot = [[NSBundle bundleForClass:[self class]] resourcePath];
|
||||
NSString *testDataDir = [xcTestBundleRoot stringByAppendingString:@"/TestData.bundle"];
|
||||
|
||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
|
||||
NSString *documentsDir = [paths objectAtIndex: 0];
|
||||
|
||||
NSString *destinationPath = [documentsDir stringByAppendingPathComponent: @"test"];
|
||||
|
||||
[self copyFileAtPath:testDataDir toPath:destinationPath];
|
||||
[self copyFileAtPath:[testDataDir stringByAppendingPathComponent: @"scripts"] toPath:[documentsDir stringByAppendingPathComponent: @"scripts"]];
|
||||
|
||||
NSLog(@"Starting test");
|
||||
std::string basePath = std::string([documentsDir UTF8String]);
|
||||
self.testStatus = self.runner->startTest(basePath) ? YES : NO;
|
||||
self.resultPath = [destinationPath stringByAppendingPathComponent: @"results.xml"];
|
||||
|
||||
BOOL fileFound = [fileManager fileExistsAtPath: self.resultPath];
|
||||
if (fileFound == NO) {
|
||||
NSLog(@"Test result file '%@' does not exist", self.resultPath);
|
||||
self.testStatus = NO;
|
||||
}
|
||||
|
||||
delete self.runner;
|
||||
self.runner = nullptr;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
/**
|
||||
Copies a file from the source path to the destination path.
|
||||
|
||||
@param sourcePath The path of the source file to be copied.
|
||||
@param destinationPath The destination path where the file should be copied.
|
||||
*/
|
||||
- (void)copyFileAtPath:(NSString *)sourcePath toPath:(NSString *)destinationPath {
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
NSError *error = nil;
|
||||
BOOL success;
|
||||
|
||||
// delete destinationPath if it exists
|
||||
if ([fileManager fileExistsAtPath:destinationPath]) {
|
||||
success = [fileManager removeItemAtPath: destinationPath error: &error];
|
||||
if (!success) {
|
||||
NSAssert1(0, @"Failed to delete '%@'.", destinationPath);
|
||||
}
|
||||
}
|
||||
|
||||
success = [fileManager copyItemAtPath:sourcePath toPath:destinationPath error:&error];
|
||||
if (!success) {
|
||||
NSAssert1(0, @"Failed to copy file '%@'.", [error localizedDescription]);
|
||||
NSLog(@"Failed to copy %@ file, error %@", sourcePath, [error localizedDescription]);
|
||||
} else {
|
||||
NSLog(@"File copied %@ OK", sourcePath);
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString*) getResultPath {
|
||||
return self.resultPath;
|
||||
}
|
||||
|
||||
- (BOOL) getTestStatus {
|
||||
return self.testStatus;
|
||||
}
|
||||
@end
|
||||
31
platform/ios/test/core/ios_test_runner.cpp
Normal file
31
platform/ios/test/core/ios_test_runner.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
#include <ios_test_runner.hpp>
|
||||
|
||||
#include <mbgl/test.hpp>
|
||||
|
||||
#include <mbgl/util/logging.hpp>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
|
||||
#define EXPORT __attribute__((visibility("default")))
|
||||
|
||||
EXPORT
|
||||
bool TestRunner::startTest(const std::string& basePath) {
|
||||
std::vector<std::string> arguments = {"mbgl-test-runner", "--gtest_output=xml:" + basePath + "/test/results.xml"};
|
||||
std::vector<char*> argv;
|
||||
for (const auto& arg : arguments) {
|
||||
argv.push_back(const_cast<char*>(arg.data()));
|
||||
}
|
||||
argv.push_back(nullptr);
|
||||
|
||||
if (chdir(basePath.c_str())) {
|
||||
mbgl::Log::Error(mbgl::Event::General, "Failed to change the directory to " + basePath);
|
||||
return false;
|
||||
}
|
||||
|
||||
mbgl::Log::Info(mbgl::Event::General, "Start TestRunner");
|
||||
int status = mbgl::runTests(static_cast<uint32_t>(argv.size()), argv.data());
|
||||
mbgl::Log::Info(mbgl::Event::General, "TestRunner finished with status: '" + std::to_string(status) + "'");
|
||||
|
||||
return status == 0;
|
||||
}
|
||||
Reference in New Issue
Block a user