Skip to content

Commit

Permalink
Add iOS test pipeline and a sample app. (#5298)
Browse files Browse the repository at this point in the history
* Add iOS test pipeline and a sample app.

* clean up the unused code.

* clean up.

* revert the unknown change

* disable the shared library for iOS.

* add open source notice text.

* ignore the skipped test.

* extract the common ortenv setup
  • Loading branch information
wenbingl authored Sep 29, 2020
1 parent f07059c commit ed102e9
Show file tree
Hide file tree
Showing 33 changed files with 1,857 additions and 23 deletions.
29 changes: 28 additions & 1 deletion ThirdPartyNotices.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4820,4 +4820,31 @@ SMHasher test suite used to verify them.
SMHasher is released under the MIT license.
All MurmurHash versions are public domain software, and the author disclaims all copyright to their code.

-----
-----

gtest-ios-framework

https://github.com/mestevens/gtest-ios-framework

Copyright (c) 2013 Matthew Stevens

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

-----
15 changes: 14 additions & 1 deletion build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,19 @@

# Get directory this script is in
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
OS=$(uname -s)

if [ "$OS" = "Darwin" ]; then
DIR_OS="MacOS"
else
DIR_OS="Linux"
fi

if [[ "$*" == *"--ios"* ]]; then
DIR_OS="iOS"
elif [[ "$*" == *"--android"* ]]; then
DIR_OS="Android"
fi

#requires python3.6 or higher
python3 $DIR/tools/ci_build/build.py --build_dir $DIR/build/Linux "$@"
python3 $DIR/tools/ci_build/build.py --build_dir $DIR/build/$DIR_OS "$@"
10 changes: 10 additions & 0 deletions cgmanifests/cgmanifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,16 @@
},
"comments": "MurmurHash3"
}
},
{
"component": {
"type": "git",
"git": {
"commitHash": "b89da3c5a0aa18fb2c6163ad9984f81ab65b22e3",
"repositoryUrl": "https://github.com/mestevens/gtest-ios-framework"
},
"comments": "gtest-ios-framework"
}
}
],
"Version": 1
Expand Down
5 changes: 4 additions & 1 deletion cmake/onnxruntime.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ foreach(f ${ONNXRUNTIME_PROVIDER_NAMES})
endforeach()

add_custom_command(OUTPUT ${SYMBOL_FILE} ${CMAKE_CURRENT_BINARY_DIR}/generated_source.c
COMMAND ${PYTHON_EXECUTABLE} "${REPO_ROOT}/tools/ci_build/gen_def.py" --version_file "${ONNXRUNTIME_ROOT}/../VERSION_NUMBER" --src_root "${ONNXRUNTIME_ROOT}" --config ${ONNXRUNTIME_PROVIDER_NAMES} --style=${OUTPUT_STYLE} --output ${SYMBOL_FILE} --output_source ${CMAKE_CURRENT_BINARY_DIR}/generated_source.c
COMMAND ${PYTHON_EXECUTABLE} "${REPO_ROOT}/tools/ci_build/gen_def.py"
--version_file "${ONNXRUNTIME_ROOT}/../VERSION_NUMBER" --src_root "${ONNXRUNTIME_ROOT}"
--config ${ONNXRUNTIME_PROVIDER_NAMES} --style=${OUTPUT_STYLE} --output ${SYMBOL_FILE}
--output_source ${CMAKE_CURRENT_BINARY_DIR}/generated_source.c
DEPENDS ${SYMBOL_FILES}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})

Expand Down
3 changes: 3 additions & 0 deletions cmake/onnxruntime_ios.toolchain.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,6 @@ set(CMAKE_SYSTEM_NAME iOS)
if (NOT DEFINED CMAKE_XCODE_ATTRIBUTE_DEVELOPMENT_TEAM)
set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED NO)
endif()

SET(CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_MODULES "YES")
SET(CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC "YES")
70 changes: 57 additions & 13 deletions cmake/onnxruntime_unittests.cmake
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
if (${CMAKE_SYSTEM_NAME} STREQUAL "iOS")
find_package(XCTest REQUIRED)
endif()

set(TEST_SRC_DIR ${ONNXRUNTIME_ROOT}/test)
set(TEST_INC_DIR ${ONNXRUNTIME_ROOT})
Expand All @@ -26,7 +29,11 @@ function(AddTest)
list(REMOVE_DUPLICATES _UT_DEPENDS)
endif(_UT_DEPENDS)

add_executable(${_UT_TARGET} ${_UT_SOURCES})
if (${CMAKE_SYSTEM_NAME} STREQUAL "iOS")
add_executable(${_UT_TARGET} ${TEST_SRC_DIR}/xctest/orttestmain.m)
else()
add_executable(${_UT_TARGET} ${_UT_SOURCES})
endif()

source_group(TREE ${REPO_ROOT} FILES ${_UT_SOURCES})

Expand Down Expand Up @@ -84,10 +91,41 @@ function(AddTest)
"--gtest_output=xml:$<SHELL_PATH:$<TARGET_FILE:${_UT_TARGET}>.$<CONFIG>.results.xml>")
endif(onnxruntime_GENERATE_TEST_REPORTS)

add_test(NAME ${_UT_TARGET}
COMMAND ${_UT_TARGET} ${TEST_ARGS}
WORKING_DIRECTORY $<TARGET_FILE_DIR:${_UT_TARGET}>
)
if (${CMAKE_SYSTEM_NAME} STREQUAL "iOS")
# target_sources(${_UT_TARGET} PRIVATE ${TEST_SRC_DIR}/xctest/orttestmain.m)
set_target_properties(${_UT_TARGET} PROPERTIES FOLDER "ONNXRuntimeTest"
MACOSX_BUNDLE_BUNDLE_NAME ${_UT_TARGET}
MACOSX_BUNDLE_GUI_IDENTIFIER com.onnxruntime.utest.${_UT_TARGET}
MACOSX_BUNDLE_LONG_VERSION_STRING ${ORT_VERSION}
MACOSX_BUNDLE_BUNDLE_VERSION ${ORT_VERSION}
MACOSX_BUNDLE_SHORT_VERSION_STRING ${ORT_VERSION}
XCODE_ATTRIBUTE_CLANG_ENABLE_MODULES "YES")

xctest_add_bundle(${_UT_TARGET}_xc ${_UT_TARGET}
${TEST_SRC_DIR}/xctest/ortxctest.m
${TEST_SRC_DIR}/xctest/xcgtest.mm
${_UT_SOURCES})

target_link_libraries(${_UT_TARGET}_xc PRIVATE ${_UT_LIBS} GTest::gtest GTest::gmock ${onnxruntime_EXTERNAL_LIBRARIES})
onnxruntime_add_include_to_target(${_UT_TARGET}_xc date_interface flatbuffers)
target_include_directories(${_UT_TARGET}_xc PRIVATE ${TEST_INC_DIR})
get_target_property(${_UT_TARGET}_DEFS ${_UT_TARGET} COMPILE_DEFINITIONS)
target_compile_definitions(${_UT_TARGET}_xc PRIVATE ${_UT_TARGET}_DEFS)

set_target_properties(${_UT_TARGET}_xc PROPERTIES FOLDER "ONNXRuntimeXCTest"
MACOSX_BUNDLE_BUNDLE_NAME ${_UT_TARGET}_xc
MACOSX_BUNDLE_GUI_IDENTIFIER com.onnxruntime.utest.${_UT_TARGET}
MACOSX_BUNDLE_LONG_VERSION_STRING ${ORT_VERSION}
MACOSX_BUNDLE_BUNDLE_VERSION ${ORT_VERSION}
MACOSX_BUNDLE_SHORT_VERSION_STRING ${ORT_VERSION})

xctest_add_test(xctest.${_UT_TARGET} ${_UT_TARGET}_xc)
else()
add_test(NAME ${_UT_TARGET}
COMMAND ${_UT_TARGET} ${TEST_ARGS}
WORKING_DIRECTORY $<TARGET_FILE_DIR:${_UT_TARGET}>
)
endif()
endfunction(AddTest)

#Do not add '${TEST_SRC_DIR}/util/include' to your include directories directly
Expand Down Expand Up @@ -552,6 +590,9 @@ set(all_dependencies ${onnxruntime_test_providers_dependencies} )
# the default logger tests conflict with the need to have an overall default logger
# so skip in this type of
target_compile_definitions(onnxruntime_test_all PUBLIC -DSKIP_DEFAULT_LOGGER_TESTS)
if (CMAKE_SYSTEM_NAME STREQUAL "iOS")
target_compile_definitions(onnxruntime_test_all_xc PUBLIC -DSKIP_DEFAULT_LOGGER_TESTS)
endif()
if(onnxruntime_RUN_MODELTEST_IN_DEBUG_MODE)
target_compile_definitions(onnxruntime_test_all PUBLIC -DRUN_MODELTEST_IN_DEBUG_MODE)
endif()
Expand Down Expand Up @@ -684,6 +725,7 @@ endif()
install(TARGETS onnx_test_runner
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
BUNDLE DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})

if(onnxruntime_BUILD_BENCHMARKS)
Expand Down Expand Up @@ -812,15 +854,17 @@ if (onnxruntime_BUILD_SHARED_LIB)
if (CMAKE_SYSTEM_NAME STREQUAL "Android")
list(APPEND onnxruntime_shared_lib_test_LIBS ${android_shared_libs})
endif()
AddTest(DYN
TARGET onnxruntime_shared_lib_test
SOURCES ${onnxruntime_shared_lib_test_SRC} ${TEST_SRC_DIR}/providers/test_main.cc
LIBS ${onnxruntime_shared_lib_test_LIBS}
DEPENDS ${all_dependencies}
)
if (NOT CMAKE_SYSTEM_NAME STREQUAL "iOS")
AddTest(DYN
TARGET onnxruntime_shared_lib_test
SOURCES ${onnxruntime_shared_lib_test_SRC} ${TEST_SRC_DIR}/providers/test_main.cc
LIBS ${onnxruntime_shared_lib_test_LIBS}
DEPENDS ${all_dependencies}
)
endif()

# test inference using global threadpools
if (NOT CMAKE_SYSTEM_NAME STREQUAL "Android" AND NOT onnxruntime_MINIMAL_BUILD)
if (NOT CMAKE_SYSTEM_NAME MATCHES "Android|iOS" AND NOT onnxruntime_MINIMAL_BUILD)
AddTest(DYN
TARGET onnxruntime_global_thread_pools_test
SOURCES ${onnxruntime_global_thread_pools_test_SRC}
Expand All @@ -830,7 +874,7 @@ if (onnxruntime_BUILD_SHARED_LIB)
endif()

# A separate test is needed to test the APIs that don't rely on the env being created first.
if (NOT CMAKE_SYSTEM_NAME STREQUAL "Android")
if (NOT CMAKE_SYSTEM_NAME MATCHES "Android|iOS")
AddTest(DYN
TARGET onnxruntime_api_tests_without_env
SOURCES ${onnxruntime_api_tests_without_env_SRC}
Expand Down
7 changes: 6 additions & 1 deletion onnxruntime/test/framework/data_types_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,12 @@ struct MapTypeProto {
class DataTypeTest : public testing::Test {
public:
static void SetUpTestCase() {
RegisterTestTypes();
// xcTest run test case by case, so the SetUp needs to be reentrant.
static std::atomic<bool> loaded(false);
if (!loaded.load()) {
loaded.store(true);
RegisterTestTypes();
}
}
};

Expand Down
20 changes: 17 additions & 3 deletions onnxruntime/test/providers/test_main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,27 @@
#include "test/test_environment.h"

std::unique_ptr<Ort::Env> ort_env;
void ortenv_setup(){
OrtThreadingOptions tpo;
ort_env.reset(new Ort::Env(&tpo, ORT_LOGGING_LEVEL_WARNING, "Default"));
}

#define TEST_MAIN main

#if defined(__APPLE__)
#include <TargetConditionals.h>
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
#define TEST_MAIN main_no_link_ // there is a UI test app for iOS.
#endif
#endif

int main(int argc, char** argv) {
int TEST_MAIN(int argc, char** argv) {
int status = 0;

ORT_TRY {
::testing::InitGoogleTest(&argc, argv);
OrtThreadingOptions tpo;
ort_env.reset(new Ort::Env(&tpo, ORT_LOGGING_LEVEL_WARNING, "Default"));

ortenv_setup();
status = RUN_ALL_TESTS();
}
ORT_CATCH(const std::exception& ex) {
Expand Down
22 changes: 22 additions & 0 deletions onnxruntime/test/xctest/Info.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?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>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>
100 changes: 100 additions & 0 deletions onnxruntime/test/xctest/orttestmain.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#import <UIKit/UIKit.h>

static void set_test_rootdir(const char* image_path){
size_t n = strlen(image_path);
for (; n >=0; n--) {
if (image_path[n] == '/') {
break;
}
}

char* bundle_dir = (char*)malloc(n + 1);
if (bundle_dir != NULL) {
strncpy(bundle_dir, image_path, n);
bundle_dir[n] = 0;
chdir(bundle_dir);
free(bundle_dir);
}
}

@interface ViewController : UIViewController

@end

@implementation ViewController

- (void)viewDidLoad
{
[super viewDidLoad];

self.view.backgroundColor = [UIColor whiteColor];
}

- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}

@end



@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;

@property (nonatomic, strong) UIViewController *rootViewController;

@end

@implementation AppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.window.tintAdjustmentMode = UIViewTintAdjustmentModeNormal;
self.window.rootViewController = [[ViewController alloc] init];

self.window.backgroundColor = [UIColor whiteColor];
self.window.clipsToBounds = NO;
[self.window makeKeyAndVisible];

return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application
{
}

- (void)applicationDidEnterBackground:(UIApplication *)application
{
}

- (void)applicationWillEnterForeground:(UIApplication *)application
{
}

- (void)applicationDidBecomeActive:(UIApplication *)application
{
}

- (void)applicationWillTerminate:(UIApplication *)application
{
}

@end


int main(int argc, char * argv[]) {
set_test_rootdir(argv[0]);
int ret = 0;
@autoreleasepool {
ret = UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}

return ret;
}
Loading

0 comments on commit ed102e9

Please sign in to comment.