7
7
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
- //
10
+
11
11
// This is a script to deploy and execute a binary on an iOS simulator.
12
- // The primary use of this is to be able to run unit tests on the simulator and retrieve the results.
12
+ // The primary use of this is to be able to run unit tests on the simulator and
13
+ // retrieve the results.
13
14
//
14
- // To do this through Cargo instead, use Dinghy (https://github.com/snipsco/dinghy):
15
- // cargo dinghy install, then cargo dinghy test.
15
+ // To do this through Cargo instead, use Dinghy
16
+ // (https://github.com/snipsco/dinghy): cargo dinghy install, then cargo dinghy
17
+ // test.
16
18
17
19
use std:: env;
18
- use std:: fs:: File ;
20
+ use std:: fs:: { self , File } ;
19
21
use std:: io:: Write ;
20
22
use std:: path:: Path ;
21
23
use std:: process;
22
24
use std:: process:: Command ;
23
25
26
+ macro_rules! t {
27
+ ( $e: expr) => ( match $e {
28
+ Ok ( e) => e,
29
+ Err ( e) => panic!( "{} failed with: {}" , stringify!( $e) , e) ,
30
+ } )
31
+ }
32
+
24
33
// Step one: Wrap as an app
25
34
fn package_as_simulator_app ( crate_name : & str , test_binary_path : & Path ) {
26
35
println ! ( "Packaging simulator app" ) ;
27
- Command :: new ( "rm" ) . arg ( "-rf" ) . arg ( "ios_simulator_app" ) . status ( ) . unwrap ( ) ;
28
- Command :: new ( "mkdir" ) . arg ( "ios_simulator_app" ) . check_status ( ) ;
29
- Command :: new ( "cp" ) . arg ( test_binary_path) . arg ( [ "ios_simulator_app/" , crate_name] . join ( "" ) ) . check_status ( ) ;
30
- let mut f = File :: create ( "ios_simulator_app/Info.plist" ) . unwrap ( ) ;
31
- f. write_all ( & [
32
- "<?xml version=\" 1.0\" encoding=\" UTF-8\" ?>" ,
33
- "<!DOCTYPE plist PUBLIC \" -//Apple//DTD PLIST 1.0//EN\" \" http://www.apple.com/DTDs/PropertyList-1.0.dtd\" >" ,
34
- "<plist version=\" 1.0\" >" ,
35
- " <dict>" ,
36
- " <key>CFBundleExecutable</key>" ,
37
- & [ " <string>" , crate_name, "</string>" ] . join ( "" ) ,
38
- " <key>CFBundleIdentifier</key>" ,
39
- " <string>com.rust.unittests</string>" ,
40
- " </dict>" ,
41
- "</plist>" ] . join ( "\n " ) . into_bytes ( ) ) . unwrap ( ) ;
36
+ drop ( fs:: remove_dir_all ( "ios_simulator_app" ) ) ;
37
+ t ! ( fs:: create_dir( "ios_simulator_app" ) ) ;
38
+ t ! ( fs:: copy( test_binary_path,
39
+ Path :: new( "ios_simulator_app" ) . join( crate_name) ) ) ;
40
+
41
+ let mut f = t ! ( File :: create( "ios_simulator_app/Info.plist" ) ) ;
42
+ t ! ( f. write_all( format!( r#"
43
+ <?xml version="1.0" encoding="UTF-8"?>
44
+ <!DOCTYPE plist PUBLIC
45
+ "-//Apple//DTD PLIST 1.0//EN"
46
+ "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
47
+ <plist version="1.0">
48
+ <dict>
49
+ <key>CFBundleExecutable</key>
50
+ <string>{}</string>
51
+ <key>CFBundleIdentifier</key>
52
+ <string>com.rust.unittests</string>
53
+ </dict>
54
+ </plist>
55
+ "# , crate_name) . as_bytes( ) ) ) ;
42
56
}
43
57
44
58
// Step two: Start the iOS simulator
45
59
fn start_simulator ( ) {
46
60
println ! ( "Looking for iOS simulator" ) ;
47
- let output = Command :: new ( "xcrun" ) . arg ( "simctl" ) . arg ( "list" ) . output ( ) . unwrap ( ) ;
61
+ let output = t ! ( Command :: new( "xcrun" ) . arg( "simctl" ) . arg( "list" ) . output( ) ) ;
62
+ assert ! ( output. status. success( ) ) ;
48
63
let mut simulator_exists = false ;
49
64
let mut simulator_booted = false ;
50
65
let mut found_rust_sim = false ;
51
- let stdout = String :: from_utf8 ( output. stdout ) . unwrap ( ) ;
66
+ let stdout = t ! ( String :: from_utf8( output. stdout) ) ;
52
67
for line in stdout. lines ( ) {
53
68
if line. contains ( "rust_ios" ) {
54
69
if found_rust_sim {
55
- panic ! ( "Duplicate rust_ios simulators found. Please double-check xcrun simctl list." ) ;
70
+ panic ! ( "Duplicate rust_ios simulators found. Please \
71
+ double-check xcrun simctl list.") ;
56
72
}
57
73
simulator_exists = true ;
58
74
simulator_booted = line. contains ( "(Booted)" ) ;
@@ -62,43 +78,69 @@ fn start_simulator() {
62
78
63
79
if simulator_exists == false {
64
80
println ! ( "Creating iOS simulator" ) ;
65
- Command :: new ( "xcrun" ) . arg ( "simctl" ) . arg ( "create" ) . arg ( "rust_ios" )
66
- . arg ( "com.apple.CoreSimulator.SimDeviceType.iPhone-SE" ) . arg ( "com.apple.CoreSimulator.SimRuntime.iOS-10-2" ) . check_status ( ) ;
81
+ Command :: new ( "xcrun" )
82
+ . arg ( "simctl" )
83
+ . arg ( "create" )
84
+ . arg ( "rust_ios" )
85
+ . arg ( "com.apple.CoreSimulator.SimDeviceType.iPhone-SE" )
86
+ . arg ( "com.apple.CoreSimulator.SimRuntime.iOS-10-2" )
87
+ . check_status ( ) ;
67
88
} else if simulator_booted == true {
68
89
println ! ( "Shutting down already-booted simulator" ) ;
69
- Command :: new ( "xcrun" ) . arg ( "simctl" ) . arg ( "shutdown" ) . arg ( "rust_ios" ) . check_status ( ) ;
90
+ Command :: new ( "xcrun" )
91
+ . arg ( "simctl" )
92
+ . arg ( "shutdown" )
93
+ . arg ( "rust_ios" )
94
+ . check_status ( ) ;
70
95
}
71
96
72
97
println ! ( "Starting iOS simulator" ) ;
73
- // We can't uninstall the app (if present) as that will hang if the simulator isn't completely booted;just erase the simulator instead.
98
+ // We can't uninstall the app (if present) as that will hang if the
99
+ // simulator isn't completely booted; just erase the simulator instead.
74
100
Command :: new ( "xcrun" ) . arg ( "simctl" ) . arg ( "erase" ) . arg ( "rust_ios" ) . check_status ( ) ;
75
101
Command :: new ( "xcrun" ) . arg ( "simctl" ) . arg ( "boot" ) . arg ( "rust_ios" ) . check_status ( ) ;
76
102
}
77
103
78
104
// Step three: Install the app
79
- fn install_app_to_simulator ( ) {
105
+ fn install_app_to_simulator ( ) {
80
106
println ! ( "Installing app to simulator" ) ;
81
- Command :: new ( "xcrun" ) . arg ( "simctl" ) . arg ( "install" ) . arg ( "booted" ) . arg ( "ios_simulator_app/" ) . check_status ( ) ;
107
+ Command :: new ( "xcrun" )
108
+ . arg ( "simctl" )
109
+ . arg ( "install" )
110
+ . arg ( "booted" )
111
+ . arg ( "ios_simulator_app/" )
112
+ . check_status ( ) ;
82
113
}
83
114
84
115
// Step four: Run the app
85
116
fn run_app_on_simulator ( ) {
86
117
println ! ( "Running app" ) ;
87
- let output = Command :: new ( "xcrun" ) . arg ( "simctl" ) . arg ( "launch" ) . arg ( "--console" ) . arg ( "booted" ) . arg ( "com.rust.unittests" ) . output ( ) . unwrap ( ) ;
88
- let mut test_run_passed = false ;
89
- let stdout = String :: from_utf8 ( output. stdout ) . unwrap ( ) ;
90
- for line in stdout. lines ( ) {
91
- println ! ( "{}" , line) ;
92
-
93
- if test_run_passed == false {
94
- // Based on all.rs test output
95
- test_run_passed = line. contains ( "PASSED" ) && line. contains ( "tests" ) ;
96
- }
97
- }
118
+ let output = t ! ( Command :: new( "xcrun" )
119
+ . arg( "simctl" )
120
+ . arg( "launch" )
121
+ . arg( "--console" )
122
+ . arg( "booted" )
123
+ . arg( "com.rust.unittests" )
124
+ . output( ) ) ;
125
+
126
+ println ! ( "stdout --\n {}\n " , String :: from_utf8_lossy( & output. stdout) ) ;
127
+ println ! ( "stderr --\n {}\n " , String :: from_utf8_lossy( & output. stderr) ) ;
128
+
129
+ let stdout = String :: from_utf8_lossy ( & output. stdout ) ;
130
+ let passed = stdout. lines ( )
131
+ . find ( |l| l. contains ( "PASSED" ) )
132
+ . map ( |l| l. contains ( "tests" ) )
133
+ . unwrap_or ( false ) ;
98
134
99
135
println ! ( "Shutting down simulator" ) ;
100
- Command :: new ( "xcrun" ) . arg ( "simctl" ) . arg ( "shutdown" ) . arg ( "rust_ios" ) . check_status ( ) ;
101
- assert ! ( test_run_passed) ;
136
+ Command :: new ( "xcrun" )
137
+ . arg ( "simctl" )
138
+ . arg ( "shutdown" )
139
+ . arg ( "rust_ios" )
140
+ . check_status ( ) ;
141
+ if !passed {
142
+ panic ! ( "tests didn't pass" ) ;
143
+ }
102
144
}
103
145
104
146
trait CheckStatus {
@@ -107,22 +149,23 @@ trait CheckStatus {
107
149
108
150
impl CheckStatus for Command {
109
151
fn check_status ( & mut self ) {
110
- assert ! ( self . status( ) . unwrap( ) . success( ) ) ;
152
+ println ! ( "\t running: {:?}" , self ) ;
153
+ assert ! ( t!( self . status( ) ) . success( ) ) ;
111
154
}
112
155
}
113
156
114
- pub fn main ( ) {
157
+ fn main ( ) {
115
158
let args: Vec < String > = env:: args ( ) . collect ( ) ;
116
159
if args. len ( ) != 2 {
117
- println ! ( "Usage: {:?} executable" , Path :: new ( & args[ 0 ] ) . file_name ( ) . unwrap ( ) ) ;
160
+ println ! ( "Usage: {} < executable> " , args[ 0 ] ) ;
118
161
process:: exit ( -1 ) ;
119
162
}
120
-
163
+
121
164
let test_binary_path = Path :: new ( & args[ 1 ] ) ;
122
165
let crate_name = test_binary_path. file_name ( ) . unwrap ( ) ;
123
166
124
167
package_as_simulator_app ( crate_name. to_str ( ) . unwrap ( ) , test_binary_path) ;
125
168
start_simulator ( ) ;
126
169
install_app_to_simulator ( ) ;
127
170
run_app_on_simulator ( ) ;
128
- }
171
+ }
0 commit comments