diff options
author | Vladimir Byko-Ianko <v.bykoianko@corp.mail.ru> | 2015-02-27 20:31:21 +0300 |
---|---|---|
committer | Alex Zolotarev <alex@maps.me> | 2015-09-23 02:46:03 +0300 |
commit | c5a45d38c2060c1b8722a387031bef03cabdc9e6 (patch) | |
tree | cfbcac93439a272583e96657c5d17caaae8c97b5 /android/UnitTests | |
parent | b6db1697139223354c36524605eb13cbdc2f9f15 (diff) |
Developing infrastucture for launching integration tests and unit tests for Android. Porting integration tests and indexer tests on Android platform.
Diffstat (limited to 'android/UnitTests')
27 files changed, 979 insertions, 0 deletions
diff --git a/android/UnitTests/.gitignore b/android/UnitTests/.gitignore new file mode 100644 index 0000000000..fccffe73ec --- /dev/null +++ b/android/UnitTests/.gitignore @@ -0,0 +1,9 @@ +.gradle +.idea +.DS_Store +bin +build +gen +libs +obj +local.properties diff --git a/android/UnitTests/AndroidManifest.xml b/android/UnitTests/AndroidManifest.xml new file mode 100644 index 0000000000..42e844142f --- /dev/null +++ b/android/UnitTests/AndroidManifest.xml @@ -0,0 +1,67 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- BEGIN_INCLUDE(manifest) --> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.mapswithme.maps.unittests" + android:versionCode="1" + android:versionName="1.0"> + + <!-- This is the platform API where NativeActivity was introduced. --> + <uses-sdk android:minSdkVersion="9" /> + + <uses-feature + android:glEsVersion="0x00020000" + android:required="true"/> + <uses-feature + android:name="android.hardware.touchscreen" + android:required="true"/> + <uses-feature + android:name="android.hardware.wifi" + android:required="false"/> + <uses-feature + android:name="android.hardware.location" + android:required="false"/> + <uses-feature + android:name="android.hardware.location.network" + android:required="false"/> + <uses-feature + android:name="android.hardware.location.gps" + android:required="false"/> + + <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> + <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> + <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> + <uses-permission android:name="android.permission.INTERNET"/> + <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> + <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/> + <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> + <uses-permission android:name="android.permission.WAKE_LOCK"/> + + <uses-permission android:name="android.permission.GET_ACCOUNTS"/> + <uses-permission android:name="android.permission.READ_PHONE_STATE"/> + <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE"/> + + + <supports-screens + android:largeScreens="true" + android:xlargeScreens="true"/> + + <!-- This .apk has no Java code itself, so set hasCode to false. android:hasCode="false" --> + <application android:label="@string/app_name"> + + <!-- Our activity is the built-in NativeActivity framework class. + This will take care of integrating with our NDK code. --> + <activity android:name="com.mapswithme.maps.unittests.AllTestsActivity" + android:label="@string/app_name" + android:configChanges="orientation|keyboardHidden"> + <!-- Tell NativeActivity the name of or .so --> + <meta-data android:name="android.app.lib_name" + android:value="all_tests" /> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + </application> + +</manifest> +<!-- END_INCLUDE(manifest) --> diff --git a/android/UnitTests/assets b/android/UnitTests/assets new file mode 120000 index 0000000000..ec2e4be2f8 --- /dev/null +++ b/android/UnitTests/assets @@ -0,0 +1 @@ +../assets
\ No newline at end of file diff --git a/android/UnitTests/build.gradle b/android/UnitTests/build.gradle new file mode 100644 index 0000000000..c7d09e5619 --- /dev/null +++ b/android/UnitTests/build.gradle @@ -0,0 +1,110 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:1.1.+' + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + jcenter() + } +} + +apply plugin: 'com.android.application' + +android { + compileSdkVersion propTargetSdkVersion.toInteger() + buildToolsVersion propBuildToolsVersion + + defaultConfig { + // Default package name is taken from the manifest and should be com.mapswithme.maps.unittests + versionCode propVersionCode.toInteger() + versionName propVersionName + minSdkVersion propMinSdkVersion.toInteger() + targetSdkVersion propTargetSdkVersion.toInteger() + } + + sourceSets.main { + manifest.srcFile 'AndroidManifest.xml' + res.srcDirs = ['res'] + java.srcDirs = ['src'] + assets.srcDirs = ['assets'] + jniLibs.srcDirs = ['libs'] + } + + signingConfigs { + mapswithme { + storeFile file('../../tools/android/mapswithmetests.keystore') + storePassword 'ITHOrMARopHE' + keyAlias 'mapswithmetests' + keyPassword 'ITHOrMARopHE' + } + } + + buildTypes { + debug { + applicationIdSuffix '.debug' // Allows to install debug and release builds together + versionNameSuffix '-debug' + jniDebuggable true // Enable jni debug build + zipAlignEnabled true + } + + release { + signingConfig signingConfigs.mapswithme + minifyEnabled true + shrinkResources true + proguardFile('proguard-mwm.txt') + } + } + + // We don't compress these extensions in assets/ because our random FileReader can't read zip-compressed files from apk + aaptOptions { + noCompress 'txt', 'bin', 'skn', 'html', 'png', 'json', 'mwm', 'ttf' + ignoreAssetsPattern "!.svn:!.git:!.DS_Store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~" + } + + // Enables new Java features in KitKat+ but needs Java 1.7 installed + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + } +} + +def NUM_OF_PARALLEL_MAKE_TASKS = Runtime.runtime.availableProcessors() + 1 +def INTEGRATION_TESTS_BUILD = '../../integration_tests/' +Properties properties = new Properties() +properties.load(project.rootProject.file('local.properties').newDataInputStream()) +def NDK_BUILD = properties.getProperty('ndk.dir') + '/ndk-build' + +// Building all static libraries +task cppLibsBuildDebug(type: Exec, description: 'Building DEBUG version of static C++ libraries') { + commandLine 'bash', './native_build.sh', 'debug' +} + +task cppLibsBuildRelease(type: Exec, description: 'Building RELEASE/PRODUCTION version of static C++ libraries') { + commandLine 'bash', './native_build.sh', 'production' +} + +tasks.withType(JavaCompile) { compileTask -> + if (compileTask.name.contains('Release')) { + compileTask.dependsOn cppLibsBuildRelease + } else { + compileTask.dependsOn cppLibsBuildDebug + } +} + +// Cleaning ndk +task cppLibsClean(type: Exec, description: 'Clean native libraries') { + commandLine 'bash', './native_clean.sh' +} + +clean.dependsOn 'cppLibsClean' + diff --git a/android/UnitTests/gradle.properties b/android/UnitTests/gradle.properties new file mode 120000 index 0000000000..7677fb73be --- /dev/null +++ b/android/UnitTests/gradle.properties @@ -0,0 +1 @@ +../gradle.properties
\ No newline at end of file diff --git a/android/UnitTests/gradle/wrapper/gradle-wrapper.jar b/android/UnitTests/gradle/wrapper/gradle-wrapper.jar Binary files differnew file mode 100644 index 0000000000..8c0fb64a86 --- /dev/null +++ b/android/UnitTests/gradle/wrapper/gradle-wrapper.jar diff --git a/android/UnitTests/gradle/wrapper/gradle-wrapper.properties b/android/UnitTests/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000..0c71e760dc --- /dev/null +++ b/android/UnitTests/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Wed Apr 10 15:27:10 PDT 2013 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip diff --git a/android/UnitTests/gradlew b/android/UnitTests/gradlew new file mode 100755 index 0000000000..91a7e269e1 --- /dev/null +++ b/android/UnitTests/gradlew @@ -0,0 +1,164 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# For Cygwin, ensure paths are in UNIX format before anything is touched. +if $cygwin ; then + [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` +fi + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >&- +APP_HOME="`pwd -P`" +cd "$SAVED" >&- + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/android/UnitTests/gradlew.bat b/android/UnitTests/gradlew.bat new file mode 100644 index 0000000000..8a0b282aa6 --- /dev/null +++ b/android/UnitTests/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/android/UnitTests/jni/Android.mk b/android/UnitTests/jni/Android.mk new file mode 100644 index 0000000000..839ba603c8 --- /dev/null +++ b/android/UnitTests/jni/Android.mk @@ -0,0 +1,32 @@ + +LOCAL_PATH := $(call my-dir) + +# Add prebuilt shared lib +# todo(VB) extract the names of the libs from tests_list.sh +MY_PREBUILT_LIBS_PATH := ../libs/tmp/$(TARGET_ARCH_ABI) +$(info $(MY_PREBUILT_LIBS_PATH)) + +include $(CLEAR_VARS) +LOCAL_MODULE := integration_tests +LOCAL_SRC_FILES := $(MY_PREBUILT_LIBS_PATH)/libintegration_tests.so +include $(PREBUILT_SHARED_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE := indexer_tests +LOCAL_SRC_FILES := $(MY_PREBUILT_LIBS_PATH)/libindexer_tests.so +include $(PREBUILT_SHARED_LIBRARY) + +include $(CLEAR_VARS) + +ROOT_PATH := ../.. +include ./jni/AndroidBeginning.mk + +LOCAL_MODULE := all_tests + +LOCAL_SRC_FILES := ./main.cpp +LOCAL_STATIC_LIBRARIES := android_native_app_glue + +# todo(VB) extract the names of the libs from tests_list.sh +LOCAL_SHARED_LIBRARIES := integration_tests indexer_tests + +include ./jni/AndroidEnding.mk diff --git a/android/UnitTests/jni/AndroidBeginning.mk b/android/UnitTests/jni/AndroidBeginning.mk new file mode 100644 index 0000000000..3cad168ef1 --- /dev/null +++ b/android/UnitTests/jni/AndroidBeginning.mk @@ -0,0 +1,63 @@ + +OMIM_CONFIG := debug +ifeq ($(NDK_DEBUG),1) + OMIM_CONFIG := debug +else + ifeq ($(PRODUCTION),1) + OMIM_CONFIG := production + endif +endif + +# Avoid clean errors due to missing external static libs +ifneq ($(MAKECMDGOALS),clean) + +ROOT_PATH_FROM_JNI = $(ROOT_PATH)/.. + +MY_PREBUILT_LIBS_PATH := $(ROOT_PATH_FROM_JNI)/../omim-android-$(OMIM_CONFIG)-$(TARGET_ARCH_ABI)/out/$(OMIM_CONFIG) +$(info $(MY_PREBUILT_LIBS_PATH)) + +define add_prebuild_static_lib + include $(CLEAR_VARS) + LOCAL_MODULE := $1 + LOCAL_SRC_FILES := $(MY_PREBUILT_LIBS_PATH)/lib$1.a + include $(PREBUILT_STATIC_LIBRARY) +endef + +prebuild_static_libs := osrm protobuf tomcrypt jansson bzip2 zlib fribidi freetype expat base coding geometry anim platform graphics indexer storage search routing gui map stats_client succinct + +$(foreach item,$(prebuild_static_libs),$(eval $(call add_prebuild_static_lib,$(item)))) + +endif + +include $(CLEAR_VARS) + +LOCAL_CPP_FEATURES += exceptions rtti + +LOCAL_C_INCLUDES := $(ROOT_PATH_FROM_JNI)/ +LOCAL_C_INCLUDES += $(ROOT_PATH)/ + +ifneq ($(NDK_DEBUG),1) + ifeq ($(PRODUCTION),1) + OMIM_CONFIG := production + LOCAL_CPPFLAGS += -fvisibility-inlines-hidden + endif + LOCAL_CFLAGS += -O3 + LOCAL_LFLAGS += -O3 +endif +LOCAL_CFLAGS += -ffunction-sections -fdata-sections -Wno-extern-c-compat + +TARGET_PLATFORM := android-9 + +$(info $(LOCAL_PATH)) + +MY_CPP_PATH = $(LOCAL_PATH)/.. +MY_LOCAL_SRC_FILES := $(wildcard $(MY_CPP_PATH)/*.cpp) +LOCAL_SRC_FILES += $(subst jni/, , $(MY_LOCAL_SRC_FILES)) + +LOCAL_SRC_FILES += $(ROOT_PATH_FROM_JNI)/testing/testingmain.cpp +LOCAL_SRC_FILES += $(ROOT_PATH_FROM_JNI)/android/UnitTests/jni/mock.cpp +LOCAL_SRC_FILES += ./test.cpp + +LOCAL_LDLIBS := -llog -landroid -lEGL -lGLESv1_CM +LOCAL_LDLIBS += -lGLESv2 -latomic +LOCAL_LDLIBS += -Wl,--gc-sections diff --git a/android/UnitTests/jni/AndroidEnding.mk b/android/UnitTests/jni/AndroidEnding.mk new file mode 100644 index 0000000000..917c9accff --- /dev/null +++ b/android/UnitTests/jni/AndroidEnding.mk @@ -0,0 +1,2 @@ +include $(BUILD_SHARED_LIBRARY) +$(call import-module,android/native_app_glue) diff --git a/android/UnitTests/jni/Application.mk b/android/UnitTests/jni/Application.mk new file mode 100644 index 0000000000..d2d2ced6bc --- /dev/null +++ b/android/UnitTests/jni/Application.mk @@ -0,0 +1,36 @@ +NDK_TOOLCHAIN_VERSION := clang3.5 +APP_ABI := armeabi-v7a-hard +# APP_ABI := armeabi-v7a + +APP_PLATFORM := android-9 +APP_STL := c++_static + +# libc++-specific issues: -std=c++11" is turned on by default. + +APP_CPPFLAGS += -Wno-deprecated-register + +#@todo(VB) Build tests for android x86 platform +#ifeq (x$(NDK_ABI_TO_BUILD), x) +# APP_ABI := armeabi-v7a-hard x86 +#else +# APP_ABI := $(NDK_ABI_TO_BUILD) +#endif + +APP_CPPFLAGS += -fexceptions +LOCAL_CPPFLAGS += -fexceptions + +APP_CPPFLAGS += -frtti +LOCAL_CPPFLAGS += -frtti + +APP_GNUSTL_FORCE_CPP_FEATURES := exceptions rtti + +ifeq ($(NDK_DEBUG),1) + APP_OPTIM := debug + APP_CFLAGS += -DDEBUG -D_DEBUG +else + APP_OPTIM := release + APP_CFLAGS += -DRELEASE -D_RELEASE +ifeq ($(PRODUCTION),1) + APP_CFLAGS += -DOMIM_PRODUCTION +endif +endif diff --git a/android/UnitTests/jni/main.cpp b/android/UnitTests/jni/main.cpp new file mode 100644 index 0000000000..53c752ee8c --- /dev/null +++ b/android/UnitTests/jni/main.cpp @@ -0,0 +1,20 @@ +// @todo(VB) this file should be generated with a script based on tests_list.sh +#include "mock.hpp" + +#include "integration_tests/jni/test.hpp" +#include "indexer/indexer_tests/jni/test.hpp" + +#include <android_native_app_glue.h> + + +void android_main(struct android_app * state) +{ + // Make sure glue isn't stripped. + app_dummy(); + + integration_tests::test(state); + indexer_tests::test(state); + + // @todo(VB) you need to write code to leave the activity correctly after all tests are finished. And show a dialog with the results. + // @todo(VB) It's nice to show the result of the test on Android screen. Message box or something like that. +} diff --git a/android/UnitTests/jni/mock.cpp b/android/UnitTests/jni/mock.cpp new file mode 100644 index 0000000000..d06c074309 --- /dev/null +++ b/android/UnitTests/jni/mock.cpp @@ -0,0 +1,256 @@ +#include "mock.hpp" + +#include "android/jni/com/mapswithme/core/logging.hpp" + +#include "coding/file_writer.hpp" + +#include "platform/file_logging.hpp" +#include "platform/platform.hpp" + +#include "base/assert.hpp" +#include "base/logging.hpp" + +#include "std/string.hpp" + +using namespace my; + +// @todo(VB) probably it's worth thinking about output of the function to make the result of the tests more readable +// @todo(VB) it's necessary display test name android log +static void AndroidLogMessage(LogLevel l, SrcPoint const & src, string const & s) +{ + android_LogPriority pr = ANDROID_LOG_SILENT; + + switch (l) + { + case LINFO: pr = ANDROID_LOG_INFO; break; + case LDEBUG: pr = ANDROID_LOG_DEBUG; break; + case LWARNING: pr = ANDROID_LOG_WARN; break; + case LERROR: pr = ANDROID_LOG_ERROR; break; + case LCRITICAL: pr = ANDROID_LOG_FATAL; break; + } + + string const out = DebugPrint(src) + " " + s; + __android_log_write(pr, " MapsMeTests ", out.c_str()); +} + +static void AndroidAssertMessage(SrcPoint const & src, string const & s) +{ +#if defined(MWM_LOG_TO_FILE) + AndroidLogToFile(LERROR, src, s); +#else + AndroidLogMessage(LERROR, src, s); +#endif + +#ifdef DEBUG + assert(false); +#else + MYTHROW(RootException, (s)); +#endif +} + +static void InitSystemLog() +{ +#if defined(MWM_LOG_TO_FILE) + SetLogMessageFn(&AndroidLogToFile); +#else + SetLogMessageFn(&AndroidLogMessage); +#endif +} + +static void InitAssertLog() +{ + SetAssertFunction(&AndroidAssertMessage); +} + +namespace +{ + JavaVM * javaVM = nullptr; +} + +namespace android_tests +{ + class MainThreadScopeGuard + { + JavaVM * m_Vm; + JNIEnv * m_Env; + public: + MainThreadScopeGuard(JavaVM * vm) : m_Vm(vm), m_Env(nullptr) + { + assert(vm); + m_Vm->AttachCurrentThread(&m_Env, NULL); + } + ~MainThreadScopeGuard() { m_Vm->DetachCurrentThread(); } + JNIEnv * GetEnv() const { return m_Env; } + }; + + static bool CheckExceptions(JNIEnv * env) + { + jthrowable exception = env->ExceptionOccurred(); + if (exception) + { + env->ExceptionDescribe(); + env->ExceptionClear(); + return true; + } + return false; + } + + static string GetApkPath(ANativeActivity * activity, JNIEnv * env) + { + ASSERT(activity, ()); + ASSERT(env, ()); + + jclass const clazz = env->GetObjectClass(activity->clazz); + ASSERT(clazz, ()); + jmethodID const methodID = env->GetMethodID(clazz, "getPackageCodePath", "()Ljava/lang/String;"); + ASSERT(methodID, ()); + jobject const result = env->CallObjectMethod(activity->clazz, methodID); + ASSERT(result, ()); + ASSERT(!CheckExceptions(env), ()); + jboolean isCopy; + std::string const res = env->GetStringUTFChars((jstring)result, &isCopy); + return res; + } + + static string GetSdcardPath(ANativeActivity * activity, JNIEnv * env) + { + ASSERT(activity, ()); + ASSERT(env, ()); + + jclass const classEnvironment = env->FindClass("android/os/Environment"); + ASSERT(classEnvironment, ()); + jmethodID const methodIDgetExternalStorageDirectory = env->GetStaticMethodID(classEnvironment, "getExternalStorageDirectory", "()Ljava/io/File;"); + ASSERT(methodIDgetExternalStorageDirectory, ()); + jobject const objectFile = env->CallStaticObjectMethod(classEnvironment, methodIDgetExternalStorageDirectory); + ASSERT(objectFile, ()); + ASSERT(!CheckExceptions(env), ()); + + jclass const classFile = env->GetObjectClass(objectFile); + ASSERT(classFile, ()); + jmethodID const methodIDgetAbsolutePath = env->GetMethodID(classFile, "getAbsolutePath", "()Ljava/lang/String;"); + ASSERT(methodIDgetAbsolutePath, ()); + jstring const stringPath = (jstring) env->CallObjectMethod(objectFile, methodIDgetAbsolutePath); + ASSERT(stringPath, ()); + ASSERT(!CheckExceptions(env), ()); + + jboolean isCopy; + std::string const res = env->GetStringUTFChars((jstring)stringPath, &isCopy); + return res; + } + + static string GetPackageName(ANativeActivity * activity, JNIEnv * env) + { + ASSERT(activity, ()); + ASSERT(env, ()); + + jclass const clazz = env->GetObjectClass(activity->clazz); + ASSERT(clazz, ()); + jmethodID const methodID = env->GetMethodID(clazz, "getPackageName", "()Ljava/lang/String;"); + ASSERT(methodID, ()); + jobject const result = env->CallObjectMethod(activity->clazz, methodID); + ASSERT(result, ()); + ASSERT(!CheckExceptions(env), ()); + jboolean isCopy; + std::string const res = env->GetStringUTFChars((jstring)result, &isCopy); + return res; + } + + class Platform : public ::Platform + { + public: + void Initialize(ANativeActivity * activity, JNIEnv * env) + { + LOG(LINFO, ("Platform::Initialize()")); + string apkPath = android_tests::GetApkPath(activity, env); + LOG(LINFO, ("Apk path FromJNI: ", apkPath.c_str())); + + string sdcardPath = android_tests::GetSdcardPath(activity, env); + LOG(LINFO, ("Sdcard path FromJNI: ", sdcardPath.c_str())); + + string packageName = android_tests::GetPackageName(activity, env); + LOG(LINFO, ("Package name FromJNI: ", packageName.c_str())); + + m_writableDir = sdcardPath + "/MapsWithMe/"; + m_resourcesDir = apkPath; + + m_tmpDir = sdcardPath + "/Android/data/" + packageName + "/cache/"; + m_settingsDir = m_writableDir; + m_androidDefResScope = "rfw"; + } + + void OnExternalStorageStatusChanged(bool isAvailable) + { + LOG(LWARNING, ("OnExternalStorageStatusChanged() is not implemented.")); + } + + /// get storage path without ending "/MapsWithMe/" + string GetStoragePathPrefix() const + { + return string("/sdcard"); + } + /// assign storage path (should contain ending "/MapsWithMe/") + void SetStoragePath(string const & path) {} + + bool HasAvailableSpaceForWriting(uint64_t size) const{ return true; } + + static void RunOnGuiThreadImpl(TFunctor const & fn, bool blocking = false) + { + ASSERT(false, ()); + } + + static Platform & Instance() + { + static Platform platform; + return platform; + } + }; +} + +Platform & GetPlatform() +{ + return android_tests::Platform::Instance(); +} + +string GetAndroidSystemLanguage() +{ + return "en_US"; +} + +void AndroidThreadAttachToJVM() +{ + LOG(LWARNING, ("AndroidThreadAttachToJVM() is not implemented.")); +} +void AndroidThreadDetachFromJVM() +{ + LOG(LWARNING, ("AndroidThreadDetachFromJVM() is not implemented.")); +} + +void Platform::RunOnGuiThread(TFunctor const & fn) +{ + LOG(LWARNING, ("Platform::RunOnGuiThread() is not implemented.")); +} + +JavaVM * GetJVM() +{ + LOG(LWARNING, ("GetJVM() returns nullptr.")); + return nullptr; +} + +void Initialize(android_app * state) +{ + LOGI("Indexperf. Initialize()"); + assert(state); + ANativeActivity * activity = state->activity; + assert(activity); + android_tests::MainThreadScopeGuard mainThreadScopeGuard(activity->vm); + JNIEnv * env = mainThreadScopeGuard.GetEnv(); + assert(env); + + javaVM = activity->vm; + + InitSystemLog(); + InitAssertLog(); + android_tests::Platform::Instance().Initialize(activity, env); + LOG(LINFO, ("Indexperf. Initialization finished....")); +} + diff --git a/android/UnitTests/jni/mock.hpp b/android/UnitTests/jni/mock.hpp new file mode 100644 index 0000000000..eaf4bebc51 --- /dev/null +++ b/android/UnitTests/jni/mock.hpp @@ -0,0 +1,11 @@ +#pragma once + +#include <android/log.h> +#include <android_native_app_glue.h> +#include <cassert> + +#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "native-activity", __VA_ARGS__)) +#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "native-activity", __VA_ARGS__)) + +void Initialize(android_app * state); +JavaVM * GetJVM(); diff --git a/android/UnitTests/native_build.sh b/android/UnitTests/native_build.sh new file mode 100755 index 0000000000..5bfcf130d0 --- /dev/null +++ b/android/UnitTests/native_build.sh @@ -0,0 +1,58 @@ +#!/bin/bash + +MY_PATH=$(dirname "$0") # relative +MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized + +source "$MY_PATH/tests_list.sh" + +declare -r NDK_ABI=armeabi-v7a-hard + +declare -r PROP_DEBUG_NDK_FLAGS="-j8 V=1 NDK_DEBUG=1 DEBUG=1 APP_ABI=$NDK_ABI" +declare -r PROP_RELEASE_NDK_FLAGS="-j8 V=1 NDK_DEBUG=0 PRODUCTION=1 APP_ABI=$NDK_ABI" + +Usage() { + echo "Usage: $0 <debug|release|production>" 1>&2 + exit 1 +} + +NdkBuild() { + if [ "$1" = "debug" ]; then + NDK_PARAMS="--directory=$2 ${PROP_DEBUG_NDK_FLAGS}" + else + NDK_PARAMS="--directory=$2 ${PROP_RELEASE_NDK_FLAGS}" + fi + echo "ndk-build $NDK_PARAMS" + ndk-build $NDK_PARAMS +} + +if [ $# != 1 ]; then + Usage +fi + +if [ "$1" != "debug" && "$1" != "release" && "$1" != "production" ]; then + Usage +fi + +echo "Building omim/andoid..." +if [ "$1" = "debug" ]; then + bash $MY_PATH/../../tools/autobuild/android.sh debug $NDK_ABI +else + bash $MY_PATH/../../tools/autobuild/android.sh production $NDK_ABI +fi + +for test in "${TESTS_LIST[@]}"; do + echo "Building test $test" + NdkBuild $1 ${test} +done + +echo "Copying so-files with tests to the libs directory: " +TMP_LIB_DIR=$MY_PATH/libs/tmp/$NDK_ABI/ +echo $TMP_LIB_DIR +mkdir -p $TMP_LIB_DIR +for test in "${TESTS_LIST[@]}"; do + echo "Copying so-file for test: $test" + cp -r $test/libs/*/*.so $TMP_LIB_DIR +done + +echo "Building main so file for the native activity... " +NdkBuild $1 . diff --git a/android/UnitTests/native_clean.sh b/android/UnitTests/native_clean.sh new file mode 100755 index 0000000000..efd4bea30b --- /dev/null +++ b/android/UnitTests/native_clean.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +MY_PATH=$(dirname "$0") # relative +MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized + +source "$MY_PATH/tests_list.sh" + +echo "Cleaning omim/andoid..." +#ndk-build --directory=$MY_PATH/.. clean + +RemoveObjLibs() { + rm -r $1/obj + rm -r $1/libs +} + +for test in "${TESTS_LIST[@]}"; do + echo "Cleaning test $test" + ndk-build --directory=$test clean + RemoveObjLibs $test +done + +ndk-build --directory=$MY_PATH clean +RemoveObjLibs $MY_PATH +rm -r $MY_PATH/build diff --git a/android/UnitTests/proguard-mwm.txt b/android/UnitTests/proguard-mwm.txt new file mode 120000 index 0000000000..a3abbc779a --- /dev/null +++ b/android/UnitTests/proguard-mwm.txt @@ -0,0 +1 @@ +./../proguard-mwm.txt
\ No newline at end of file diff --git a/android/UnitTests/res/mipmap-hdpi/ic_launcher.png b/android/UnitTests/res/mipmap-hdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000000..cde69bccce --- /dev/null +++ b/android/UnitTests/res/mipmap-hdpi/ic_launcher.png diff --git a/android/UnitTests/res/mipmap-mdpi/ic_launcher.png b/android/UnitTests/res/mipmap-mdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000000..c133a0cbd3 --- /dev/null +++ b/android/UnitTests/res/mipmap-mdpi/ic_launcher.png diff --git a/android/UnitTests/res/mipmap-xhdpi/ic_launcher.png b/android/UnitTests/res/mipmap-xhdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000000..bfa42f0e7b --- /dev/null +++ b/android/UnitTests/res/mipmap-xhdpi/ic_launcher.png diff --git a/android/UnitTests/res/mipmap-xxhdpi/ic_launcher.png b/android/UnitTests/res/mipmap-xxhdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000000..324e72cdd7 --- /dev/null +++ b/android/UnitTests/res/mipmap-xxhdpi/ic_launcher.png diff --git a/android/UnitTests/res/values/strings.xml b/android/UnitTests/res/values/strings.xml new file mode 100644 index 0000000000..a36dbd5633 --- /dev/null +++ b/android/UnitTests/res/values/strings.xml @@ -0,0 +1,3 @@ +<resources> + <string name="app_name">MAPS.ME Unit Tests</string> +</resources> diff --git a/android/UnitTests/settings.gradle b/android/UnitTests/settings.gradle new file mode 100644 index 0000000000..e7b4def49c --- /dev/null +++ b/android/UnitTests/settings.gradle @@ -0,0 +1 @@ +include ':app' diff --git a/android/UnitTests/src/com/mapswithme/maps/unittests/AllTestsActivity.java b/android/UnitTests/src/com/mapswithme/maps/unittests/AllTestsActivity.java new file mode 100644 index 0000000000..5dcfb6355f --- /dev/null +++ b/android/UnitTests/src/com/mapswithme/maps/unittests/AllTestsActivity.java @@ -0,0 +1,12 @@ +package com.mapswithme.maps.unittests; +// @todo(VB) This file should be generaged based on tests_list.h + +public class AllTestsActivity extends android.app.NativeActivity { + + static { + System.loadLibrary("integration_tests"); + System.loadLibrary("indexer_tests"); + System.loadLibrary("all_tests"); + } + } +
\ No newline at end of file diff --git a/android/UnitTests/tests_list.sh b/android/UnitTests/tests_list.sh new file mode 100644 index 0000000000..d5b625e4b2 --- /dev/null +++ b/android/UnitTests/tests_list.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +# This file contains a list of test which will be built for android. +# If you want you can leave a subset of tests here for developent purpose + +# @todo this list of test paths should be used in sh scripts and in C++ as well. +# The main point is you need to add a test to UnitTests project only once and here. + +MY_PATH=$(dirname "$0") # relative +MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized + +declare -r TESTS_LIST=($MY_PATH/../../integration_tests/ $MY_PATH/../../indexer/indexer_tests/) |