4 using System
.Threading
;
5 using System
.Diagnostics
;
7 using System
.Net
.Sockets
;
12 public const string SIM_NAME
= "xamarin.ios-sdk.sim";
14 static void Usage () {
15 Console
.WriteLine ("Usage: mono harness.exe <options> <app dir>");
16 Console
.WriteLine ("Where options are:");
17 Console
.WriteLine ("\t--run-sim");
18 Console
.WriteLine ("\t--app=<app bundle id>");
19 Console
.WriteLine ("\t--logfile=<log file name>");
22 public static int Main (string[] args
) {
23 new Harness ().Run (args
);
32 public void Run (string[] args
) {
38 var p
= new OptionSet () {
39 { "start-sim", s => action = "start-sim" }
,
40 { "run-sim", s => action = "run-sim" }
,
41 { "run-dev", s => action = "run-dev" }
,
42 { "bundle-id=", s => bundle_id = s }
,
43 { "bundle-dir=", s => bundle_dir = s }
,
44 { "logfile=", s => logfile_name = s }
,
46 new_args
= p
.Parse (args
).ToArray ();
48 if (action
== "start-sim") {
50 } else if (action
== "run-sim") {
51 if (bundle_id
== "" || bundle_dir
== "") {
52 Console
.WriteLine ("The --bundle-id and --bundle-dir arguments are mandatory.");
56 } else if (action
== "run-dev") {
57 if (bundle_dir
== "") {
58 Console
.WriteLine ("The --bundle-dir argument is mandatory.");
69 // Check whenever our simulator instance exists
70 string state_line
= "";
72 var args
= "simctl list devices";
73 Console
.WriteLine ("Running: " + "xcrun " + args
);
74 var start_info
= new ProcessStartInfo ("xcrun", args
);
75 start_info
.RedirectStandardOutput
= true;
76 start_info
.UseShellExecute
= false;
77 var process
= Process
.Start (start_info
);
78 var stream
= process
.StandardOutput
;
81 line
= stream
.ReadLine ();
84 if (line
.Contains (SIM_NAME
)) {
89 process
.WaitForExit ();
90 if (process
.ExitCode
!= 0)
94 if (state_line
.Contains ("unavailable")) {
95 // Created for an older version of xcode
96 var args
= "simctl delete unavailable";
97 Console
.WriteLine ("Running: " + "xcrun " + args
);
98 var process
= Process
.Start ("xcrun", args
);
99 process
.WaitForExit ();
103 bool need_start
= false;
104 if (state_line
== "") {
105 // Get the runtime type
106 var args
= "simctl list -j runtimes";
107 Console
.WriteLine ("Running: " + "xcrun " + args
);
108 var start_info
= new ProcessStartInfo ("xcrun", args
);
109 start_info
.RedirectStandardOutput
= true;
110 start_info
.UseShellExecute
= false;
111 var process
= Process
.Start (start_info
);
112 var stream
= process
.StandardOutput
;
113 JsonObject
value = JsonValue
.Parse (stream
.ReadToEnd ()) as JsonObject
;
114 string runtime
= value ["runtimes"][0]["identifier"];
116 // Create the simulator
117 args
= "simctl create " + SIM_NAME
+ " 'iPhone 7' " + runtime
;
118 Console
.WriteLine ("Running: " + "xcrun " + args
);
119 process
= Process
.Start ("xcrun", args
);
120 process
.WaitForExit ();
121 if (process
.ExitCode
!= 0)
122 Environment
.Exit (1);
124 } else if (state_line
.Contains ("(Shutdown)")) {
129 var args
= "simctl boot " + SIM_NAME
;
130 Console
.WriteLine ("Running: " + "xcrun " + args
);
131 var process
= Process
.Start ("xcrun", args
);
132 process
.WaitForExit ();
133 if (process
.ExitCode
!= 0)
134 Environment
.Exit (1);
139 Console
.WriteLine ("App: " + bundle_id
);
144 // We do this all the time since its cheap
145 string exe
= "xcrun";
146 string args
= "simctl install " + SIM_NAME
+ " " + bundle_dir
;
147 Console
.WriteLine ("Running: " + exe
+ " " + args
);
148 var process
= Process
.Start (exe
, args
);
149 process
.WaitForExit ();
150 if (process
.ExitCode
!= 0)
151 Environment
.Exit (1);
154 // Test results are returned using an socket connection.
156 var host
= Dns
.GetHostEntry (Dns
.GetHostName ());
157 var server
= new TcpListener (System
.Net
.IPAddress
.Loopback
, 0);
159 int port
= ((IPEndPoint
)server
.LocalEndpoint
).Port
;
161 string app_args
= "";
162 foreach (var a
in new_args
)
164 if (!app_args
.Contains ("CONNSTR"))
165 throw new Exception ();
166 app_args
= app_args
.Replace ("CONNSTR", $"tcp:localhost:{port}");
168 // Terminate previous app
170 args
= "simctl terminate " + SIM_NAME
+ " " + bundle_id
;
171 Console
.WriteLine ("Running: " + exe
+ " " + args
);
172 process
= Process
.Start (exe
, args
);
173 process
.WaitForExit ();
174 if (process
.ExitCode
!= 0)
175 Environment
.Exit (1);
179 args
= "simctl launch " + SIM_NAME
+ " " + bundle_id
+ " " + app_args
;
180 Console
.WriteLine ("Running: " + exe
+ " " + args
);
181 process
= Process
.Start (exe
, args
);
182 process
.WaitForExit ();
183 if (process
.ExitCode
!= 0)
184 Environment
.Exit (1);
187 // Read test results from the tcp connection
189 TextWriter w
= new StreamWriter (logfile_name
);
190 string result_line
= null;
191 var client
= server
.AcceptTcpClient ();
192 var stream
= client
.GetStream ();
193 var reader
= new StreamReader (stream
);
195 var line
= reader
.ReadLine ();
198 Console
.WriteLine (line
);
200 if (line
.Contains ("Tests run:"))
202 // Printed by the runtime
203 if (line
.Contains ("Exit code:"))
207 if (result_line
!= null && result_line
.Contains ("Errors: 0") && result_line
.Contains ("Failures: 0"))
208 Environment
.Exit (0);
210 Environment
.Exit (1);
214 Console
.WriteLine ("App: " + bundle_dir
);
217 // Test results are returned using an socket connection.
219 var host
= Dns
.GetHostEntry (Dns
.GetHostName ());
220 var hostip
= host
.AddressList
[0].ToString ();
221 Console
.WriteLine ("Host ip: " + hostip
);
222 var server
= new TcpListener (host
.AddressList
[0], 0);
224 int port
= ((IPEndPoint
)server
.LocalEndpoint
).Port
;
226 string app_args
= "";
227 foreach (var a
in new_args
)
229 if (!app_args
.Contains ("CONNSTR"))
230 throw new Exception ();
231 app_args
= app_args
.Replace ("CONNSTR", $"tcp:{hostip}:{port}");
238 // -u unbuffered stdout
241 string exe
= "ios-deploy";
242 string args
= "-v -L -u -b " + bundle_dir
+ " -a '" + app_args
+ "'";
243 Console
.WriteLine ("Running: " + exe
+ " " + args
);
244 var process
= Process
.Start (exe
, args
);
245 process
.WaitForExit ();
246 if (process
.ExitCode
!= 0)
247 Environment
.Exit (1);
250 // Read test results from the tcp connection
252 TextWriter w
= new StreamWriter (logfile_name
);
253 string result_line
= null;
255 Console
.WriteLine ("*** test-runner output ***");
258 while (!server
.Pending ()) {
260 if (wait_time
== 10 * 1000) {
261 Console
.Error
.WriteLine ("Timed out waiting for test runner to connect.");
262 Environment
.Exit (1);
266 var client
= server
.AcceptTcpClient ();
267 var stream
= client
.GetStream ();
268 var reader
= new StreamReader (stream
);
271 var line
= reader
.ReadLine ();
274 Console
.WriteLine (line
);
276 if (line
.Contains ("Tests run:"))
278 // Printed by the runtime
279 if (line
.Contains ("Exit code:"))
283 if (result_line
!= null && result_line
.Contains ("Errors: 0") && result_line
.Contains ("Failures: 0"))
284 Environment
.Exit (0);
286 Environment
.Exit (1);