mod common;
use tempfile::TempDir;
fn stdout( out : &std::process::Output ) -> String
{
String::from_utf8_lossy( &out.stdout ).into_owned()
}
fn stderr( out : &std::process::Output ) -> String
{
String::from_utf8_lossy( &out.stderr ).into_owned()
}
fn assert_exit( out : &std::process::Output, code : i32 )
{
assert_eq!(
out.status.code().unwrap_or( -1 ),
code,
"expected exit {code}, got {:?}; stderr: {}",
out.status.code(),
stderr( out )
);
}
#[ test ]
fn ec_1_session_partial_match_at_start()
{
let root = TempDir::new().unwrap();
common::write_test_session( root.path(), "proj-sess", "-default_topic", 2 );
let out = common::clg_cmd()
.env( "CLAUDE_STORAGE_ROOT", root.path() )
.arg( ".list" )
.arg( "session::default" )
.output()
.unwrap();
assert_exit( &out, 0 );
let output = stdout( &out );
assert!(
output.contains( "default" ),
"EC-1: session with 'default' prefix must appear; got: {output}"
);
}
#[ test ]
fn ec_2_session_partial_match_in_middle()
{
let root = TempDir::new().unwrap();
common::write_test_session( root.path(), "proj-sess2", "-default_topic", 2 );
let out = common::clg_cmd()
.env( "CLAUDE_STORAGE_ROOT", root.path() )
.arg( ".list" )
.arg( "session::topic" )
.output()
.unwrap();
assert_exit( &out, 0 );
let output = stdout( &out );
assert!(
output.contains( "topic" ),
"EC-2: session containing 'topic' must appear; got: {output}"
);
}
#[ test ]
fn ec_3_session_case_insensitive_match()
{
let root = TempDir::new().unwrap();
common::write_test_session( root.path(), "proj-sess3", "-default_topic", 2 );
let out_lower = common::clg_cmd()
.env( "CLAUDE_STORAGE_ROOT", root.path() )
.arg( ".list" )
.arg( "session::default" )
.output()
.unwrap();
let out_upper = common::clg_cmd()
.env( "CLAUDE_STORAGE_ROOT", root.path() )
.arg( ".list" )
.arg( "session::DEFAULT" )
.output()
.unwrap();
assert_exit( &out_lower, 0 );
assert_exit( &out_upper, 0 );
assert_eq!(
stdout( &out_lower ),
stdout( &out_upper ),
"EC-3: case-insensitive session filter must return identical results"
);
}
#[ test ]
fn ec_4_session_no_match_returns_empty()
{
let root = TempDir::new().unwrap();
common::write_test_session( root.path(), "proj-sess4", "-default_topic", 2 );
let out = common::clg_cmd()
.env( "CLAUDE_STORAGE_ROOT", root.path() )
.arg( ".list" )
.arg( "session::zzznomatch999" )
.output()
.unwrap();
assert_exit( &out, 0 );
let output = stdout( &out );
assert!(
!output.contains( "default" ),
"EC-4: non-matching session filter must return empty list; got: {output}"
);
}
#[ test ]
fn ec_5_session_empty_rejected()
{
let out = common::clg_cmd()
.arg( ".list" )
.arg( "session::" )
.output()
.unwrap();
assert_exit( &out, 1 );
let combined = format!( "{}{}", stderr( &out ), stdout( &out ) );
assert!(
combined.contains( "session" ),
"EC-5: error must mention 'session'; got: {combined}"
);
}
#[ test ]
fn ec_6_session_auto_enables_display()
{
let root = TempDir::new().unwrap();
common::write_test_session( root.path(), "proj-sess6", "-default_topic", 2 );
let out = common::clg_cmd()
.env( "CLAUDE_STORAGE_ROOT", root.path() )
.arg( ".list" )
.arg( "session::default" )
.output()
.unwrap();
assert_exit( &out, 0 );
let output = stdout( &out );
assert!(
output.contains( "default" ),
"EC-6: session filter must auto-enable session display; got: {output}"
);
}
#[ test ]
fn ec_7_session_in_count_restricts_scope()
{
let root = TempDir::new().unwrap();
common::write_test_session( root.path(), "proj-sess7", "-default_topic", 4 );
common::write_test_session( root.path(), "proj-sess7", "other-session", 10 );
let out = common::clg_cmd()
.env( "CLAUDE_STORAGE_ROOT", root.path() )
.arg( ".count" )
.arg( "target::entries" )
.arg( "session::-default_topic" )
.arg( "project::proj-sess7" )
.output()
.unwrap();
assert_exit( &out, 0 );
let output = stdout( &out ).trim().to_owned();
let count : usize = output.parse().unwrap_or( 999 );
assert!(
count < 10,
"EC-7: count with session::-default_topic must not include other-session entries (10); got: {count}"
);
}