blue-lang-cli 0.0.171

The blue command line: run, fmt, ast, erase, check.
use std::path::PathBuf;
use std::process::{Command, Output};
use std::time::{Duration, Instant};

fn blue() -> Command {
    let mut c = Command::new(env!("CARGO_BIN_EXE_blue"));
    c.env_remove("BLUE_PATH")
        .env_remove("BLUE_CONFIG")
        .env_remove("BLUE_TIER")
        .env_remove("BLUE_MEMO")
        .env_remove("BLUE_WITNESS");
    c
}

fn dir(name: &str) -> PathBuf {
    let p = std::env::temp_dir().join(format!("blue-virtual-clock-{name}"));
    let _ = std::fs::remove_dir_all(&p);
    std::fs::create_dir_all(&p).expect("scratch dir");
    p
}

fn text(o: &Output) -> String {
    format!(
        "{}{}",
        String::from_utf8_lossy(&o.stdout),
        String::from_utf8_lossy(&o.stderr)
    )
}

const TIMED: &str = r#"test "a ten minute sleep observes ten minutes"
  t0 = node_time
  sleep_for(600_000)
  assert node_time - t0 == 600_000
end

test "a thirty second timeout raises timeout at thirty seconds"
  t0 = node_time
  kind = begin
    timeout(30000, () -> receive([:never]))
  rescue :timeout as e
    e.kind
  end
  assert kind == :timeout
  assert node_time - t0 == 30000
end

test "timers fire in the order of their deadlines"
  after(300, :late)
  after(100, :early)
  assert [receive(), receive()] == %i[early late]
end

test "the clock in a test is virtual"
  assert context[:clock] == :virtual
end
"#;

#[test]
fn blue_test_runs_timed_tests_on_the_virtual_clock_in_well_under_a_second_of_waiting() {
    let d = dir("test");
    let f = d.join("timed_test.b");
    std::fs::write(&f, TIMED).expect("write");
    let started = Instant::now();
    let o = blue()
        .args(["test", f.to_str().unwrap()])
        .output()
        .expect("spawn blue");
    let wall = started.elapsed();
    assert!(o.status.success(), "{}", text(&o));
    assert!(text(&o).contains("4 passed"), "{}", text(&o));
    assert!(wall < Duration::from_secs(20), "took {wall:?}");
}

#[test]
fn blue_run_keeps_the_wall_clock() {
    let d = dir("run");
    let f = d.join("wall.b");
    std::fs::write(
        &f,
        "sleep_for(80)\nprintln([context[:clock], node_time >= 80])\n",
    )
    .expect("write");
    let started = Instant::now();
    let o = blue()
        .args(["run", f.to_str().unwrap()])
        .output()
        .expect("spawn blue");
    assert!(o.status.success(), "{}", text(&o));
    assert!(started.elapsed() >= Duration::from_millis(80));
    assert!(String::from_utf8_lossy(&o.stdout).starts_with("(:real #t)\n"));
}