test: expand e2e raw coverage across agent, channels, inference, memory, tools (#3023)

This commit is contained in:
Steven Enamakel
2026-05-30 14:38:50 -07:00
committed by GitHub
parent acb12adf80
commit 5345f2a834
129 changed files with 67834 additions and 250 deletions
@@ -0,0 +1,484 @@
#[path = "config_auth_app_state_connectivity_e2e.rs"]
mod base_coverage;
use std::path::{Path, PathBuf};
use serde_json::{json, Value};
use tempfile::{tempdir, TempDir};
use openhuman_core::openhuman::app_state::{snapshot, update_local_state, StoredAppStatePatch};
use openhuman_core::openhuman::config::rpc as config_rpc;
use openhuman_core::openhuman::credentials::{
auth_get_session_token_json, clear_session, list_provider_credentials,
remove_provider_credentials, store_provider_credentials, store_session, AuthService,
};
use tokio::io::{AsyncReadExt, AsyncWriteExt};
struct Round13EnvVarGuard {
key: &'static str,
old: Option<String>,
}
impl Round13EnvVarGuard {
fn set(key: &'static str, value: &str) -> Self {
let old = std::env::var(key).ok();
std::env::set_var(key, value);
Self { key, old }
}
fn set_to_path(key: &'static str, path: &Path) -> Self {
let old = std::env::var(key).ok();
std::env::set_var(key, path.as_os_str());
Self { key, old }
}
fn unset(key: &'static str) -> Self {
let old = std::env::var(key).ok();
std::env::remove_var(key);
Self { key, old }
}
}
impl Drop for Round13EnvVarGuard {
fn drop(&mut self) {
match &self.old {
Some(value) => std::env::set_var(self.key, value),
None => std::env::remove_var(self.key),
}
}
}
struct Round13Harness {
_tmp: TempDir,
workspace_override: PathBuf,
_guards: Vec<Round13EnvVarGuard>,
}
impl Round13Harness {
async fn config(&self) -> openhuman_core::openhuman::config::Config {
config_rpc::load_config_with_timeout()
.await
.expect("isolated config should load")
}
fn app_state_file(&self) -> PathBuf {
self.workspace_override
.join("workspace/state/app-state.json")
}
}
fn round13_env_lock() -> std::sync::MutexGuard<'static, ()> {
// Delegate to the lock owned by the included `base_coverage` (config_auth)
// module so round13 env mutations serialize against every other
// OPENHUMAN_WORKSPACE/BACKEND_URL-mutating test in this combined binary.
// Two separate mutexes let the two groups race and quarantine the wrong
// workspace (flaky `!state_file.exists()` / spurious JSON-RPC errors).
base_coverage::env_lock()
}
fn write_round13_min_config(openhuman_dir: &Path) {
std::fs::create_dir_all(openhuman_dir).expect("create openhuman config dir");
let cfg = r#"api_url = "http://127.0.0.1:9"
default_model = "round13-raw-coverage-model"
default_temperature = 0.2
onboarding_completed = false
chat_onboarding_completed = false
[secrets]
encrypt = false
[local_ai]
enabled = false
runtime_enabled = false
opt_in_confirmed = false
[memory]
provider = "none"
embedding_provider = "none"
embedding_model = "none"
embedding_dimensions = 0
auto_save = false
[memory_tree]
embedding_strict = false
"#;
std::fs::write(openhuman_dir.join("config.toml"), cfg).expect("write config.toml");
let _: openhuman_core::openhuman::config::Config =
toml::from_str(cfg).expect("test config must match schema");
}
fn round13_setup() -> Round13Harness {
let tmp = tempdir().expect("tempdir");
let workspace_override = tmp.path().join("openhuman");
write_round13_min_config(&workspace_override);
let guards = vec![
Round13EnvVarGuard::set_to_path("OPENHUMAN_WORKSPACE", &workspace_override),
Round13EnvVarGuard::set_to_path("HOME", tmp.path()),
Round13EnvVarGuard::unset("BACKEND_URL"),
Round13EnvVarGuard::unset("VITE_BACKEND_URL"),
Round13EnvVarGuard::unset("OPENHUMAN_API_URL"),
Round13EnvVarGuard::unset("OPENHUMAN_CORE_RPC_URL"),
Round13EnvVarGuard::unset("OPENHUMAN_CORE_PORT"),
Round13EnvVarGuard::set("OPENHUMAN_KEYRING_BACKEND", "file"),
Round13EnvVarGuard::set("OPENHUMAN_MEMORY_EMBED_STRICT", "false"),
Round13EnvVarGuard::set("OPENHUMAN_MEMORY_EMBED_ENDPOINT", ""),
Round13EnvVarGuard::set("OPENHUMAN_MEMORY_EMBED_MODEL", ""),
Round13EnvVarGuard::set("OPENHUMAN_BROWSER_ALLOW_ALL_RPC_ENABLE", ""),
];
Round13Harness {
_tmp: tmp,
workspace_override,
_guards: guards,
}
}
#[tokio::test]
async fn raw_round13_provider_field_fallbacks_default_profile_and_non_active_listing() {
let _lock = round13_env_lock();
let harness = round13_setup();
let config = harness.config().await;
let empty = store_provider_credentials(&config, " ", None, None, None, None).await;
assert_eq!(empty.unwrap_err(), "provider is required");
let invalid_fields = store_provider_credentials(
&config,
"raw-provider",
None,
None,
Some(json!("bad")),
None,
)
.await;
assert!(invalid_fields
.unwrap_err()
.contains("fields must be a JSON object"));
let missing =
store_provider_credentials(&config, "raw-provider", None, None, Some(json!({})), None)
.await;
assert!(missing
.unwrap_err()
.contains("provide at least one credential"));
let stored_from_token_field = store_provider_credentials(
&config,
"raw-provider",
None,
None,
Some(json!({
"token": "field-token",
"region": "us-test-1"
})),
Some(true),
)
.await
.expect("store token field credential");
assert_eq!(stored_from_token_field.value.provider, "raw-provider");
assert_eq!(stored_from_token_field.value.profile_name, "default");
assert!(stored_from_token_field.value.has_token);
let auth = AuthService::from_config(&config);
assert_eq!(
auth.get_provider_bearer_token("raw-provider", None)
.expect("read active bearer")
.as_deref(),
Some("field-token")
);
let stored_from_api_key = store_provider_credentials(
&config,
"raw-provider",
Some("secondary"),
None,
Some(json!({
"api_key": "api-key-token",
"label": "kept as metadata"
})),
Some(false),
)
.await
.expect("store api_key field credential");
assert_eq!(stored_from_api_key.value.profile_name, "secondary");
let listed = list_provider_credentials(&config, Some("raw-provider".to_string()))
.await
.expect("list raw provider credentials")
.value;
let names = listed
.iter()
.map(|profile| profile.profile_name.as_str())
.collect::<Vec<_>>();
assert_eq!(names, vec!["default", "secondary"]);
let removed_default = remove_provider_credentials(&config, "raw-provider", None)
.await
.expect("remove default profile");
assert_eq!(removed_default.value["removed"], true);
assert_eq!(removed_default.value["profile"], "default");
let removed_missing = remove_provider_credentials(&config, "raw-provider", Some("missing"))
.await
.expect("remove missing profile is non-fatal");
assert_eq!(removed_missing.value["removed"], false);
}
#[tokio::test]
async fn raw_round13_local_session_string_payload_and_double_clear_are_offline() {
let _lock = round13_env_lock();
let harness = round13_setup();
let config = harness.config().await;
let empty_token = store_session(&config, " ", None, None).await;
assert_eq!(empty_token.unwrap_err(), "token is required");
let local_without_user = store_session(&config, "header.payload.local", None, None).await;
assert_eq!(
local_without_user.unwrap_err(),
"local session requires a user payload"
);
let stored = store_session(
&config,
"header.payload.local",
Some("ignored-user-hint".to_string()),
Some(json!("string user payload is preserved")),
)
.await
.expect("store local session with non-object user payload");
assert_eq!(stored.value.provider, "app-session");
assert!(stored
.logs
.iter()
.any(|log| log == "local session accepted without backend validation"));
let effective_config = config_rpc::load_config_with_timeout()
.await
.expect("reload active local user config");
let token = auth_get_session_token_json(&effective_config)
.await
.expect("session token")
.value;
assert_eq!(token["token"], "header.payload.local");
let first_clear = clear_session(&effective_config)
.await
.expect("clear stored session");
assert_eq!(first_clear.value["removed"], true);
let signed_out_config = config_rpc::load_config_with_timeout()
.await
.expect("reload signed-out config");
let second_clear = clear_session(&signed_out_config)
.await
.expect("clear missing session is idempotent");
assert_eq!(second_clear.value["removed"], false);
}
#[tokio::test]
async fn raw_round13_app_state_update_trims_clears_and_preserves_optional_local_state() {
let _lock = round13_env_lock();
let harness = round13_setup();
let updated = update_local_state(StoredAppStatePatch {
encryption_key: Some(Some(" raw-key ".to_string())),
onboarding_tasks: Some(Some(Default::default())),
})
.await
.expect("update local app state")
.value;
assert_eq!(updated.encryption_key.as_deref(), Some("raw-key"));
assert!(updated.onboarding_tasks.is_some());
let cleared_key = update_local_state(StoredAppStatePatch {
encryption_key: Some(Some(" ".to_string())),
onboarding_tasks: None,
})
.await
.expect("blank key clears encryption key")
.value;
assert!(cleared_key.encryption_key.is_none());
assert!(cleared_key.onboarding_tasks.is_some());
let cleared_tasks = update_local_state(StoredAppStatePatch {
encryption_key: None,
onboarding_tasks: Some(None),
})
.await
.expect("null tasks clear onboarding tasks")
.value;
assert!(cleared_tasks.encryption_key.is_none());
assert!(cleared_tasks.onboarding_tasks.is_none());
let unchanged = update_local_state(StoredAppStatePatch {
encryption_key: None,
onboarding_tasks: None,
})
.await
.expect("empty patch preserves cleared state")
.value;
assert!(unchanged.encryption_key.is_none());
assert!(unchanged.onboarding_tasks.is_none());
let raw = std::fs::read_to_string(harness.app_state_file()).expect("app state persisted");
assert_eq!(
serde_json::from_str::<Value>(&raw).expect("valid app state json"),
json!({})
);
}
#[tokio::test]
async fn raw_round13_app_state_snapshot_quarantines_null_and_malformed_local_state_files() {
let _lock = round13_env_lock();
let harness = round13_setup();
let state_file = harness.app_state_file();
let state_dir = state_file.parent().expect("state dir");
std::fs::create_dir_all(state_dir).expect("create state dir");
std::fs::write(&state_file, "null").expect("write semantically invalid app state");
let null_snapshot = snapshot().await.expect("snapshot with null state").value;
assert!(null_snapshot.local_state.encryption_key.is_none());
assert!(null_snapshot.local_state.onboarding_tasks.is_none());
assert!(
!state_file.exists(),
"invalid app-state.json should be quarantined or removed"
);
assert!(
std::fs::read_dir(state_dir)
.expect("state dir entries")
.filter_map(Result::ok)
.any(|entry| entry
.file_name()
.to_string_lossy()
.starts_with("app-state.json.corrupted.")),
"null app-state file should leave a quarantine artifact"
);
std::fs::write(&state_file, "{not-json").expect("write malformed app state");
let malformed_snapshot = snapshot()
.await
.expect("snapshot with malformed state")
.value;
assert!(malformed_snapshot.local_state.encryption_key.is_none());
assert!(malformed_snapshot.local_state.onboarding_tasks.is_none());
assert!(!state_file.exists());
}
async fn spawn_probe_listener(
host: &str,
status: &str,
body: &'static str,
) -> Option<(
u16,
tokio::task::JoinHandle<()>,
tokio::sync::oneshot::Sender<()>,
)> {
let listener = match tokio::net::TcpListener::bind((host, 0)).await {
Ok(listener) => listener,
Err(_) => return None,
};
let port = listener.local_addr().expect("probe listener addr").port();
let status = status.to_string();
let (shutdown_tx, mut shutdown_rx) = tokio::sync::oneshot::channel::<()>();
let task = tokio::spawn(async move {
loop {
tokio::select! {
_ = &mut shutdown_rx => break,
accepted = listener.accept() => {
let Ok((mut stream, _addr)) = accepted else {
break;
};
let mut req_buf = [0_u8; 1024];
let _ = stream.read(&mut req_buf).await;
let response = format!(
"HTTP/1.1 {status}\r\ncontent-type: application/json\r\ncontent-length: {}\r\nconnection: close\r\n\r\n{}",
body.len(),
body
);
let _ = stream.write_all(response.as_bytes()).await;
let _ = stream.shutdown().await;
}
}
}
});
Some((port, task, shutdown_tx))
}
#[tokio::test]
async fn raw_round13_connectivity_picker_identifies_openhuman_probe_listener() {
let Some((preferred, task, shutdown_tx)) =
spawn_probe_listener("127.0.0.1", "200 OK", r#"{"name":"openhuman","ok":true}"#).await
else {
return;
};
let result = openhuman_core::openhuman::connectivity::rpc::pick_listen_port_for_host(
"127.0.0.1",
preferred,
)
.await;
let err = result.expect_err("openhuman probe listener should request takeover");
assert!(
matches!(
err,
openhuman_core::openhuman::connectivity::rpc::PickListenPortError::WouldTakeOver {
preferred: p,
ref fingerprint
} if p == preferred && fingerprint == "openhuman-core"
),
"unexpected picker error: {err:?}"
);
let _ = shutdown_tx.send(());
let _ = task.await;
}
#[tokio::test]
async fn raw_round13_connectivity_picker_falls_back_for_non_success_probe_status() {
let Some((preferred, task, shutdown_tx)) = spawn_probe_listener(
"127.0.0.1",
"503 Service Unavailable",
r#"{"name":"openhuman"}"#,
)
.await
else {
return;
};
let picked = openhuman_core::openhuman::connectivity::rpc::pick_listen_port_for_host(
"127.0.0.1",
preferred,
)
.await
.expect("non-openhuman status should fall back");
assert_ne!(picked.port, preferred);
assert_eq!(picked.fallback_from, Some(preferred));
drop(picked.listener);
let _ = shutdown_tx.send(());
let _ = task.await;
}
#[tokio::test]
async fn raw_round13_connectivity_picker_falls_back_for_non_identifying_probe_body() {
let Some((preferred, task, shutdown_tx)) =
spawn_probe_listener("127.0.0.1", "200 OK", r#"{"name":"someone-else"}"#).await
else {
return;
};
let picked = openhuman_core::openhuman::connectivity::rpc::pick_listen_port_for_host(
"127.0.0.1",
preferred,
)
.await
.expect("non-identifying body should fall back");
assert_ne!(picked.port, preferred);
assert_eq!(picked.fallback_from, Some(preferred));
drop(picked.listener);
let _ = shutdown_tx.send(());
let _ = task.await;
}