use unilang_parser ::{ Parser, UnilangParserOptions, ShellArgv, ReplInput };
#[ test ]
fn shell_argv_round_trips_via_parse_cli()
{
let parser = Parser::new( UnilangParserOptions::default() );
let argv = ShellArgv::from_vec(
vec![ "prog".into(), ".cmd".into(), "key::value".into() ]
);
let result = parser.parse_cli( &argv );
assert!( result.is_ok(), "parse_cli must succeed for valid argv, got: {:?}", result );
}
#[ test ]
fn repl_input_round_trips_via_parse_repl()
{
let parser = Parser::new( UnilangParserOptions::default() );
let input = ReplInput::new( ".cmd key::value" );
let result = parser.parse_repl( &input );
assert!( result.is_ok(), "parse_repl must succeed for valid string, got: {:?}", result );
}
#[ test ]
fn shell_argv_from_vec_conversion()
{
let argv : ShellArgv = vec![ "prog".to_owned(), ".cmd".to_owned() ].into();
assert_eq!( argv.as_slice().len(), 2, "from Vec conversion must preserve all elements" );
}
#[ test ]
fn repl_input_from_str_conversion()
{
let input : ReplInput = ".cmd key::val".into();
assert_eq!( input.as_str(), ".cmd key::val", "from &str must preserve content" );
}
#[ test ]
fn repl_input_from_string_conversion()
{
let input : ReplInput = ".cmd key::val".to_owned().into();
assert_eq!( input.as_str(), ".cmd key::val", "from String must preserve content" );
}
#[ test ]
fn shell_argv_empty_yields_empty_instruction()
{
let parser = Parser::new( UnilangParserOptions::default() );
let argv = ShellArgv::from_vec( vec![] );
let result = parser.parse_cli( &argv );
assert!( result.is_ok(), "empty argv must produce Ok result" );
let instr = result.unwrap();
assert!( instr.command_path_slices.is_empty(), "empty argv must yield empty command path" );
}
#[ test ]
fn parse_repl_delegates_to_parse_repl_input()
{
let parser = Parser::new( UnilangParserOptions::default() );
let raw = "cmd key::value";
let expected = parser.parse_repl_input( raw ).expect( "parse_repl_input must succeed" );
let actual = parser.parse_repl( &ReplInput::new( raw ) ).expect( "parse_repl must succeed" );
assert_eq!(
actual, expected,
"parse_repl must produce identical result to parse_repl_input"
);
}
#[ test ]
fn parse_cli_delegates_to_parse_from_argv()
{
let parser = Parser::new( UnilangParserOptions::default() );
let argv : Vec< String > = vec![ "prog".into(), ".cmd".into(), "key::value".into() ];
let expected = parser.parse_from_argv( &argv ).expect( "parse_from_argv must succeed" );
let shell_argv = ShellArgv::from_vec( argv );
let actual = parser.parse_cli( &shell_argv ).expect( "parse_cli must succeed" );
assert_eq!(
actual, expected,
"parse_cli must produce identical result to parse_from_argv"
);
}
#[ test ]
#[ allow( deprecated ) ]
fn deprecated_shim_matches_parse_repl_input()
{
let parser = Parser::new( UnilangParserOptions::default() );
let raw = "cmd key::value";
let expected = parser.parse_repl_input( raw ).expect( "parse_repl_input must succeed" );
let actual = parser.parse_single_instruction( raw )
.expect( "deprecated shim must succeed" );
assert_eq!(
actual, expected,
"deprecated shim must produce identical result to parse_repl_input"
);
}
#[ test ]
fn parse_cli_extracts_named_argument()
{
let parser = Parser::new( UnilangParserOptions::default() );
let argv = ShellArgv::from_vec(
vec![ "prog".into(), ".cmd".into(), "key::value".into() ]
);
let instr = parser.parse_cli( &argv ).expect( "parse_cli must succeed" );
assert!(
instr.named_arguments.contains_key( "key" ),
"named argument 'key' must be present, got args: {:?}", instr.named_arguments
);
assert_eq!(
instr.named_arguments[ "key" ][ 0 ].value, "value",
"named argument 'key' must have value 'value'"
);
}
#[ test ]
fn parse_repl_extracts_named_argument()
{
let parser = Parser::new( UnilangParserOptions::default() );
let input = ReplInput::new( "cmd key::value" );
let instr = parser.parse_repl( &input ).expect( "parse_repl must succeed" );
assert!(
instr.named_arguments.contains_key( "key" ),
"named argument 'key' must be present, got args: {:?}", instr.named_arguments
);
assert_eq!(
instr.named_arguments[ "key" ][ 0 ].value, "value",
"named argument 'key' must have value 'value'"
);
}
#[ test ]
fn parse_repl_sets_help_requested_flag()
{
let parser = Parser::new( UnilangParserOptions::default() );
let input = ReplInput::new( "cmd ?" );
let instr = parser.parse_repl( &input ).expect( "parse_repl must succeed" );
assert!(
instr.help_requested,
"parse_repl must set help_requested for '?' operator"
);
}
#[ test ]
fn parse_cli_sets_help_requested_flag()
{
let parser = Parser::new( UnilangParserOptions::default() );
let argv = ShellArgv::from_vec(
vec![ "prog".into(), ".cmd".into(), "?".into() ]
);
let instr = parser.parse_cli( &argv ).expect( "parse_cli must succeed" );
assert!(
instr.help_requested,
"parse_cli must set help_requested for '?' operator"
);
}
#[ test ]
fn repl_input_empty_string_yields_empty_instruction()
{
let parser = Parser::new( UnilangParserOptions::default() );
let input = ReplInput::new( "" );
let result = parser.parse_repl( &input );
assert!( result.is_ok(), "empty ReplInput must produce Ok, got: {:?}", result );
let instr = result.unwrap();
assert!(
instr.command_path_slices.is_empty(),
"empty ReplInput must yield empty command path"
);
}
#[ test ]
fn repl_input_whitespace_only_yields_empty_instruction()
{
let parser = Parser::new( UnilangParserOptions::default() );
let input = ReplInput::new( " " );
let result = parser.parse_repl( &input );
assert!( result.is_ok(), "whitespace-only ReplInput must produce Ok, got: {:?}", result );
let instr = result.unwrap();
assert!(
instr.command_path_slices.is_empty(),
"whitespace-only ReplInput must yield empty command path"
);
}
#[ test ]
fn parse_repl_propagates_error_for_unclosed_quote()
{
let parser = Parser::new( UnilangParserOptions::default() );
let input = ReplInput::new( "cmd key::\"unclosed" );
let result = parser.parse_repl( &input );
assert!( result.is_err(), "unclosed quote must propagate Err through parse_repl" );
}
#[ test ]
fn parse_cli_propagates_error_for_single_colon_arg()
{
let parser = Parser::new( UnilangParserOptions::default() );
let argv = ShellArgv::from_vec(
vec![ "prog".into(), ".cmd".into(), "bad:syntax".into() ]
);
let result = parser.parse_cli( &argv );
assert!( result.is_err(), "single-colon arg must propagate Err through parse_cli" );
}
#[ test ]
fn shell_argv_clone_is_independent()
{
let original = ShellArgv::from_vec( vec![ "prog".into(), ".cmd".into() ] );
let cloned = original.clone();
assert_eq!(
original.as_slice(), cloned.as_slice(),
"clone must preserve all elements"
);
}
#[ test ]
fn repl_input_clone_is_independent()
{
let original = ReplInput::new( ".cmd key::val" );
let cloned = original.clone();
assert_eq!(
original.as_str(), cloned.as_str(),
"clone must preserve content"
);
}