mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-01 17:00:21 +08:00
Align runtime miss tests with skipped candidates
This commit is contained in:
@@ -1610,6 +1610,7 @@ fn local_execution_runtime_miss_skip_reason_label(reason: &str) -> &str {
|
|||||||
"auth_snapshot_missing" => "API Key 本地执行配置缺失",
|
"auth_snapshot_missing" => "API Key 本地执行配置缺失",
|
||||||
"endpoint_api_format_changed" => "端点 API 格式已变更",
|
"endpoint_api_format_changed" => "端点 API 格式已变更",
|
||||||
"endpoint_inactive" => "端点未启用",
|
"endpoint_inactive" => "端点未启用",
|
||||||
|
"format_conversion_disabled" => "格式转换未启用",
|
||||||
"key_api_format_disabled" => "API Key 未启用该 API 格式",
|
"key_api_format_disabled" => "API Key 未启用该 API 格式",
|
||||||
"key_inactive" => "API Key 未启用",
|
"key_inactive" => "API Key 未启用",
|
||||||
"key_model_disabled" => "API Key 未允许该模型",
|
"key_model_disabled" => "API Key 未允许该模型",
|
||||||
|
|||||||
@@ -952,20 +952,25 @@ async fn gateway_marks_claude_cli_cross_format_runtime_miss_when_format_conversi
|
|||||||
.headers()
|
.headers()
|
||||||
.get(LOCAL_EXECUTION_RUNTIME_MISS_REASON_HEADER)
|
.get(LOCAL_EXECUTION_RUNTIME_MISS_REASON_HEADER)
|
||||||
.and_then(|value| value.to_str().ok()),
|
.and_then(|value| value.to_str().ok()),
|
||||||
Some("candidate_list_empty")
|
Some("all_candidates_skipped")
|
||||||
);
|
);
|
||||||
let response_json: serde_json::Value = response.json().await.expect("body should parse");
|
let response_json: serde_json::Value = response.json().await.expect("body should parse");
|
||||||
assert_eq!(response_json["error"]["type"], "http_error");
|
assert_eq!(response_json["error"]["type"], "http_error");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
response_json["error"]["message"],
|
response_json["error"]["message"],
|
||||||
"没有可用提供商支持模型 gpt-5.4 的同步请求"
|
"找到 1 个支持模型 gpt-5.4 的候选提供商,但本次同步请求全部不可用:格式转换未启用 2 次"
|
||||||
);
|
);
|
||||||
|
|
||||||
let stored_candidates = request_candidate_repository
|
let stored_candidates = request_candidate_repository
|
||||||
.list_by_request_id("trace-claude-cli-openai-local-miss-123")
|
.list_by_request_id("trace-claude-cli-openai-local-miss-123")
|
||||||
.await
|
.await
|
||||||
.expect("request candidate trace should read");
|
.expect("request candidate trace should read");
|
||||||
assert!(stored_candidates.is_empty());
|
assert_eq!(stored_candidates.len(), 1);
|
||||||
|
assert_eq!(stored_candidates[0].status, RequestCandidateStatus::Skipped);
|
||||||
|
assert_eq!(
|
||||||
|
stored_candidates[0].skip_reason.as_deref(),
|
||||||
|
Some("format_conversion_disabled")
|
||||||
|
);
|
||||||
assert_eq!(*public_hits.lock().expect("mutex should lock"), 0);
|
assert_eq!(*public_hits.lock().expect("mutex should lock"), 0);
|
||||||
|
|
||||||
gateway_handle.abort();
|
gateway_handle.abort();
|
||||||
|
|||||||
@@ -370,14 +370,18 @@ fn scheduler_candidate_runtime_paths_depend_on_scheduler_core_and_state_trait()
|
|||||||
}
|
}
|
||||||
|
|
||||||
let affinity = read_workspace_file("apps/aether-gateway/src/scheduler/candidate/affinity.rs");
|
let affinity = read_workspace_file("apps/aether-gateway/src/scheduler/candidate/affinity.rs");
|
||||||
|
let ranking = read_workspace_file("apps/aether-gateway/src/scheduler/candidate/ranking.rs");
|
||||||
|
let resolution =
|
||||||
|
read_workspace_file("apps/aether-gateway/src/scheduler/candidate/resolution.rs");
|
||||||
|
let candidate_runtime_path_source = format!("{affinity}\n{ranking}\n{resolution}");
|
||||||
assert!(
|
assert!(
|
||||||
affinity.contains("SchedulerRuntimeState"),
|
affinity.contains("SchedulerRuntimeState"),
|
||||||
"candidate/affinity.rs should depend on SchedulerRuntimeState"
|
"candidate/affinity.rs should depend on SchedulerRuntimeState"
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
affinity.contains("aether_scheduler_core::{")
|
candidate_runtime_path_source.contains("aether_scheduler_core::{")
|
||||||
&& affinity.contains("SchedulerAffinityTarget"),
|
&& candidate_runtime_path_source.contains("SchedulerAffinityTarget"),
|
||||||
"candidate/affinity.rs should depend on core SchedulerAffinityTarget"
|
"scheduler candidate runtime path should depend on core SchedulerAffinityTarget"
|
||||||
);
|
);
|
||||||
for pattern in [
|
for pattern in [
|
||||||
"candidate_affinity_hash",
|
"candidate_affinity_hash",
|
||||||
@@ -385,21 +389,21 @@ fn scheduler_candidate_runtime_paths_depend_on_scheduler_core_and_state_trait()
|
|||||||
"candidate_key",
|
"candidate_key",
|
||||||
] {
|
] {
|
||||||
assert!(
|
assert!(
|
||||||
affinity.contains(pattern),
|
candidate_runtime_path_source.contains(pattern),
|
||||||
"candidate/affinity.rs should depend on core affinity helper {pattern}"
|
"scheduler candidate runtime path should depend on core affinity helper {pattern}"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
assert!(
|
assert!(
|
||||||
!affinity.contains("use crate::AppState"),
|
!candidate_runtime_path_source.contains("use crate::AppState"),
|
||||||
"candidate/affinity.rs should not depend on AppState directly"
|
"scheduler candidate runtime path should not depend on AppState directly"
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
!affinity.contains("crate::cache::SchedulerAffinityTarget"),
|
!candidate_runtime_path_source.contains("crate::cache::SchedulerAffinityTarget"),
|
||||||
"candidate/affinity.rs should not depend on gateway-local SchedulerAffinityTarget"
|
"scheduler candidate runtime path should not depend on gateway-local SchedulerAffinityTarget"
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
!affinity.contains("use sha2::{Digest, Sha256};"),
|
!candidate_runtime_path_source.contains("use sha2::{Digest, Sha256};"),
|
||||||
"candidate/affinity.rs should not own affinity hashing implementation anymore"
|
"scheduler candidate runtime path should not own affinity hashing implementation anymore"
|
||||||
);
|
);
|
||||||
for pattern in [
|
for pattern in [
|
||||||
"fn compare_affinity_order(",
|
"fn compare_affinity_order(",
|
||||||
|
|||||||
@@ -1570,13 +1570,13 @@ async fn gateway_records_failed_usage_when_all_local_claude_cli_candidates_are_s
|
|||||||
.headers()
|
.headers()
|
||||||
.get(LOCAL_EXECUTION_RUNTIME_MISS_REASON_HEADER)
|
.get(LOCAL_EXECUTION_RUNTIME_MISS_REASON_HEADER)
|
||||||
.and_then(|value| value.to_str().ok()),
|
.and_then(|value| value.to_str().ok()),
|
||||||
Some("candidate_list_empty")
|
Some("all_candidates_skipped")
|
||||||
);
|
);
|
||||||
let body_json: serde_json::Value = response.json().await.expect("body should parse");
|
let body_json: serde_json::Value = response.json().await.expect("body should parse");
|
||||||
assert_eq!(body_json["error"]["type"], "http_error");
|
assert_eq!(body_json["error"]["type"], "http_error");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
body_json["error"]["message"],
|
body_json["error"]["message"],
|
||||||
"没有可用提供商支持模型 gpt-5.4 的同步请求"
|
"找到 1 个支持模型 gpt-5.4 的候选提供商,但本次同步请求全部不可用:格式转换未启用 2 次"
|
||||||
);
|
);
|
||||||
|
|
||||||
let stored_usage = wait_for_usage_status(
|
let stored_usage = wait_for_usage_status(
|
||||||
@@ -1610,12 +1610,12 @@ async fn gateway_records_failed_usage_when_all_local_claude_cli_candidates_are_s
|
|||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
stored_usage.routing_local_execution_runtime_miss_reason(),
|
stored_usage.routing_local_execution_runtime_miss_reason(),
|
||||||
Some("candidate_list_empty")
|
Some("all_candidates_skipped")
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
stored_usage.error_message.as_deref(),
|
stored_usage.error_message.as_deref(),
|
||||||
Some(
|
Some(
|
||||||
"没有可用提供商支持模型 gpt-5.4 的同步请求。请检查模型映射、端点启用状态和 API Key 权限(原因代码: candidate_list_empty)"
|
"找到 1 个支持模型 gpt-5.4 的候选提供商,但本次同步请求全部不可用:格式转换未启用 2 次(原因代码: all_candidates_skipped)"
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -1656,7 +1656,12 @@ async fn gateway_records_failed_usage_when_all_local_claude_cli_candidates_are_s
|
|||||||
.list_by_request_id("trace-claude-cli-usage-local-miss-123")
|
.list_by_request_id("trace-claude-cli-usage-local-miss-123")
|
||||||
.await
|
.await
|
||||||
.expect("request candidate trace should read");
|
.expect("request candidate trace should read");
|
||||||
assert!(stored_candidates.is_empty());
|
assert_eq!(stored_candidates.len(), 1);
|
||||||
|
assert_eq!(stored_candidates[0].status, RequestCandidateStatus::Skipped);
|
||||||
|
assert_eq!(
|
||||||
|
stored_candidates[0].skip_reason.as_deref(),
|
||||||
|
Some("format_conversion_disabled")
|
||||||
|
);
|
||||||
assert_eq!(stored_usage.routing_candidate_id(), None);
|
assert_eq!(stored_usage.routing_candidate_id(), None);
|
||||||
assert_eq!(*public_hits.lock().expect("mutex should lock"), 0);
|
assert_eq!(*public_hits.lock().expect("mutex should lock"), 0);
|
||||||
|
|
||||||
@@ -1878,7 +1883,7 @@ async fn gateway_keeps_failed_usage_request_capture_lightweight_for_large_local_
|
|||||||
.headers()
|
.headers()
|
||||||
.get(LOCAL_EXECUTION_RUNTIME_MISS_REASON_HEADER)
|
.get(LOCAL_EXECUTION_RUNTIME_MISS_REASON_HEADER)
|
||||||
.and_then(|value| value.to_str().ok()),
|
.and_then(|value| value.to_str().ok()),
|
||||||
Some("candidate_list_empty")
|
Some("all_candidates_skipped")
|
||||||
);
|
);
|
||||||
|
|
||||||
let stored_usage = wait_for_usage_status(
|
let stored_usage = wait_for_usage_status(
|
||||||
@@ -1914,7 +1919,12 @@ async fn gateway_keeps_failed_usage_request_capture_lightweight_for_large_local_
|
|||||||
.list_by_request_id("trace-claude-cli-usage-local-miss-large-123")
|
.list_by_request_id("trace-claude-cli-usage-local-miss-large-123")
|
||||||
.await
|
.await
|
||||||
.expect("request candidate trace should read");
|
.expect("request candidate trace should read");
|
||||||
assert!(stored_candidates.is_empty());
|
assert_eq!(stored_candidates.len(), 1);
|
||||||
|
assert_eq!(stored_candidates[0].status, RequestCandidateStatus::Skipped);
|
||||||
|
assert_eq!(
|
||||||
|
stored_candidates[0].skip_reason.as_deref(),
|
||||||
|
Some("format_conversion_disabled")
|
||||||
|
);
|
||||||
|
|
||||||
gateway_handle.abort();
|
gateway_handle.abort();
|
||||||
execution_runtime_handle.abort();
|
execution_runtime_handle.abort();
|
||||||
|
|||||||
Reference in New Issue
Block a user