magi-code 0.77.1

Repository-aware CLI coding agent for terminal work
Documentation
use super::*;
use serde_json::json;

fn installation_fixture(root: &Path, package: &str) -> PathBuf {
    fs::create_dir_all(root.join("bin")).unwrap();
    let executable = root.join("bin").join(BINARY);
    fs::write(&executable, b"fixture, never executed").unwrap();
    fs::write(
        root.join(".crates.toml"),
        format!("[v1]\n{package:?} = [{BINARY:?}]\n"),
    )
    .unwrap();
    fs::write(
        root.join(".crates2.json"),
        json!({"installs": {package: {"bins": [BINARY], "target": "aarch64-apple-darwin"}}})
            .to_string(),
    )
    .unwrap();
    executable
}

fn official_package() -> String {
    format!("magi-code {} ({REGISTRY})", env!("CARGO_PKG_VERSION"))
}

#[test]
fn newer_versions_exclude_yanked_and_prereleases_and_compare_semver() {
    let response = json!({"versions": [
        {"num":"0.10.0", "yanked":false},
        {"num":"1.0.0-rc.1", "yanked":false},
        {"num":"0.11.0", "yanked":true},
        {"num":"0.9.0", "yanked":false}
    ]});
    let body = serde_json::to_vec(&response).unwrap();
    assert_eq!(
        newest_stable(&body, &Version::parse("0.9.0").unwrap()).unwrap(),
        Some(Version::parse("0.10.0").unwrap())
    );
    assert_eq!(
        newest_stable(&body, &Version::parse("0.10.0").unwrap()).unwrap(),
        None
    );
    assert!(newest_stable(b"not registry data", &Version::new(0, 1, 0)).is_err());
}

#[test]
fn custom_cargo_root_is_inferred_from_executable_not_environment() {
    let temp = tempfile::tempdir().unwrap();
    let root = temp.path().join("custom root with spaces");
    let executable = installation_fixture(&root, &official_package());
    let installation = CargoInstallation::discover(&executable).unwrap();
    assert_eq!(installation.root, root.canonicalize().unwrap());
    let command = cargo_install_command(&installation, &Version::new(1, 2, 3), temp.path());
    let args: Vec<_> = command.get_args().collect();
    let root_index = args.iter().position(|arg| *arg == "--root").unwrap();
    assert_eq!(args[root_index + 1], installation.root.as_os_str());
    assert!(args.contains(&std::ffi::OsStr::new("=1.2.3")));
    assert!(args.contains(&std::ffi::OsStr::new("--locked")));
    assert!(!args.contains(&std::ffi::OsStr::new("--no-track")));
    assert_eq!(command.get_current_dir(), Some(temp.path()));
}

#[test]
fn source_installs_and_inconsistent_or_ambiguous_records_are_rejected() {
    let temp = tempfile::tempdir().unwrap();
    let source_package = format!(
        "magi-code {} (path+file:///checkout)",
        env!("CARGO_PKG_VERSION")
    );
    let executable = installation_fixture(temp.path(), &source_package);
    assert!(CargoInstallation::discover(&executable).is_err());
    installation_fixture(temp.path(), &official_package());
    fs::write(temp.path().join(".crates2.json"), r#"{"installs":{}}"#).unwrap();
    assert!(CargoInstallation::discover(&executable).is_err());
    installation_fixture(temp.path(), &official_package());
    let mut file = fs::OpenOptions::new()
        .append(true)
        .open(temp.path().join(".crates.toml"))
        .unwrap();
    use std::io::Write;
    writeln!(file, "\"other 1.0.0 ({REGISTRY})\" = [{BINARY:?}]").unwrap();
    assert!(CargoInstallation::discover(&executable).is_err());
}

#[test]
fn untracked_build_and_stale_running_version_are_rejected() {
    let temp = tempfile::tempdir().unwrap();
    let executable = installation_fixture(temp.path(), &format!("magi-code 0.0.1 ({REGISTRY})"));
    assert!(CargoInstallation::discover(&executable).is_err());
    fs::remove_file(temp.path().join(".crates.toml")).unwrap();
    assert!(CargoInstallation::discover(&executable).is_err());
}

#[cfg(unix)]
#[test]
fn symlinked_install_records_are_not_followed() {
    let temp = tempfile::tempdir().unwrap();
    let executable = installation_fixture(temp.path(), &official_package());
    fs::rename(
        temp.path().join(".crates.toml"),
        temp.path().join("elsewhere"),
    )
    .unwrap();
    std::os::unix::fs::symlink(
        temp.path().join("elsewhere"),
        temp.path().join(".crates.toml"),
    )
    .unwrap();
    assert!(CargoInstallation::discover(&executable).is_err());
}

fn completed_check(result: Result<Option<Version>>) -> JoinHandle<Result<Option<Version>>> {
    let handle = thread::spawn(move || result);
    let deadline = Instant::now() + Duration::from_secs(2);
    while !handle.is_finished() {
        assert!(Instant::now() < deadline);
        thread::sleep(Duration::from_millis(1));
    }
    handle
}

#[test]
fn checks_notify_once_and_failed_checks_do_not_prevent_later_notification() {
    let now = Instant::now();
    let mut checks = UpdateChecks {
        next_check: Some(now + RECHECK_INTERVAL),
        ..Default::default()
    };
    checks.worker = Some(completed_check(Err(anyhow::anyhow!("offline"))));
    assert!(checks.poll(now).is_none());
    assert_eq!(checks.next_check, Some(now + RECHECK_INTERVAL));
    let version = Version::new(1, 2, 3);
    checks.worker = Some(completed_check(Ok(Some(version.clone()))));
    assert_eq!(checks.poll(now), Some(version.clone()));
    checks.worker = Some(completed_check(Ok(Some(version))));
    assert!(checks.poll(now).is_none());
    checks.worker = Some(completed_check(Ok(Some(Version::new(1, 2, 4)))));
    assert_eq!(checks.poll(now), Some(Version::new(1, 2, 4)));
}

#[test]
fn checks_start_at_startup_and_four_hours_but_never_overlap() {
    let now = Instant::now();
    let mut checks = UpdateChecks::default();
    let (release, waiting) = crossbeam_channel::bounded(1);
    assert!(
        checks
            .poll_with_check(now, move || {
                waiting.recv().unwrap();
                Ok(None)
            })
            .is_none()
    );
    assert!(checks.worker.is_some());
    checks.poll_with_check(now + RECHECK_INTERVAL, || panic!("overlapping check"));
    release.send(()).unwrap();
    let deadline = Instant::now() + Duration::from_secs(2);
    while !checks.worker.as_ref().unwrap().is_finished() {
        assert!(Instant::now() < deadline);
        thread::sleep(Duration::from_millis(1));
    }
    checks.poll_with_check(now + RECHECK_INTERVAL - Duration::from_secs(1), || {
        panic!("early check")
    });
    assert!(checks.worker.is_none());
    checks.poll_with_check(now + RECHECK_INTERVAL, || Ok(None));
    assert!(checks.worker.is_some());
    assert_eq!(checks.next_check, Some(now + RECHECK_INTERVAL * 2));
}

#[test]
fn restart_waits_for_last_session_writer_clone_and_never_selects_latest() {
    let temp = tempfile::tempdir().unwrap();
    let root = temp.path().join("sessions");
    let manager = crate::sessions::SessionManager::new(root.clone());
    let session = manager.create().unwrap().admit_standalone_writer().unwrap();
    session
        .append(&crate::sessions::SessionEvent::new_kind(
            crate::sessions::SessionEventKind::Diagnostic,
            session.id().to_owned(),
            temp.path().to_path_buf(),
            json!({"lifecycle": "created"}),
        ))
        .unwrap();
    let id = session.id().to_owned();
    let worker_session = session.clone();
    drop(session);
    let _newer_session = manager.create().unwrap();
    assert!(wait_for_session_release(&root, &id, Duration::ZERO).is_err());
    drop(worker_session);
    assert!(wait_for_session_release(&root, &id, Duration::ZERO).is_ok());
}