iOS C++ Unit Tests Bazel target & running on CI (#1534)

This commit is contained in:
Bart Louwers
2023-08-22 21:52:20 +02:00
committed by GitHub
parent e16995ec33
commit 32d65850c9
21 changed files with 308 additions and 155 deletions

View File

@@ -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",
],
)

View File

@@ -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

View 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",
],
)

View 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>

View File

@@ -0,0 +1,11 @@
#pragma once
#import <Foundation/Foundation.h>
__attribute__((visibility ("default")))
@interface IosTestRunner : NSObject
- (NSString*) getResultPath;
- (BOOL) getTestStatus;
@end

View 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

View 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;
}