Skip to content

Instantly share code, notes, and snippets.

@roubachof
Last active June 28, 2016 11:43
Show Gist options
  • Save roubachof/824a83bd7a9cf1680d8e741164bf7efa to your computer and use it in GitHub Desktop.
Save roubachof/824a83bd7a9cf1680d8e741164bf7efa to your computer and use it in GitHub Desktop.
Script and tcp server listening to log results with NUnit.Xamarin 3 with TcpWriterParameters option (https://github.com/nunit/nunit.xamarin)
#
# Notes:
#
# - 10/06/16
# - the script attempts to connect to the first active Android emulator
# found in the list returned by the "adb devices" command, and launches it, if this list is empty.
# In this case, the AVD launched is the first .ini file found in the directory.
#
# paramètres (exemple):
# .\launch-emulator.ps1
# -tcpListenerPath .\Stago.Mhp.Instr.Pocm.UnitTests.Droid.Server.exe
# -tcpListenerIp 127.0.0.1
# -tcpListenerPort 13000
# -packageName Stago.Mhp.Instr.Pocm.UnitTests.Droid
# -activityName stago.mhp.instr.pocm.unitTests.droid.mainActivity
# [option] -avdName Nexus-S-API22-ARM
# [option] -outXmlReportPath ..\..\artifacts\DroidTestResults.xml
# [option] -logServerTimeoutInSeconds 1200​
# [option] -apkName xxxx-Signed.pak
# powershell.exe -noprofile -executionpolicy bypass -file .\launch-emulator.ps1 -tcpListenerPath .\Stago.Mhp.Instr.Pocm.UnitTests.Droid.Server.exe -tcpListenerIp 127.0.0.1 -tcpListenerPort 13000 -packageName Stago.Mhp.Instr.Pocm.UnitTests.Droid -activityName stago.mhp.instr.pocm.unitTests.droid.mainActivity -outXmlReportPath ..\..\artifacts\DroidTestResults.xml -logServerTimeoutInSeconds 1200
[CmdletBinding()]
Param(
[Parameter(Mandatory=$True)]
[string]$tcpListenerPath,
[Parameter(Mandatory=$True)]
[string]$tcpListenerIp,
[Parameter(Mandatory=$True)]
[int]$tcpListenerPort,
[Parameter(Mandatory=$True)]
[string]$packageName,
[Parameter(Mandatory=$True)]
[string]$activityName,
[string]$avdName,
[string]$apkName,
[string]$outXmlReportPath,
[int]$logServerTimeoutInSeconds
)
try
{
#region --- try
Write-Host "Version=1.0.503"
Write-Host ""
#
# IMPORTANT: cleanup des process 'adb', 'emulator', ...
#
Write-Host "Get-Process emulator*, adb*(0)"
Get-Process emulator*, adb*
Write-Host "-------------------------------"
Get-Process emulator*, adb* | Stop-Process
Write-Host "Get-Process emulator*, adb*(1)"
Get-Process emulator*, adb*
Write-Host "-------------------------------"
#region --- Prepare environment
# Add needed pathes
Write-Host "Adding the needed paths to the process environment path"
$VerifiedPathsToAdd = $Null
$PathToAdd = @(
"C:\Users\AgentTeamcity\AppData\Local\Android\android-sdk\platform-tools",
"C:\Users\AgentTeamcity\AppData\Local\Android\android-sdk\tools")
Foreach ($Path in $PathToAdd)
{
if ($env:Path -like "*$Path*")
{
Write-Host "$Path already exists in Path statement"
}
else
{
$VerifiedPathsToAdd += ";$Path"
Write-Host "`$Path will be added to the environment path"
}
}
if($VerifiedPathsToAdd -ne $null)
{
Write-Host "Adding $VerifiedPathsToAdd to Path statement now..."
[Environment]::SetEnvironmentVariable("Path",$env:Path + $VerifiedPathsToAdd,"Process") # replace 'Process' with [EnvironmentVariableTarget]::Machine, if you want to make this persistent
}
Write-Host "--------------------------------------------------------------------"
#endregion
#region --- Find or starts an emulator
# Find the emulator name is one is already running
Write-Host "adb devices"
adb devices
Write-Host "-------------------------------"
$aDevice = adb devices
foreach ($device in $aDevice)
{
$position0 = $device.IndexOf("emulator")
if ($position0 -lt 0)
{
continue
}
$emulator = $device.Substring($position0)
$position1 = $emulator.IndexOf(0x09)
if ($position1 -gt 0)
{
$emulator = $emulator.Substring(0, $position1);
}
break
}
Write-Host "emulator='"$emulator"'"
# A running emulator wasn't found lookup in .ini file
if (!$emulator)
{
#region --- Choose the AVD from .ini file
$avdDir = "C:\Users\AgentTeamcity\.android\avd"
Write-Host "Value of the avdName parameter="$avdName
Write-Host "----------------------------------------"
if (!$avdName)
{
Write-Host "Looking for the first .ini file in the avdDir="$avdDir" directory"
Write-Host "--------------------------------------------------------------------"
$List = get-childitem $avdDir | where {$_.extension -eq ".ini"}
if (!$List)
{
throw "EXIT: NO .ini file was found in the directory avdDir=" + $avdDir
}
foreach ($item in $List)
{
$avdName = $item.BaseName
break
}
}
if (!$avdName)
{
throw "EXIT: No AVD was found"
}
Write-Host "Effective value of the avdName="$avdName
Write-Host "----------------------------------------"
#endregion
#region --- Starts the emulator
Try
{
Write-Host "Start-Process(-) -PassThru -FilePath emulator.exe -ArgumentList -no-boot-anim -no-window -avd="$avdName
$process_emulator = Start-Process -PassThru -FilePath emulator.exe -ArgumentList "-no-boot-anim -no-window -avd $avdName"
Write-Host "Start-Process(+) process_emulator="$process_emulator
}
Catch
{
$ErrorMessage = $_.Exception.Message
$FailedItem = $_.Exception.ItemName
Write-Host "Start-Process(EXCEPTION) ErrorMessage="$ErrorMessage
}
if (!$process_emulator)
{
throw "EXIT: no emulator could be launched."
}
#endregion
Write-Host "adb wait-for-device"
adb wait-for-device
Write-Host "--------------------------------------"
#region --- wait for end of boot
Write-Host "Waiting for the end of the boot sequence"
$timeout = 400
for ($attempts = 0; $attempts -lt $timeout; $attempts++)
{
$result = adb shell getprop sys.boot_completed
Write-Host "adb shell getprop sys.boot_completed -> " $result
if ($result -match "invalid|error|fail")
{
throw "EXIT: failed to communicate with the emulator: $result"
}
Sleep 1
if ($result -like "1*")
{
"Boot sequence ended"
break;
}
}
Write-Host "--------------------------------"
if ($attempts -ge $timeout)
{
throw "Timeout reached while waiting for the end of the boot sequence ($attempts attempts with a 1 second delay)"
}
#endregion
#region --- Get emulator name
Write-Host "adb devices"
adb devices
Write-Host "-------------------------------"
$aDevice = adb devices
foreach ($device in $aDevice)
{
$position0 = $device.IndexOf("emulator")
if ($position0 -lt 0)
{
continue
}
$emulator = $device.Substring($position0)
$position1 = $emulator.IndexOf(0x09)
if ($position1 -gt 0)
{
$emulator = $emulator.Substring(0, $position1);
}
break
}
Write-Host "emulator=<<"$emulator">>"
#endregion
#endregion
}
#endregion
#region --- Launch log server
# $tcpListenerPath_name <- $tcpListenerPath, 'nettoyage'
$tcpListenerPath_name=$tcpListenerPath.ToUpper()
while ($true)
{
if ($tcpListenerPath_name.StartsWith("."))
{
$tcpListenerPath_name = $tcpListenerPath_name.Substring(1)
continue
}
if ($tcpListenerPath_name.StartsWith("\"))
{
$tcpListenerPath_name = $tcpListenerPath_name.Substring(1)
continue
}
break
}
if ($tcpListenerPath_name.EndsWith(".EXE"))
{
$tcpListenerPath_name = $tcpListenerPath_name.Substring(0, $tcpListenerPath_name.Length - 4)
}
Write-Host "tcpListenerPath_name="$tcpListenerPath_name
# kill old server log process
$aProcess = Get-Process
foreach ($process in $aProcess)
{
$processName = $process.Name.ToUpper()
if ($processName.Equals($tcpListenerPath_name))
{
Write-Host "process.Kill()="$process
$process.Kill()
}
}
Write-Host "-------------------------------"
Try
{
Write-Host "Start-Process(-) -PassThru -FilePath tcpListenerPath="$tcpListenerPath
$process_tcpListenerPath = Start-Process -PassThru -FilePath $tcpListenerPath -ArgumentList "-hostname=$tcpListenerIp -port=$tcpListenerPort -output=$outXmlReportPath"
Write-Host "Start-Process(+) process_tcpListenerPath="$process_tcpListenerPath
}
Catch
{
$ErrorMessage = $_.Exception.Message
$FailedItem = $_.Exception.ItemName
Write-Host "Start-Process(EXCEPTION) ErrorMessage="$ErrorMessage
}
if (!$process_tcpListenerPath)
{
throw "EXIT: process_tcpListenerPath='" + $process_tcpListenerPath + "' could not be launched"
}
#endregion
#region --- Starting the APK
Write-Host "apkName(-)="$apkName
if (-Not $apkName)
{
$apkName = "$packageName-Signed.apk"
}
Write-Host "apkName(+)="$apkName
Write-Host "-------------------------"
Write-Host "Unlocking the emulator screen"
Write-Host "adb -s $emulator shell input keyevent 82"
adb -s $emulator shell input keyevent 82
Write-Host "-------------------------"
Write-Host "Trying to uninstall the package previous version"
Write-Host "adb -s $emulator uninstall $packageName"
adb -s $emulator uninstall $packageName
Write-Host "-------------------------"
Write-Host "Installing the APK"
Write-Host "adb -s $emulator install -r $apkName"
$result = adb -s $emulator install -r "$apkName"
if ($result -match "invalid|error|fail")
{
throw "APK installation failed: $result"
}
Write-Host "-------------------------"
Write-Host "Removing the existing xml results"
Write-Host "adb -s $emulator shell run-as $packageName rm -fr files/NUnitTestsOutput"
adb -s $emulator shell run-as $packageName rm -fr files/NUnitTestsOutput
Write-Host "-------------------------"
Write-Host "Launching the test Activity"
"adb -s $emulator shell am start $packageName/$activityName"
Sleep 5
$result = adb -s $emulator shell am start "$packageName/$activityName"
if ($result -match "invalid|error|fail")
{
throw "Error while launching main activity: $result"
}
Write-Host "-------------------------"
$logServerTimeoutInSeconds = if ($logServerTimeoutInSeconds -eq 0) { 5 * 60 } else { $logServerTimeoutInSeconds }
Write-Host "Waiting for process $logServerProcess with timeout of $logServerTimeoutInSeconds seconds"
if (-Not $process_tcpListenerPath -Or -Not $process_tcpListenerPath.WaitForExit($logServerTimeoutInSeconds * 1000))
{
throw "The log server hasn't received any log in $logServerTimeoutInSeconds seconds: a timeout is detected"
}
Write-Host "-------------------------"
#endregion
#endregion
}
finally
{
#
# IMPORTANT: cleanup processes 'adb', 'emulator', ...
#
Write-Host "Get-Process emulator*, adb*(0)"
Get-Process emulator*, adb*
Write-Host "-------------------------------"
Get-Process emulator*, adb* | Stop-Process
Write-Host "Get-Process emulator*, adb*(1)"
Get-Process emulator*, adb*
Write-Host "-------------------------------"
}
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using Mono.Options;
namespace Company.Whatever.UnitTests.Droid.Server
{
public class MyTcpListener
{
public static void Main(string[] args)
{
TcpListener server = null;
try
{
// Set the TcpListener on port 13000.
int port = 13000;
var localAddr = IPAddress.Parse("127.0.0.1");
string outputPath = @".\output.xml";
var options = new OptionSet
{
{
"h|hostname=", "the host dns name or IP address.",
host => localAddr = IPAddress.Parse(host)
},
{
"p|port=", "the port number to listen to.\n" + "this must be an integer.",
(int p) => port = p
},
{
"o|output=", "the path of the output result.",
o => outputPath = o
}
};
options.Parse(args);
// TcpListener server = new TcpListener(port);
server = new TcpListener(localAddr, port);
// Start listening for client requests.
server.Start();
// Buffer for reading data
var bytes = new byte[256];
// Enter the listening loop.
//while (true)
{
Console.Write($"Waiting for a connection on {localAddr}:{port}, will drop output to {outputPath}");
// Perform a blocking call to accept requests.
// You could also user server.AcceptSocket() here.
TcpClient client = server.AcceptTcpClient();
Console.WriteLine("Connected!");
// Get a stream object for reading and writing
NetworkStream stream = client.GetStream();
int i;
StringBuilder builder = new StringBuilder();
// Loop to receive all the data sent by the client.
while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
{
// Translate data bytes to a ASCII string.
var data = Encoding.UTF8.GetString(bytes, 0, i);
builder.Append(data);
Console.WriteLine("Received: {0}", data);
}
// Shutdown and end connection
client.Close();
// Create a file to write to.
File.WriteAllText(outputPath, builder.ToString());
}
}
catch (SocketException e)
{
Console.WriteLine("SocketException: {0}", e);
}
finally
{
// Stop listening for new clients.
server?.Stop();
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment