use super::*;
#[test]
fn for_loop_increments_cyclomatic() {
assert_eq!(
metrics_of("fn f() { for _ in 0..2 { let _ = (); } }").cyclomatic_complexity,
2
);
}
#[test]
fn while_loop_increments_cyclomatic() {
assert_eq!(
metrics_of("fn f() { while false { let _ = (); } }").cyclomatic_complexity,
2
);
}
#[test]
fn loop_increments_cyclomatic() {
assert_eq!(
metrics_of("fn f() { loop { break; } }").cyclomatic_complexity,
2
);
}
#[test]
fn and_after_or_increments_cognitive() {
let m = metrics_of("fn f(a: bool, b: bool, c: bool) -> bool { a && b || c }");
assert!(
m.cognitive_complexity > 0,
"an alternating && after an || is a cognitive jump, got {}",
m.cognitive_complexity
);
}
#[test]
fn unsafe_block_counted() {
assert!(metrics_of("fn f(x: bool) { if x { unsafe { let _ = 1; } } }").unsafe_blocks > 0);
}
#[test]
fn panic_macro_counted() {
assert!(metrics_of(r#"fn f(x: bool) { if x { panic!("boom") } }"#).panic_count > 0);
}
#[test]
fn unreachable_macro_counted_as_panic() {
assert!(metrics_of("fn f(x: bool) { if x { unreachable!() } }").panic_count > 0);
}
#[test]
fn todo_macro_counted() {
assert!(metrics_of("fn f(x: bool) { if x { todo!() } }").todo_count > 0);
}
#[test]
fn unwrap_counted() {
assert!(
metrics_of("fn f(o: Option<i32>, x: bool) -> i32 { if x { o.unwrap() } else { 0 } }")
.unwrap_count
> 0
);
}
#[test]
fn expect_counted() {
assert!(
metrics_of(r#"fn f(o: Option<i32>, x: bool) -> i32 { if x { o.expect("e") } else { 0 } }"#)
.expect_count
> 0
);
}
#[test]
fn comparison_counts_as_logic() {
assert!(metrics_of("fn f(a: i32, b: i32) -> bool { a == b }").logic_count > 0);
}
#[test]
fn bitwise_counts_as_logic() {
assert!(metrics_of("fn f(a: i32, b: i32) -> i32 { a & b }").logic_count > 0);
}
#[test]
fn float_literal_is_a_magic_number() {
assert!(
!metrics_of("fn f(x: bool) { if x { let _ = 3.14; } }")
.magic_numbers
.is_empty(),
"a bare float literal is a magic number"
);
}
#[test]
fn negative_float_literal_records_signed_value() {
let m = metrics_of("fn f(x: bool) { if x { let _ = -3.14; } }");
assert!(
m.magic_numbers.iter().any(|n| n.value == "-3.14"),
"a negative float literal records its signed value, got {:?}",
m.magic_numbers
);
}
#[test]
fn non_negation_unary_on_int_records_unsigned_value() {
let m = metrics_of("fn f(x: bool) { if x { let _ = !5; } }");
assert!(
m.magic_numbers.iter().any(|n| n.value == "5"),
"a `!` unary is not a negative literal; inner value stays unsigned, got {:?}",
m.magic_numbers
);
}
#[test]
fn const_context_resets_after_const_item() {
let m = metrics_of("fn f(x: bool) { if x { const K: i32 = 42; let _ = 99; } }");
assert!(
m.magic_numbers.iter().any(|n| n.value == "99"),
"the literal after a const item must still be a magic number"
);
assert!(
!m.magic_numbers.iter().any(|n| n.value == "42"),
"the const's own value is suppressed"
);
}
#[test]
fn static_context_resets_after_static_item() {
let m = metrics_of("fn f(x: bool) { if x { static S: i32 = 42; let _ = 99; } }");
assert!(
m.magic_numbers.iter().any(|n| n.value == "99"),
"the literal after a static item must still be a magic number"
);
}