1
+ //! `run-make-support` is a support library for run-make tests. It provides command wrappers and
2
+ //! convenience utility functions to help test writers reduce duplication. The support library
3
+ //! notably is built via cargo: this means that if your test wants some non-trivial utility, such
4
+ //! as `object` or `wasmparser`, they can be re-exported and be made available through this library.
5
+
1
6
pub mod cc;
2
7
pub mod run;
3
8
pub mod rustc;
@@ -82,7 +87,7 @@ pub fn cygpath_windows<P: AsRef<Path>>(path: P) -> String {
82
87
cygpath. arg ( path. as_ref ( ) ) ;
83
88
let output = cygpath. output ( ) . unwrap ( ) ;
84
89
if !output. status . success ( ) {
85
- handle_failed_output ( & format ! ( "{:#?}" , cygpath) , output, caller_line_number) ;
90
+ handle_failed_output ( & cygpath, output, caller_line_number) ;
86
91
}
87
92
let s = String :: from_utf8 ( output. stdout ) . unwrap ( ) ;
88
93
// cygpath -w can attach a newline
@@ -98,18 +103,18 @@ pub fn uname() -> String {
98
103
let mut uname = Command :: new ( "uname" ) ;
99
104
let output = uname. output ( ) . unwrap ( ) ;
100
105
if !output. status . success ( ) {
101
- handle_failed_output ( & format ! ( "{:#?}" , uname) , output, caller_line_number) ;
106
+ handle_failed_output ( & uname, output, caller_line_number) ;
102
107
}
103
108
String :: from_utf8 ( output. stdout ) . unwrap ( )
104
109
}
105
110
106
- fn handle_failed_output ( cmd : & str , output : Output , caller_line_number : u32 ) -> ! {
111
+ fn handle_failed_output ( cmd : & Command , output : Output , caller_line_number : u32 ) -> ! {
107
112
if output. status . success ( ) {
108
- eprintln ! ( "command incorrectly succeeded at line {caller_line_number}" ) ;
113
+ eprintln ! ( "command unexpectedly succeeded at line {caller_line_number}" ) ;
109
114
} else {
110
115
eprintln ! ( "command failed at line {caller_line_number}" ) ;
111
116
}
112
- eprintln ! ( "{cmd}" ) ;
117
+ eprintln ! ( "{cmd:? }" ) ;
113
118
eprintln ! ( "output status: `{}`" , output. status) ;
114
119
eprintln ! ( "=== STDOUT ===\n {}\n \n " , String :: from_utf8( output. stdout) . unwrap( ) ) ;
115
120
eprintln ! ( "=== STDERR ===\n {}\n \n " , String :: from_utf8( output. stderr) . unwrap( ) ) ;
@@ -129,3 +134,127 @@ pub fn set_host_rpath(cmd: &mut Command) {
129
134
env:: join_paths ( paths. iter ( ) ) . unwrap ( )
130
135
} ) ;
131
136
}
137
+
138
+ /// Implement common helpers for command wrappers. This assumes that the command wrapper is a struct
139
+ /// containing a `cmd: Command` field. The provided helpers are:
140
+ ///
141
+ /// 1. Generic argument acceptors: `arg` and `args` (delegated to [`Command`]). These are intended
142
+ /// to be *fallback* argument acceptors, when specific helpers don't make sense. Prefer to add
143
+ /// new specific helper methods over relying on these generic argument providers.
144
+ /// 2. Environment manipulation methods: `env`, `env_remove` and `env_clear`: these delegate to
145
+ /// methods of the same name on [`Command`].
146
+ /// 3. Output and execution: `output`, `run` and `run_fail` are provided. `output` waits for the
147
+ /// command to finish running and returns the process's [`Output`]. `run` and `run_fail` are
148
+ /// higher-level convenience methods which waits for the command to finish running and assert
149
+ /// that the command successfully ran or failed as expected. Prefer `run` and `run_fail` when
150
+ /// possible.
151
+ ///
152
+ /// Example usage:
153
+ ///
154
+ /// ```ignore (illustrative)
155
+ /// struct CommandWrapper { cmd: Command }
156
+ ///
157
+ /// crate::impl_common_helpers!(CommandWrapper);
158
+ ///
159
+ /// impl CommandWrapper {
160
+ /// // ... additional specific helper methods
161
+ /// }
162
+ /// ```
163
+ ///
164
+ /// [`Command`]: ::std::process::Command
165
+ /// [`Output`]: ::std::process::Output
166
+ macro_rules! impl_common_helpers {
167
+ ( $wrapper: ident) => {
168
+ impl $wrapper {
169
+ /// Specify an environment variable.
170
+ pub fn env<K , V >( & mut self , key: K , value: V ) -> & mut Self
171
+ where
172
+ K : AsRef <:: std:: ffi:: OsStr >,
173
+ V : AsRef <:: std:: ffi:: OsStr >,
174
+ {
175
+ self . cmd. env( key, value) ;
176
+ self
177
+ }
178
+
179
+ /// Remove an environmental variable.
180
+ pub fn env_remove<K >( & mut self , key: K ) -> & mut Self
181
+ where
182
+ K : AsRef <:: std:: ffi:: OsStr >,
183
+ {
184
+ self . cmd. env_remove( key) ;
185
+ self
186
+ }
187
+
188
+ /// Clear all environmental variables.
189
+ pub fn env_var( & mut self ) -> & mut Self {
190
+ self . cmd. env_clear( ) ;
191
+ self
192
+ }
193
+
194
+ /// Generic command argument provider. Prefer specific helper methods if possible.
195
+ /// Note that for some executables, arguments might be platform specific. For C/C++
196
+ /// compilers, arguments might be platform *and* compiler specific.
197
+ pub fn arg<S >( & mut self , arg: S ) -> & mut Self
198
+ where
199
+ S : AsRef <:: std:: ffi:: OsStr >,
200
+ {
201
+ self . cmd. arg( arg) ;
202
+ self
203
+ }
204
+
205
+ /// Generic command arguments provider. Prefer specific helper methods if possible.
206
+ /// Note that for some executables, arguments might be platform specific. For C/C++
207
+ /// compilers, arguments might be platform *and* compiler specific.
208
+ pub fn args<S >( & mut self , args: & [ S ] ) -> & mut Self
209
+ where
210
+ S : AsRef <:: std:: ffi:: OsStr >,
211
+ {
212
+ self . cmd. args( args) ;
213
+ self
214
+ }
215
+
216
+ /// Inspect what the underlying [`Command`][::std::process::Command] is up to the
217
+ /// current construction.
218
+ pub fn inspect<I >( & mut self , inspector: I ) -> & mut Self
219
+ where
220
+ I : FnOnce ( & :: std:: process:: Command ) ,
221
+ {
222
+ inspector( & self . cmd) ;
223
+ self
224
+ }
225
+
226
+ /// Get the [`Output`][::std::process::Output] of the finished process.
227
+ pub fn output( & mut self ) -> :: std:: process:: Output {
228
+ self . cmd. output( ) . expect( "failed to get output of finished process" )
229
+ }
230
+
231
+ /// Run the constructed command and assert that it is successfully run.
232
+ #[ track_caller]
233
+ pub fn run( & mut self ) -> :: std:: process:: Output {
234
+ let caller_location = :: std:: panic:: Location :: caller( ) ;
235
+ let caller_line_number = caller_location. line( ) ;
236
+
237
+ let output = self . cmd. output( ) . unwrap( ) ;
238
+ if !output. status. success( ) {
239
+ handle_failed_output( & self . cmd, output, caller_line_number) ;
240
+ }
241
+ output
242
+ }
243
+
244
+ /// Run the constructed command and assert that it does not successfully run.
245
+ #[ track_caller]
246
+ pub fn run_fail( & mut self ) -> :: std:: process:: Output {
247
+ let caller_location = :: std:: panic:: Location :: caller( ) ;
248
+ let caller_line_number = caller_location. line( ) ;
249
+
250
+ let output = self . cmd. output( ) . unwrap( ) ;
251
+ if output. status. success( ) {
252
+ handle_failed_output( & self . cmd, output, caller_line_number) ;
253
+ }
254
+ output
255
+ }
256
+ }
257
+ } ;
258
+ }
259
+
260
+ pub ( crate ) use impl_common_helpers;
0 commit comments