mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-05 00:47:48 +08:00
test(gateway): align CI fixtures with routing contracts
This commit is contained in:
@@ -1,6 +1,5 @@
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use aether_ai_formats::openai_responses_message_item_id;
|
|
||||||
use axum::body::to_bytes;
|
use axum::body::to_bytes;
|
||||||
use base64::Engine as _;
|
use base64::Engine as _;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
@@ -12,10 +11,10 @@ use super::{
|
|||||||
convert_gemini_chat_response_to_openai_chat, convert_gemini_response_to_openai_responses,
|
convert_gemini_chat_response_to_openai_chat, convert_gemini_response_to_openai_responses,
|
||||||
maybe_build_local_core_sync_finalize_response,
|
maybe_build_local_core_sync_finalize_response,
|
||||||
};
|
};
|
||||||
use crate::ai_serving::GatewayControlDecision;
|
|
||||||
use crate::ai_serving::{
|
use crate::ai_serving::{
|
||||||
convert_openai_chat_response_to_openai_responses,
|
convert_openai_chat_response_to_openai_responses,
|
||||||
convert_openai_responses_response_to_openai_chat,
|
convert_openai_responses_response_to_openai_chat, openai_responses_message_item_id,
|
||||||
|
GatewayControlDecision,
|
||||||
};
|
};
|
||||||
use crate::usage::GatewaySyncReportRequest;
|
use crate::usage::GatewaySyncReportRequest;
|
||||||
|
|
||||||
|
|||||||
@@ -1963,8 +1963,9 @@ fn admin_provider_oauth_quota_mod_stays_thin() {
|
|||||||
"handlers/admin/provider/oauth/quota/antigravity.rs should import common quota helpers from shared.rs"
|
"handlers/admin/provider/oauth/quota/antigravity.rs should import common quota helpers from shared.rs"
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
quota_antigravity
|
quota_antigravity.contains("use aether_provider_pool::{")
|
||||||
.contains("use aether_provider_pool::build_antigravity_pool_quota_request;"),
|
&& quota_antigravity.contains("build_antigravity_pool_quota_request")
|
||||||
|
&& quota_antigravity.contains("build_antigravity_pool_quota_summary_request"),
|
||||||
"handlers/admin/provider/oauth/quota/antigravity.rs should delegate antigravity quota request construction to aether-provider-pool"
|
"handlers/admin/provider/oauth/quota/antigravity.rs should delegate antigravity quota request construction to aether-provider-pool"
|
||||||
);
|
);
|
||||||
let quota_chatgpt_web = read_workspace_file(
|
let quota_chatgpt_web = read_workspace_file(
|
||||||
|
|||||||
@@ -850,10 +850,7 @@ async fn gateway_handles_admin_global_model_routing_locally_with_trusted_admin_p
|
|||||||
provider_catalog_repository,
|
provider_catalog_repository,
|
||||||
)
|
)
|
||||||
.with_global_model_repository_for_tests(global_model_repository)
|
.with_global_model_repository_for_tests(global_model_repository)
|
||||||
.with_system_config_values_for_tests(vec![
|
.with_system_default_routing_group_for_tests(),
|
||||||
("scheduling_mode".to_string(), json!("fixed_order")),
|
|
||||||
("provider_priority_mode".to_string(), json!("global_key")),
|
|
||||||
]),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
let (gateway_url, gateway_handle) = start_server(gateway).await;
|
let (gateway_url, gateway_handle) = start_server(gateway).await;
|
||||||
@@ -876,8 +873,8 @@ async fn gateway_handles_admin_global_model_routing_locally_with_trusted_admin_p
|
|||||||
assert_eq!(payload["global_model_name"], "gpt-5");
|
assert_eq!(payload["global_model_name"], "gpt-5");
|
||||||
assert_eq!(payload["display_name"], "GPT 5");
|
assert_eq!(payload["display_name"], "GPT 5");
|
||||||
assert_eq!(payload["global_model_mappings"], json!(["gpt-5-upstream"]));
|
assert_eq!(payload["global_model_mappings"], json!(["gpt-5-upstream"]));
|
||||||
assert_eq!(payload["scheduling_mode"], "fixed_order");
|
assert_eq!(payload["scheduling_mode"], "cache_affinity");
|
||||||
assert_eq!(payload["priority_mode"], "global_key");
|
assert_eq!(payload["priority_mode"], "provider");
|
||||||
assert_eq!(payload["total_providers"], 2);
|
assert_eq!(payload["total_providers"], 2);
|
||||||
assert_eq!(payload["active_providers"], 2);
|
assert_eq!(payload["active_providers"], 2);
|
||||||
|
|
||||||
|
|||||||
@@ -1948,7 +1948,7 @@ async fn gateway_validates_chat_pii_redaction_system_config_locally_with_trusted
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn gateway_handles_admin_system_provider_priority_mode_locally_with_bearer_admin_session() {
|
async fn gateway_rejects_removed_admin_system_provider_priority_mode_with_bearer_admin_session() {
|
||||||
let upstream_hits = Arc::new(Mutex::new(0usize));
|
let upstream_hits = Arc::new(Mutex::new(0usize));
|
||||||
let upstream_hits_clone = Arc::clone(&upstream_hits);
|
let upstream_hits_clone = Arc::clone(&upstream_hits);
|
||||||
let upstream = Router::new().route(
|
let upstream = Router::new().route(
|
||||||
@@ -1962,7 +1962,7 @@ async fn gateway_handles_admin_system_provider_priority_mode_locally_with_bearer
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
let (upstream_url, upstream_handle) = start_server(upstream).await;
|
let (_upstream_url, upstream_handle) = start_server(upstream).await;
|
||||||
let state = AppState::new().expect("gateway should build");
|
let state = AppState::new().expect("gateway should build");
|
||||||
let access_token = issue_test_admin_access_token(&state, "device-admin-config").await;
|
let access_token = issue_test_admin_access_token(&state, "device-admin-config").await;
|
||||||
let gateway = build_router_with_state(state);
|
let gateway = build_router_with_state(state);
|
||||||
@@ -1978,10 +1978,7 @@ async fn gateway_handles_admin_system_provider_priority_mode_locally_with_bearer
|
|||||||
.await
|
.await
|
||||||
.expect("request should succeed");
|
.expect("request should succeed");
|
||||||
|
|
||||||
assert_eq!(response.status(), StatusCode::OK);
|
assert_eq!(response.status(), StatusCode::NOT_FOUND);
|
||||||
let payload: serde_json::Value = response.json().await.expect("json body should parse");
|
|
||||||
assert_eq!(payload["key"], "provider_priority_mode");
|
|
||||||
assert_eq!(payload["value"], "provider");
|
|
||||||
assert_eq!(*upstream_hits.lock().expect("mutex should lock"), 0);
|
assert_eq!(*upstream_hits.lock().expect("mutex should lock"), 0);
|
||||||
|
|
||||||
gateway_handle.abort();
|
gateway_handle.abort();
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ use super::{
|
|||||||
InMemoryVideoTaskRepository, StoredAuthApiKeySnapshot, UpsertVideoTask, VideoTaskLookupKey,
|
InMemoryVideoTaskRepository, StoredAuthApiKeySnapshot, UpsertVideoTask, VideoTaskLookupKey,
|
||||||
VideoTaskReadRepository, VideoTaskStatus, VideoTaskWriteRepository, DEVELOPMENT_ENCRYPTION_KEY,
|
VideoTaskReadRepository, VideoTaskStatus, VideoTaskWriteRepository, DEVELOPMENT_ENCRYPTION_KEY,
|
||||||
};
|
};
|
||||||
|
use crate::data::GatewayDataState;
|
||||||
use crate::image_capabilities::openai_image_gateway_max_generation_count;
|
use crate::image_capabilities::openai_image_gateway_max_generation_count;
|
||||||
use crate::tests::{
|
use crate::tests::{
|
||||||
any, build_router_with_state, build_state_with_execution_runtime_override, json, start_server,
|
any, build_router_with_state, build_state_with_execution_runtime_override, json, start_server,
|
||||||
@@ -3477,7 +3478,10 @@ async fn gateway_does_not_locally_reject_image_model_name_on_chat_completions()
|
|||||||
let gateway = build_router_with_state(
|
let gateway = build_router_with_state(
|
||||||
AppState::new()
|
AppState::new()
|
||||||
.expect("gateway should build")
|
.expect("gateway should build")
|
||||||
.with_auth_api_key_data_reader_for_tests(auth_repository),
|
.with_data_state_for_tests(
|
||||||
|
GatewayDataState::with_auth_api_key_reader_for_tests(auth_repository)
|
||||||
|
.with_system_default_routing_group_for_tests(),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
let (gateway_url, gateway_handle) = start_server(gateway).await;
|
let (gateway_url, gateway_handle) = start_server(gateway).await;
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ use super::{
|
|||||||
InMemoryProviderCatalogReadRepository, InMemoryRequestCandidateRepository,
|
InMemoryProviderCatalogReadRepository, InMemoryRequestCandidateRepository,
|
||||||
DEVELOPMENT_ENCRYPTION_KEY,
|
DEVELOPMENT_ENCRYPTION_KEY,
|
||||||
};
|
};
|
||||||
|
use crate::data::GatewayDataState;
|
||||||
use crate::tests::{
|
use crate::tests::{
|
||||||
any, build_router, build_router_with_state, build_state_with_execution_runtime_override, json,
|
any, build_router, build_router_with_state, build_state_with_execution_runtime_override, json,
|
||||||
start_server, strip_sse_keepalive_comments, AppState, Arc, Body, HeaderValue, Json, Mutex,
|
start_server, strip_sse_keepalive_comments, AppState, Arc, Body, HeaderValue, Json, Mutex,
|
||||||
@@ -1301,7 +1302,10 @@ async fn gateway_returns_internal_gateway_decision_sync_fallback_with_resolved_a
|
|||||||
let gateway = build_router_with_state(
|
let gateway = build_router_with_state(
|
||||||
AppState::new()
|
AppState::new()
|
||||||
.expect("gateway should build")
|
.expect("gateway should build")
|
||||||
.with_auth_api_key_data_reader_for_tests(auth_repository),
|
.with_data_state_for_tests(
|
||||||
|
GatewayDataState::with_auth_api_key_reader_for_tests(auth_repository)
|
||||||
|
.with_system_default_routing_group_for_tests(),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
let (gateway_url, gateway_handle) = start_server(gateway).await;
|
let (gateway_url, gateway_handle) = start_server(gateway).await;
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,10 @@ use aether_data::repository::provider_catalog::InMemoryProviderCatalogReadReposi
|
|||||||
use aether_data_contracts::repository::provider_catalog::{
|
use aether_data_contracts::repository::provider_catalog::{
|
||||||
StoredProviderCatalogEndpoint, StoredProviderCatalogKey, StoredProviderCatalogProvider,
|
StoredProviderCatalogEndpoint, StoredProviderCatalogKey, StoredProviderCatalogProvider,
|
||||||
};
|
};
|
||||||
|
use aether_scheduler_core::{
|
||||||
|
build_scheduler_affinity_cache_key_for_api_key_id_with_client_session_and_scope,
|
||||||
|
SchedulerAffinityScope,
|
||||||
|
};
|
||||||
use sha2::{Digest, Sha256};
|
use sha2::{Digest, Sha256};
|
||||||
|
|
||||||
fn hash_api_key(value: &str) -> String {
|
fn hash_api_key(value: &str) -> String {
|
||||||
@@ -26,6 +30,18 @@ fn hash_api_key(value: &str) -> String {
|
|||||||
format!("{:x}", hasher.finalize())
|
format!("{:x}", hasher.finalize())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn system_default_affinity_cache_key(api_key_id: &str, api_format: &str, model: &str) -> String {
|
||||||
|
let scope = SchedulerAffinityScope::new("system-default", Some(1));
|
||||||
|
build_scheduler_affinity_cache_key_for_api_key_id_with_client_session_and_scope(
|
||||||
|
api_key_id,
|
||||||
|
api_format,
|
||||||
|
model,
|
||||||
|
None,
|
||||||
|
Some(&scope),
|
||||||
|
)
|
||||||
|
.expect("system-default affinity cache key should build")
|
||||||
|
}
|
||||||
|
|
||||||
fn sample_auth_snapshot(
|
fn sample_auth_snapshot(
|
||||||
api_key_id: &str,
|
api_key_id: &str,
|
||||||
user_id: &str,
|
user_id: &str,
|
||||||
@@ -626,6 +642,7 @@ async fn gateway_forwards_public_request_to_remote_tunnel_owner_before_fallback_
|
|||||||
"development-key",
|
"development-key",
|
||||||
)
|
)
|
||||||
.with_auth_api_key_reader(auth_repository)
|
.with_auth_api_key_reader(auth_repository)
|
||||||
|
.with_system_default_routing_group_for_tests()
|
||||||
.with_system_config_values_for_tests(vec![(
|
.with_system_config_values_for_tests(vec![(
|
||||||
tunnel_attachment_key("node-owner"),
|
tunnel_attachment_key("node-owner"),
|
||||||
serde_json::to_value(crate::tunnel::TunnelAttachmentRecord {
|
serde_json::to_value(crate::tunnel::TunnelAttachmentRecord {
|
||||||
@@ -648,7 +665,7 @@ async fn gateway_forwards_public_request_to_remote_tunnel_owner_before_fallback_
|
|||||||
state.client = short_timeout_client.clone();
|
state.client = short_timeout_client.clone();
|
||||||
state.owner_forward_client = short_timeout_client;
|
state.owner_forward_client = short_timeout_client;
|
||||||
state.remember_scheduler_affinity_target(
|
state.remember_scheduler_affinity_target(
|
||||||
"scheduler_affinity:api-key-affinity-1:openai:chat:gpt-4.1",
|
&system_default_affinity_cache_key("api-key-affinity-1", "openai:chat", "gpt-4.1"),
|
||||||
crate::cache::SchedulerAffinityTarget {
|
crate::cache::SchedulerAffinityTarget {
|
||||||
provider_id: "provider-owner".to_string(),
|
provider_id: "provider-owner".to_string(),
|
||||||
endpoint_id: "endpoint-owner".to_string(),
|
endpoint_id: "endpoint-owner".to_string(),
|
||||||
@@ -853,6 +870,7 @@ async fn gateway_aggregates_sync_sse_from_remote_tunnel_owner_before_returning_t
|
|||||||
"development-key",
|
"development-key",
|
||||||
)
|
)
|
||||||
.with_auth_api_key_reader(auth_repository)
|
.with_auth_api_key_reader(auth_repository)
|
||||||
|
.with_system_default_routing_group_for_tests()
|
||||||
.with_system_config_values_for_tests(vec![(
|
.with_system_config_values_for_tests(vec![(
|
||||||
tunnel_attachment_key("node-cli-owner"),
|
tunnel_attachment_key("node-cli-owner"),
|
||||||
serde_json::to_value(crate::tunnel::TunnelAttachmentRecord {
|
serde_json::to_value(crate::tunnel::TunnelAttachmentRecord {
|
||||||
@@ -869,7 +887,7 @@ async fn gateway_aggregates_sync_sse_from_remote_tunnel_owner_before_returning_t
|
|||||||
.with_data_state_for_tests(data_state)
|
.with_data_state_for_tests(data_state)
|
||||||
.with_tunnel_identity_for_tests("gateway-a", Some("http://gateway-a:8080"));
|
.with_tunnel_identity_for_tests("gateway-a", Some("http://gateway-a:8080"));
|
||||||
state.remember_scheduler_affinity_target(
|
state.remember_scheduler_affinity_target(
|
||||||
"scheduler_affinity:api-key-affinity-cli-1:openai:responses:gpt-5.4",
|
&system_default_affinity_cache_key("api-key-affinity-cli-1", "openai:responses", "gpt-5.4"),
|
||||||
crate::cache::SchedulerAffinityTarget {
|
crate::cache::SchedulerAffinityTarget {
|
||||||
provider_id: "provider-cli-owner".to_string(),
|
provider_id: "provider-cli-owner".to_string(),
|
||||||
endpoint_id: "endpoint-cli-owner".to_string(),
|
endpoint_id: "endpoint-cli-owner".to_string(),
|
||||||
@@ -1100,6 +1118,7 @@ async fn gateway_streamifies_sync_json_from_remote_tunnel_owner_before_returning
|
|||||||
"development-key",
|
"development-key",
|
||||||
)
|
)
|
||||||
.with_auth_api_key_reader(auth_repository)
|
.with_auth_api_key_reader(auth_repository)
|
||||||
|
.with_system_default_routing_group_for_tests()
|
||||||
.with_system_config_values_for_tests(vec![(
|
.with_system_config_values_for_tests(vec![(
|
||||||
tunnel_attachment_key("node-cli-owner"),
|
tunnel_attachment_key("node-cli-owner"),
|
||||||
serde_json::to_value(crate::tunnel::TunnelAttachmentRecord {
|
serde_json::to_value(crate::tunnel::TunnelAttachmentRecord {
|
||||||
@@ -1120,7 +1139,7 @@ async fn gateway_streamifies_sync_json_from_remote_tunnel_owner_before_returning
|
|||||||
.build()
|
.build()
|
||||||
.expect("short shared client should build");
|
.expect("short shared client should build");
|
||||||
state.remember_scheduler_affinity_target(
|
state.remember_scheduler_affinity_target(
|
||||||
"scheduler_affinity:api-key-affinity-cli-1:openai:responses:gpt-5.4",
|
&system_default_affinity_cache_key("api-key-affinity-cli-1", "openai:responses", "gpt-5.4"),
|
||||||
crate::cache::SchedulerAffinityTarget {
|
crate::cache::SchedulerAffinityTarget {
|
||||||
provider_id: "provider-cli-owner".to_string(),
|
provider_id: "provider-cli-owner".to_string(),
|
||||||
endpoint_id: "endpoint-cli-owner".to_string(),
|
endpoint_id: "endpoint-cli-owner".to_string(),
|
||||||
|
|||||||
Reference in New Issue
Block a user