mod common;
use predicates::prelude::*;
use wiremock::matchers::{body_json, header, method, path};
use wiremock::{Mock, MockServer, ResponseTemplate};
#[tokio::test]
#[ignore = "real-resource: weekly/release tier; spawns newt and touches the filesystem"]
async fn setup_url_probes_with_token_reference_and_writes_backend_dropin() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/v1/models"))
.and(header("authorization", "Bearer secret-value"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"data": [{"id": "served-model"}]
})))
.mount(&server)
.await;
Mock::given(method("POST"))
.and(path("/v1/chat/completions"))
.and(header("authorization", "Bearer secret-value"))
.and(body_json(serde_json::json!({
"model": "served-model",
"messages": [{"role": "user", "content": "Reply with OK."}],
"max_tokens": 8,
"stream": false
})))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"choices": [{"message": {"role": "assistant", "content": "hi"}}]
})))
.expect(1)
.mount(&server)
.await;
let config_dir = common::isolated_root();
common::newt()
.env("DGX_SETUP_TEST_TOKEN", "secret-value")
.arg("--config-dir")
.arg(config_dir.path())
.args([
"setup",
&server.uri(),
"--token-env",
"DGX_SETUP_TEST_TOKEN",
"--yes",
])
.assert()
.success()
.stdout(predicate::str::contains("Detected 1 inference backend"))
.stdout(predicate::str::contains("secret-value").not())
.stderr(predicate::str::contains("secret-value").not());
let config_path = config_dir.path().join("config.toml");
let config = newt_core::Config::load(&config_path, &mut |_| {}).unwrap();
let backend_name = format!("127-0-0-1-{}", server.address().port());
assert_eq!(
config.default_backend.as_deref(),
Some(backend_name.as_str())
);
let backend_path = config_dir
.path()
.join("backends")
.join(format!("{backend_name}.toml"));
let text = std::fs::read_to_string(&backend_path).unwrap();
let backend: newt_core::BackendConfig = toml::from_str(&text).unwrap();
assert_eq!(backend.endpoint, server.uri());
assert_eq!(backend.effective_model(), Some("served-model"));
assert_eq!(backend.kind, Some(newt_core::BackendKind::Openai));
assert_eq!(backend.api_key_env.as_deref(), Some("DGX_SETUP_TEST_TOKEN"));
assert!(!text.contains("secret-value"));
common::newt()
.arg("--config-dir")
.arg(config_dir.path())
.arg("config")
.assert()
.success()
.stdout(predicate::str::contains(server.uri()))
.stdout(predicate::str::contains("served-model"));
}
#[tokio::test]
async fn setup_url_failure_writes_nothing() {
let server = MockServer::start().await;
let config_dir = common::isolated_root();
common::newt()
.env("NEWT_CONFIG", "")
.arg("--config-dir")
.arg(config_dir.path())
.args(["setup", &server.uri(), "--yes"])
.assert()
.failure()
.stderr(predicate::str::contains("no supported inference API"));
assert!(!config_dir.path().join("config.toml").exists());
assert!(!config_dir.path().join("backends").exists());
}
#[test]
fn setup_target_rejects_explicit_config_before_writing() {
let dir = common::isolated_root();
let config_path = dir.path().join("custom.toml");
common::newt()
.arg("--config")
.arg(&config_path)
.args(["setup", "127.0.0.1:9", "--yes"])
.assert()
.failure()
.stderr(predicate::str::contains("use --config-dir"));
assert!(!config_path.exists());
assert!(!dir.path().join("backends").exists());
}
#[test]
fn setup_target_rejects_newt_config_before_writing() {
let dir = common::isolated_root();
let explicit_config = dir.path().join("explicit.toml");
let config_dir = dir.path().join("managed");
common::newt()
.env("NEWT_CONFIG", &explicit_config)
.arg("--config-dir")
.arg(&config_dir)
.args(["setup", "127.0.0.1:9", "--yes"])
.assert()
.failure()
.stderr(predicate::str::contains("NEWT_CONFIG"))
.stderr(predicate::str::contains("use --config-dir"));
assert!(!explicit_config.exists());
assert!(!config_dir.join("config.toml").exists());
assert!(!config_dir.join("backends").exists());
}
#[test]
fn setup_target_requires_yes_when_stdin_is_not_a_terminal() {
let config_dir = common::isolated_root();
common::newt()
.arg("--config-dir")
.arg(config_dir.path())
.args(["setup", "127.0.0.1:9"])
.assert()
.failure()
.stderr(predicate::str::contains("pass --yes"));
assert!(!config_dir.path().join("config.toml").exists());
assert!(!config_dir.path().join("backends").exists());
}
#[tokio::test]
#[ignore = "real-resource: weekly/release tier; spawns newt and touches the filesystem"]
async fn setup_v1_url_requires_generation_and_persists_canonical_token_reference() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/v1/models"))
.and(header("authorization", "Bearer secret-value"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"data": [{"id": "secured-model"}]
})))
.expect(1)
.mount(&server)
.await;
Mock::given(method("POST"))
.and(path("/v1/chat/completions"))
.and(header("authorization", "Bearer secret-value"))
.and(body_json(serde_json::json!({
"model": "secured-model",
"messages": [{"role": "user", "content": "Reply with OK."}],
"max_tokens": 8,
"stream": false
})))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"choices": [{"message": {"role": "assistant", "content": "hi"}}]
})))
.expect(1)
.mount(&server)
.await;
let root = common::isolated_root();
let token_path = root.path().join("dgx.token");
std::fs::write(&token_path, "secret-value\n").unwrap();
let target = format!("{}/v1/", server.uri());
let assertion = common::newt()
.current_dir(root.path())
.args([
"--config-dir",
"config",
"setup",
&target,
"--token-file",
"dgx.token",
"--model",
"secured-model",
"--yes",
])
.assert()
.success();
assertion
.stdout(predicate::str::contains("generation accepted"))
.stdout(predicate::str::contains("secret-value").not())
.stderr(predicate::str::contains("secret-value").not());
let name = format!("127-0-0-1-{}", server.address().port());
let config_body = std::fs::read_to_string(root.path().join("config/config.toml")).unwrap();
let body = std::fs::read_to_string(
root.path()
.join("config/backends")
.join(format!("{name}.toml")),
)
.unwrap();
let backend: newt_core::BackendConfig = toml::from_str(&body).unwrap();
assert_eq!(backend.endpoint, server.uri());
assert_eq!(
backend.api_key_file.as_deref(),
std::fs::canonicalize(&token_path).unwrap().to_str()
);
assert!(!config_body.contains("secret-value"));
assert!(!body.contains("secret-value"));
}
#[tokio::test]
#[ignore = "real-resource: weekly/release tier; spawns newt and touches the filesystem"]
async fn setup_public_models_but_unauthorized_generation_writes_nothing() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/v1/models"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"data": [{"id": "catalog-model"}]
})))
.expect(1)
.mount(&server)
.await;
Mock::given(method("POST"))
.and(path("/v1/chat/completions"))
.and(header("authorization", "Bearer rejected-secret"))
.and(body_json(serde_json::json!({
"model": "catalog-model",
"messages": [{"role": "user", "content": "Reply with OK."}],
"max_tokens": 8,
"stream": false
})))
.respond_with(ResponseTemplate::new(401).set_body_json(serde_json::json!({
"error": {"message": "unauthorized"}
})))
.expect(1)
.mount(&server)
.await;
let root = common::isolated_root();
let token_path = root.path().join("token");
std::fs::write(&token_path, "rejected-secret\n").unwrap();
let config_dir = root.path().join("config");
let target = format!("{}/v1/", server.uri());
common::newt()
.arg("--config-dir")
.arg(&config_dir)
.args(["setup", &target, "--token-file"])
.arg(&token_path)
.arg("--yes")
.assert()
.failure()
.stdout(predicate::str::contains("HTTP 401"))
.stdout(predicate::str::contains("rejected-secret").not())
.stderr(predicate::str::contains("minimal generation check"))
.stderr(predicate::str::contains("rejected-secret").not());
assert!(!config_dir.join("config.toml").exists());
assert!(!config_dir.join("backends").exists());
}
#[tokio::test]
#[ignore = "real-resource: weekly/release tier; spawns newt and touches the filesystem"]
async fn setup_bare_host_without_token_discovers_every_live_configured_port() {
let first = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/v1/models"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"data": [{"id": "vllm-model"}]
})))
.mount(&first)
.await;
Mock::given(method("POST"))
.and(path("/v1/chat/completions"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"choices": [{"message": {"role": "assistant", "content": "hi"}}]
})))
.mount(&first)
.await;
let second = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/v1/models"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"data": [{"id": "router-a"}, {"id": "router-b"}]
})))
.mount(&second)
.await;
Mock::given(method("POST"))
.and(path("/v1/chat/completions"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"choices": [{"message": {"role": "assistant", "content": "hi"}}]
})))
.mount(&second)
.await;
let config_dir = common::isolated_root();
std::fs::write(
config_dir.path().join("config.toml"),
format!(
"[discovery]\nhosts = []\nollama_ports = []\nvllm_ports = [{}, {}]\n",
first.address().port(),
second.address().port()
),
)
.unwrap();
common::newt()
.arg("--config-dir")
.arg(config_dir.path())
.args(["setup", "127.0.0.1", "--yes"])
.assert()
.success()
.stdout(predicate::str::contains("Detected 2 inference backends"));
assert_eq!(
std::fs::read_dir(config_dir.path().join("backends"))
.unwrap()
.count(),
2
);
common::newt()
.arg("--config-dir")
.arg(config_dir.path())
.arg("config")
.assert()
.success()
.stdout(predicate::str::contains("vllm-model"))
.stdout(predicate::str::contains("router-a"));
}
#[test]
fn setup_help_explains_host_expansion_and_authenticated_target_scope() {
common::newt()
.args(["setup", "--help"])
.assert()
.success()
.stdout(predicate::str::contains("Bare hosts expand"))
.stdout(predicate::str::contains("Requires an explicit HTTPS URL"));
}