use std::fs;
use std::path::Path;
fn read_command_src() -> String
{
let dir_path = Path::new( "src/command" );
let file_path = Path::new( "src/command.rs" );
if dir_path.is_dir()
{
let mut content = String::new();
let mut entries : Vec<_> = fs::read_dir( dir_path )
.expect( "Failed to read src/command/ directory" )
.filter_map( | e | e.ok() )
.filter( | e |
{
e.path().extension().map_or( false, | ext | ext == "rs" )
})
.collect();
entries.sort_by_key( | e | e.path() );
for entry in entries
{
let file_content = fs::read_to_string( entry.path() )
.unwrap_or_default();
content.push_str( &file_content );
content.push( '\n' );
}
content
}
else if file_path.exists()
{
fs::read_to_string( file_path ).unwrap_or_default()
}
else
{
String::new()
}
}
fn assert_pattern_not_exists( _file_path : &str, pattern : &str, description : &str )
{
let content = read_command_src();
let count = content.matches( pattern ).count();
assert_eq!( count, 0,
"{description} should not exist in command module, found {count} occurrences");
}
fn assert_pattern_exists( _file_path : &str, pattern : &str, description : &str )
{
let content = read_command_src();
assert!( content.contains( pattern ),
"{description} should exist in command module" );
}
#[test]
fn test_no_backward_compatibility_layer()
{
assert_pattern_not_exists(
"src/command.rs",
"// DEPRECATED:",
"Deprecation comments"
);
assert_pattern_not_exists(
"src/command.rs",
"#[deprecated",
"Deprecated attributes"
);
assert_pattern_not_exists(
"src/command.rs",
"_compat(",
"Compatibility wrapper functions"
);
assert_pattern_not_exists(
"src/command.rs",
"_legacy(",
"Legacy adapter functions"
);
}
#[test]
fn test_factory_signatures_incompatible()
{
assert_pattern_not_exists(
"src/command.rs",
"pub fn from_message(",
"from_message factory"
);
assert_pattern_exists(
"src/command.rs",
"pub fn new(",
"new() constructor (builder entry point)"
);
assert_pattern_exists(
"src/command.rs",
"pub fn with_",
"Builder methods (with_*)"
);
}
#[test]
fn test_execution_method_signature_changed()
{
assert_pattern_not_exists(
"src/command.rs",
"pub fn execute_non_interactive(",
"execute_non_interactive"
);
assert_pattern_exists(
"src/command.rs",
"pub fn execute(",
"execute() method"
);
}
#[test]
fn test_default_delegates_to_new_if_exists()
{
let content = read_command_src();
if content.contains( "impl Default for ClaudeCommand" )
{
let default_impl = content
.split( "impl Default for ClaudeCommand" )
.nth( 1 )
.and_then( | s | s.split( "\n}" ).next() )
.unwrap_or( "" );
assert!( default_impl.contains( "Self::new()" ),
"Default implementation should delegate to Self::new(), not bypass builder" );
}
}
#[test]
fn test_struct_initialization_requires_builder()
{
let content = read_command_src();
let struct_section = content
.split( "pub struct ClaudeCommand" )
.nth( 1 )
.and_then( | s | s.split( "\n}" ).next() )
.unwrap_or( "" );
let pub_field_count = struct_section
.lines()
.filter( | line |
{
let trimmed = line.trim();
trimmed.starts_with( "pub " ) && !trimmed.starts_with( "pub(" )
})
.count();
assert_eq!( pub_field_count, 0,
"Struct should have 0 public fields (prevents direct construction)" );
}
#[test]
fn test_action_mode_enum_required()
{
let types_content = fs::read_to_string( "src/types.rs" )
.expect( "src/types.rs should exist" );
assert!( types_content.contains( "pub enum ActionMode" ),
"ActionMode enum must exist (type system dependency)" );
let command_content = read_command_src();
assert!( command_content.contains( "ActionMode" ),
"command.rs should reference ActionMode (proves enum in use)" );
}
#[test]
fn test_log_level_enum_required()
{
let types_content = fs::read_to_string( "src/types.rs" )
.expect( "src/types.rs should exist" );
assert!( types_content.contains( "pub enum LogLevel" ),
"LogLevel enum must exist (type system dependency)" );
let command_content = read_command_src();
assert!( command_content.contains( "LogLevel" ),
"command.rs should reference LogLevel (proves enum in use)" );
}
#[test]
fn test_enum_conversions_one_way_only()
{
let types_content = fs::read_to_string( "src/types.rs" ).unwrap();
assert!( types_content.contains( "pub enum ActionMode" ) );
assert!( types_content.contains( "pub enum LogLevel" ) );
}
#[test]
fn test_no_type_aliases_hiding_migration()
{
let content = read_command_src();
let has_old_alias = content.contains( "type Old" ) ||
content.contains( "type Legacy" ) ||
content.contains( "type Compat" );
assert!( !has_old_alias,
"No type aliases should hide migration (Old*, Legacy*, Compat*)" );
}
#[test]
fn test_no_feature_flags_for_old_api()
{
let content = read_command_src();
assert!( !content.contains( r#"feature = "old"#),
"No feature flags for old API (prevents conditional rollback)" );
assert!( !content.contains( r#"feature = "legacy"#),
"No legacy feature flags" );
assert!( !content.contains( r#"feature = "compat"#),
"No compatibility feature flags" );
}
#[test]
fn test_builder_pattern_hardcoded()
{
let content = read_command_src();
let constructor_count = content.matches( "pub fn new(" ).count();
assert_eq!( constructor_count, 1,
"Should have exactly 1 constructor (new), found {constructor_count}" );
let with_methods = content.matches( "pub fn with_" ).count();
assert!( with_methods > 0,
"Should have builder methods (with_*), found {with_methods}" );
}
#[test]
fn test_private_fields_enforce_builder()
{
let content = read_command_src();
let struct_section = content
.split( "pub struct ClaudeCommand" )
.nth( 1 )
.and_then( | s | s.split( "\n}" ).next() )
.unwrap_or( "" );
let public_fields = struct_section
.lines()
.filter( | line |
{
let trimmed = line.trim();
trimmed.starts_with( "pub " ) &&
!trimmed.starts_with( "pub(" ) &&
trimmed.contains( ':' )
})
.count();
assert_eq!( public_fields, 0,
"All fields must be private to enforce builder pattern" );
}
#[test]
fn test_no_struct_update_syntax_support()
{
let content = read_command_src();
let struct_section = content
.split( "pub struct ClaudeCommand" )
.nth( 1 )
.and_then( | s | s.split( "\n}" ).next() )
.unwrap_or( "" );
let private_fields = struct_section
.lines()
.filter( | line |
{
let trimmed = line.trim();
!trimmed.starts_with( "pub " ) &&
!trimmed.starts_with( "//" ) &&
trimmed.contains( ':' ) &&
!trimmed.starts_with( '#' )
})
.count();
assert!( private_fields > 5,
"Should have many private fields (enforces builder), found {private_fields}" );
}
#[test]
fn test_single_execution_api()
{
let content = read_command_src();
let execute_count = content.matches( "pub fn execute(" ).count();
let execute_interactive_count = content.matches( "pub fn execute_interactive(" ).count();
assert_eq!( execute_count, 1, "Should have exactly 1 execute() method" );
assert_eq!( execute_interactive_count, 1, "Should have exactly 1 execute_interactive() method" );
assert!( !content.contains( "pub fn execute_sync(" ), "No execute_sync" );
assert!( !content.contains( "pub fn execute_async(" ), "No execute_async" );
assert!( !content.contains( "pub fn execute_non_interactive(" ), "No execute_non_interactive" );
}
#[test]
fn test_no_partial_construction_helpers()
{
let content = read_command_src();
assert!( !content.contains( "pub fn partial(" ), "No partial() constructor" );
assert!( !content.contains( "pub fn incomplete(" ), "No incomplete() constructor" );
assert!( !content.contains( "pub fn minimal(" ), "No minimal() constructor" );
assert!( !content.contains( "pub fn with_defaults(" ), "No with_defaults() constructor" );
assert!( !content.contains( "pub fn quick_build(" ), "No quick_build() constructor" );
}
#[test]
fn test_builder_methods_return_self()
{
let content = read_command_src();
let with_methods : Vec< &str > = content
.lines()
.filter( | line | line.contains( "pub fn with_" ) )
.collect();
assert!( !with_methods.is_empty(), "Should have with_* methods" );
for method in &with_methods
{
assert!( method.contains( "mut self" ),
"Builder method should take mut self: {method}" );
}
}
#[test]
fn test_no_mutable_getters()
{
let content = read_command_src();
let has_mut_getters = content.contains( "_mut(" );
assert!( !has_mut_getters,
"No mutable getters should exist (would bypass builder)" );
}
#[test]
fn test_no_setter_methods()
{
let content = read_command_src();
let has_setters = content.contains( "pub fn set_" );
assert!( !has_setters,
"No setter methods should exist (use builder with_* instead)" );
}
#[test]
fn test_env_var_automation_baked_in()
{
let content = read_command_src();
let claude_env_count = content.matches( "CLAUDE_CODE_" ).count();
assert!( claude_env_count >= 10,
"Should have automated env var setting (>=10 CLAUDE_CODE_*), found {claude_env_count}");
}
#[test]
fn test_rollback_would_fail()
{
assert_pattern_not_exists( "src/command.rs", "pub fn from_message(", "from_message factory" );
assert_pattern_not_exists( "src/command.rs", "pub fn execute_non_interactive(", "execute_non_interactive" );
let types_content = fs::read_to_string( "src/types.rs" ).expect( "types.rs should exist" );
assert!( types_content.contains( "pub enum ActionMode" ), "ActionMode enum required" );
assert!( types_content.contains( "pub enum LogLevel" ), "LogLevel enum required" );
let command_content = read_command_src();
let with_count = command_content.matches( "pub fn with_" ).count();
assert!( with_count > 10, "Builder pattern required (many with_* methods)" );
assert!( !command_content.contains( "#[deprecated" ), "No deprecated attributes" );
assert!( !command_content.contains( r#"feature = "old"# ), "No old-api feature flags" );
}