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()