--- /dev/null
+#!/usr/bin/env bash
+
+EXECUTION_DIR=$(dirname $0)
+TEST_NAME=$1
+TARGET_ARCH=$2
+
+APK=$EXECUTION_DIR/Bundle/bin/$TEST_NAME.apk
+
+# it doesn't support parallel execution yet, so, here is a hand-made semaphore:
+LOCKDIR=/tmp/androidtests.lock
+while true; do
+ if mkdir "$LOCKDIR"
+ then
+ trap 'rm -rf "$LOCKDIR"' 0
+ break
+ else
+ sleep 5
+ fi
+done
+
+
+## XHarness doesn't support macOS/Linux yet (in progress) so we'll use a hand-made adb script
+# dotnet xharness android test -i="net.dot.MonoRunner" \
+# --package-name="net.dot.$TEST_NAME" \
+# --app=$APK -o=$EXECUTION_DIR/Bundle/TestResults -v
+
+ADB=$ANDROID_SDK_ROOT/platform-tools/adb
+echo "Installing net.dot.$TEST_NAME on an active device/emulator..."
+$ADB uninstall net.dot.$TEST_NAME > /dev/null 2>&1 || true
+$ADB install "$APK"
+echo "Running tests for $TEST_NAME (see live logs via logcat)..."
+$ADB shell am instrument -w net.dot.$TEST_NAME/net.dot.MonoRunner
+echo "Finished. See logcat for details, e.g. '$ADB logcat DOTNET:V -s'"
<RunScriptInputName Condition="'$(TargetOS)' == 'Windows_NT'">RunnerTemplate.cmd</RunScriptInputName>
<RunScriptInputName Condition="'$(TargetOS)' != 'Windows_NT'">RunnerTemplate.sh</RunScriptInputName>
- <RunScriptInputName Condition="'$(TargetOS)' == 'iOS'">MobileRunnerTemplate.sh</RunScriptInputName>
+ <RunScriptInputName Condition="'$(TargetOS)' == 'iOS'">AppleRunnerTemplate.sh</RunScriptInputName>
+ <RunScriptInputName Condition="'$(TargetOS)' == 'Android'">AndroidRunnerTemplate.sh</RunScriptInputName>
<RunScriptInputPath>$(MSBuildThisFileDirectory)$(RunScriptInputName)</RunScriptInputPath>
<PropertyGroup>
<RunTestsCommand>"$(RunScriptOutputPath)" --runtime-path "$(TestHostRootPath.TrimEnd('\/'))"</RunTestsCommand>
<RunTestsCommand Condition="'$(TestRspFile)' != '' and '$(RuntimeFlavor)' != 'Mono'">$(RunTestsCommand) --rsp-file "$(TestRspFile)"</RunTestsCommand>
- <RunTestsCommand Condition="'$(TargetOS)'=='iOS'">"$(RunScriptOutputPath)" $(AssemblyName) $(TargetArchitecture)</RunTestsCommand>
+ <RunTestsCommand Condition="'$(TargetsMobile)'">"$(RunScriptOutputPath)" $(AssemblyName) $(TargetArchitecture)</RunTestsCommand>
</PropertyGroup>
<!-- Invoke the run script with the test host as the runtime path. -->
<Output TaskParameter="ApkPackageId" PropertyName="ApkPackageId" />
<Output TaskParameter="ApkBundlePath" PropertyName="ApkBundlePath" />
</AndroidAppBuilderTask>
- <Message Importance="High" Text="PackageId: $(ApkPackageId)"/>
- <Message Importance="High" Text="Apk: $(ApkBundlePath)"/>
+ <Message Importance="High" Text="PackageId: $(ApkPackageId)"/>
+ <Message Importance="High" Text="Instrumentation: net.dot.MonoRunner"/>
+ <Message Importance="High" Text="Apk: $(ApkBundlePath)"/>
</Target>
<!-- Generate a self-contained app bundle for iOS with tests.
public override unsafe void Write(byte[] buffer, int offset, int count)
{
string log = ConsolePal.OutputEncoding.GetString(buffer, offset, count);
- Interop.Logcat.AndroidLogPrint(Interop.Logcat.LogLevel.Info, null, log);
+ Interop.Logcat.AndroidLogPrint(Interop.Logcat.LogLevel.Info, "DOTNET", log);
}
}
a:versionName="1.0">
<uses-sdk a:minSdkVersion="%MinSdkLevel%" />
<uses-permission a:name="android.permission.INTERNET"/>
+ <uses-permission a:name="android.permission.READ_EXTERNAL_STORAGE"/>
+ <uses-permission a:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application a:label="%PackageName%"
a:largeHeap="true">
<activity a:name="net.dot.MainActivity">
import android.view.View;
import android.app.Activity;
import android.os.Bundle;
+import android.os.Environment;
import java.io.File;
import java.io.FileNotFoundException;
Context context = getContext();
AssetManager am = context.getAssets();
String filesDir = context.getFilesDir().getAbsolutePath();
- String cacheDir = context.getCacheDir().getAbsolutePath ();
+ String cacheDir = context.getCacheDir().getAbsolutePath();
+ String docsDir = context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS).getAbsolutePath();
copyAssetDir(am, "", filesDir);
- // retcode is what Main() returns in C#
- int retcode = initRuntime(filesDir, cacheDir);
- WriteLineToInstrumentation("[Mono] Main() returned " + retcode);
- runOnMainSync (new Runnable() {
+ int retcode = initRuntime(filesDir, cacheDir, docsDir);
+ runOnMainSync(new Runnable() {
public void run() {
- finish (retcode, null);
+ Bundle result = new Bundle();
+ result.putInt("return-code", retcode);
+ // Xharness cli expects "test-results-path" with test results
+ result.putString("test-results-path", docsDir + "/testResults.xml");
+ finish(retcode, result);
}
});
}
-
- static void WriteLineToInstrumentation(String line) {
- Bundle b = new Bundle();
- b.putString(Instrumentation.REPORT_KEY_STREAMRESULT, line + "\n");
- MonoRunner.inst.sendStatus(0, b);
- }
static void copyAssetDir(AssetManager am, String path, String outpath) {
try {
String toFile = outpath + "/" + res[i];
try {
InputStream fromStream = am.open(fromFile);
- Log.w("MONO", "\tCOPYING " + fromFile + " to " + toFile);
+ Log.w("DOTNET", "\tCOPYING " + fromFile + " to " + toFile);
copy(fromStream, new FileOutputStream(toFile));
} catch (FileNotFoundException e) {
new File(toFile).mkdirs();
}
}
catch (Exception e) {
- Log.w("MONO", "EXCEPTION", e);
+ Log.w("DOTNET", "EXCEPTION", e);
}
}
out.close();
}
- native int initRuntime(String libsDir, String cacheDir);
+ native int initRuntime(String libsDir, String cacheDir, String docsDir);
}
static char *bundle_path;
-#define LOG_INFO(fmt, ...) __android_log_print(ANDROID_LOG_DEBUG, "MONO", fmt, ##__VA_ARGS__)
-#define LOG_ERROR(fmt, ...) __android_log_print(ANDROID_LOG_ERROR, "MONO", fmt, ##__VA_ARGS__)
+#define LOG_INFO(fmt, ...) __android_log_print(ANDROID_LOG_DEBUG, "DOTNET", fmt, ##__VA_ARGS__)
+#define LOG_ERROR(fmt, ...) __android_log_print(ANDROID_LOG_ERROR, "DOTNET", fmt, ##__VA_ARGS__)
static MonoAssembly*
load_assembly (const char *name, const char *culture)
}
int
-Java_net_dot_MonoRunner_initRuntime (JNIEnv* env, jobject thiz, jstring j_files_dir, jstring j_cache_dir)
+Java_net_dot_MonoRunner_initRuntime (JNIEnv* env, jobject thiz, jstring j_files_dir, jstring j_cache_dir, jstring j_docs_dir)
{
char file_dir[2048];
char cache_dir[2048];
+ char docs_dir[2048];
strncpy_str (env, file_dir, j_files_dir, sizeof(file_dir));
strncpy_str (env, cache_dir, j_cache_dir, sizeof(cache_dir));
+ strncpy_str (env, docs_dir, j_docs_dir, sizeof(docs_dir));
bundle_path = file_dir;
setenv ("HOME", bundle_path, true);
setenv ("TMPDIR", cache_dir, true);
+ setenv ("DOCSDIR", docs_dir, true);
return mono_mobile_runtime_init ();
}
}
}
- protected override void TerminateWithSuccess()
- {
- Console.WriteLine("[TerminateWithSuccess]");
- }
+ protected override void TerminateWithSuccess() {}
private int? _maxParallelThreads;
public override TextWriter? Logger => null;
- public override string TestsResultsFinalPath =>
- Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "testResults.xml");
+ public override string TestsResultsFinalPath
+ {
+ get
+ {
+ string? publicDir = Environment.GetEnvironmentVariable("DOCSDIR");
+ if (string.IsNullOrEmpty(publicDir))
+ throw new ArgumentException("DOCSDIR should not be empty");
+
+ return Path.Combine(publicDir, "testResults.xml");
+ }
+ }
}