From 96e9d97770d1f1147e4d0a9b7bc2299cebaa58c3 Mon Sep 17 00:00:00 2001 From: MyungJoo Ham Date: Fri, 18 Sep 2026 15:43:03 +0900 Subject: [PATCH 1/2] [CI] run the instrumented tests of the Android API on Ubuntu The instrumented tests under java/android/nnstreamer/src/androidTest never run in CI: the Android jobs only build the library, and running them needs a device. So a regression in the JNI wrapper or in the C-API behavior it relies on is not caught before it is merged. The JNI wrapper is the same code on Ubuntu (meson -Djava-home builds it, and build-nnstreamer-ubuntu.sh builds the Java API), and most of the tests do not need Android. test-nnstreamer-ubuntu.sh compiles the Java API the same way as build-nnstreamer-ubuntu.sh, compiles the tests against small stubs of the Android classes they use (java/host-test/stub), and runs them on a desktop JVM against the JNI wrapper from the meson build. If the JVM crashes, the native stack from the crash report is printed. HostTestRunner runs the test classes with JUnit 4 and skips the tests listed in java/host-test/exclude.txt: the tests that need an Android element (amcsrc), an Android native window for the video sink, the Android application context, or the test assets copied from the Android test package. The video sink cases go together, as the three negative ones would otherwise pass on the pipeline failing to start rather than on the call they are written for. An entry that matches no test fails the run, so the list cannot silently go stale. ml-service is not built, so APITestMLService is left out. The new workflow installs nnstreamer from the PPA, builds ml-api with -Djava-home and runs the script for pull requests that change c/, java/ or the meson files. Adding the PPA is retried, as the Launchpad API it queries has answered with a gateway timeout. 164 tests pass and 10 are excluded, in about 100 seconds of test time. java/README.md, which was empty, now describes the scripts. Signed-off-by: MyungJoo Ham Co-Authored-By: Claude Opus 5 --- .github/workflows/android-jni-test-ubuntu.yml | 45 ++++++ java/README.md | 20 +++ java/host-test/exclude.txt | 22 +++ .../nnsuite/nnstreamer/HostTestRunner.java | 111 +++++++++++++ .../stub/android/content/Context.java | 43 +++++ .../android/content/res/AssetManager.java | 24 +++ java/host-test/stub/android/os/Build.java | 19 +++ .../support/test/InstrumentationRegistry.java | 24 +++ .../support/test/runner/AndroidJUnit4.java | 19 +++ java/host-test/stub/android/view/Surface.java | 16 ++ .../stub/android/view/SurfaceHolder.java | 14 ++ .../stub/android/view/SurfaceView.java | 28 ++++ java/test-nnstreamer-ubuntu.sh | 150 ++++++++++++++++++ 13 files changed, 535 insertions(+) create mode 100644 .github/workflows/android-jni-test-ubuntu.yml create mode 100644 java/host-test/exclude.txt create mode 100644 java/host-test/src/org/nnsuite/nnstreamer/HostTestRunner.java create mode 100644 java/host-test/stub/android/content/Context.java create mode 100644 java/host-test/stub/android/content/res/AssetManager.java create mode 100644 java/host-test/stub/android/os/Build.java create mode 100644 java/host-test/stub/android/support/test/InstrumentationRegistry.java create mode 100644 java/host-test/stub/android/support/test/runner/AndroidJUnit4.java create mode 100644 java/host-test/stub/android/view/Surface.java create mode 100644 java/host-test/stub/android/view/SurfaceHolder.java create mode 100644 java/host-test/stub/android/view/SurfaceView.java create mode 100755 java/test-nnstreamer-ubuntu.sh diff --git a/.github/workflows/android-jni-test-ubuntu.yml b/.github/workflows/android-jni-test-ubuntu.yml new file mode 100644 index 00000000..db207f3f --- /dev/null +++ b/.github/workflows/android-jni-test-ubuntu.yml @@ -0,0 +1,45 @@ +name: Android JNI test on Ubuntu + +# Build the JNI wrapper of the Android API on Ubuntu and run the instrumented tests +# that do not require an Android device (java/test-nnstreamer-ubuntu.sh). + +on: + pull_request: + branches: [ main ] + paths: + - 'c/**' + - 'java/**' + - 'meson.build' + - 'meson_options.txt' + - '.github/workflows/android-jni-test-ubuntu.yml' + + # Allow manually triggering the workflow + workflow_dispatch: + +jobs: + test: + name: Android JNI host test + runs-on: ubuntu-22.04 + timeout-minutes: 60 + env: + JAVA_HOME: /usr/lib/jvm/java-17-openjdk-amd64 + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + - name: Install dependencies + run: | + for i in 1 2 3; do sudo add-apt-repository -y ppa:nnstreamer/ppa && break || sleep 30; done + sudo apt-get update + sudo apt-get install -y meson ninja-build \ + libglib2.0-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libunwind-dev \ + gstreamer1.0-plugins-base gstreamer1.0-plugins-good \ + nnstreamer nnstreamer-dev nnstreamer-dev-internal nnstreamer-single-dev \ + openjdk-17-jdk-headless junit4 + - name: Build JNI wrapper + run: | + meson setup build -Djava-home=${JAVA_HOME} -Denable-test=false -Denable-ml-service=false + ninja -C build + - name: Run tests + run: | + bash java/test-nnstreamer-ubuntu.sh --ml_api_dir=${{ github.workspace }} --build_dir=build diff --git a/java/README.md b/java/README.md index e69de29b..e6a21a01 100644 --- a/java/README.md +++ b/java/README.md @@ -0,0 +1,20 @@ +# NNStreamer API for Java + +The Java API and its JNI wrapper for the Android API of NNStreamer. + +- `android/`: the Android library project. `android/nnstreamer/src/main/jni` is the + JNI wrapper, which is also built on Ubuntu by meson when `java-home` is given. +- `build-nnstreamer-android.sh`: build the Android library (AAR). Use + `--build_test=yes` to build the instrumented tests as well, and `--run_test=yes` + to run them on a connected device. +- `build-nnstreamer-ubuntu.sh`: build the Java API as a jar for Ubuntu. +- `test-nnstreamer-ubuntu.sh`: run the instrumented tests that do not require an + Android device on a desktop JVM, against the JNI wrapper built by meson. The + tests that cannot run on the host are listed in `host-test/exclude.txt`, and the + Android classes they use are stubbed in `host-test/stub`. + +``` +meson setup build -Djava-home=$JAVA_HOME -Denable-test=false -Denable-ml-service=false +ninja -C build +bash java/test-nnstreamer-ubuntu.sh --ml_api_dir=. --build_dir=build +``` diff --git a/java/host-test/exclude.txt b/java/host-test/exclude.txt new file mode 100644 index 00000000..39ce9c56 --- /dev/null +++ b/java/host-test/exclude.txt @@ -0,0 +1,22 @@ +# Instrumented tests that cannot run on the host, one per line: Class#method or Class. +# An entry that does not match any test fails the run, remove it with the test. + +# Android application context is not checked on the host (@BUILD_ANDROID@). +org.nnsuite.nnstreamer.APITestCommon#testInitWithInvalidCtx_n + +# amcsrc is an Android element. +org.nnsuite.nnstreamer.APITestPipeline#testAvailableElement +org.nnsuite.nnstreamer.APITestPipeline#testAMCsrc + +# The video sink renders to an Android native window; glimagesink needs a display. +# Without one the pipeline does not start, so the negative cases below would pass +# on the failure of start() rather than on the call they are written for. +org.nnsuite.nnstreamer.APITestPipeline#testSetNullSurface +org.nnsuite.nnstreamer.APITestPipeline#testSetSurfaceNullName_n +org.nnsuite.nnstreamer.APITestPipeline#testSetSurfaceEmptyName_n +org.nnsuite.nnstreamer.APITestPipeline#testSetInvalidSurface_n + +# Test assets (image, model) are copied from the Android test package. +org.nnsuite.nnstreamer.APITestPipeline#testAppsrcPng +org.nnsuite.nnstreamer.APITestSingleShot#testOptionsUnknownFW_n +org.nnsuite.nnstreamer.APITestSingleShot#testOptionsInvalidFW_n diff --git a/java/host-test/src/org/nnsuite/nnstreamer/HostTestRunner.java b/java/host-test/src/org/nnsuite/nnstreamer/HostTestRunner.java new file mode 100644 index 00000000..30fa431d --- /dev/null +++ b/java/host-test/src/org/nnsuite/nnstreamer/HostTestRunner.java @@ -0,0 +1,111 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * NNStreamer Android API host test + * Copyright (C) 2026 Samsung Electronics Co., Ltd. + */ + +package org.nnsuite.nnstreamer; + +import org.junit.internal.TextListener; +import org.junit.runner.Description; +import org.junit.runner.JUnitCore; +import org.junit.runner.Request; +import org.junit.runner.Result; +import org.junit.runner.manipulation.Filter; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * Runs the instrumented test classes on a desktop JVM, skipping the tests listed in an exclude file. + * + * Usage: HostTestRunner (exclude file) (test class name)... + * + * Each line of the exclude file is a class name, or a class name and a method name joined + * with '#'. Text after '#' at the start of a line or after whitespace is a comment. + * An entry that does not match any test fails the run, so that the list stays accurate. + */ +public final class HostTestRunner { + private static Set readExcludeFile(String path) throws IOException { + Set entries = new HashSet<>(); + + for (String line : Files.readAllLines(Paths.get(path), StandardCharsets.UTF_8)) { + int comment = line.indexOf(" #"); + String entry = (comment >= 0 ? line.substring(0, comment) : line).trim(); + + if (!entry.isEmpty() && !entry.startsWith("#")) { + entries.add(entry); + } + } + + return entries; + } + + public static void main(String[] args) throws Exception { + if (args.length < 2) { + System.err.println("Usage: HostTestRunner ..."); + System.exit(2); + } + + final Set excluded = readExcludeFile(args[0]); + final Set matched = new HashSet<>(); + List> classes = new ArrayList<>(); + + for (int i = 1; i < args.length; i++) { + Class klass = Class.forName(args[i]); + + if (excluded.contains(klass.getName())) { + matched.add(klass.getName()); + System.out.println("Excluded class " + klass.getName()); + } else { + classes.add(klass); + } + } + + Filter filter = new Filter() { + @Override + public boolean shouldRun(Description description) { + if (!description.isTest()) { + return true; + } + + String name = description.getClassName() + "#" + description.getMethodName(); + + if (excluded.contains(name)) { + matched.add(name); + return false; + } + + return true; + } + + @Override + public String describe() { + return "exclude tests listed in " + args[0]; + } + }; + + JUnitCore core = new JUnitCore(); + core.addListener(new TextListener(System.out)); + + Result result = core.run(Request.classes(classes.toArray(new Class[0])).filterWith(filter)); + boolean success = result.wasSuccessful(); + + System.out.println("Excluded " + (matched.size()) + " entries."); + + for (String entry : excluded) { + if (!matched.contains(entry)) { + System.out.println("Exclude entry does not match any test: " + entry); + success = false; + } + } + + System.exit(success ? 0 : 1); + } +} diff --git a/java/host-test/stub/android/content/Context.java b/java/host-test/stub/android/content/Context.java new file mode 100644 index 00000000..68ceeb9a --- /dev/null +++ b/java/host-test/stub/android/content/Context.java @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * NNStreamer Android API host test + * Copyright (C) 2026 Samsung Electronics Co., Ltd. + */ + +package android.content; + +import android.content.res.AssetManager; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; + +/** + * Host stub of android.content.Context for running the instrumented tests on a desktop JVM. + * The files directory is a temporary directory, and the assets are empty. + */ +public class Context { + private final File mFilesDir; + private final AssetManager mAssets = new AssetManager(); + + public Context() { + try { + mFilesDir = Files.createTempDirectory("nns-host-test").toFile(); + mFilesDir.deleteOnExit(); + } catch (IOException e) { + throw new IllegalStateException("Failed to create the files directory", e); + } + } + + public AssetManager getAssets() { + return mAssets; + } + + public File getFilesDir() { + return mFilesDir; + } + + public String getPackageName() { + return "org.nnsuite.nnstreamer.test"; + } +} diff --git a/java/host-test/stub/android/content/res/AssetManager.java b/java/host-test/stub/android/content/res/AssetManager.java new file mode 100644 index 00000000..6e668ab3 --- /dev/null +++ b/java/host-test/stub/android/content/res/AssetManager.java @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * NNStreamer Android API host test + * Copyright (C) 2026 Samsung Electronics Co., Ltd. + */ + +package android.content.res; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; + +/** + * Host stub of android.content.res.AssetManager. The host test has no assets. + */ +public final class AssetManager { + public String[] list(String path) throws IOException { + return null; + } + + public InputStream open(String fileName) throws IOException { + throw new FileNotFoundException(fileName); + } +} diff --git a/java/host-test/stub/android/os/Build.java b/java/host-test/stub/android/os/Build.java new file mode 100644 index 00000000..b09b2cac --- /dev/null +++ b/java/host-test/stub/android/os/Build.java @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * NNStreamer Android API host test + * Copyright (C) 2026 Samsung Electronics Co., Ltd. + */ + +package android.os; + +/** + * Host stub of android.os.Build. + */ +public final class Build { + public static final String HARDWARE = "host"; + public static final String MANUFACTURER = "host"; + + public static final class VERSION { + public static final int SDK_INT = 0; + } +} diff --git a/java/host-test/stub/android/support/test/InstrumentationRegistry.java b/java/host-test/stub/android/support/test/InstrumentationRegistry.java new file mode 100644 index 00000000..78c71c52 --- /dev/null +++ b/java/host-test/stub/android/support/test/InstrumentationRegistry.java @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * NNStreamer Android API host test + * Copyright (C) 2026 Samsung Electronics Co., Ltd. + */ + +package android.support.test; + +import android.content.Context; + +/** + * Host stub of android.support.test.InstrumentationRegistry. + */ +public final class InstrumentationRegistry { + private static Context sContext; + + public static synchronized Context getTargetContext() { + if (sContext == null) { + sContext = new Context(); + } + + return sContext; + } +} diff --git a/java/host-test/stub/android/support/test/runner/AndroidJUnit4.java b/java/host-test/stub/android/support/test/runner/AndroidJUnit4.java new file mode 100644 index 00000000..de2feea1 --- /dev/null +++ b/java/host-test/stub/android/support/test/runner/AndroidJUnit4.java @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * NNStreamer Android API host test + * Copyright (C) 2026 Samsung Electronics Co., Ltd. + */ + +package android.support.test.runner; + +import org.junit.runners.BlockJUnit4ClassRunner; +import org.junit.runners.model.InitializationError; + +/** + * Host stub of android.support.test.runner.AndroidJUnit4, the plain JUnit 4 runner. + */ +public final class AndroidJUnit4 extends BlockJUnit4ClassRunner { + public AndroidJUnit4(Class klass) throws InitializationError { + super(klass); + } +} diff --git a/java/host-test/stub/android/view/Surface.java b/java/host-test/stub/android/view/Surface.java new file mode 100644 index 00000000..49829f81 --- /dev/null +++ b/java/host-test/stub/android/view/Surface.java @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * NNStreamer Android API host test + * Copyright (C) 2026 Samsung Electronics Co., Ltd. + */ + +package android.view; + +/** + * Host stub of android.view.Surface. A host surface is never valid. + */ +public final class Surface { + public boolean isValid() { + return false; + } +} diff --git a/java/host-test/stub/android/view/SurfaceHolder.java b/java/host-test/stub/android/view/SurfaceHolder.java new file mode 100644 index 00000000..99644ea7 --- /dev/null +++ b/java/host-test/stub/android/view/SurfaceHolder.java @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * NNStreamer Android API host test + * Copyright (C) 2026 Samsung Electronics Co., Ltd. + */ + +package android.view; + +/** + * Host stub of android.view.SurfaceHolder. + */ +public interface SurfaceHolder { + Surface getSurface(); +} diff --git a/java/host-test/stub/android/view/SurfaceView.java b/java/host-test/stub/android/view/SurfaceView.java new file mode 100644 index 00000000..297953ae --- /dev/null +++ b/java/host-test/stub/android/view/SurfaceView.java @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * NNStreamer Android API host test + * Copyright (C) 2026 Samsung Electronics Co., Ltd. + */ + +package android.view; + +import android.content.Context; + +/** + * Host stub of android.view.SurfaceView. + */ +public class SurfaceView { + private final Surface mSurface = new Surface(); + + public SurfaceView(Context context) { + } + + public SurfaceHolder getHolder() { + return new SurfaceHolder() { + @Override + public Surface getSurface() { + return mSurface; + } + }; + } +} diff --git a/java/test-nnstreamer-ubuntu.sh b/java/test-nnstreamer-ubuntu.sh new file mode 100755 index 00000000..f959ca1d --- /dev/null +++ b/java/test-nnstreamer-ubuntu.sh @@ -0,0 +1,150 @@ +#!/usr/bin/env bash + +## +## SPDX-License-Identifier: Apache-2.0 +## +# @file test-nnstreamer-ubuntu.sh +# @brief A script to run the Android instrumented tests of NNStreamer API on Ubuntu +# +# The JNI wrapper is the same code as Android. This script builds the Java API with +# the host stubs in java/host-test, and runs the instrumented tests on a desktop JVM +# against the JNI wrapper built by meson (-Djava-home). +# +# The following comments that start with '##@@' are for the generation of usage messages. +##@@ Test script for NNStreamer API Library on Ubuntu +##@@ - Before running this script, below variables must be set. +##@@ - JAVA_HOME: Path to JDK +##@@ - ML_API_ROOT: The source root directory of ML API +##@@ +##@@ usage: test-nnstreamer-ubuntu.sh [OPTIONS] +##@@ +##@@ basic options: +##@@ --help +##@@ display this help and exit +##@@ --java_home=(path to JDK) +##@@ This option overrides the JAVA_HOME variable +##@@ --ml_api_dir=(the_source_root_of_ml_api) +##@@ This option overrides the ML_API_ROOT variable +##@@ --build_dir=(meson build directory) +##@@ The meson build directory configured with -Djava-home +##@@ Default path is 'ml_api_dir/build' +##@@ --junit_classpath=(class path of JUnit 4 and Hamcrest) +##@@ Default is '/usr/share/java/junit4.jar:/usr/share/java/hamcrest-core.jar' +##@@ +##@@ For example, to run the tests with the default meson build directory +##@@ ./test-nnstreamer-ubuntu.sh --java_home=/usr/lib/jvm/java-17-openjdk-amd64 + +# Find '--help' in the given arguments +arg_help="--help" +for arg in "$@"; do + if [[ ${arg} == "${arg_help}" ]]; then + sed -ne 's/^##@@ \(.*\)/\1/p' "$0" && exit 1 + fi +done + +junit_classpath="/usr/share/java/junit4.jar:/usr/share/java/hamcrest-core.jar" + +# Parse args +for arg in "$@"; do + case ${arg} in + --java_home=*) + java_home=${arg#*=} + ;; + --ml_api_dir=*) + ml_api_dir=${arg#*=} + ;; + --build_dir=*) + build_dir=${arg#*=} + ;; + --junit_classpath=*) + junit_classpath=${arg#*=} + ;; + esac +done + +# Java home +if [[ -z "${java_home}" ]]; then + [ -z "${JAVA_HOME}" ] && echo "Need to set JAVA_HOME." && exit 1 + java_home=${JAVA_HOME} +fi + +echo "Java home: ${java_home}" + +# ML API root directory +if [[ -z "${ml_api_dir}" ]]; then + [ -z "${ML_API_ROOT}" ] && echo "Need to set ML_API_ROOT." && exit 1 + ml_api_dir=${ML_API_ROOT} +fi + +ml_api_dir=$(realpath "${ml_api_dir}") +echo "ML API root directory: ${ml_api_dir}" + +# Meson build directory +if [[ -z "${build_dir}" ]]; then + build_dir=${ml_api_dir}/build +fi + +build_dir=$(realpath "${build_dir}") +native_lib_dir=${build_dir}/java + +if [[ ! -f ${native_lib_dir}/libnnstreamer-native.so ]]; then + echo "Cannot find ${native_lib_dir}/libnnstreamer-native.so, configure meson with -Djava-home and build first." + exit 1 +fi + +java_src_dir=${ml_api_dir}/java/android/nnstreamer/src +host_test_dir=${ml_api_dir}/java/host-test + +work_dir=$(mktemp -d) +trap 'rm -rf "${work_dir}"' EXIT + +src_dir=${work_dir}/src/org/nnsuite/nnstreamer +class_dir=${work_dir}/classes +mkdir -p "${src_dir}" "${class_dir}" + +# Java API, same as build-nnstreamer-ubuntu.sh +cp "${java_src_dir}"/main/java/org/nnsuite/nnstreamer/*.java "${src_dir}" +sed -i "s|android.content.Context|Object|" "${src_dir}"/*.java +sed -i "s|android.view.Surface|Object|" "${src_dir}"/*.java +sed -i "s|@BUILD_ANDROID@|//|" "${src_dir}"/*.java + +# The host build does not include ml-service. +rm -f "${src_dir}/MLService.java" + +# Instrumented tests and host runner +test_files=() +for file in "${java_src_dir}"/androidTest/java/org/nnsuite/nnstreamer/APITest*.java; do + name=$(basename "${file}" .java) + [[ ${name} == "APITestMLService" ]] && continue + cp "${file}" "${src_dir}" + test_files+=("org.nnsuite.nnstreamer.${name}") +done + +cp "${host_test_dir}"/src/org/nnsuite/nnstreamer/*.java "${src_dir}" + +echo "Compiling the Java API and the tests." +find "${host_test_dir}/stub" "${work_dir}/src" -name "*.java" > "${work_dir}/sources.txt" + +if ! "${java_home}/bin/javac" -encoding UTF-8 -nowarn -d "${class_dir}" \ + -cp "${junit_classpath}" "@${work_dir}/sources.txt"; then + echo "Failed to compile the tests." + exit 1 +fi + +echo "Running the tests." +export LD_LIBRARY_PATH=${build_dir}/c/src${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}} + +"${java_home}/bin/java" \ + -XX:ErrorFile="${work_dir}/hs_err_pid%p.log" \ + -Djava.library.path="${native_lib_dir}" \ + -cp "${class_dir}:${junit_classpath}" \ + org.nnsuite.nnstreamer.HostTestRunner "${host_test_dir}/exclude.txt" "${test_files[@]}" +test_res=$? + +# Show the native stack if the JVM has crashed. +for file in "${work_dir}"/hs_err_pid*.log; do + [[ -f ${file} ]] && sed -n '1,/^Java frames/p' "${file}" +done + +# exit with success/failure status +exit ${test_res} From 29fe7e673d1cb23c613cb33382b6518e82be87a5 Mon Sep 17 00:00:00 2001 From: MyungJoo Ham Date: Tue, 15 Sep 2026 15:59:00 +0900 Subject: [PATCH 2/2] [Android] build the instrumented tests in the x86_64 build Nothing builds the instrumented tests, so a change in the Java API or in a test that breaks their compilation goes unnoticed, including the tests that the Ubuntu job has to exclude. Add --build_test to build-nnstreamer-android.sh, which runs assembleDebugAndroidTest after the library is built, and enable it for the x86_64 Android build in CI. Other ABIs build the same Java code, so one ABI is enough. Signed-off-by: MyungJoo Ham Co-Authored-By: Claude Opus 5 --- .github/actions/android-build/action.yml | 2 +- java/build-nnstreamer-android.sh | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/.github/actions/android-build/action.yml b/.github/actions/android-build/action.yml index 7050e5a9..fca751a6 100644 --- a/.github/actions/android-build/action.yml +++ b/.github/actions/android-build/action.yml @@ -80,7 +80,7 @@ runs: if [ ${TARGET_ABI} == 'arm64-v8a' ]; then bash ${{ github.workspace }}/java/build-nnstreamer-android.sh --target_abi=${TARGET_ABI} --enable_nnfw=yes --build_type=${BUILD_TYPE} --enable_mqtt=yes --enable_ml_offloading=yes --enable_ml_service=yes --enable_llamacpp=yes elif [ ${TARGET_ABI} == 'x86_64' ]; then - bash ${{ github.workspace }}/java/build-nnstreamer-android.sh --target_abi=${TARGET_ABI} --enable_nnfw=no --build_type=${BUILD_TYPE} + bash ${{ github.workspace }}/java/build-nnstreamer-android.sh --target_abi=${TARGET_ABI} --enable_nnfw=no --build_type=${BUILD_TYPE} --build_test=yes else bash ${{ github.workspace }}/java/build-nnstreamer-android.sh --target_abi=${TARGET_ABI} --enable_nnfw=no --enable_tflite=no --build_type=${BUILD_TYPE} fi diff --git a/java/build-nnstreamer-android.sh b/java/build-nnstreamer-android.sh index 7ba73d72..71e37582 100755 --- a/java/build-nnstreamer-android.sh +++ b/java/build-nnstreamer-android.sh @@ -30,6 +30,9 @@ ##@@ 'internal' : no plugins except for enable single-shot only, enable NNFW only ##@@ --target_abi=(armeabi-v7a|arm64-v8a) ##@@ 'arm64-v8a' is the default Android ABI +##@@ --build_test=(yes|no) +##@@ 'yes' : build instrumentation test after build procedure is done +##@@ 'no' : [default] ##@@ --run_test=(yes|no) ##@@ 'yes' : run instrumentation test after build procedure is done ##@@ 'no' : [default] @@ -128,6 +131,9 @@ include_assets="no" # Set target ABI ('armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64') target_abi="arm64-v8a" +# Build instrumentation test after build procedure is done +build_test="no" + # Run instrumentation test after build procedure is done run_test="no" @@ -212,6 +218,9 @@ for arg in "$@"; do --target_abi=*) target_abi=${arg#*=} ;; + --build_test=*) + build_test=${arg#*=} + ;; --run_test=*) run_test=${arg#*=} ;; @@ -794,6 +803,13 @@ chmod +x gradlew sh ./gradlew nnstreamer:build android_lib_build_res=$? +# Build instrumentation test if build procedure is done. +if [[ ${android_lib_build_res} -eq 0 && ${build_test} == "yes" ]]; then + echo "Build instrumentation test." + sh ./gradlew nnstreamer:assembleDebugAndroidTest + android_lib_build_res=$? +fi + # Run instrumentation test if build procedure is done. if [[ ${android_lib_build_res} -eq 0 ]]; then if [[ ${run_test} == "yes" ]]; then