@@ -50,7 +50,7 @@ pub fn get_cargo_workspace() -> &'static std::path::Path {
5050}
5151
5252#[ derive( clap:: Parser , Debug ) ]
53- pub struct TestOpts {
53+ pub struct TestAll {
5454 /// Run a long test (it's very long)
5555 #[ clap( short = 'l' , long) ]
5656 pub long_test : bool ,
@@ -59,7 +59,7 @@ pub struct TestOpts {
5959 #[ clap( short = 'c' , long) ]
6060 pub chip : Vec < String > ,
6161
62- /// Filter by manufacturer, case sensitive, may be combined with other filters
62+ /// Filter by manufacturer, may be combined with other filters
6363 #[ clap(
6464 short = 'm' ,
6565 long = "manufacturer" ,
@@ -68,7 +68,7 @@ pub struct TestOpts {
6868) ]
6969 pub mfgr : Option < String > ,
7070
71- /// Filter by architecture, case sensitive, may be combined with other filters
71+ /// Filter by architecture, may be combined with other filters
7272 #[ clap(
7373 short = 'a' ,
7474 long = "architecture" ,
@@ -104,7 +104,97 @@ pub struct TestOpts {
104104 // TODO: Compile svd2rust?
105105}
106106
107- impl TestOpts {
107+ #[ derive( clap:: Parser , Debug ) ]
108+ // TODO: Replace with https://github.com/clap-rs/clap/issues/2621 when available
109+ #[ group( id = "svd_source" , required = true ) ]
110+ pub struct Test {
111+ /// Enable formatting with `rustfmt`
112+ #[ arg( short = 'f' , long) ]
113+ pub format : bool ,
114+
115+ #[ arg( long) ]
116+ /// Enable splitting `lib.rs` with `form`
117+ pub form_lib : bool ,
118+
119+ #[ arg(
120+ short = 'm' ,
121+ long = "manufacturer" ,
122+ ignore_case = true ,
123+ value_parser = manufacturers( ) ,
124+ ) ]
125+ /// Manufacturer
126+ pub mfgr : Option < String > ,
127+ #[ arg(
128+ short = 'a' ,
129+ long = "architecture" ,
130+ ignore_case = true ,
131+ value_parser = architectures( ) ,
132+ ) ]
133+ /// Architecture
134+ pub arch : Option < String > ,
135+ #[ arg( long, group = "svd_source" , conflicts_with_all = [ "svd_file" ] , requires = "arch" ) ]
136+ /// URL to SVD file to test
137+ pub url : Option < String > ,
138+ #[ arg( long = "svd" , group = "svd_source" ) ]
139+ /// Path to SVD file to test
140+ pub svd_file : Option < PathBuf > ,
141+ #[ arg( long, group = "svd_source" ) ]
142+ /// Chip to use, use `--url` or `--svd-file` for another way to specify svd
143+ pub chip : Option < String > ,
144+
145+ /// Path to an `svd2rust` binary, relative or absolute.
146+ /// Defaults to `target/release/svd2rust[.exe]` of this repository
147+ /// (which must be already built)
148+ #[ clap( short = 'p' , long = "svd2rust-path" , default_value = default_svd2rust( ) ) ]
149+ pub current_bin_path : PathBuf ,
150+ #[ clap( last = true ) ]
151+ pub command : Option < String > ,
152+ }
153+
154+ impl Test {
155+ fn run ( & self , opts : & Opts ) -> Result < ( ) , anyhow:: Error > {
156+ match self {
157+ Self { url : Some ( url) , .. } => { }
158+ Self {
159+ svd_file : Some ( svd_file) ,
160+ ..
161+ } => { }
162+ Self {
163+ chip : Some ( chip) , ..
164+ } => { }
165+ _ => unreachable ! ( "clap should not allow this" ) ,
166+ }
167+ let test = if let ( Some ( url) , Some ( arch) ) = ( & self . url , & self . arch ) {
168+ tests:: TestCase {
169+ arch : svd2rust:: Target :: parse ( & arch) ?,
170+ mfgr : tests:: Manufacturer :: Unknown ,
171+ chip : self
172+ . chip
173+ . as_deref ( )
174+ . or_else ( || url. rsplit ( '/' ) . next ( ) . and_then ( |s| s. strip_suffix ( ".svd" ) ) )
175+ . ok_or_else ( || {
176+ anyhow:: anyhow!(
177+ "could not figure out chip name, specify with `--chip <name>`" ,
178+ )
179+ } ) ?
180+ . to_owned ( ) ,
181+ svd_url : Some ( url. clone ( ) ) ,
182+ should_pass : true ,
183+ run_when : tests:: RunWhen :: default ( ) ,
184+ }
185+ } else {
186+ tests:: tests ( Some ( & opts. test_cases ) ) ?
187+ . iter ( )
188+ . find ( |t| self . chip . iter ( ) . any ( |c| WildMatch :: new ( c) . matches ( & t. chip ) ) )
189+ . ok_or_else ( || anyhow:: anyhow!( "no test found for chip" ) ) ?
190+ . to_owned ( )
191+ } ;
192+ test. test ( opts, & self . current_bin_path , self . command . as_deref ( ) ) ?;
193+ Ok ( ( ) )
194+ }
195+ }
196+
197+ impl TestAll {
108198 fn run ( & self , opt : & Opts ) -> Result < ( ) , anyhow:: Error > {
109199 let tests = tests:: tests ( Some ( & opt. test_cases ) ) ?
110200 . iter ( )
@@ -152,7 +242,7 @@ impl TestOpts {
152242 tests. par_iter ( ) . for_each ( |t| {
153243 let start = Instant :: now ( ) ;
154244
155- match t. test ( opt, self ) {
245+ match t. test ( opt, & self . current_bin_path , self . command . as_deref ( ) ) {
156246 Ok ( s) => {
157247 if let Some ( stderrs) = s {
158248 let mut buf = String :: new ( ) ;
@@ -217,7 +307,8 @@ impl TestOpts {
217307#[ derive( clap:: Subcommand , Debug ) ]
218308pub enum Subcommand {
219309 Diff ( Diffing ) ,
220- Tests ( TestOpts ) ,
310+ Tests ( TestAll ) ,
311+ Test ( Test ) ,
221312 Ci ( Ci ) ,
222313}
223314
@@ -256,15 +347,17 @@ pub struct Opts {
256347impl Opts {
257348 const fn use_rustfmt ( & self ) -> bool {
258349 match self . subcommand {
259- Subcommand :: Tests ( TestOpts { format, .. } )
350+ Subcommand :: Tests ( TestAll { format, .. } )
351+ | Subcommand :: Test ( Test { format, .. } )
260352 | Subcommand :: Diff ( Diffing { format, .. } )
261353 | Subcommand :: Ci ( Ci { format, .. } ) => format,
262354 }
263355 }
264356
265357 const fn use_form ( & self ) -> bool {
266358 match self . subcommand {
267- Subcommand :: Tests ( TestOpts { form_lib, .. } )
359+ Subcommand :: Tests ( TestAll { form_lib, .. } )
360+ | Subcommand :: Test ( Test { form_lib, .. } )
268361 | Subcommand :: Diff ( Diffing {
269362 form_split : form_lib,
270363 ..
@@ -278,13 +371,10 @@ impl Opts {
278371fn default_test_cases ( ) -> std:: ffi:: OsString {
279372 std:: env:: var_os ( "CARGO_MANIFEST_DIR" ) . map_or_else (
280373 || std:: ffi:: OsString :: from ( "tests.yml" . to_owned ( ) ) ,
281- |mut e| {
282- e. extend ( [ std:: ffi:: OsStr :: new ( "/tests.yml" ) ] ) ;
283- std:: path:: PathBuf :: from ( e)
284- . strip_prefix ( std:: env:: current_dir ( ) . unwrap ( ) )
285- . unwrap ( )
286- . to_owned ( )
287- . into_os_string ( )
374+ |path| {
375+ let path = std:: path:: PathBuf :: from ( path) ;
376+ let path = path. join ( "tests.yml" ) ;
377+ path. to_owned ( ) . into_os_string ( )
288378 } ,
289379 )
290380}
@@ -414,6 +504,13 @@ fn main() -> Result<(), anyhow::Error> {
414504 }
415505 Subcommand :: Diff ( diff) => diff. run ( & opt) . with_context ( || "failed to run diff" ) ,
416506 Subcommand :: Ci ( ci) => ci. run ( & opt) . with_context ( || "failed to run ci" ) ,
507+ Subcommand :: Test ( test) => {
508+ anyhow:: ensure!(
509+ test. current_bin_path. exists( ) ,
510+ "svd2rust binary does not exist"
511+ ) ;
512+ test. run ( & opt) . with_context ( || "failed to run test" )
513+ }
417514 }
418515}
419516
0 commit comments