#![cfg(feature = "localfs")]
#![allow(clippy::unwrap_used, clippy::expect_used)]
use kaish_kernel::{ExecuteOptions, Kernel, KernelConfig};
fn kernel() -> Kernel {
Kernel::new(KernelConfig::repl().with_trash(false))
.expect("failed to create kernel")
}
async fn run(prog: &str, stdin: &str) -> (String, i64) {
let kernel = kernel();
let result = kernel
.execute_with_options(prog, ExecuteOptions::new().with_stdin(stdin))
.await
.expect("kernel execute");
(result.text_out().to_string(), result.code)
}
#[tokio::test]
async fn numeric_field_gt_number_literal_is_numeric_compare() {
let (out, code) = run(r#"awk '{ if ($1 > 9) print "GT"; else print "LE" }'"#, "10\n").await;
assert_eq!(code, 0, "out={out:?}");
assert_eq!(out, "GT\n", "$1=10 > 9 must compare numerically (not string where 10<9)");
}
#[tokio::test]
async fn numeric_field_gt_five_ten_passes() {
let (out, code) = run(r#"awk '$1 > 5 { print $1 }'"#, "10\n3\n6\n").await;
assert_eq!(code, 0, "out={out:?}");
assert_eq!(out, "10\n6\n", "$1>5 must use numeric compare; string compare would miss 10");
}
#[tokio::test]
async fn strnum_vs_number_literal_uses_numeric_compare() {
let (out, code) = run(r#"awk '{ print ($1 > 9) }'"#, "10\n").await;
assert_eq!(code, 0, "out={out:?}");
assert_eq!(out, "1\n", "strnum 10 > number 9 must be 1 (numeric), not 0 (string)");
}
#[tokio::test]
async fn field_zero_string_equals_zero_number() {
let (out, code) = run(r#"awk '{ print ($1 == 0) }'"#, "0\n").await;
assert_eq!(code, 0, "out={out:?}");
assert_eq!(out, "1\n", "$1=0 == 0 must be true (numeric compare)");
}
#[tokio::test]
async fn field_zero_point_zero_equals_zero_number() {
let (out, code) = run(r#"awk '{ print ($1 == 0) }'"#, "0.0\n").await;
assert_eq!(code, 0, "out={out:?}");
assert_eq!(out, "1\n", "$1=0.0 == 0 must be true (numeric); string compare would give 0");
}
#[tokio::test]
async fn non_numeric_field_vs_zero_is_string_compare() {
let (out, code) = run(r#"awk '{ print ($1 == 0) }'"#, "abc\n").await;
assert_eq!(code, 0, "out={out:?}");
assert_eq!(out, "0\n", "$1=abc (non-numeric strnum) == 0 must be 0 (string compare)");
}
#[tokio::test]
async fn strnum_vs_string_constant_uses_string_compare() {
let (out, code) = run(r#"awk '{ print ($1 > "9") }'"#, "10\n").await;
assert_eq!(code, 0, "out={out:?}");
assert_eq!(out, "0\n", "strnum 10 vs string \"9\" must be string compare (10<9 lexically)");
}
#[tokio::test]
async fn string_constant_vs_zero_is_string_compare() {
let (out, code) = run(r#"awk 'BEGIN { print ("abc" == 0) }'"#, "").await;
assert_eq!(code, 0, "out={out:?}");
assert_eq!(out, "0\n", "string literal \"abc\" == 0 must be 0 (string compare)");
}
#[tokio::test]
async fn two_string_constants_compare_lexically() {
let (out, code) = run(r#"awk 'BEGIN { print ("10" < "9") }'"#, "").await;
assert_eq!(code, 0, "out={out:?}");
assert_eq!(out, "1\n", "string constants must compare lexically: \"10\" < \"9\"");
}
#[tokio::test]
async fn pattern_numeric_gt_filters_correctly() {
let (out, code) = run(r#"awk '$1 > 5 { print $1 }'"#, "3\n10\n7\n4\n").await;
assert_eq!(code, 0, "out={out:?}");
assert_eq!(out, "10\n7\n", "$1>5 pattern must use numeric compare");
}
#[tokio::test]
async fn two_numeric_fields_compare_numerically() {
let (out, code) = run(r#"awk '{ if ($1 > $2) print "GT"; else print "LE" }'"#, "10 9\n").await;
assert_eq!(code, 0, "out={out:?}");
assert_eq!(out, "GT\n", "strnum vs strnum numeric compare: 10 > 9");
}
#[tokio::test]
async fn var_v_assignment_compares_numerically() {
let (out, code) = run(r#"awk -v threshold=5 '$1 > threshold { print $1 }'"#, "3\n10\n7\n4\n").await;
assert_eq!(code, 0, "out={out:?}");
assert_eq!(out, "10\n7\n", "-v numeric assignment must allow numeric compare");
}