#![ cfg( unix ) ]
mod cli_binary_test_helpers;
use cli_binary_test_helpers::{ fake_claude_dir, run_cli_with_env, stderr_str };
#[ test ]
#[ doc = "bug_reproducer(BUG-037)" ]
fn rate_limit_exit2_emits_labeled_message()
{
let ( _dir, path_val ) = fake_claude_dir( "exit 2" );
let out = run_cli_with_env(
&[ "--print", "--retry-override", "0", "--max-sessions", "0", "test" ],
&[ ( "PATH", &path_val ) ],
);
let err = stderr_str( &out );
assert!(
err.contains( "Error: [Transient] rate limit (exit 2)" ),
"T09 (BUG-037): stderr must contain 'Error: [Transient] rate limit (exit 2)'; got:\n{err}"
);
assert!(
!err.contains( "possible rate limit or quota exhaustion" ),
"T09 (BUG-037): generic phrase must be absent; got:\n{err}"
);
}
#[ test ]
#[ doc = "bug_reproducer(BUG-037)" ]
fn auth_error_pattern_in_stdout_emits_labeled_message()
{
let ( _dir, path_val ) = fake_claude_dir(
"echo 'Your organization does not have access to Claude'; exit 1",
);
let out = run_cli_with_env(
&[ "--print", "--retry-override", "0", "--max-sessions", "0", "test" ],
&[ ( "PATH", &path_val ) ],
);
let err = stderr_str( &out );
assert!(
err.contains( "Error: [Auth]" ),
"T10 (BUG-037): stderr must contain 'Error: [Auth]' prefix; got:\n{err}"
);
assert!(
err.contains( "Your organization does not have access to Claude" ),
"T10 (BUG-037): stderr must contain the original auth message; got:\n{err}"
);
assert!(
!err.contains( "possible rate limit or quota exhaustion" ),
"T10 (BUG-037): generic phrase must be absent; got:\n{err}"
);
}
#[ test ]
fn quota_exhausted_pattern_emits_labeled_message()
{
let ( _dir, path_val ) = fake_claude_dir(
"echo \"You've hit your limit\" >&2; exit 1",
);
let out = run_cli_with_env(
&[ "--print", "--retry-override", "0", "--max-sessions", "0", "test" ],
&[ ( "PATH", &path_val ) ],
);
let err = stderr_str( &out );
assert!(
err.contains( "Error: [Account]" ),
"T11 (TSK-253): stderr must contain 'Error: [Account]' prefix; got:\n{err}"
);
assert!(
err.contains( "You've hit your limit" ),
"T11 (TSK-253): stderr must contain the original quota message; got:\n{err}"
);
assert!(
!err.contains( "[Transient]" ),
"T11 (TSK-253): [Transient] must be absent for quota exhaustion; got:\n{err}"
);
}
#[ test ]
fn tc_12_runner_spawn_failed_prefix()
{
use std::os::unix::fs::PermissionsExt;
let dir = tempfile::TempDir::new().expect( "create temp dir for chmod 000 test" );
let claude = dir.path().join( "claude" );
std::fs::copy( "/bin/sleep", &claude ).expect( "copy sleep as claude" );
std::fs::set_permissions( &claude, std::fs::Permissions::from_mode( 0o755 ) )
.expect( "set 755 on claude copy" );
std::fs::set_permissions( &claude, std::fs::Permissions::from_mode( 0o000 ) )
.expect( "set 000 on claude (deny execute)" );
let path_val = dir.path().to_str().expect( "dir UTF-8" ).to_string();
let out = run_cli_with_env(
&[ "--print", "--max-sessions", "0", "--retry-override", "0", "msg" ],
&[ ( "PATH", &path_val ) ],
);
let err = stderr_str( &out );
let _ = std::fs::set_permissions( &claude, std::fs::Permissions::from_mode( 0o644 ) );
assert!(
!out.status.success(),
"TC-12 (BUG-298): expected non-zero exit for chmod 000 binary; got 0"
);
assert!(
err.contains( "[Runner]" ),
"TC-12 (BUG-298): stderr must contain '[Runner]' prefix; got:\n{err}"
);
}