4 using System.Collections.Generic;
 
    8 using System.Net.NetworkInformation;
 
    9 using System.Net.Sockets;
 
   10 using System.Reflection;
 
   12 using System.Threading;
 
   14 using SiliconStudio.Paradox.Graphics.Regression;
 
   16 namespace SiliconStudio.Paradox.TestRunner2
 
   20         private const char IpAddressesSplitCharacter = 
'%';
 
   25         private string branchName;
 
   30         private string serverAddresses;
 
   35         private int buildNumber = -1;
 
   40         private TcpListener server;
 
   48         int FindAvailablePort(
int startRange, 
int endRange)
 
   51             for (
int i = 0; i < 100; ++i)
 
   54                 var ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();
 
   55                 var tcpConnInfoArray = ipGlobalProperties.GetActiveTcpConnections();
 
   58                 for (
int port = startRange; port <= endRange; ++port)
 
   60                     bool isAvailable = 
true;
 
   62                     foreach (TcpConnectionInformation tcpi 
in tcpConnInfoArray)
 
   64                         if (tcpi.LocalEndPoint.Port == port)
 
   79             throw new InvalidOperationException(
string.Format(
"Could not find a valid port in the range {0}-{1}", startRange, endRange));
 
   85         TcpListener StartServer()
 
   88             var nics = NetworkInterface.GetAllNetworkInterfaces();
 
   93             foreach (var ip 
in nics.Select(x => x.GetIPProperties()).OrderBy(x => x.GatewayAddresses.Count > 0 ? 0 : 1))
 
   95                 foreach (var addr 
in ip.UnicastAddresses)
 
   97                     if (addr.Address.AddressFamily == AddressFamily.InterNetwork && !
String.IsNullOrEmpty(addr.Address.ToString()) && !addr.Address.ToString().Equals(
@"127.0.0.1"))
 
   98                         serverAddresses = String.Join(IpAddressesSplitCharacter.ToString(), serverAddresses, addr.Address);
 
  102             if (serverAddresses.Equals(
""))
 
  104                 Console.WriteLine(
@"No IP address found.");
 
  108             var serverPort = FindAvailablePort(20000, 20100);
 
  109             var server = 
new TcpListener(IPAddress.Any, serverPort);
 
  110             Console.WriteLine(
@"Server listening to port {0}", serverPort);
 
  120                 server = StartServer();
 
  125                     var o0 = ShellHelper.RunProcessAndGetOutput(
@"adb", string.Format(
@"-s {0} shell am force-stop {1}", device.Serial, packageName));
 
  128                     ShellHelper.RunProcessAndGetOutput(
@"adb", string.Format(
@"-s {0} uninstall {1}", device.Serial, packageName));
 
  131                     var o1 = ShellHelper.RunProcessAndGetOutput(
@"adb", string.Format(
@"-s {0} install {1}", device.Serial, packageFile));
 
  132                     Console.WriteLine(
"adb install: exitcode {0}\nOutput: {1}\nErrors: {2}", o1.ExitCode, string.Join(Environment.NewLine, o1.OutputLines), 
string.Join(Environment.NewLine, o1.OutputErrors));
 
  133                     if (o1.ExitCode != 0)
 
  134                         throw new InvalidOperationException(
"Invalid error code from adb install");
 
  138                 var parameters = 
new StringBuilder();
 
  139                 parameters.Append(
"-s "); parameters.Append(device.Serial);
 
  140                 parameters.Append(
@" shell am start -a android.intent.action.MAIN -n " + packageName + 
"/nunitlite.tests.MainActivity");
 
  144                 if (!String.IsNullOrEmpty(branchName))
 
  146                 Console.WriteLine(parameters.ToString());
 
  148                 var o2 = ShellHelper.RunProcessAndGetOutput(
@"adb", parameters.ToString());
 
  149                 Console.WriteLine(
"adb shell am start: exitcode {0}\nOutput: {1}\nErrors: {2}", o2.ExitCode, string.Join(Environment.NewLine, o2.OutputLines), 
string.Join(Environment.NewLine, o2.OutputErrors));
 
  150                 if (o2.ExitCode != 0)
 
  151                     throw new InvalidOperationException(
"Invalid error code from adb shell am start");
 
  154                 var client = server.AcceptTcpClient();
 
  156                 Console.WriteLine(
"Device connected, wait for results...");
 
  158                 var clientStream = client.GetStream();
 
  159                 var binaryReader = 
new BinaryReader(clientStream);
 
  162                 var output = binaryReader.ReadString();
 
  163                 Console.WriteLine(output);
 
  166                 var result = binaryReader.ReadString();
 
  167                 Console.WriteLine(result);
 
  170                 File.WriteAllText(resultFile, result);
 
  176                 Console.WriteLine(
@"An error was thrown when running the test on Android: {0}", e);
 
  187         private static void AddAndroidParameter(StringBuilder builder, 
string parameterName, 
string parameterValue)
 
  189             builder.Append(
@" -e ");
 
  190             builder.Append(parameterName);
 
  191             builder.Append(
@" ");
 
  192             builder.Append(parameterValue);
 
  206                 return Name + 
" " + Serial + 
" " + PlatformPermutator.GetPlatformName(Platform);
 
  213         static int Main(
string[] args)
 
  215             var exeName = Path.GetFileName(Assembly.GetExecutingAssembly().Location);
 
  216             var showHelp = 
false;
 
  218             string resultPath = 
"TestResults";
 
  219             bool reinstall = 
true;
 
  221             var p = 
new OptionSet
 
  223                     "Copyright (C) 2011-2013 Silicon Studio Corporation. All Rights Reserved",
 
  224                     "Paradox Test Suite Tool - Version: " 
  228                         typeof(
Program).Assembly.GetName().Version.Major,
 
  229                         typeof(
Program).Assembly.GetName().Version.Minor,
 
  230                         typeof(
Program).Assembly.GetName().Version.Build) + string.Empty,
 
  231                     string.Format(
"Usage: {0} [assemblies|apk] -option1 -option2:a", exeName),
 
  235                     { 
"h|help", 
"Show this message and exit", v => showHelp = v != null },
 
  236                     { 
"result-path:", 
"Result .XML output path", v => resultPath = v },
 
  237                     { 
"no-reinstall-apk", 
"Do not reinstall APK", v => reinstall = 
false },
 
  242                 var commandArgs = p.Parse(args);
 
  245                     p.WriteOptionDescriptions(Console.Out);
 
  250                 Directory.CreateDirectory(resultPath);
 
  251                 exitCode = BuildAndRunAndroidTests(commandArgs, reinstall, resultPath);
 
  255                 Console.WriteLine(
"{0}: {1}", exeName, e);
 
  256                 if (e is OptionException)
 
  257                     p.WriteOptionDescriptions(Console.Out);
 
  264         private static int BuildAndRunAndroidTests(List<string> commandArgs, 
bool reinstall, 
string resultPath)
 
  266             if (commandArgs.Count == 0)
 
  267                 throw new OptionException(
"One APK should be provided", 
"apk");
 
  271             if (!Int32.TryParse(Environment.GetEnvironmentVariable(
"PARADOX_BUILD_NUMBER"), out buildNumber))
 
  275             var branchName = Environment.GetEnvironmentVariable(
"PARADOX_BRANCH_NAME");
 
  279             foreach (var packageFile 
in commandArgs)
 
  281                 if (!packageFile.EndsWith(
"-Signed.apk"))
 
  282                     throw new OptionException(
"APK should end up with \"-Signed.apk\"", 
"apk");
 
  285                 var packageName = Path.GetFileName(packageFile);
 
  286                 packageName = packageName.Replace(
"-Signed.apk", string.Empty);
 
  288                 var androidDevices = AndroidDeviceEnumerator.ListAndroidDevices();
 
  289                 if (androidDevices.Length == 0)
 
  290                     throw new InvalidOperationException(
"Could not find any Android device connected.");
 
  292                 foreach (var device 
in androidDevices)
 
  295                     Directory.CreateDirectory(resultPath);
 
  296                     var deviceResultFile = Path.Combine(resultPath, 
"TestResult_" + packageName + 
"_Android_" + device.Name + 
"_" + device.Serial + 
".xml");
 
  298                     var currentExitCode = testServerHost.RunAndroidTest(
 
  302                             Serial = device.Serial,
 
  303                             Platform = TestPlatform.Android,
 
  305                         reinstall, packageName, packageFile, deviceResultFile);
 
  306                     if (currentExitCode != 0)
 
  307                         exitCode = currentExitCode;
 
const string ParadoxServerIp
 
const string ParadoxBuildNumber
 
A structure to store information about the connected test devices. 
 
const string ParadoxBranchName
 
int RunAndroidTest(ConnectedDevice device, bool reinstall, string packageName, string packageFile, string resultFile)
 
TestServerHost(int bn, string branch)
 
const string ParadoxServerPort
 
override string ToString()