Skip to content

Commit e9a27b8

Browse files
authored
Merge pull request #83 from epage/test-lexarg
fix(test-lexarg)!: Clean up overall structure
2 parents b892828 + 0c5844b commit e9a27b8

3 files changed

Lines changed: 77 additions & 27 deletions

File tree

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
fn main() -> lexarg::Result<()> {
2+
use lexarg::prelude::*;
3+
4+
let mut test_opts = libtest_lexarg::TestOptsBuilder::new();
5+
6+
let raw = std::env::args_os().collect::<Vec<_>>();
7+
let mut parser = lexarg::Parser::new(&raw);
8+
let bin = parser
9+
.next_raw()
10+
.expect("first arg, no pending values")
11+
.unwrap_or(std::ffi::OsStr::new("test"));
12+
let mut prev_arg = Value(bin);
13+
while let Some(arg) = parser.next_arg() {
14+
match arg {
15+
Short("h") | Long("help") => {
16+
let bin = bin.to_string_lossy();
17+
let options_help = libtest_lexarg::OPTIONS_HELP.trim();
18+
let after_help = libtest_lexarg::AFTER_HELP.trim();
19+
println!(
20+
"Usage: {bin} [OPTIONS] [FILTER]...
21+
22+
{options_help}
23+
24+
{after_help}"
25+
);
26+
std::process::exit(0);
27+
}
28+
// All values are the same, whether escaped or not, so its a no-op
29+
Escape(_) => {
30+
prev_arg = arg;
31+
continue;
32+
}
33+
Unexpected(_) => {
34+
return Err(lexarg::ErrorContext::msg("unexpected value")
35+
.unexpected(arg)
36+
.within(prev_arg)
37+
.into());
38+
}
39+
_ => {}
40+
}
41+
prev_arg = arg;
42+
43+
let arg = test_opts.parse_next(&mut parser, arg)?;
44+
45+
if let Some(arg) = arg {
46+
return Err(lexarg::ErrorContext::msg("unexpected argument")
47+
.unexpected(arg)
48+
.into());
49+
}
50+
}
51+
52+
let opts = test_opts.finish()?;
53+
println!("{opts:#?}");
54+
55+
Ok(())
56+
}

crates/libtest-lexarg/src/lib.rs

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
//! libtest-compatible argument parser
22
//!
3-
//! This does not drive parsing but provides [`TestOptsParseState`] to plug into the parsing,
3+
//! This does not drive parsing but provides [`TestOptsBuilder`] to plug into the parsing,
44
//! allowing additional parsers to be integrated.
5+
//!
6+
//! ## Example
7+
//!
8+
//! ```no_run
9+
#![doc = include_str!("../examples/libtest-cli.rs")]
10+
//! ```
511
612
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
713
#![forbid(unsafe_code)]
@@ -12,7 +18,7 @@ use lexarg_error::ErrorContext;
1218

1319
/// Parsed command-line options
1420
///
15-
/// To parse, see [`TestOptsParseState`]
21+
/// To parse, see [`TestOptsBuilder`]
1622
#[derive(Debug, Default)]
1723
pub struct TestOpts {
1824
pub list: bool,
@@ -23,7 +29,6 @@ pub struct TestOpts {
2329
pub run_ignored: RunIgnored,
2430
pub run_tests: bool,
2531
pub bench_benchmarks: bool,
26-
pub logfile: Option<std::path::PathBuf>,
2732
pub nocapture: bool,
2833
pub color: ColorConfig,
2934
pub format: OutputFormat,
@@ -40,7 +45,7 @@ pub struct TestOpts {
4045
pub allowed_unstable: Vec<String>,
4146
}
4247

43-
/// Whether ignored test should be run or not
48+
/// Whether ignored test should be run or not (see [`TestOpts::run_ignored`])
4449
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
4550
pub enum RunIgnored {
4651
Yes,
@@ -55,7 +60,7 @@ impl Default for RunIgnored {
5560
}
5661
}
5762

58-
/// Whether should console output be colored or not
63+
/// Whether should console output be colored or not (see [`TestOpts::color`])
5964
#[derive(Copy, Clone, Debug)]
6065
pub enum ColorConfig {
6166
AutoColor,
@@ -69,7 +74,7 @@ impl Default for ColorConfig {
6974
}
7075
}
7176

72-
/// Format of the test results output
77+
/// Format of the test results output (see [`TestOpts::format`])
7378
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
7479
pub enum OutputFormat {
7580
/// Verbose output
@@ -88,7 +93,7 @@ impl Default for OutputFormat {
8893
}
8994
}
9095

91-
/// Structure with parameters for calculating test execution time.
96+
/// Structure with parameters for calculating test execution time (see [`TestOpts::time_options`])
9297
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
9398
pub struct TestTimeOptions {
9499
/// Denotes if the test critical execution time limit excess should be considered
@@ -119,7 +124,7 @@ impl Default for TestTimeOptions {
119124
}
120125
}
121126

122-
/// Structure denoting time limits for test execution.
127+
/// Structure denoting time limits for test execution (see [`TestTimeOptions`])
123128
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
124129
pub struct TimeThreshold {
125130
pub warn: std::time::Duration,
@@ -172,7 +177,9 @@ impl TimeThreshold {
172177
}
173178
}
174179

175-
/// Options for the test run defined by the caller (instead of CLI arguments).
180+
/// Options for the test run defined by the caller (instead of CLI arguments) (see
181+
/// [`TestOpts::options`])
182+
///
176183
/// In case we want to add other options as well, just add them in this struct.
177184
#[derive(Copy, Clone, Debug, Default)]
178185
pub struct Options {
@@ -194,7 +201,6 @@ Options:
194201
--test Run tests and not benchmarks
195202
--bench Run benchmarks instead of tests
196203
--list List all tests and benchmarks
197-
--logfile PATH Write logs to the specified file
198204
--nocapture don't capture stdout/stderr of each task, allow
199205
printing directly
200206
--test-threads n_threads
@@ -284,17 +290,17 @@ Test Attributes:
284290

285291
/// Intermediate CLI parser state for [`TestOpts`]
286292
///
287-
/// See [`TestOptsParseState::parse_next`]
293+
/// See [`TestOptsBuilder::parse_next`]
288294
#[derive(Debug, Default)]
289-
pub struct TestOptsParseState {
295+
pub struct TestOptsBuilder {
290296
opts: TestOpts,
291297
quiet: bool,
292298
format: Option<OutputFormat>,
293299
include_ignored: bool,
294300
ignored: bool,
295301
}
296302

297-
impl TestOptsParseState {
303+
impl TestOptsBuilder {
298304
pub fn new() -> Self {
299305
Default::default()
300306
}
@@ -327,14 +333,6 @@ impl TestOptsParseState {
327333
Long("list") => {
328334
self.opts.list = true;
329335
}
330-
Long("logfile") => {
331-
let path = parser
332-
.next_flag_value()
333-
.ok_or_missing(Value(std::ffi::OsStr::new("PATH")))
334-
.path()
335-
.within(arg)?;
336-
self.opts.logfile = Some(path.to_owned());
337-
}
338336
Long("nocapture") => {
339337
self.opts.nocapture = true;
340338
}
@@ -508,8 +506,7 @@ impl TestOptsParseState {
508506
}
509507
if let Some(format) = self.format {
510508
self.opts.format = format;
511-
}
512-
if self.quiet {
509+
} else if self.quiet {
513510
self.opts.format = OutputFormat::Terse;
514511
}
515512

crates/libtest2-harness/src/harness.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ const ERROR_EXIT_CODE: i32 = 101;
7373
fn parse<'p>(
7474
parser: &mut cli::Parser<'p>,
7575
) -> Result<libtest_lexarg::TestOpts, cli::ErrorContext<'p>> {
76-
let mut test_opts = libtest_lexarg::TestOptsParseState::new();
76+
let mut test_opts = libtest_lexarg::TestOptsBuilder::new();
7777

7878
let bin = parser
7979
.next_raw()
@@ -235,9 +235,6 @@ fn run(
235235
if opts.options.panic_abort {
236236
todo!("panic-abort is not yet supported");
237237
}
238-
if opts.logfile.is_some() {
239-
todo!("`--logfile` is not yet supported");
240-
}
241238

242239
let threads = opts.test_threads.map(|t| t.get()).unwrap_or(1);
243240

0 commit comments

Comments
 (0)