Skip to content

Commit 8ced87c

Browse files
committed
test(e2e): cover inference endpoint verification
1 parent 557fa1a commit 8ced87c

File tree

1 file changed

+95
-16
lines changed

1 file changed

+95
-16
lines changed

e2e/rust/tests/host_gateway_alias.rs

Lines changed: 95 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use tempfile::NamedTempFile;
1616
use tokio::time::{interval, timeout};
1717

1818
const INFERENCE_PROVIDER_NAME: &str = "e2e-host-inference";
19+
const INFERENCE_PROVIDER_UNREACHABLE_NAME: &str = "e2e-host-inference-unreachable";
1920
const TEST_SERVER_IMAGE: &str = "python:3.13-alpine";
2021
static INFERENCE_ROUTE_LOCK: Mutex<()> = Mutex::new(());
2122

@@ -177,6 +178,22 @@ async fn delete_provider(name: &str) {
177178
let _ = cmd.status().await;
178179
}
179180

181+
async fn create_openai_provider(name: &str, base_url: &str) -> Result<String, String> {
182+
run_cli(&[
183+
"provider",
184+
"create",
185+
"--name",
186+
name,
187+
"--type",
188+
"openai",
189+
"--credential",
190+
"OPENAI_API_KEY=dummy",
191+
"--config",
192+
&format!("OPENAI_BASE_URL={base_url}"),
193+
])
194+
.await
195+
}
196+
180197
fn write_policy(port: u16) -> Result<NamedTempFile, String> {
181198
let mut file = NamedTempFile::new().map_err(|e| format!("create temp policy file: {e}"))?;
182199
let policy = format!(
@@ -282,36 +299,33 @@ async fn sandbox_inference_local_routes_to_host_openshell_internal() {
282299
delete_provider(INFERENCE_PROVIDER_NAME).await;
283300
}
284301

285-
run_cli(&[
286-
"provider",
287-
"create",
288-
"--name",
302+
let create_output = create_openai_provider(
289303
INFERENCE_PROVIDER_NAME,
290-
"--type",
291-
"openai",
292-
"--credential",
293-
"OPENAI_API_KEY=dummy",
294-
"--config",
295-
&format!(
296-
"OPENAI_BASE_URL=http://host.openshell.internal:{}/v1",
297-
server.port
298-
),
299-
])
304+
&format!("http://host.openshell.internal:{}/v1", server.port),
305+
)
300306
.await
301307
.expect("create host-backed OpenAI provider");
302308

303-
run_cli(&[
309+
let inference_output = run_cli(&[
304310
"inference",
305311
"set",
306312
"--provider",
307313
INFERENCE_PROVIDER_NAME,
308314
"--model",
309315
"host-echo-model",
310-
"--no-verify",
311316
])
312317
.await
313318
.expect("point inference.local at host-backed provider");
314319

320+
assert!(
321+
inference_output.contains("Validated Endpoints:"),
322+
"expected verification details in output:\n{inference_output}"
323+
);
324+
assert!(
325+
inference_output.contains("/v1/chat/completions (openai_chat_completions)"),
326+
"expected validated endpoint in output:\n{inference_output}"
327+
);
328+
315329
let guard = SandboxGuard::create(&[
316330
"--",
317331
"curl",
@@ -338,4 +352,69 @@ async fn sandbox_inference_local_routes_to_host_openshell_internal() {
338352
"expected sandbox to receive echoed inference content:\n{}",
339353
guard.create_output
340354
);
355+
356+
let _ = create_output;
357+
}
358+
359+
#[tokio::test]
360+
async fn inference_set_supports_no_verify_for_unreachable_endpoint() {
361+
let _inference_lock = INFERENCE_ROUTE_LOCK
362+
.lock()
363+
.unwrap_or_else(std::sync::PoisonError::into_inner);
364+
365+
let current_inference = run_cli(&["inference", "get"])
366+
.await
367+
.expect("read current inference config");
368+
if !current_inference.contains("Not configured") {
369+
eprintln!("Skipping test: existing inference config would make shared state unsafe");
370+
return;
371+
}
372+
373+
if provider_exists(INFERENCE_PROVIDER_UNREACHABLE_NAME).await {
374+
delete_provider(INFERENCE_PROVIDER_UNREACHABLE_NAME).await;
375+
}
376+
377+
create_openai_provider(
378+
INFERENCE_PROVIDER_UNREACHABLE_NAME,
379+
"http://host.openshell.internal:9/v1",
380+
)
381+
.await
382+
.expect("create unreachable OpenAI provider");
383+
384+
let verify_err = run_cli(&[
385+
"inference",
386+
"set",
387+
"--provider",
388+
INFERENCE_PROVIDER_UNREACHABLE_NAME,
389+
"--model",
390+
"host-echo-model",
391+
])
392+
.await
393+
.expect_err("default verification should fail for unreachable endpoint");
394+
395+
assert!(
396+
verify_err.contains("failed to verify inference endpoint"),
397+
"expected verification failure output:\n{verify_err}"
398+
);
399+
assert!(
400+
verify_err.contains("--no-verify"),
401+
"expected retry hint in failure output:\n{verify_err}"
402+
);
403+
404+
let no_verify_output = run_cli(&[
405+
"inference",
406+
"set",
407+
"--provider",
408+
INFERENCE_PROVIDER_UNREACHABLE_NAME,
409+
"--model",
410+
"host-echo-model",
411+
"--no-verify",
412+
])
413+
.await
414+
.expect("no-verify should bypass validation");
415+
416+
assert!(
417+
!no_verify_output.contains("Validated Endpoints:"),
418+
"did not expect validation output when bypassing verification:\n{no_verify_output}"
419+
);
341420
}

0 commit comments

Comments
 (0)