Skip to content

Commit

Permalink
First pass on Android tests
Browse files Browse the repository at this point in the history
  • Loading branch information
gershnik committed Nov 3, 2023
1 parent aa13c2c commit db96f12
Show file tree
Hide file tree
Showing 46 changed files with 1,003 additions and 36 deletions.
63 changes: 57 additions & 6 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,12 @@ on:

env:
BUILD_TYPE: Release
NDK_VER: 21.3.6528147
NDK_ARCH: x86_64
NDK_API: 29

jobs:
build:
desktop:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
Expand Down Expand Up @@ -139,10 +142,58 @@ jobs:

- name: Build and Test JniGen
shell: bash
run: cmake --build build --config $BUILD_TYPE --target run-java-tests
run: cmake --build build --config $BUILD_TYPE --target test-jnigen

# - name: Test JniGen
# working-directory: ${{github.workspace}}/jnigen
# shell: bash
# run: ./gradlew -PbuildDir=build -Pcode.version=SNAPSHOT test
android:
runs-on: macos-latest

steps:
- name: Checkout
uses: actions/checkout@v3

- name: AVD cache
uses: actions/cache@v3
id: avd-cache
with:
path: |
~/.android/avd/*
~/.android/adb*
key: avd-${{env.NDK_VER}}-${{env.NDK_ARCH}}-${{env.NDK_API}}

- name: Create AVD and generate snapshot for caching
if: steps.avd-cache.outputs.cache-hit != 'true'
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: ${{env.NDK_API}}
arch: ${{env.NDK_ARCH}}
target: google_apis
ndk: ${{env.NDK_VER}}
force-avd-creation: false
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: false
script: echo "Generated AVD snapshot for caching."

- name: Configure, Build and Test
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: ${{env.NDK_API}}
arch: ${{env.NDK_ARCH}}
target: google_apis
ndk: ${{env.NDK_VER}}
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: true
script: |
echo "::group::Configure"
cmake -S . -B build -DCMAKE_BUILD_TYPE:STRING=$BUILD_TYPE -DCMAKE_TOOLCHAIN_FILE:FILEPATH=$ANDROID_SDK_ROOT/ndk/$NDK_VER/build/cmake/android.toolchain.cmake -DANDROID_ABI:STRING=$NDK_ARCH -DANDROID_PLATFORM:STRING=19 -DANDROID_STL:STRING=c++_static
echo "::endgroup::"
echo "::group::Build and Test Native"
cmake --build build --config $BUILD_TYPE --target run-app
echo "::endgroup::"
echo "::group::Build and Test JniGen"
cmake --build build --config $BUILD_TYPE --target test-jnigen
echo "::endgroup::"



4 changes: 1 addition & 3 deletions tests/.gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
/local.properties
/gradle.properties
local.properties
/src/cpp/generated
/xcode
28 changes: 8 additions & 20 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,33 +16,21 @@

cmake_minimum_required(VERSION 3.16)

project(test)

find_package(Java COMPONENTS Development REQUIRED)

add_subdirectory("src/cpp" ${CMAKE_CURRENT_BINARY_DIR}/test)

add_custom_target(build-jnigen
COMMAND ${CMAKE_CURRENT_LIST_DIR}/gradlew -Pcode.version=SNAPSHOT publishToMavenLocal
COMMAND ./gradlew -Pcode.version=SNAPSHOT publishToMavenLocal
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/../jnigen
)

add_custom_target(run-java-tests ALL
COMMAND ${CMAKE_CURRENT_LIST_DIR}/gradlew -Pcode.version=SNAPSHOT test
add_custom_target(test-jnigen ALL
COMMAND ./gradlew -Pcode.version=SNAPSHOT test
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/../jnigen
)

add_custom_target(javabuild
DEPENDS build-jnigen
COMMAND ${CMAKE_CURRENT_LIST_DIR}/gradlew -PbuildDir=${CMAKE_CURRENT_BINARY_DIR}/java assemble
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
)
if (${CMAKE_SYSTEM_NAME} STREQUAL Android)
add_subdirectory("android")
else()
add_subdirectory("desktop")
endif()

add_dependencies(smjnitests javabuild)

add_custom_target(run-jar ALL
DEPENDS javabuild smjnitests
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:smjnitests> ${CMAKE_CURRENT_BINARY_DIR}/java
COMMAND ${CMAKE_COMMAND} -E env "LD_LIBRARY_PATH=${CMAKE_CURRENT_BINARY_DIR}/java:$ENV{LD_LIBRARY_PATH}" ${Java_JAVA_EXECUTABLE} -jar smjnitests.jar
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/java
)
1 change: 1 addition & 0 deletions tests/android/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.cxx/
49 changes: 49 additions & 0 deletions tests/android/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#
# Copyright 2023 SmJNI Contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

cmake_minimum_required(VERSION 3.16)

find_package (Python3 COMPONENTS Interpreter REQUIRED)

add_custom_target(javabuild
DEPENDS build-jnigen
COMMAND ${CMAKE_CURRENT_LIST_DIR}/gradlew -PbuildDir=${CMAKE_CURRENT_BINARY_DIR}/gradle :app:compileDebugJavaWithJavac
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
)

add_dependencies(smjnitests javabuild)

add_custom_target(androidbuild ALL
DEPENDS javabuild smjnitests
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_LIST_DIR}/app/libs/${ANDROID_ABI}
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:smjnitests> ${CMAKE_CURRENT_LIST_DIR}/app/libs/${ANDROID_ABI}/$<TARGET_FILE_NAME:smjnitests>
COMMAND ${CMAKE_CURRENT_LIST_DIR}/gradlew -PbuildDir=${CMAKE_CURRENT_BINARY_DIR}/gradle :app:assembleDebug
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
)

set(ANDROID_SDK_DIR ${CMAKE_ANDROID_NDK}/../..)
set(ADB ${ANDROID_SDK_DIR}/platform-tools/adb)


add_custom_target(run-app ALL
DEPENDS androidbuild smjnitests
COMMAND ${ADB} install -r -d ${CMAKE_CURRENT_BINARY_DIR}/gradle/outputs/apk/debug/app-debug.apk
COMMAND ${ADB} shell content call --uri content://com.example.smjni_test.provider --method blah
COMMAND ${ADB} pull /sdcard/Download/smjni_test/results.json ${CMAKE_CURRENT_BINARY_DIR}/results.json
COMMAND ${Python3_EXECUTABLE} parse-output.py ${CMAKE_CURRENT_BINARY_DIR}/results.json
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
)

110 changes: 110 additions & 0 deletions tests/android/app/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
plugins {
id 'com.android.application'
}

//JniGen settings
def jniGenProps = new Object() {
def generatedPath = "../../src/cpp/generated"
def outputListName = "outputs.txt"
def additionalClasses = ["java.lang.AssertionError"]
}

dependencies {

annotationProcessor("io.github.gershnik:smjni-jnigen-processor:SNAPSHOT")

compileOnly 'io.github.gershnik:smjni-jnigen-annotations:SNAPSHOT'

implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.10.0'
implementation 'org.junit.jupiter:junit-jupiter-api:5.10.0'


testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
}

android {
compileSdk 34
namespace 'com.example.smjni_test'

defaultConfig {
applicationId "com.example.smjni_test"
minSdk 16
targetSdk 34
versionCode 1
versionName "1.0"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

javaCompileOptions {
annotationProcessorOptions {
arguments = [
"smjni.jnigen.dest.path" : file(jniGenProps.generatedPath).path,
"smjni.jnigen.own.dest.path" : "true",
"smjni.jnigen.output.list.name": jniGenProps.outputListName,
"smjni.jnigen.expose.extra" : jniGenProps.additionalClasses.join(";").toString()
]
}
}
}

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}

sourceSets {
main.java.srcDirs += '../../src/java'
main.jniLibs.srcDirs += 'libs'
}

packaging {
resources.excludes += ["META-INF/LICENSE.md", "META-INF/LICENSE-notice.md"]
}
}


android.applicationVariants.all { variant ->

variant.javaCompileProvider.get().outputs.upToDateWhen {

def jniGenOutputList = file("${jniGenProps.generatedPath}/${jniGenProps.outputListName}")

if (!jniGenOutputList.exists()) {
return false
}

for(line in jniGenOutputList) {
if (!file("${jniGenProps.generatedPath}/$line").exists()) {
return false
}
}
return true
}
}

task cleanJNIHeaders(type: Delete) {
delete file("${jniGenProps.generatedPath}")
}
clean.dependsOn cleanJNIHeaders

tasks.whenTaskAdded { theTask ->
def match = theTask.name =~ ~/^buildCMake([^\[]*).*$/
if (match) {
def config
switch(match.group(1)) {
case "RelWithDebInfo": config = "Release"; break
default: config = match.group(1); break
}
theTask.dependsOn "compile${config}JavaWithJavac"
}
}
Binary file added tests/android/app/libs/x86_64/libsmjnitests.so
Binary file not shown.
26 changes: 26 additions & 0 deletions tests/android/app/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

-keep @smjni.jnigen.ExposeToNative class *
-keepclassmembers class * {
@smjni.jnigen.CalledByNative *;
}
23 changes: 23 additions & 0 deletions tests/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.smjni_test">

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.smjni_test">

<provider
android:name=".TestContentProvider"
android:authorities="com.example.smjni_test.provider"
android:enabled="true"
android:exported="true"/>
</application>

</manifest>
Loading

0 comments on commit db96f12

Please sign in to comment.