[tests] Run .apk unit tests and collect TestResults.xml (#305)

What do we want? Execution of unit tests!

When do we want it? Uh...4 months ago?

The `Xamarin.Android.NUnitLite` assembly allows writing NUnit-based
unit tests that execute on-device, and the `Mono.Android-Tests.csproj`
project contains a number of such unit tests.

The problem is that these unit tests aren't executed as part of the
Jenkins build process, so there's no way to know if a given commit
actually breaks anything.

In short, the existence of those unit tests is meaningless.

The task, then, is to fix the `make run-all-tests` target so that it
runs on-device unit tests...on an Android device.

Which raises all manner of problems. :-) (Hence 4+ months!)

For starters, our internal tooling is a horrible mish-mash of make(1),
ruby(1), bash(1), which creates an emulator, launches it, installs the
test .apk onto the emulator, and runs the tests. I don't want all of
that "cruft" in this repo, which means it needs to be rewritten in a
form more amenable to this repo: MSBuild tasks....and some make(1).

:-)

Add a new `build-tools/scripts/UnitTestApks.targets` file, which will
process an `@(UnitTestApk)` Item Group to permit deploying, running,
and undeploying test .apks from an attached Android device.

Add a slew of MSBuild tasks to support `@(UnitTestApk)`.

Update the default `$(AndroidSupportedTargetJitAbis)` value to be
`armeabi-v7a:x86`. The created Android emulator is x86.
This commit is contained in:
Jonathan Pryor 2016-11-21 15:44:37 -05:00 коммит произвёл Dean Ellis
Родитель 908f56d6fb
Коммит 48e3fc2672
26 изменённых файлов: 956 добавлений и 114 удалений

1
.gitignore поставляемый
Просмотреть файл

@ -8,3 +8,4 @@ packages
.DS_Store
.nuget
TestResult.xml
TestResult-*.xml

Просмотреть файл

@ -38,7 +38,7 @@
<AndroidSdkDirectory>$(AndroidToolchainDirectory)\sdk</AndroidSdkDirectory>
<AndroidNdkDirectory>$(AndroidToolchainDirectory)\ndk</AndroidNdkDirectory>
<AndroidSupportedHostJitAbis Condition=" '$(AndroidSupportedHostJitAbis)' == '' ">$(HostOS)</AndroidSupportedHostJitAbis>
<AndroidSupportedTargetJitAbis Condition=" '$(AndroidSupportedTargetJitAbis)' == '' ">armeabi-v7a</AndroidSupportedTargetJitAbis>
<AndroidSupportedTargetJitAbis Condition=" '$(AndroidSupportedTargetJitAbis)' == '' ">armeabi-v7a:x86</AndroidSupportedTargetJitAbis>
<JavaInteropSourceDirectory Condition=" '$(JavaInteropSourceDirectory)' == '' ">$(MSBuildThisFileDirectory)external\Java.Interop</JavaInteropSourceDirectory>
<LlvmSourceDirectory Condition=" '$(LlvmSourceDirectory)' == '' ">$(MSBuildThisFileDirectory)external\llvm</LlvmSourceDirectory>
<MonoSourceDirectory>$(MSBuildThisFileDirectory)external\mono</MonoSourceDirectory>
@ -70,6 +70,14 @@
<LibZipSourceFullPath>$([System.IO.Path]::GetFullPath ('$(LibZipSourceDirectory)'))</LibZipSourceFullPath>
<LibZipSharpSourceFullPath>$([System.IO.Path]::GetFullPath ('$(LibZipSharpSourceDirectory)'))</LibZipSharpSourceFullPath>
</PropertyGroup>
<PropertyGroup>
<AdbToolPath Condition=" '$(AdbToolPath)' == '' ">$(AndroidSdkFullPath)\platform-tools</AdbToolPath>
<AdbToolExe Condition=" '$(AdbToolExe)' == '' ">adb</AdbToolExe>
<AndroidToolPath Condition=" '$(AndroidToolPath)' == '' ">$(AndroidSdkFullPath)\tools</AndroidToolPath>
<AndroidToolExe Condition=" '$(AndroidToolExe)' == '' ">android</AndroidToolExe>
<EmulatorToolPath Condition=" '$(EmulatorToolPath)' == '' ">$(AndroidSdkFullPath)\tools</EmulatorToolPath>
<EmulatorToolExe Condition=" '$(EmulatorToolExe)' == '' ">emulator</EmulatorToolExe>
</PropertyGroup>
<!--
"Fixup" $(AndroidSupportedHostJitAbis) so that Condition attributes elsewhere
can use `:ABI-NAME:`, to avoid substring mismatches.

Просмотреть файл

@ -0,0 +1,77 @@
# Development Tips
Tips and tricks while developing Xamarin.Android.
# How do I rebuild the Mono Runtime and Native Binaries?
The various Mono runtimes -- over *20* of them (!) -- all store object code
within `build-tools/mono-runtimes/obj/$(Configuration)/TARGET`.
If you change sources within `external/mono`, a top-level `make`/`xbuild`
invocation may not rebuild those mono native binaries. To explicitly rebuild
*all* Mono runtimes, use the `ForceBuild` target:
# Build and install all runtimes
$ xbuild /t:ForceBuild build-tools/mono-runtimes/mono-runtimes.mdproj
To build Mono for a specific target, run `make` from the relevant directory
and invoke the `_InstallRuntimes` target. For example, to rebuild
Mono for armeabi-v7a:
$ cd build-tools/mono-runtimes
$ make -C obj/Debug/armeabi-v7a
# This updates bin/$(Configuration)/lib/xbuild/Xamarin/Android/lib/armeabi-v7a/libmonosgen-2.0.so
$ xbuild /t:_InstallRuntimes
# How do I rebuild BCL assemblies?
The Xamarin.Android Base Class Library assemblies, such as `mscorlib.dll`,
are built within `external/mono`, using Mono's normal build system:
# This updates external/mono/mcs/class/lib/monodroid/ASSEMBLY.dll
$ make -C external/mono/mcs/class/ASSEMBLY PROFILE=monodroid
Alternatively, if you want to rebuild *all* the assemblies, the "host"
Mono needs to be rebuilt. Note that the name of the "host" directory
varies based on the operating system you're building from:
$ make -C build-tools/mono-runtimes/obj/Debug/host-Darwin
Once the assemblies have been rebuilt, they can be copied into the appropriate
Xamarin.Android SDK directory by using the `_InstallBcl` target:
# This updates bin/$(Configuration)/lib/xbuild-frameworks/MonoAndroid/v1.0/ASSEMBLY.dll
$ xbuild build-tools/mono-runtimes/mono-runtimes.mdproj /t:_InstallBcl
# Testing Updated Assemblies
The `xamarin-android` repo does not support [fast deployment][fastdep],
which means that, *normally*, if you wanted to e.g. test a fix within
`Mono.Android.dll` you would need to:
[fastdev]: https://developer.xamarin.com/guides/android/under_the_hood/build_process/#Fast_Deployment
1. Build `src/Mono.Android/Mono.Android.csproj`
2. Rebuild your test project, e.g.
`src/Mono.Android/Test/Mono.Android-Tests.csproj`
3. Reinstall the test project
4. Re-run the test project.
The resulting `.apk`s can be quite big, e.g.
`bin/TestDebug/Mono.Android_Tests-Signed.apk` is 59MB, so steps
(2) through (4) can be annoyingly time consuming.
Fortunately, a key part of fast deployment *is* part of the `xamarin-android`:
an "update directory" is created by `libmono-android*.so` during process
startup, in *non*-`RELEASE` builds. This directory is printed to `adb logcat`:
W/monodroid( 2796): Creating public update directory: `/data/data/Mono.Android_Tests/files/.__override__`
Assemblies located within the "update directory" are used *in preference to*
assemblies located within the executing `.apk`. Assemblies can be `adb push`ed
into the update directory:
adb push bin/Debug/lib/xbuild-frameworks/MonoAndroid/v7.1/Mono.Android.dll /data/data/Mono.Android_Tests/files/.__override__
When the process restarts the new assembly will be used.

Просмотреть файл

@ -25,7 +25,7 @@ all::
$(MSBUILD) $(MSBUILD_FLAGS) $(SOLUTION)
all-tests::
tools/scripts/xabuild $(MSBUILD_FLAGS) Xamarin.Android-Tests.sln
MSBUILD="$(MSBUILD)" tools/scripts/xabuild $(MSBUILD_FLAGS) Xamarin.Android-Tests.sln
prepare:: prepare-external prepare-props
@ -142,27 +142,25 @@ define RUN_NUNIT_TEST
$(RUNTIME) --runtime=v4.0.0 \
$(NUNIT_CONSOLE) $(NUNIT_EXTRA) $(1) \
$(if $(RUN),-run:$(RUN)) \
--result=TestResult-$(basename $(notdir $(1))).xml \
-output=bin/Test$(CONFIGURATION)/TestOutput-$(basename $(notdir $(1))).txt ;
endef
run-nunit-tests: $(NUNIT_TESTS)
$(foreach t,$(NUNIT_TESTS), $(call RUN_NUNIT_TEST,$(t),1))
# Test .apk projects must satisfy the following requirements:
# 1. They must have a UnDeploy target
# 2. They must have a Deploy target
# 3. They must have a RunTests target
# .apk files to test on-device need to:
# (1) Have their .csproj files listed here
# (2) Add a `@(UnitTestApk)` entry to `tests/RunApkTests.targets`
TEST_APK_PROJECTS = \
src/Mono.Android/Test/Mono.Android-Tests.csproj
# Syntax: $(call RUN_TEST_APK,path/to/project.csproj)
define RUN_TEST_APK
# Syntax: $(call BUILD_TEST_APK,path/to/project.csproj)
define BUILD_TEST_APK
# Must use xabuild to ensure correct assemblies are resolved
tools/scripts/xabuild /t:SignAndroidPackage $(1) && \
$(MSBUILD) $(MSBUILD_FLAGS) /t:UnDeploy $(1) && \
$(MSBUILD) $(MSBUILD_FLAGS) /t:Deploy $(1) && \
$(MSBUILD) $(MSBUILD_FLAGS) /t:RunTests $(1) $(if $(ADB_TARGET),"/p:AdbTarget=$(ADB_TARGET)",)
endef
MSBUILD="$(MSBUILD)" tools/scripts/xabuild /t:SignAndroidPackage $(1)
endef # BUILD_TEST_APK
run-apk-tests:
$(foreach p, $(TEST_APK_PROJECTS), $(call RUN_TEST_APK, $(p)))
$(foreach p, $(TEST_APK_PROJECTS), $(call BUILD_TEST_APK, $(p)))
$(MSBUILD) $(MSBUILD_FLAGS) tests/RunApkTests.targets

Просмотреть файл

@ -290,44 +290,4 @@ We use [Bugzilla](https://bugzilla.xamarin.com/enter_bug.cgi?product=Android) to
# Maintainer FAQ
## How do I rebuild the Mono Runtime and Native Binaries?
The various Mono runtimes -- over *20* of them (!) -- all store object code
within `build-tools/mono-runtimes/obj/$(Configuration)/TARGET`.
If you change sources within `external/mono`, a top-level `make`/`xbuild`
invocation may not rebuild those mono native binaries. To explicitly rebuild
*all* Mono runtimes, use the `ForceBuild` target:
# Build and install all runtimes
$ xbuild /t:ForceBuild build-tools/mono-runtimes/mono-runtimes.mdproj
To build Mono for a specific target, run `make` from the relevant directory
and invoke the `_InstallRuntimes` target. For example, to rebuild
Mono for armeabi-v7a:
$ cd build-tools/mono-runtimes
$ make -C obj/Debug/armeabi-v7a
# This updates bin/$(Configuration)/lib/xbuild/Xamarin/Android/lib/armeabi-v7a/libmonosgen-2.0.so
$ xbuild /t:_InstallRuntimes
## How do I rebuild BCL assemblies?
The Xamarin.Android Base Class Library assemblies, such as `mscorlib.dll`,
are built within `external/mono`, using Mono's normal build system:
# This updates external/mono/mcs/class/lib/monodroid/ASSEMBLY.dll
$ make -C external/mono/mcs/class/ASSEMBLY PROFILE=monodroid
Alternatively, if you want to rebuild *all* the assemblies, the "host"
Mono needs to be rebuilt. Note that the name of the "host" directory
varies based on the operating system you're building from:
$ make -C build-tools/mono-runtimes/obj/Debug/host-Darwin
Once the assemblies have been rebuilt, they can be copied into the appropriate
Xamarin.Android SDK directory by using the `_InstallBcl` target:
# This updates bin/$(Configuration)/lib/xbuild-frameworks/MonoAndroid/v1.0/ASSEMBLY.dll
$ xbuild build-tools/mono-runtimes/mono-runtimes.mdproj /t:_InstallBcl
See [DevelopmentTips.md](Documentation/DevelopmentTips.md).

Просмотреть файл

@ -86,6 +86,11 @@
<HostOS></HostOS>
<DestDir>extras\android\m2repository</DestDir>
</AndroidSdkItem>
<AndroidSdkItem Include="sysimg_x86-21_r03.zip">
<HostOS></HostOS>
<RelUrl>sys-img/android/</RelUrl>
<DestDir>system-images\android-21\x86</DestDir>
</AndroidSdkItem>
</ItemGroup>
<ItemGroup>
<_NdkToolchain Include="arm-linux-androideabi-clang" Condition="$(AndroidSupportedTargetJitAbisForConditionalChecks.Contains(':armeabi:')) Or $(AndroidSupportedTargetJitAbisForConditionalChecks.Contains(':armeabi-v7a:')) Or $(AndroidSupportedTargetAotAbisForConditionalChecks.Contains (':win-armeabi:'))">

Просмотреть файл

@ -32,7 +32,7 @@
Outputs="@(_PlatformAndroidSdkItem->'$(AndroidToolchainCacheDirectory)\%(Identity)');@(_PlatformAndroidNdkItem->'$(AndroidToolchainCacheDirectory)\%(Identity)')">
<MakeDir Directories="$(AndroidToolchainCacheDirectory)" />
<DownloadUri
SourceUris="@(_PlatformAndroidSdkItem->'$(AndroidUri)/%(Identity)');@(_PlatformAndroidNdkItem->'$(AndroidUri)/%(Identity)')"
SourceUris="@(_PlatformAndroidSdkItem->'$(AndroidUri)/%(RelUrl)%(Identity)');@(_PlatformAndroidNdkItem->'$(AndroidUri)/%(RelUrl)%(Identity)')"
DestinationFiles="@(_PlatformAndroidSdkItem->'$(AndroidToolchainCacheDirectory)\%(Identity)');@(_PlatformAndroidNdkItem->'$(AndroidToolchainCacheDirectory)\%(Identity)')"
/>
</Target>

Просмотреть файл

@ -0,0 +1,99 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<UsingTask AssemblyFile="$(MSBuildThisFileDirectory)..\..\bin\Build$(Configuration)\Xamarin.Android.Tools.BootstrapTasks.dll" TaskName="Xamarin.Android.Tools.BootstrapTasks.Adb" />
<UsingTask AssemblyFile="$(MSBuildThisFileDirectory)..\..\bin\Build$(Configuration)\Xamarin.Android.Tools.BootstrapTasks.dll" TaskName="Xamarin.Android.Tools.BootstrapTasks.CheckAdbTarget" />
<UsingTask AssemblyFile="$(MSBuildThisFileDirectory)..\..\bin\Build$(Configuration)\Xamarin.Android.Tools.BootstrapTasks.dll" TaskName="Xamarin.Android.Tools.BootstrapTasks.CreateAndroidEmulator" />
<UsingTask AssemblyFile="$(MSBuildThisFileDirectory)..\..\bin\Build$(Configuration)\Xamarin.Android.Tools.BootstrapTasks.dll" TaskName="Xamarin.Android.Tools.BootstrapTasks.RunInstrumentationTests" />
<UsingTask AssemblyFile="$(MSBuildThisFileDirectory)..\..\bin\Build$(Configuration)\Xamarin.Android.Tools.BootstrapTasks.dll" TaskName="Xamarin.Android.Tools.BootstrapTasks.StartAndroidEmulator" />
<PropertyGroup>
<_TestImageName>XamarinAndroidUnitTestRunner</_TestImageName>
<_AdbEmulatorPort>5600</_AdbEmulatorPort>
</PropertyGroup>
<Target Name="AcquireAndroidTarget">
<CheckAdbTarget
Condition=" '$(RequireNewEmulator)' != 'True' "
AdbTarget="$(AdbTarget)"
ToolPath="$(AdbToolPath)">
<Output TaskParameter="AdbTarget" PropertyName="_AdbTarget" />
<Output TaskParameter="IsValidTarget" PropertyName="_ValidAdbTarget" />
</CheckAdbTarget>
<CreateAndroidEmulator
Condition=" '$(_ValidAdbTarget)' != 'True' "
AndroidAbi="x86"
AndroidSdkHome="$(AndroidSdkDirectory)"
SdkVersion="21"
ImageName="$(_TestImageName)"
ToolExe="$(AndroidToolExe)"
ToolPath="$(AndroidToolPath)"
/>
<StartAndroidEmulator
Condition=" '$(_ValidAdbTarget)' != 'True' "
AndroidSdkHome="$(AndroidSdkDirectory)"
ImageName="$(_TestImageName)"
Port="$(_AdbEmulatorPort)"
ToolExe="$(EmulatorToolExe)"
ToolPath="$(EmulatorToolPath)">
<Output TaskParameter="AdbTarget" PropertyName="_AdbTarget" />
<Output TaskParameter="AdbTarget" PropertyName="_EmuTarget" />
<Output TaskParameter="AdbProcess" PropertyName="_EmuProcess" />
</StartAndroidEmulator>
<Adb
Condition=" '$(_ValidAdbTarget)' != 'True' "
Arguments="$(_AdbTarget) wait-for-device"
/>
<Message
Condition=" '$(_EmuTarget)' != '' "
Text="Launched Android emulator; `adb` target: '$(_AdbTarget)'"
/>
</Target>
<Target Name="ReleaseAndroidTarget">
<Adb
Condition=" '$(_EmuTarget)' != '' "
Arguments="$(_EmuTarget) emu kill"
/>
</Target>
<!--
<ItemGroup>
<UnitTestApk Include="ApkFile">
<Package></Package>
<InstrumentationType></InstrumentationType>
<ResultsPath></ResultsPath>
</UnitTestApk>
</ItemGroup>
-->
<Target Name="DeployUnitTestApks"
Condition=" '@(UnitTestApk)' != '' ">
<Adb
Arguments="$(_AdbTarget) $(AdbOptions) install -r &quot;%(UnitTestApk.Identity)&quot;"
ToolExe="$(AdbToolExe)"
ToolPath="$(AdbToolPath)"
/>
</Target>
<Target Name="UndeployUnitTestApks"
Condition=" '@(UnitTestApk)' != '' ">
<Adb
Arguments="$(_AdbTarget) $(AdbOptions) uninstall &quot;%(UnitTestApk.Package)&quot;"
ToolExe="$(AdbToolExe)"
ToolPath="$(AdbToolPath)"
/>
</Target>
<Target Name="RunUnitTestApks"
Condition=" '@(UnitTestApk)' != '' ">
<RunInstrumentationTests
AdbTarget="$(_AdbTarget)"
AdbOptions="$(AdbOptions)"
Component="%(UnitTestApk.Package)/%(UnitTestApk.InstrumentationType)"
NUnit2TestResultsFile="%(UnitTestApk.ResultsPath)"
ToolExe="$(AdbToolExe)"
ToolPath="$(AdbToolPath)">
<Output TaskParameter="NUnit2TestResultsFile" PropertyName="_ResultsFile "/>
</RunInstrumentationTests>
</Target>
</Project>

Просмотреть файл

@ -12,7 +12,7 @@ using IOFile = System.IO.File;
namespace Xamarin.Android.BuildTools.PrepTasks
{
public class Git : ToolTask
public class Git : PathToolTask
{
[Required]
public ITaskItem WorkingDirectory { get; set; }
@ -26,10 +26,8 @@ namespace Xamarin.Android.BuildTools.PrepTasks
get { return true; }
}
protected override string ToolName {
get {
return "git" + (Path.DirectorySeparatorChar == '\\' ? ".exe" : "");
}
protected override string ToolBaseName {
get { return "git"; }
}
List<string> lines;
@ -57,23 +55,6 @@ namespace Xamarin.Android.BuildTools.PrepTasks
return !Log.HasLoggedErrors;
}
protected override string GenerateFullPathToTool ()
{
var app = string.IsNullOrEmpty (ToolExe) ? ToolName: ToolExe;
var path = !string.IsNullOrEmpty (ToolPath) ? ToolPath : GetDirectoryFromPath (app);
return Path.Combine (path, app);
}
string GetDirectoryFromPath (string app)
{
foreach (var p in Environment.GetEnvironmentVariable ("PATH").Split (new [] { Path.PathSeparator.ToString () }, StringSplitOptions.RemoveEmptyEntries)) {
if (File.Exists (Path.Combine (p, app))) {
return p;
}
}
return null;
}
protected override string GenerateCommandLineCommands ()
{
return Arguments;
@ -86,6 +67,7 @@ namespace Xamarin.Android.BuildTools.PrepTasks
protected override void LogEventsFromTextOutput (string singleLine, MessageImportance messageImportance)
{
base.LogEventsFromTextOutput (singleLine, messageImportance);
Lines.Add (singleLine);
}
}

Просмотреть файл

@ -0,0 +1,48 @@
using System;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace Xamarin.Android.BuildTools.PrepTasks
{
public abstract class PathToolTask : ToolTask
{
protected abstract string ToolBaseName { get; }
protected override string ToolName {
get {
var dirs = string.IsNullOrEmpty (ToolPath)
? null
: new [] { ToolPath };
string filename;
Which.GetProgramLocation (ToolBaseName, out filename, dirs);
return filename;
}
}
protected override string GenerateFullPathToTool ()
{
var dirs = string.IsNullOrEmpty (ToolPath)
? null
: new [] { ToolPath };
string filename;
var path = Which.GetProgramLocation (ToolBaseName, out filename, dirs);
return path;
}
protected void AddEnvironmentVariables (string[] variables)
{
if (EnvironmentVariables == null) {
EnvironmentVariables = variables;
return;
}
if (variables == null)
return;
var newVariables = new string [checked(EnvironmentVariables.Length + variables.Length)];
Array.Copy (EnvironmentVariables, newVariables, EnvironmentVariables.Length);
Array.Copy (variables, 0, newVariables, EnvironmentVariables.Length, variables.Length);
EnvironmentVariables = newVariables;
}
}
}

Просмотреть файл

@ -32,11 +32,42 @@ namespace Xamarin.Android.BuildTools.PrepTasks
}
}
public static string GetProgramLocation (string programBasename, out string filename, string[] directories = null)
{
directories = directories ?? GetPathDirectories ();
foreach (var d in directories) {
var p = GetProgramLocation (programBasename, d, out filename);
if (p != null)
return p;
}
filename = programBasename;
return null;
}
static string GetProgramLocation (string programBasename, string directory, out string filename)
{
foreach (var ext in FileExtensions) {
filename = Path.ChangeExtension (programBasename, ext);
var p = Path.Combine (directory, filename);
if (File.Exists (p)) {
return p;
}
}
filename = programBasename;
return null;
}
static string[] GetPathDirectories ()
{
return Environment.GetEnvironmentVariable ("PATH")
.Split (Path.PathSeparator);
}
public override bool Execute ()
{
string[] paths = Directories?.Select (d => d.ItemSpec).ToArray ();
if (paths == null || paths.Length == 0) {
paths = Environment.GetEnvironmentVariable ("PATH").Split (Path.PathSeparator);
paths = GetPathDirectories ();
}
Log.LogMessage (MessageImportance.Low, $"Task {nameof (Which)}");
@ -47,17 +78,10 @@ namespace Xamarin.Android.BuildTools.PrepTasks
}
Log.LogMessage (MessageImportance.Low, $" {nameof (Required)}: {Required}");
foreach (var path in paths) {
var p = Path.Combine (path, Program.ItemSpec);
foreach (var ext in FileExtensions) {
var e = Path.ChangeExtension (p, ext);
if (File.Exists (e)) {
Location = new TaskItem (e);
break;
}
}
if (Location != null)
break;
string _;
var e = GetProgramLocation (Program.ItemSpec, out _, paths);
if (e != null) {
Location = new TaskItem (e);
}
if (Location == null && Required) {

Просмотреть файл

@ -7,7 +7,7 @@
<OutputType>Library</OutputType>
<RootNamespace>Xamarin.Android.BuildTools.PrepTasks</RootNamespace>
<AssemblyName>xa-prep-tasks</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
</PropertyGroup>
<Import Project="..\..\Configuration.props" />
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
@ -41,6 +41,7 @@
<Compile Include="Xamarin.Android.BuildTools.PrepTasks\Git.cs" />
<Compile Include="Xamarin.Android.BuildTools.PrepTasks\GitBranch.cs" />
<Compile Include="Xamarin.Android.BuildTools.PrepTasks\GitCommitHash.cs" />
<Compile Include="Xamarin.Android.BuildTools.PrepTasks\PathToolTask.cs" />
<Compile Include="Xamarin.Android.BuildTools.PrepTasks\SystemUnzip.cs" />
<Compile Include="Xamarin.Android.BuildTools.PrepTasks\Which.cs" />
<Compile Include="Xamarin.Android.BuildTools.PrepTasks\GitBlame.cs" />

Просмотреть файл

@ -31,6 +31,7 @@
<AndroidLinkMode>None</AndroidLinkMode>
<ConsolePause>false</ConsolePause>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<AndroidSupportedAbis>armeabi-v7a;x86</AndroidSupportedAbis>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<Optimize>true</Optimize>

Просмотреть файл

@ -7,6 +7,14 @@
<AndroidNativeLibrary Include="libs\x86\libreuse-threads.so" />
<AndroidNativeLibrary Include="libs\x86_64\libreuse-threads.so" />
</ItemGroup>
<ItemGroup>
<UnitTestApk Include="$(OutputPath)Mono.Android_Tests-Signed.apk">
<Package>Mono.Android_Tests</Package>
<InstrumentationType>xamarin.android.runtimetests.TestInstrumentation</InstrumentationType>
<ResultsPath>..\..\..\TestResult-Mono.Android_Tests.xml</ResultsPath>
</UnitTestApk>
</ItemGroup>
<Import Project="..\..\..\build-tools\scripts\UnitTestApks.targets" />
<Target Name="BuildNativeLibs"
BeforeTargets="Build"
DependsOnTargets="_ResolveMonoAndroidSdks"
@ -15,19 +23,4 @@
<Error Text="Could not locate Android NDK." Condition="!Exists ('$(AndroidNdkDirectory)\ndk-build')" />
<Exec Command="&quot;$(AndroidNdkDirectory)\ndk-build&quot;" />
</Target>
<Target Name="UnDeploy"
DependsOnTargets="_ValidateAndroidPackageProperties">
<Exec Command="&quot;$(AndroidSdkDirectory)\platform-tools\adb&quot; $(AdbTarget) $(AdbOptions) uninstall $(_AndroidPackage)" />
</Target>
<Target Name="Deploy">
<Exec Command="&quot;$(AndroidSdkDirectory)\platform-tools\adb&quot; $(AdbTarget) $(AdbOptions) install $(OutputPath)\Mono.Android_Tests-Signed.apk" />
</Target>
<Target Name="RunTests"
DependsOnTargets="_ValidateAndroidPackageProperties">
<Exec Command="&quot;$(AndroidSdkDirectory)\platform-tools\adb&quot; $(AdbTarget) $(AdbOptions) shell am instrument -w $(_AndroidPackage)/xamarin.android.runtimetests.TestInstrumentation" />
</Target>
<Target Name="RunSdbTests"
DependsOnTargets="_ValidateAndroidPackageProperties">
<Exec Command="&quot;$(AndroidSdkDirectory)\platform-tools\adb&quot; $(AdbTarget) $(AdbOptions) shell am start -n $(_AndroidPackage)/xamarin.android.runtimetests.MainActivity" />
</Target>
</Project>

Просмотреть файл

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="Mono.Android_Tests">
<uses-sdk android:minSdkVersion="4" />
<uses-sdk android:minSdkVersion="10" />
<application android:label="Xamarin.Android.RuntimeTests" android:name="android.apptests.App">
<activity
android:name="xamarin.android.runtimetests.RenamedActivity"

Просмотреть файл

@ -93,10 +93,11 @@ namespace Xamarin.Android.NUnitLite {
string GetResultsPath ()
{
var docsDir = Context.GetExternalFilesDir (global::Android.OS.Environment.DirectoryDocuments);
if (docsDir == null)
return null;
return Path.Combine (docsDir.AbsolutePath, "TestResults.xml");
var resultsPathFile = Context.GetExternalFilesDir (global::Android.OS.Environment.DirectoryDocuments);
var resultsPath = resultsPathFile != null && resultsPathFile.Exists ()
? resultsPathFile.AbsolutePath
: Path.Combine (Context.FilesDir.AbsolutePath, ".__override__");
return Path.Combine (resultsPath, "TestResults.xml");
}
// On some Android targets, the external storage directory is "emulated",

Просмотреть файл

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
@ -8,7 +8,6 @@
<RootNamespace>Xamarin.Android.Tools.BootstrapTasks</RootNamespace>
<AssemblyName>Xamarin.Android.Tools.BootstrapTasks</AssemblyName>
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
<TargetFrameworkProfile />
</PropertyGroup>
<Import Project="..\..\Configuration.props" />
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
@ -39,9 +38,16 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Xamarin.Android.Tools.BootstrapTasks\UnzipDirectoryChildren.cs" />
<Compile Include="Xamarin.Android.Tools.BootstrapTasks\Adb.cs" />
<Compile Include="Xamarin.Android.Tools.BootstrapTasks\Android.cs" />
<Compile Include="Xamarin.Android.Tools.BootstrapTasks\CheckAdbTarget.cs" />
<Compile Include="Xamarin.Android.Tools.BootstrapTasks\CreateAndroidEmulator.cs" />
<Compile Include="Xamarin.Android.Tools.BootstrapTasks\Emulator.cs" />
<Compile Include="Xamarin.Android.Tools.BootstrapTasks\GenerateProfile.cs" />
<Compile Include="Xamarin.Android.Tools.BootstrapTasks\GetNugetPackageBasePath.cs" />
<Compile Include="Xamarin.Android.Tools.BootstrapTasks\RunInstrumentationTests.cs" />
<Compile Include="Xamarin.Android.Tools.BootstrapTasks\StartAndroidEmulator.cs" />
<Compile Include="Xamarin.Android.Tools.BootstrapTasks\UnzipDirectoryChildren.cs" />
<Compile Include="Xamarin.Android.Tools.BootstrapTasks\Zip.cs" />
</ItemGroup>
<ItemGroup>
@ -58,6 +64,10 @@
<Project>{900A0F71-BAAD-417A-8D1A-8D330297CDD0}</Project>
<Name>libzip</Name>
</ProjectReference>
<ProjectReference Include="..\..\build-tools\xa-prep-tasks\xa-prep-tasks.csproj">
<Project>{7CE69551-BD73-4726-ACAA-AAF89C84BAF8}</Project>
<Name>xa-prep-tasks</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project>

Просмотреть файл

@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Xamarin.Android.BuildTools.PrepTasks;
namespace Xamarin.Android.Tools.BootstrapTasks
{
public class Adb : PathToolTask
{
public string Arguments { get; set; }
[Output]
public string[] Output { get; set; }
protected virtual bool LogTaskMessages {
get { return true; }
}
protected override string ToolBaseName {
get { return "adb"; }
}
List<string> lines;
List<string> Lines {
get { return lines ?? (lines = new List<string> ()); }
}
public override bool Execute ()
{
if (LogTaskMessages) {
Log.LogMessage (MessageImportance.Low, $"Task {nameof (Adb)}");
Log.LogMessage (MessageImportance.Low, $" {nameof (Arguments)}: {Arguments}");
}
base.Execute ();
Output = lines?.ToArray ();
if (LogTaskMessages) {
Log.LogMessage (MessageImportance.Low, $" [Output] {nameof (Output)}:");
foreach (var line in (Output ?? new string [0]))
Log.LogMessage (MessageImportance.Low, $" {line}");
}
return !Log.HasLoggedErrors;
}
protected override string GenerateCommandLineCommands ()
{
return Arguments;
}
protected override void LogEventsFromTextOutput (string singleLine, MessageImportance messageImportance)
{
base.LogEventsFromTextOutput (singleLine, messageImportance);
Lines.Add (singleLine);
}
}
}

Просмотреть файл

@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Xamarin.Android.BuildTools.PrepTasks;
namespace Xamarin.Android.Tools.BootstrapTasks
{
public class Android : PathToolTask
{
public string Arguments { get; set; }
[Output]
public string[] Output { get; set; }
protected virtual bool LogTaskMessages {
get { return true; }
}
protected override string ToolBaseName {
get { return "android"; }
}
List<string> lines;
List<string> Lines {
get { return lines ?? (lines = new List<string> ()); }
}
public override bool Execute ()
{
if (LogTaskMessages) {
Log.LogMessage (MessageImportance.Low, $"Task {nameof (Android)}");
Log.LogMessage (MessageImportance.Low, $" {nameof (Arguments)}: {Arguments}");
}
base.Execute ();
Output = lines?.ToArray ();
if (LogTaskMessages) {
Log.LogMessage (MessageImportance.Low, $" [Output] {nameof (Output)}:");
foreach (var line in (Output ?? new string [0]))
Log.LogMessage (MessageImportance.Low, $" {line}");
}
return !Log.HasLoggedErrors;
}
protected override string GenerateCommandLineCommands ()
{
return Arguments;
}
protected override void LogEventsFromTextOutput (string singleLine, MessageImportance messageImportance)
{
base.LogEventsFromTextOutput (singleLine, messageImportance);
Lines.Add (singleLine);
}
}
}

Просмотреть файл

@ -0,0 +1,84 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Xamarin.Android.BuildTools.PrepTasks;
namespace Xamarin.Android.Tools.BootstrapTasks
{
public class CheckAdbTarget : Adb
{
public string SdkVersion {get; set;}
[Output]
public string AdbTarget {get; set;}
[Output]
public bool IsValidTarget {get; set;}
protected override bool LogTaskMessages {
get { return false; }
}
public override bool Execute ()
{
Log.LogMessage (MessageImportance.Low, $"Task {nameof (CheckAdbTarget)}");
Log.LogMessage (MessageImportance.Low, $" {nameof (AdbTarget)}: {AdbTarget}");
Log.LogMessage (MessageImportance.Low, $" {nameof (SdkVersion)}: {SdkVersion}");
base.Execute ();
Log.LogMessage (MessageImportance.Low, $" [Output] {nameof (AdbTarget)}: {AdbTarget}");
Log.LogMessage (MessageImportance.Low, $" [Output] {nameof (IsValidTarget)}: {IsValidTarget}");
return true;
}
protected override bool HandleTaskExecutionErrors ()
{
// We ignore all generated errors
return true;
}
protected override string GenerateCommandLineCommands ()
{
return $"{AdbTarget} shell getprop ro.build.version.sdk";
}
protected override void LogEventsFromTextOutput (string singleLine, MessageImportance messageImportance)
{
base.LogEventsFromTextOutput (singleLine, messageImportance);
// Log.LogMessage ($"# jonp: messageImportance={messageImportance}; line='{singleLine}'");
if (string.IsNullOrEmpty (singleLine))
return;
if (singleLine.Equals ("List of devices attached", StringComparison.OrdinalIgnoreCase))
return;
if (messageImportance == MessageImportance.High)
return;
if (string.IsNullOrEmpty (SdkVersion)) {
IsValidTarget = true;
return;
}
if (string.Equals (SdkVersion, singleLine, StringComparison.OrdinalIgnoreCase)) {
IsValidTarget = true;
return;
}
int required, target;
if (int.TryParse (SdkVersion, out required) &&
int.TryParse (singleLine, out target) &&
target >= required) {
IsValidTarget = true;
return;
}
}
}
}

Просмотреть файл

@ -0,0 +1,126 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Xamarin.Android.BuildTools.PrepTasks;
namespace Xamarin.Android.Tools.BootstrapTasks
{
public class CreateAndroidEmulator : Task
{
public string SdkVersion {get; set;}
public string AndroidAbi {get; set;}
public string AndroidSdkHome {get; set;}
public string ToolPath {get; set;}
public string ToolExe {get; set;}
public string TargetId {get; set;}
public string ImageName {get; set;} = "XamarinAndroidUnitTestRunner";
public override bool Execute ()
{
if (string.IsNullOrEmpty (TargetId) && !string.IsNullOrEmpty (SdkVersion)) {
TargetId = "android-" + SdkVersion;
}
Log.LogMessage (MessageImportance.Low, $"Task {nameof (CreateAndroidEmulator)}");
Log.LogMessage (MessageImportance.Low, $" {nameof (AndroidAbi)}: {AndroidAbi}");
Log.LogMessage (MessageImportance.Low, $" {nameof (AndroidSdkHome)}: {AndroidSdkHome}");
Log.LogMessage (MessageImportance.Low, $" {nameof (ImageName)}: {ImageName}");
Log.LogMessage (MessageImportance.Low, $" {nameof (SdkVersion)}: {SdkVersion}");
Log.LogMessage (MessageImportance.Low, $" {nameof (TargetId)}: {TargetId}");
Log.LogMessage (MessageImportance.Low, $" {nameof (ToolExe)}: {ToolExe}");
Log.LogMessage (MessageImportance.Low, $" {nameof (ToolPath)}: {ToolPath}");
Run (GetAndroidPath ());
return !Log.HasLoggedErrors;
}
string GetAndroidPath ()
{
if (string.IsNullOrEmpty (ToolExe))
ToolExe = "android";
var dirs = string.IsNullOrEmpty (ToolPath)
? null
: new [] { ToolPath };
string filename;
var path = Which.GetProgramLocation (ToolExe, out filename, dirs);
if (path == null) {
Log.LogError ($"Could not find `android`. Please set the `{nameof (CreateAndroidEmulator)}.{nameof (ToolPath)}` property appropriately.");
return null;
}
return path;
}
void Run (string android)
{
if (android == null)
return;
var arguments = $"create avd --abi \"{AndroidAbi}\" -f -n \"{ImageName}\" -t \"{TargetId}\"";
foreach (var line in Exec (android, arguments)) {
stdin.WriteLine ("no");
Log.LogMessage (MessageImportance.Low, line);
}
}
StreamWriter stdin;
IEnumerable<string> Exec (string android, string arguments, DataReceivedEventHandler stderr = null)
{
Log.LogMessage (MessageImportance.Low, $"Tool {android} execution started with arguments: {arguments}");
var psi = new ProcessStartInfo () {
FileName = android,
Arguments = arguments,
UseShellExecute = false,
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden,
};
Log.LogMessage (MessageImportance.Low, $"Environment variables being passed to the tool:");
if (!string.IsNullOrEmpty (AndroidSdkHome)) {
psi.EnvironmentVariables ["ANDROID_SDK_HOME"] = AndroidSdkHome;
Log.LogMessage (MessageImportance.Low, $"\tANDROID_SDK_HOME=\"{AndroidSdkHome}\"");
}
var p = new Process () {
StartInfo = psi,
};
stderr = stderr ?? DefaultErrorHandler;
p.ErrorDataReceived += stderr;
using (p) {
p.StartInfo = psi;
p.Start ();
p.BeginErrorReadLine ();
stdin = p.StandardInput;
string line;
while ((line = p.StandardOutput.ReadLine ()) != null) {
yield return line;
}
p.WaitForExit ();
if (p.ExitCode != 0) {
Log.LogError ($"Process `{android}` exited with value {p.ExitCode}.");
}
}
}
void DefaultErrorHandler (object sender, DataReceivedEventArgs e)
{
if (string.IsNullOrEmpty (e.Data))
return;
Log.LogError ($"{e.Data}");
}
}
}

Просмотреть файл

@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Xamarin.Android.BuildTools.PrepTasks;
namespace Xamarin.Android.Tools.BootstrapTasks
{
public class Emulator : PathToolTask
{
public string Arguments { get; set; }
[Output]
public string[] Output { get; set; }
protected virtual bool LogTaskMessages {
get { return true; }
}
protected override string ToolBaseName {
get { return "emulator"; }
}
List<string> lines;
List<string> Lines {
get { return lines ?? (lines = new List<string> ()); }
}
public override bool Execute ()
{
if (LogTaskMessages) {
Log.LogMessage (MessageImportance.Low, $"Task {nameof (Emulator)}");
Log.LogMessage (MessageImportance.Low, $" {nameof (Arguments)}: {Arguments}");
}
base.Execute ();
Output = lines?.ToArray ();
if (LogTaskMessages) {
Log.LogMessage (MessageImportance.Low, $" [Output] {nameof (Output)}:");
foreach (var line in (Output ?? new string [0]))
Log.LogMessage (MessageImportance.Low, $" {line}");
}
return !Log.HasLoggedErrors;
}
protected override string GenerateCommandLineCommands ()
{
return Arguments;
}
protected override void LogEventsFromTextOutput (string singleLine, MessageImportance messageImportance)
{
base.LogEventsFromTextOutput (singleLine, messageImportance);
Lines.Add (singleLine);
}
}
}

Просмотреть файл

@ -0,0 +1,107 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace Xamarin.Android.Tools.BootstrapTasks
{
public class RunInstrumentationTests : Adb
{
public string AdbTarget { get; set; }
public string AdbOptions { get; set; }
[Required]
public string Component { get; set; }
public string[] InstrumentationArguments { get; set; }
[Output]
public string NUnit2TestResultsFile { get; set; }
protected override bool LogTaskMessages {
get { return false; }
}
enum ExecuteState {
RunInstrumentation,
PullFiles,
}
ExecuteState executionState;
string targetTestResultsPath;
public override bool Execute ()
{
InstrumentationArguments = InstrumentationArguments ?? new string [0];
if (string.IsNullOrEmpty (NUnit2TestResultsFile)) {
var n = new StringBuilder ("TestResult-").Append (Component);
foreach (var c in Path.GetInvalidFileNameChars ()) {
n.Replace (c, '_');
}
n.Append (".xml");
NUnit2TestResultsFile = n.ToString ();
}
Log.LogMessage (MessageImportance.Low, $"Task {nameof (RunInstrumentationTests)}");
Log.LogMessage (MessageImportance.Low, $" {nameof (AdbTarget)}: {AdbTarget}");
Log.LogMessage (MessageImportance.Low, $" {nameof (AdbOptions)}: {AdbOptions}");
Log.LogMessage (MessageImportance.Low, $" {nameof (Component)}: {Component}");
Log.LogMessage (MessageImportance.Low, $" {nameof (InstrumentationArguments)}:");
foreach (var a in InstrumentationArguments) {
Log.LogMessage (MessageImportance.Low, $" {a}:");
}
Log.LogMessage (MessageImportance.Low, $" {nameof (NUnit2TestResultsFile)}: {NUnit2TestResultsFile}");
executionState = ExecuteState.RunInstrumentation;
base.Execute ();
if (string.IsNullOrEmpty (targetTestResultsPath)) {
Log.LogError ("No `nunit2-results-path` bundle value found in command output! Cannot find NUnit2 XML output!");
return false;
}
executionState = ExecuteState.PullFiles;
base.Execute ();
Log.LogMessage (MessageImportance.Low, $" [Output] {nameof (NUnit2TestResultsFile)}: {NUnit2TestResultsFile}");
return !Log.HasLoggedErrors;
}
protected override string GenerateCommandLineCommands ()
{
switch (executionState) {
case ExecuteState.RunInstrumentation:
var args = new StringBuilder ();
foreach (var a in InstrumentationArguments) {
var kvp = a.Split (new [] { '=' }, 2);
args.Append (" -e \"").Append (kvp [0]).Append ("\" \"");
args.Append (kvp.Length > 1 ? kvp [1] : "");
args.Append ("\"");
}
return $"{AdbTarget} {AdbOptions} shell am instrument {args.ToString ()} -w \"{Component}\"";
case ExecuteState.PullFiles:
return $"{AdbTarget} {AdbOptions} pull \"{targetTestResultsPath}\" \"{NUnit2TestResultsFile}\"";
}
throw new InvalidOperationException ($"Invalid state `{executionState}`!");
}
protected override void LogEventsFromTextOutput (string singleLine, MessageImportance messageImportance)
{
const string TestResultsPathResult = "INSTRUMENTATION_RESULT: nunit2-results-path=";
base.LogEventsFromTextOutput (singleLine, messageImportance);
if (string.IsNullOrEmpty (singleLine))
return;
if (!singleLine.Contains (TestResultsPathResult))
return;
var i = singleLine.IndexOf (TestResultsPathResult);
targetTestResultsPath = singleLine.Substring (i + TestResultsPathResult.Length);
}
}
}

Просмотреть файл

@ -0,0 +1,84 @@
using System;
using System.Diagnostics;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Xamarin.Android.BuildTools.PrepTasks;
namespace Xamarin.Android.Tools.BootstrapTasks
{
public class StartAndroidEmulator : Task
{
[Output]
public string AdbTarget {get; set;}
[Output]
public Process AdbProcess {get; set;}
public string AndroidSdkHome {get; set;}
public string Port {get; set;}
public string ImageName {get; set;} = "XamarinAndroidUnitTestRunner";
public string ToolPath {get; set;}
public string ToolExe {get; set;}
public override bool Execute ()
{
Log.LogMessage (MessageImportance.Low, $"Task {nameof (StartAndroidEmulator)}");
Log.LogMessage (MessageImportance.Low, $" {nameof (AndroidSdkHome)}: {AndroidSdkHome}");
Log.LogMessage (MessageImportance.Low, $" {nameof (ImageName)}: {ImageName}");
Log.LogMessage (MessageImportance.Low, $" {nameof (Port)}: {Port}");
Run (GetEmulatorPath ());
if (!string.IsNullOrEmpty (Port)) {
AdbTarget = $"-s emulator-{Port}";
}
return !Log.HasLoggedErrors;
}
string GetEmulatorPath ()
{
if (string.IsNullOrEmpty (ToolExe))
ToolExe = "emulator";
var dirs = string.IsNullOrEmpty (ToolPath)
? null
: new [] { ToolPath };
string filename;
var path = Which.GetProgramLocation (ToolExe, out filename, dirs);
if (path == null) {
Log.LogError ($"Could not find `emulator`. Please set the `{nameof (StartAndroidEmulator)}.{nameof (ToolExe)}` property appropriately.");
return null;
}
return path;
}
void Run (string emulator)
{
if (emulator == null)
return;
var port = string.IsNullOrEmpty (Port) ? "" : $" -port \"{Port}\"";
var arguments = $"-avd \"{ImageName}\"{port}";
Log.LogMessage (MessageImportance.Low, $"Tool {emulator} execution started with arguments: {arguments}");
var psi = new ProcessStartInfo () {
FileName = emulator,
Arguments = arguments,
UseShellExecute = false,
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden,
};
Log.LogMessage (MessageImportance.Low, $"Environment variables being passed to the tool:");
if (!string.IsNullOrEmpty (AndroidSdkHome)) {
psi.EnvironmentVariables ["ANDROID_SDK_HOME"] = AndroidSdkHome;
Log.LogMessage (MessageImportance.Low, $"\tANDROID_SDK_HOME=\"{AndroidSdkHome}\"");
}
var p = new Process () {
StartInfo = psi,
};
p.Start ();
}
}
}

Просмотреть файл

@ -417,6 +417,7 @@ create_update_dir (char *override_dir)
override_dirs [0] = override_dir;
create_public_directory (override_dir);
log_warn (LOG_DEFAULT, "Creating public update directory: `%s`", override_dir);
}
static int

31
tests/RunApkTests.targets Normal file
Просмотреть файл

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Project DefaultTargets="RunApkTests" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Condition)' == '' ">Debug</Configuration>
<OutputPath>$(MSBuildThisFileDirectory)..\bin\Test$(Configuration)\</OutputPath>
</PropertyGroup>
<Import Project="..\Configuration.props" />
<!--
Note that the `.csproj` for each `@(UnitTestApk)` entry *must* be added to
`$(TEST_APK_PROJECTS)` in the toplevel Makefile so that the `.apk` is built.
-->
<ItemGroup>
<UnitTestApk Include="$(OutputPath)Mono.Android_Tests-Signed.apk">
<Package>Mono.Android_Tests</Package>
<InstrumentationType>xamarin.android.runtimetests.TestInstrumentation</InstrumentationType>
<ResultsPath>..\TestResult-Mono.Android_Tests.xml</ResultsPath>
</UnitTestApk>
</ItemGroup>
<Import Project="..\build-tools\scripts\UnitTestApks.targets" />
<PropertyGroup>
<RunApkTestsDependsOn>
AcquireAndroidTarget;
DeployUnitTestApks;
RunUnitTestApks;
ReleaseAndroidTarget
</RunApkTestsDependsOn>
</PropertyGroup>
<Target Name="RunApkTests"
DependsOnTargets="$(RunApkTestsDependsOn)">
</Target>
</Project>