Skip to content

Commit ed102e9

Browse files
authored
Add iOS test pipeline and a sample app. (microsoft#5298)
* 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
1 parent f07059c commit ed102e9

33 files changed

+1857
-23
lines changed

ThirdPartyNotices.txt

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4820,4 +4820,31 @@ SMHasher test suite used to verify them.
48204820
SMHasher is released under the MIT license.
48214821
All MurmurHash versions are public domain software, and the author disclaims all copyright to their code.
48224822

4823-
-----
4823+
-----
4824+
4825+
gtest-ios-framework
4826+
4827+
https://github.com/mestevens/gtest-ios-framework
4828+
4829+
Copyright (c) 2013 Matthew Stevens
4830+
4831+
Permission is hereby granted, free of charge, to any person obtaining
4832+
a copy of this software and associated documentation files (the
4833+
"Software"), to deal in the Software without restriction, including
4834+
without limitation the rights to use, copy, modify, merge, publish,
4835+
distribute, sublicense, and/or sell copies of the Software, and to
4836+
permit persons to whom the Software is furnished to do so, subject to
4837+
the following conditions:
4838+
4839+
The above copyright notice and this permission notice shall be
4840+
included in all copies or substantial portions of the Software.
4841+
4842+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
4843+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
4844+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
4845+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
4846+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
4847+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
4848+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
4849+
4850+
-----

build.sh

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,19 @@
44

55
# Get directory this script is in
66
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
7+
OS=$(uname -s)
8+
9+
if [ "$OS" = "Darwin" ]; then
10+
DIR_OS="MacOS"
11+
else
12+
DIR_OS="Linux"
13+
fi
14+
15+
if [[ "$*" == *"--ios"* ]]; then
16+
DIR_OS="iOS"
17+
elif [[ "$*" == *"--android"* ]]; then
18+
DIR_OS="Android"
19+
fi
720

821
#requires python3.6 or higher
9-
python3 $DIR/tools/ci_build/build.py --build_dir $DIR/build/Linux "$@"
22+
python3 $DIR/tools/ci_build/build.py --build_dir $DIR/build/$DIR_OS "$@"

cgmanifests/cgmanifest.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,16 @@
467467
},
468468
"comments": "MurmurHash3"
469469
}
470+
},
471+
{
472+
"component": {
473+
"type": "git",
474+
"git": {
475+
"commitHash": "b89da3c5a0aa18fb2c6163ad9984f81ab65b22e3",
476+
"repositoryUrl": "https://github.com/mestevens/gtest-ios-framework"
477+
},
478+
"comments": "gtest-ios-framework"
479+
}
470480
}
471481
],
472482
"Version": 1

cmake/onnxruntime.cmake

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@ foreach(f ${ONNXRUNTIME_PROVIDER_NAMES})
2424
endforeach()
2525

2626
add_custom_command(OUTPUT ${SYMBOL_FILE} ${CMAKE_CURRENT_BINARY_DIR}/generated_source.c
27-
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
27+
COMMAND ${PYTHON_EXECUTABLE} "${REPO_ROOT}/tools/ci_build/gen_def.py"
28+
--version_file "${ONNXRUNTIME_ROOT}/../VERSION_NUMBER" --src_root "${ONNXRUNTIME_ROOT}"
29+
--config ${ONNXRUNTIME_PROVIDER_NAMES} --style=${OUTPUT_STYLE} --output ${SYMBOL_FILE}
30+
--output_source ${CMAKE_CURRENT_BINARY_DIR}/generated_source.c
2831
DEPENDS ${SYMBOL_FILES}
2932
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
3033

cmake/onnxruntime_ios.toolchain.cmake

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,6 @@ set(CMAKE_SYSTEM_NAME iOS)
55
if (NOT DEFINED CMAKE_XCODE_ATTRIBUTE_DEVELOPMENT_TEAM)
66
set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED NO)
77
endif()
8+
9+
SET(CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_MODULES "YES")
10+
SET(CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC "YES")

cmake/onnxruntime_unittests.cmake

Lines changed: 57 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# Copyright (c) Microsoft Corporation. All rights reserved.
22
# Licensed under the MIT License.
3+
if (${CMAKE_SYSTEM_NAME} STREQUAL "iOS")
4+
find_package(XCTest REQUIRED)
5+
endif()
36

47
set(TEST_SRC_DIR ${ONNXRUNTIME_ROOT}/test)
58
set(TEST_INC_DIR ${ONNXRUNTIME_ROOT})
@@ -26,7 +29,11 @@ function(AddTest)
2629
list(REMOVE_DUPLICATES _UT_DEPENDS)
2730
endif(_UT_DEPENDS)
2831

29-
add_executable(${_UT_TARGET} ${_UT_SOURCES})
32+
if (${CMAKE_SYSTEM_NAME} STREQUAL "iOS")
33+
add_executable(${_UT_TARGET} ${TEST_SRC_DIR}/xctest/orttestmain.m)
34+
else()
35+
add_executable(${_UT_TARGET} ${_UT_SOURCES})
36+
endif()
3037

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

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

87-
add_test(NAME ${_UT_TARGET}
88-
COMMAND ${_UT_TARGET} ${TEST_ARGS}
89-
WORKING_DIRECTORY $<TARGET_FILE_DIR:${_UT_TARGET}>
90-
)
94+
if (${CMAKE_SYSTEM_NAME} STREQUAL "iOS")
95+
# target_sources(${_UT_TARGET} PRIVATE ${TEST_SRC_DIR}/xctest/orttestmain.m)
96+
set_target_properties(${_UT_TARGET} PROPERTIES FOLDER "ONNXRuntimeTest"
97+
MACOSX_BUNDLE_BUNDLE_NAME ${_UT_TARGET}
98+
MACOSX_BUNDLE_GUI_IDENTIFIER com.onnxruntime.utest.${_UT_TARGET}
99+
MACOSX_BUNDLE_LONG_VERSION_STRING ${ORT_VERSION}
100+
MACOSX_BUNDLE_BUNDLE_VERSION ${ORT_VERSION}
101+
MACOSX_BUNDLE_SHORT_VERSION_STRING ${ORT_VERSION}
102+
XCODE_ATTRIBUTE_CLANG_ENABLE_MODULES "YES")
103+
104+
xctest_add_bundle(${_UT_TARGET}_xc ${_UT_TARGET}
105+
${TEST_SRC_DIR}/xctest/ortxctest.m
106+
${TEST_SRC_DIR}/xctest/xcgtest.mm
107+
${_UT_SOURCES})
108+
109+
target_link_libraries(${_UT_TARGET}_xc PRIVATE ${_UT_LIBS} GTest::gtest GTest::gmock ${onnxruntime_EXTERNAL_LIBRARIES})
110+
onnxruntime_add_include_to_target(${_UT_TARGET}_xc date_interface flatbuffers)
111+
target_include_directories(${_UT_TARGET}_xc PRIVATE ${TEST_INC_DIR})
112+
get_target_property(${_UT_TARGET}_DEFS ${_UT_TARGET} COMPILE_DEFINITIONS)
113+
target_compile_definitions(${_UT_TARGET}_xc PRIVATE ${_UT_TARGET}_DEFS)
114+
115+
set_target_properties(${_UT_TARGET}_xc PROPERTIES FOLDER "ONNXRuntimeXCTest"
116+
MACOSX_BUNDLE_BUNDLE_NAME ${_UT_TARGET}_xc
117+
MACOSX_BUNDLE_GUI_IDENTIFIER com.onnxruntime.utest.${_UT_TARGET}
118+
MACOSX_BUNDLE_LONG_VERSION_STRING ${ORT_VERSION}
119+
MACOSX_BUNDLE_BUNDLE_VERSION ${ORT_VERSION}
120+
MACOSX_BUNDLE_SHORT_VERSION_STRING ${ORT_VERSION})
121+
122+
xctest_add_test(xctest.${_UT_TARGET} ${_UT_TARGET}_xc)
123+
else()
124+
add_test(NAME ${_UT_TARGET}
125+
COMMAND ${_UT_TARGET} ${TEST_ARGS}
126+
WORKING_DIRECTORY $<TARGET_FILE_DIR:${_UT_TARGET}>
127+
)
128+
endif()
91129
endfunction(AddTest)
92130

93131
#Do not add '${TEST_SRC_DIR}/util/include' to your include directories directly
@@ -552,6 +590,9 @@ set(all_dependencies ${onnxruntime_test_providers_dependencies} )
552590
# the default logger tests conflict with the need to have an overall default logger
553591
# so skip in this type of
554592
target_compile_definitions(onnxruntime_test_all PUBLIC -DSKIP_DEFAULT_LOGGER_TESTS)
593+
if (CMAKE_SYSTEM_NAME STREQUAL "iOS")
594+
target_compile_definitions(onnxruntime_test_all_xc PUBLIC -DSKIP_DEFAULT_LOGGER_TESTS)
595+
endif()
555596
if(onnxruntime_RUN_MODELTEST_IN_DEBUG_MODE)
556597
target_compile_definitions(onnxruntime_test_all PUBLIC -DRUN_MODELTEST_IN_DEBUG_MODE)
557598
endif()
@@ -684,6 +725,7 @@ endif()
684725
install(TARGETS onnx_test_runner
685726
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
686727
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
728+
BUNDLE DESTINATION ${CMAKE_INSTALL_LIBDIR}
687729
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
688730

689731
if(onnxruntime_BUILD_BENCHMARKS)
@@ -812,15 +854,17 @@ if (onnxruntime_BUILD_SHARED_LIB)
812854
if (CMAKE_SYSTEM_NAME STREQUAL "Android")
813855
list(APPEND onnxruntime_shared_lib_test_LIBS ${android_shared_libs})
814856
endif()
815-
AddTest(DYN
816-
TARGET onnxruntime_shared_lib_test
817-
SOURCES ${onnxruntime_shared_lib_test_SRC} ${TEST_SRC_DIR}/providers/test_main.cc
818-
LIBS ${onnxruntime_shared_lib_test_LIBS}
819-
DEPENDS ${all_dependencies}
820-
)
857+
if (NOT CMAKE_SYSTEM_NAME STREQUAL "iOS")
858+
AddTest(DYN
859+
TARGET onnxruntime_shared_lib_test
860+
SOURCES ${onnxruntime_shared_lib_test_SRC} ${TEST_SRC_DIR}/providers/test_main.cc
861+
LIBS ${onnxruntime_shared_lib_test_LIBS}
862+
DEPENDS ${all_dependencies}
863+
)
864+
endif()
821865

822866
# test inference using global threadpools
823-
if (NOT CMAKE_SYSTEM_NAME STREQUAL "Android" AND NOT onnxruntime_MINIMAL_BUILD)
867+
if (NOT CMAKE_SYSTEM_NAME MATCHES "Android|iOS" AND NOT onnxruntime_MINIMAL_BUILD)
824868
AddTest(DYN
825869
TARGET onnxruntime_global_thread_pools_test
826870
SOURCES ${onnxruntime_global_thread_pools_test_SRC}
@@ -830,7 +874,7 @@ if (onnxruntime_BUILD_SHARED_LIB)
830874
endif()
831875

832876
# A separate test is needed to test the APIs that don't rely on the env being created first.
833-
if (NOT CMAKE_SYSTEM_NAME STREQUAL "Android")
877+
if (NOT CMAKE_SYSTEM_NAME MATCHES "Android|iOS")
834878
AddTest(DYN
835879
TARGET onnxruntime_api_tests_without_env
836880
SOURCES ${onnxruntime_api_tests_without_env_SRC}

onnxruntime/test/framework/data_types_test.cc

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,12 @@ struct MapTypeProto {
204204
class DataTypeTest : public testing::Test {
205205
public:
206206
static void SetUpTestCase() {
207-
RegisterTestTypes();
207+
// xcTest run test case by case, so the SetUp needs to be reentrant.
208+
static std::atomic<bool> loaded(false);
209+
if (!loaded.load()) {
210+
loaded.store(true);
211+
RegisterTestTypes();
212+
}
208213
}
209214
};
210215

onnxruntime/test/providers/test_main.cc

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,27 @@
4242
#include "test/test_environment.h"
4343

4444
std::unique_ptr<Ort::Env> ort_env;
45+
void ortenv_setup(){
46+
OrtThreadingOptions tpo;
47+
ort_env.reset(new Ort::Env(&tpo, ORT_LOGGING_LEVEL_WARNING, "Default"));
48+
}
49+
50+
#define TEST_MAIN main
51+
52+
#if defined(__APPLE__)
53+
#include <TargetConditionals.h>
54+
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
55+
#define TEST_MAIN main_no_link_ // there is a UI test app for iOS.
56+
#endif
57+
#endif
4558

46-
int main(int argc, char** argv) {
59+
int TEST_MAIN(int argc, char** argv) {
4760
int status = 0;
61+
4862
ORT_TRY {
4963
::testing::InitGoogleTest(&argc, argv);
50-
OrtThreadingOptions tpo;
51-
ort_env.reset(new Ort::Env(&tpo, ORT_LOGGING_LEVEL_WARNING, "Default"));
64+
65+
ortenv_setup();
5266
status = RUN_ALL_TESTS();
5367
}
5468
ORT_CATCH(const std::exception& ex) {

onnxruntime/test/xctest/Info.plist

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>CFBundleDevelopmentRegion</key>
6+
<string>$(DEVELOPMENT_LANGUAGE)</string>
7+
<key>CFBundleExecutable</key>
8+
<string>$(EXECUTABLE_NAME)</string>
9+
<key>CFBundleIdentifier</key>
10+
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
11+
<key>CFBundleInfoDictionaryVersion</key>
12+
<string>6.0</string>
13+
<key>CFBundleName</key>
14+
<string>$(PRODUCT_NAME)</string>
15+
<key>CFBundlePackageType</key>
16+
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
17+
<key>CFBundleShortVersionString</key>
18+
<string>1.0</string>
19+
<key>CFBundleVersion</key>
20+
<string>1</string>
21+
</dict>
22+
</plist>

onnxruntime/test/xctest/orttestmain.m

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
#import <UIKit/UIKit.h>
5+
6+
static void set_test_rootdir(const char* image_path){
7+
size_t n = strlen(image_path);
8+
for (; n >=0; n--) {
9+
if (image_path[n] == '/') {
10+
break;
11+
}
12+
}
13+
14+
char* bundle_dir = (char*)malloc(n + 1);
15+
if (bundle_dir != NULL) {
16+
strncpy(bundle_dir, image_path, n);
17+
bundle_dir[n] = 0;
18+
chdir(bundle_dir);
19+
free(bundle_dir);
20+
}
21+
}
22+
23+
@interface ViewController : UIViewController
24+
25+
@end
26+
27+
@implementation ViewController
28+
29+
- (void)viewDidLoad
30+
{
31+
[super viewDidLoad];
32+
33+
self.view.backgroundColor = [UIColor whiteColor];
34+
}
35+
36+
- (void)didReceiveMemoryWarning
37+
{
38+
[super didReceiveMemoryWarning];
39+
}
40+
41+
@end
42+
43+
44+
45+
@interface AppDelegate : UIResponder <UIApplicationDelegate>
46+
47+
@property (strong, nonatomic) UIWindow *window;
48+
49+
@property (nonatomic, strong) UIViewController *rootViewController;
50+
51+
@end
52+
53+
@implementation AppDelegate
54+
55+
56+
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
57+
{
58+
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
59+
self.window.tintAdjustmentMode = UIViewTintAdjustmentModeNormal;
60+
self.window.rootViewController = [[ViewController alloc] init];
61+
62+
self.window.backgroundColor = [UIColor whiteColor];
63+
self.window.clipsToBounds = NO;
64+
[self.window makeKeyAndVisible];
65+
66+
return YES;
67+
}
68+
69+
- (void)applicationWillResignActive:(UIApplication *)application
70+
{
71+
}
72+
73+
- (void)applicationDidEnterBackground:(UIApplication *)application
74+
{
75+
}
76+
77+
- (void)applicationWillEnterForeground:(UIApplication *)application
78+
{
79+
}
80+
81+
- (void)applicationDidBecomeActive:(UIApplication *)application
82+
{
83+
}
84+
85+
- (void)applicationWillTerminate:(UIApplication *)application
86+
{
87+
}
88+
89+
@end
90+
91+
92+
int main(int argc, char * argv[]) {
93+
set_test_rootdir(argv[0]);
94+
int ret = 0;
95+
@autoreleasepool {
96+
ret = UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
97+
}
98+
99+
return ret;
100+
}

0 commit comments

Comments
 (0)