//! Runnable smoke test for the Rust origin-client SDK. //! //! Without ORIGIN_SERVICE_KEY set, it spins up a local mock check-in server //! and exercises the client against it — no network, no credentials needed. //! With ORIGIN_SERVICE_KEY set, it performs a real check-in against //! ORIGIN_URL (or Origin's public endpoint) so the SDK can be smoke-tested //! end-to-end against a live server. //! //! Usage: `cargo run --example testclient [-- --watch]` use std::env; use std::sync::Arc; use origin_client::{Client, Config, FnLogger}; use tokio_util::sync::CancellationToken; fn env_or(key: &str, default: &str) -> String { env::var(key).unwrap_or_else(|_| default.to_string()) } #[tokio::main] async fn main() { let watch = env::args().any(|a| a == "--watch"); let mut cfg = Config { url: env::var("ORIGIN_URL").ok(), service_key: env::var("ORIGIN_SERVICE_KEY").unwrap_or_default(), type_: env_or("ORIGIN_TYPE", "icy2-testclient"), version: env_or("ORIGIN_VERSION", "0.0.0-test"), name: env_or("ORIGIN_NAME", "icy2-testclient-local"), site: env::var("ORIGIN_SITE").ok(), environment: env::var("ORIGIN_ENVIRONMENT").ok(), logger: Arc::new(FnLogger(|msg: &str, err| { eprintln!("[warn] {msg}: {err:?}"); })), ..Default::default() }; // Held so the mock server stays alive for the client's lifetime; unused // in real-endpoint mode. let mut _mock_server = None; if cfg.service_key.is_empty() { println!("ORIGIN_SERVICE_KEY not set — using a local mock check-in server"); let mut server = mockito::Server::new_async().await; server .mock("POST", "/") .with_status(200) .with_header("content-type", "application/json") .with_body( r#"{"success":true,"service_instance_id":1,"unique_install_id":"test-install-id","status":"provisioning","pinged_at":"2026-08-01T00:00:00Z"}"#, ) .create_async() .await; cfg.url = Some(server.url()); cfg.service_key = "test-key".to_string(); cfg.install_id = Some("test-install-id".to_string()); _mock_server = Some(server); } if let Ok(h) = env::var("ORIGIN_INTERVAL_HOURS") { if let Ok(n) = h.parse() { cfg.interval_hours = Some(n); } } let client = Client::new(cfg).expect("origin_client::Config validation failed"); if watch { println!("watching — Ctrl-C to stop"); let cancel = CancellationToken::new(); let cancel_clone = cancel.clone(); tokio::spawn(async move { tokio::signal::ctrl_c().await.ok(); cancel_clone.cancel(); }); client.run(cancel).await; return; } match client.checkin_once().await { Ok(resp) => { println!("{resp:#?}"); } Err(err) => { eprintln!("checkin failed: {err}"); std::process::exit(1); } } }