mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-04 08:27:46 +08:00
ci(gateway): slim Test (Gateway) batch 1 — split architecture guards, pin build fingerprint
第一批减负(对应 docs/operations/gateway-ci-timeout-reduction-plan.md): A1 架构守卫迁出 - 将 src/tests/architecture/**(208 项 / 约 1.5 万行字符串断言)迁至 tests/architecture/,入口 tests/architecture_guard.rs - 从 lib cfg(test) 巨型编译单元移除,压低 rustc 峰值与 OOM 风险 - 断言逻辑不变;helper 可见性改为 pub(crate) A2 构建指纹统一 - test_gateway 的 mold RUSTFLAGS / RUST_MIN_STACK / sccache 上移至 job 级 env - rust-ci.yml 全部 toolchain 钉住 1.95.0(与 rust-toolchain.toml、fmt/clippy 一致) - Gateway 独立 cache key,避免 mold 指纹与无 mold job 互相污染 A4 补安全集成测试 - 新增 Test integration targets:cargo nextest run -p aether-gateway --tests - 覆盖 architecture_guard + 此前未执行的 admin_unsigned_identity_headers 验证:architecture_guard + admin_unsigned 209 passed; cargo check -p aether-gateway --lib --tests 通过;cargo fmt --check 通过。 不创建 PR,仅本地分支提交。
This commit is contained in:
@@ -0,0 +1,148 @@
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn admin_billing_wallets_boundaries_are_split() {
|
||||
let wallets_mod =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/billing/wallets/mod.rs");
|
||||
for pattern in ["mod mutations;", "mod reads;", "mod routes;", "mod shared;"] {
|
||||
assert!(
|
||||
wallets_mod.contains(pattern),
|
||||
"handlers/admin/billing/wallets/mod.rs should register {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
let shared_mod =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/billing/wallets/shared/mod.rs");
|
||||
for pattern in [
|
||||
"mod normalizers;",
|
||||
"mod payloads;",
|
||||
"mod requests;",
|
||||
"mod responses;",
|
||||
"mod support;",
|
||||
] {
|
||||
assert!(
|
||||
shared_mod.contains(pattern),
|
||||
"handlers/admin/billing/wallets/shared/mod.rs should register {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
let mutations_mod = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/billing/wallets/mutations/mod.rs",
|
||||
);
|
||||
for pattern in [
|
||||
"mod adjust;",
|
||||
"mod complete_refund;",
|
||||
"mod fail_refund;",
|
||||
"mod process_refund;",
|
||||
"mod recharge;",
|
||||
] {
|
||||
assert!(
|
||||
mutations_mod.contains(pattern),
|
||||
"handlers/admin/billing/wallets/mutations/mod.rs should register {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
let reads_mod =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/billing/wallets/reads/mod.rs");
|
||||
for pattern in [
|
||||
"mod detail;",
|
||||
"mod ledger;",
|
||||
"mod list;",
|
||||
"mod refund_requests;",
|
||||
"mod refunds;",
|
||||
"mod transactions;",
|
||||
] {
|
||||
assert!(
|
||||
reads_mod.contains(pattern),
|
||||
"handlers/admin/billing/wallets/reads/mod.rs should register {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
for path in [
|
||||
"apps/aether-gateway/src/handlers/admin/billing/wallets/shared/core.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/billing/wallets/mutations/core.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/billing/wallets/reads.rs",
|
||||
] {
|
||||
assert!(
|
||||
!workspace_file_exists(path),
|
||||
"{path} should be removed after wallets boundaries are split"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn admin_billing_collectors_owner_is_split() {
|
||||
let collectors_mod =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/billing/collectors/mod.rs");
|
||||
for pattern in ["mod reads;", "mod support;", "mod writes;"] {
|
||||
assert!(
|
||||
collectors_mod.contains(pattern),
|
||||
"handlers/admin/billing/collectors/mod.rs should register {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
for path in [
|
||||
"apps/aether-gateway/src/handlers/admin/billing/collectors/support.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/billing/collectors/reads.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/billing/collectors/writes.rs",
|
||||
] {
|
||||
assert!(
|
||||
workspace_file_exists(path),
|
||||
"{path} should exist after collectors owner split"
|
||||
);
|
||||
}
|
||||
|
||||
assert!(
|
||||
!workspace_file_exists("apps/aether-gateway/src/handlers/admin/billing/collectors.rs"),
|
||||
"handlers/admin/billing/collectors.rs should be removed after collectors owner split"
|
||||
);
|
||||
|
||||
let collectors_support =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/billing/collectors/support.rs");
|
||||
assert!(
|
||||
!collectors_support.contains("pub(super) use super::super::{"),
|
||||
"handlers/admin/billing/collectors/support.rs should not keep wildcard bridge re-export from billing root"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn admin_billing_presets_owner_is_split() {
|
||||
let presets_mod =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/billing/presets/mod.rs");
|
||||
for pattern in ["mod apply;", "mod support;"] {
|
||||
assert!(
|
||||
presets_mod.contains(pattern),
|
||||
"handlers/admin/billing/presets/mod.rs should register {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
for path in [
|
||||
"apps/aether-gateway/src/handlers/admin/billing/presets/support.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/billing/presets/apply.rs",
|
||||
] {
|
||||
assert!(
|
||||
workspace_file_exists(path),
|
||||
"{path} should exist after presets owner split"
|
||||
);
|
||||
}
|
||||
|
||||
assert!(
|
||||
!workspace_file_exists("apps/aether-gateway/src/handlers/admin/billing/presets.rs"),
|
||||
"handlers/admin/billing/presets.rs should be removed after presets owner split"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn admin_billing_wallets_support_uses_wrapped_request_context() {
|
||||
let wallets_support = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/billing/wallets/shared/support.rs",
|
||||
);
|
||||
assert!(
|
||||
wallets_support.contains("use crate::handlers::admin::request::AdminRequestContext;"),
|
||||
"handlers/admin/billing/wallets/shared/support.rs should consume wrapped AdminRequestContext"
|
||||
);
|
||||
assert!(
|
||||
!wallets_support.contains("GatewayPublicRequestContext"),
|
||||
"handlers/admin/billing/wallets/shared/support.rs should not keep raw GatewayPublicRequestContext seam"
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn admin_model_global_owner_is_split() {
|
||||
let global_mod =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/model/global/mod.rs");
|
||||
for pattern in ["mod helpers;", "mod payloads;", "mod providers;"] {
|
||||
assert!(
|
||||
global_mod.contains(pattern),
|
||||
"handlers/admin/model/global/mod.rs should register {pattern}"
|
||||
);
|
||||
}
|
||||
for path in [
|
||||
"apps/aether-gateway/src/handlers/admin/model/global/helpers.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/model/global/payloads.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/model/global/providers.rs",
|
||||
] {
|
||||
assert!(
|
||||
workspace_file_exists(path),
|
||||
"{path} should exist after model/global owner split"
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
!workspace_file_exists("apps/aether-gateway/src/handlers/admin/model/global.rs"),
|
||||
"handlers/admin/model/global.rs should be removed after owner split"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn admin_model_root_exposes_single_route_seam() {
|
||||
let model_mod = read_workspace_file("apps/aether-gateway/src/handlers/admin/model/mod.rs");
|
||||
assert!(
|
||||
model_mod.contains("mod routes;"),
|
||||
"handlers/admin/model/mod.rs should register routes.rs as the model route seam"
|
||||
);
|
||||
assert!(
|
||||
model_mod.contains("pub(super) use self::routes::maybe_build_local_admin_model_response;"),
|
||||
"handlers/admin/model/mod.rs should expose maybe_build_local_admin_model_response"
|
||||
);
|
||||
|
||||
let model_routes =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/model/routes.rs");
|
||||
for pattern in [
|
||||
"catalog_routes::maybe_build_local_admin_model_catalog_response(",
|
||||
"global_models::maybe_build_local_admin_global_models_response(",
|
||||
] {
|
||||
assert!(
|
||||
model_routes.contains(pattern),
|
||||
"handlers/admin/model/routes.rs should dispatch through {pattern}"
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,670 @@
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn non_admin_handlers_do_not_depend_on_admin_stats_module() {
|
||||
let handlers_mod = read_workspace_file("apps/aether-gateway/src/handlers/mod.rs");
|
||||
assert!(
|
||||
!handlers_mod.contains("pub(crate) use admin::{"),
|
||||
"handlers/mod.rs should stay as pure module wiring after shared usage stats facade extraction"
|
||||
);
|
||||
|
||||
for path in [
|
||||
"apps/aether-gateway/src/handlers/public/support/user_me.rs",
|
||||
"apps/aether-gateway/src/handlers/public/support/wallet/reads.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/cache_store.rs",
|
||||
] {
|
||||
let file = read_workspace_file(path);
|
||||
assert!(
|
||||
!file.contains("handlers::admin::stats::"),
|
||||
"{path} should not depend directly on admin::stats"
|
||||
);
|
||||
}
|
||||
|
||||
let admin_mod = read_workspace_file("apps/aether-gateway/src/handlers/admin/mod.rs");
|
||||
assert!(
|
||||
!admin_mod.contains("pub(crate) mod facade;"),
|
||||
"handlers/admin/mod.rs should not keep admin facade after direct subdomain exposure"
|
||||
);
|
||||
|
||||
let shared_mod = read_workspace_file("apps/aether-gateway/src/handlers/shared/mod.rs");
|
||||
for pattern in [
|
||||
"admin_stats_bad_request_response",
|
||||
"parse_bounded_u32",
|
||||
"round_to",
|
||||
"AdminStatsTimeRange",
|
||||
"AdminStatsUsageFilter",
|
||||
] {
|
||||
assert!(
|
||||
shared_mod.contains(pattern),
|
||||
"handlers/shared/mod.rs should expose shared usage stats helper {pattern}"
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
!shared_mod.contains("list_usage_for_optional_range"),
|
||||
"handlers/shared/mod.rs should not expose unbounded usage range helpers"
|
||||
);
|
||||
|
||||
let admin_observability_mod =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/observability/mod.rs");
|
||||
for pattern in [
|
||||
"aggregate_usage_stats",
|
||||
"match_admin_monitoring_route",
|
||||
"AdminMonitoringRoute",
|
||||
"ADMIN_MONITORING_REDIS_REQUIRED_DETAIL",
|
||||
"test_support",
|
||||
] {
|
||||
assert!(
|
||||
!admin_observability_mod.contains(pattern),
|
||||
"handlers/admin/observability/mod.rs should not re-export {pattern}"
|
||||
);
|
||||
}
|
||||
for pattern in [
|
||||
"admin_stats_bad_request_response",
|
||||
"parse_bounded_u32",
|
||||
"round_to",
|
||||
"AdminStatsTimeRange",
|
||||
"AdminStatsUsageFilter",
|
||||
] {
|
||||
assert!(
|
||||
admin_observability_mod.contains(pattern),
|
||||
"handlers/admin/observability/mod.rs should expose admin stats facade helper {pattern}"
|
||||
);
|
||||
}
|
||||
for pattern in ["list_usage_for_optional_range", "list_usage_for_range"] {
|
||||
assert!(
|
||||
!admin_observability_mod.contains(pattern),
|
||||
"handlers/admin/observability/mod.rs should not re-export deprecated usage helper {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
let shared_usage_stats =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/shared/usage_stats.rs");
|
||||
assert!(
|
||||
shared_usage_stats.contains("crate::admin_api::{"),
|
||||
"handlers/shared/usage_stats.rs should depend on crate::admin_api facade directly"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn admin_monitoring_root_stays_thin() {
|
||||
let monitoring_mod = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/mod.rs",
|
||||
);
|
||||
for pattern in [
|
||||
"mod common;",
|
||||
"use self::activity::{",
|
||||
"use self::cache::{",
|
||||
"use self::resilience::{",
|
||||
"use self::trace::{",
|
||||
"pub(crate) use self::routes::{",
|
||||
"const ADMIN_MONITORING_",
|
||||
] {
|
||||
assert!(
|
||||
!monitoring_mod.contains(pattern),
|
||||
"handlers/admin/observability/monitoring/mod.rs should not act as a glue re-export layer for {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
assert!(
|
||||
monitoring_mod.contains("routes::maybe_build_local_admin_monitoring_response"),
|
||||
"handlers/admin/observability/monitoring/mod.rs should delegate through routes module"
|
||||
);
|
||||
assert!(
|
||||
monitoring_mod.contains("mod cache_config;"),
|
||||
"handlers/admin/observability/monitoring/mod.rs should register cache_config as a dedicated cache boundary"
|
||||
);
|
||||
assert!(
|
||||
monitoring_mod.contains("mod cache_mutations;"),
|
||||
"handlers/admin/observability/monitoring/mod.rs should register cache_mutations as a dedicated mutation boundary"
|
||||
);
|
||||
assert!(
|
||||
!monitoring_mod.contains("mod responses;"),
|
||||
"handlers/admin/observability/monitoring/mod.rs should not keep local monitoring responses after crate split"
|
||||
);
|
||||
assert!(
|
||||
!workspace_file_exists(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/common.rs",
|
||||
),
|
||||
"handlers/admin/observability/monitoring/common.rs should stay removed after boundary split"
|
||||
);
|
||||
assert!(
|
||||
!workspace_file_exists(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/responses.rs",
|
||||
),
|
||||
"handlers/admin/observability/monitoring/responses.rs should stay removed after crate split"
|
||||
);
|
||||
|
||||
let monitoring_routes = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/routes.rs",
|
||||
);
|
||||
for pattern in [
|
||||
"use aether_admin::observability::monitoring::{",
|
||||
"match_admin_monitoring_route",
|
||||
"AdminMonitoringRoute",
|
||||
] {
|
||||
assert!(
|
||||
monitoring_routes.contains(pattern),
|
||||
"handlers/admin/observability/monitoring/routes.rs should depend on crate-owned monitoring seam {pattern}"
|
||||
);
|
||||
}
|
||||
for pattern in [
|
||||
"pub(crate) enum AdminMonitoringRoute",
|
||||
"pub(crate) fn match_admin_monitoring_route(",
|
||||
] {
|
||||
assert!(
|
||||
!monitoring_routes.contains(pattern),
|
||||
"handlers/admin/observability/monitoring/routes.rs should not keep local monitoring route matcher {pattern}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn admin_stats_root_stays_thin() {
|
||||
let stats_mod =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/observability/stats/mod.rs");
|
||||
for pattern in [
|
||||
"use self::leaderboard::{",
|
||||
"enum AdminStatsComparisonType",
|
||||
"enum AdminStatsGranularity",
|
||||
"struct AdminStatsForecastPoint",
|
||||
"struct AdminStatsLeaderboardItem",
|
||||
"struct AdminStatsUserMetadata",
|
||||
"struct AdminStatsTimeSeriesBucket",
|
||||
"impl AdminStatsTimeRange {",
|
||||
"pub(crate) fn round_to(",
|
||||
"mod helpers;",
|
||||
"mod responses;",
|
||||
"mod timeseries;",
|
||||
"pub(crate) use self::helpers::{round_to, AdminStatsTimeRange, AdminStatsUsageFilter};",
|
||||
"pub(crate) use self::responses::admin_stats_bad_request_response;",
|
||||
"pub(crate) use self::timeseries::aggregate_usage_stats;",
|
||||
] {
|
||||
assert!(
|
||||
!stats_mod.contains(pattern),
|
||||
"handlers/admin/observability/stats/mod.rs should not own stats helper implementation {pattern}"
|
||||
);
|
||||
}
|
||||
for pattern in [
|
||||
"pub(crate) use aether_admin::observability::stats::{",
|
||||
"admin_stats_bad_request_response",
|
||||
"aggregate_usage_stats",
|
||||
"round_to",
|
||||
"AdminStatsTimeRange",
|
||||
"AdminStatsUsageFilter",
|
||||
] {
|
||||
assert!(
|
||||
stats_mod.contains(pattern),
|
||||
"handlers/admin/observability/stats/mod.rs should stay as a thin seam for {pattern}"
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
stats_mod.contains("pub(crate) use self::range::{"),
|
||||
"handlers/admin/observability/stats/mod.rs should re-export the split range seam"
|
||||
);
|
||||
let pattern = "parse_bounded_u32";
|
||||
assert!(
|
||||
stats_mod.contains(pattern),
|
||||
"handlers/admin/observability/stats/mod.rs should keep range re-export {pattern}"
|
||||
);
|
||||
for pattern in ["list_usage_for_optional_range", "list_usage_for_range"] {
|
||||
assert!(
|
||||
!stats_mod.contains(pattern),
|
||||
"handlers/admin/observability/stats/mod.rs should not re-export deprecated range helper {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
let analytics_routes = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/stats/analytics_routes.rs",
|
||||
);
|
||||
for pattern in [
|
||||
"use aether_admin::observability::stats::{",
|
||||
"AdminStatsComparisonType",
|
||||
"build_admin_stats_comparison_response",
|
||||
] {
|
||||
assert!(
|
||||
analytics_routes.contains(pattern),
|
||||
"stats/analytics_routes.rs should depend on crate-owned stats helper {pattern}"
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
!analytics_routes.contains("use super::helpers::{")
|
||||
&& !analytics_routes.contains("use super::responses::{")
|
||||
&& !analytics_routes.contains("use super::timeseries::{"),
|
||||
"stats/analytics_routes.rs should no longer depend on local stats pure bridges"
|
||||
);
|
||||
assert!(
|
||||
analytics_routes.contains("use super::range::{")
|
||||
|| analytics_routes.contains("use super::range::build_comparison_range;"),
|
||||
"stats/analytics_routes.rs should depend on the split stats range seam"
|
||||
);
|
||||
|
||||
let cost_routes = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/stats/cost_routes.rs",
|
||||
);
|
||||
for pattern in [
|
||||
"use super::range::{",
|
||||
"use aether_admin::observability::stats::{",
|
||||
"build_admin_stats_cost_forecast_response",
|
||||
] {
|
||||
assert!(
|
||||
cost_routes.contains(pattern),
|
||||
"stats/cost_routes.rs should depend on crate-owned stats helper {pattern}"
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
!cost_routes.contains("use super::helpers::{")
|
||||
&& !cost_routes.contains("use super::responses::{")
|
||||
&& !cost_routes.contains("use super::timeseries::{"),
|
||||
"stats/cost_routes.rs should no longer depend on local stats pure bridges"
|
||||
);
|
||||
|
||||
let leaderboard_routes = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/stats/leaderboard_routes.rs",
|
||||
);
|
||||
for pattern in [
|
||||
"use super::leaderboard::{",
|
||||
"use super::range::{",
|
||||
"use aether_admin::observability::stats::{",
|
||||
"admin_stats_leaderboard_empty_response",
|
||||
] {
|
||||
assert!(
|
||||
leaderboard_routes.contains(pattern),
|
||||
"stats/leaderboard_routes.rs should depend on explicit local/crate owner {pattern}"
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
!leaderboard_routes.contains("use super::helpers::{")
|
||||
&& !leaderboard_routes.contains("use super::responses::{"),
|
||||
"stats/leaderboard_routes.rs should no longer depend on local stats pure bridges"
|
||||
);
|
||||
|
||||
let provider_quota_routes = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/stats/provider_quota_routes.rs",
|
||||
);
|
||||
assert!(
|
||||
provider_quota_routes.contains("use aether_admin::observability::stats::{")
|
||||
|| provider_quota_routes.contains(
|
||||
"use aether_admin::observability::stats::admin_stats_provider_quota_usage_empty_response;",
|
||||
),
|
||||
"stats/provider_quota_routes.rs should depend on crate-owned responses directly"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn admin_monitoring_cache_mutations_are_split_from_reads() {
|
||||
let monitoring_cache = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/cache.rs",
|
||||
);
|
||||
for pattern in [
|
||||
"pub(super) async fn build_admin_monitoring_cache_users_delete_response(",
|
||||
"pub(super) async fn build_admin_monitoring_cache_affinity_delete_response(",
|
||||
"pub(super) async fn build_admin_monitoring_cache_flush_response(",
|
||||
"pub(super) async fn build_admin_monitoring_cache_provider_delete_response(",
|
||||
"pub(super) async fn build_admin_monitoring_model_mapping_delete_response(",
|
||||
"pub(super) async fn build_admin_monitoring_model_mapping_delete_model_response(",
|
||||
"pub(super) async fn build_admin_monitoring_model_mapping_delete_provider_response(",
|
||||
"pub(super) async fn build_admin_monitoring_redis_keys_delete_response(",
|
||||
] {
|
||||
assert!(
|
||||
!monitoring_cache.contains(pattern),
|
||||
"monitoring/cache.rs should stay focused on read/report handlers, not {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
let monitoring_cache_mutations = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/cache_mutations/mod.rs",
|
||||
);
|
||||
for pattern in [
|
||||
"mod users;",
|
||||
"mod affinity;",
|
||||
"mod flush;",
|
||||
"mod provider;",
|
||||
"mod model_mapping;",
|
||||
"mod redis_keys;",
|
||||
"pub(super) use users::build_admin_monitoring_cache_users_delete_response;",
|
||||
"pub(super) use affinity::build_admin_monitoring_cache_affinity_delete_response;",
|
||||
"pub(super) use flush::build_admin_monitoring_cache_flush_response;",
|
||||
"pub(super) use provider::build_admin_monitoring_cache_provider_delete_response;",
|
||||
"pub(super) use model_mapping::{",
|
||||
"pub(super) use redis_keys::build_admin_monitoring_redis_keys_delete_response;",
|
||||
] {
|
||||
assert!(
|
||||
monitoring_cache_mutations.contains(pattern),
|
||||
"monitoring/cache_mutations/mod.rs should own {pattern}"
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
!workspace_file_exists(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/cache_mutations.rs"
|
||||
),
|
||||
"monitoring/cache_mutations.rs should stay removed after directory split"
|
||||
);
|
||||
|
||||
let monitoring_routes = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/routes.rs",
|
||||
);
|
||||
assert!(
|
||||
monitoring_routes.contains("use super::cache_mutations::{"),
|
||||
"monitoring/routes.rs should depend on cache_mutations directly for delete handlers"
|
||||
);
|
||||
assert!(
|
||||
monitoring_routes.contains("use super::cache_affinity_reads::{"),
|
||||
"monitoring/routes.rs should depend on cache_affinity_reads directly for affinity read handlers"
|
||||
);
|
||||
assert!(
|
||||
monitoring_routes.contains("use super::cache_model_mapping::{"),
|
||||
"monitoring/routes.rs should depend on cache_model_mapping directly for model-mapping read handlers"
|
||||
);
|
||||
|
||||
let monitoring_mod = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/mod.rs",
|
||||
);
|
||||
for pattern in ["mod cache_affinity_reads;", "mod cache_model_mapping;"] {
|
||||
assert!(
|
||||
monitoring_mod.contains(pattern),
|
||||
"monitoring/mod.rs should register split read module {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
let monitoring_affinity_reads = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/cache_affinity_reads.rs",
|
||||
);
|
||||
for pattern in [
|
||||
"pub(super) async fn build_admin_monitoring_cache_affinities_response(",
|
||||
"pub(super) async fn build_admin_monitoring_cache_affinity_response(",
|
||||
] {
|
||||
assert!(
|
||||
monitoring_affinity_reads.contains(pattern),
|
||||
"monitoring/cache_affinity_reads.rs should own {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
let monitoring_model_mapping = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/cache_model_mapping.rs",
|
||||
);
|
||||
for pattern in [
|
||||
"pub(super) async fn build_admin_monitoring_model_mapping_stats_response(",
|
||||
"pub(super) async fn build_admin_monitoring_redis_cache_categories_response(",
|
||||
] {
|
||||
assert!(
|
||||
monitoring_model_mapping.contains(pattern),
|
||||
"monitoring/cache_model_mapping.rs should own {pattern}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn admin_monitoring_route_payloads_prefer_crate_owned_builders() {
|
||||
for (path, pattern) in [
|
||||
(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/activity.rs",
|
||||
"build_admin_monitoring_system_status_payload_response",
|
||||
),
|
||||
(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/trace.rs",
|
||||
"build_admin_monitoring_trace_provider_stats_payload_response",
|
||||
),
|
||||
(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/resilience/history.rs",
|
||||
"build_admin_monitoring_circuit_history_payload_response",
|
||||
),
|
||||
(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/resilience/status.rs",
|
||||
"build_admin_monitoring_resilience_status_payload_response",
|
||||
),
|
||||
(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/resilience/reset.rs",
|
||||
"build_admin_monitoring_reset_error_stats_payload_response",
|
||||
),
|
||||
(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/cache_mutations/flush.rs",
|
||||
"build_admin_monitoring_cache_flush_success_response",
|
||||
),
|
||||
(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/cache_mutations/provider.rs",
|
||||
"admin_monitoring_cache_provider_not_found_response",
|
||||
),
|
||||
(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/cache_mutations/model_mapping.rs",
|
||||
"build_admin_monitoring_model_mapping_delete_success_response",
|
||||
),
|
||||
(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/cache_mutations/redis_keys.rs",
|
||||
"build_admin_monitoring_redis_keys_delete_success_response",
|
||||
),
|
||||
] {
|
||||
let file = read_workspace_file(path);
|
||||
assert!(
|
||||
file.contains("use aether_admin::observability::monitoring::{")
|
||||
|| file.contains("use aether_admin::observability::monitoring::"),
|
||||
"{path} should depend on aether_admin::observability::monitoring"
|
||||
);
|
||||
assert!(
|
||||
file.contains(pattern),
|
||||
"{path} should route payload building through crate-owned helper {pattern}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn admin_usage_root_stays_thin() {
|
||||
let usage_mod =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/observability/usage/mod.rs");
|
||||
for pattern in ["pub(crate) use analytics::{", "pub(crate) use helpers::{"] {
|
||||
assert!(
|
||||
!usage_mod.contains(pattern),
|
||||
"handlers/admin/observability/usage/mod.rs should not re-export helper seam {pattern}"
|
||||
);
|
||||
}
|
||||
for pattern in [
|
||||
"mod analytics;",
|
||||
"mod analytics_routes;",
|
||||
"mod detail_routes;",
|
||||
"mod replay;",
|
||||
"mod summary_routes;",
|
||||
"detail_routes::maybe_build_local_admin_usage_detail_response",
|
||||
"summary_routes::maybe_build_local_admin_usage_summary_response",
|
||||
"analytics_routes::maybe_build_local_admin_usage_analytics_response",
|
||||
] {
|
||||
assert!(
|
||||
usage_mod.contains(pattern),
|
||||
"handlers/admin/observability/usage/mod.rs should stay as a thin router for {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
let analytics_mod = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/usage/analytics/mod.rs",
|
||||
);
|
||||
for pattern in [
|
||||
"mod aggregations;",
|
||||
"mod cache_affinity;",
|
||||
"mod filters;",
|
||||
"pub(super) use aggregations::admin_usage_aggregation_by_user_json;",
|
||||
"pub(super) use cache_affinity::list_usage_cache_affinity_intervals;",
|
||||
"pub(super) use filters::admin_usage_provider_key_names;",
|
||||
] {
|
||||
assert!(
|
||||
analytics_mod.contains(pattern),
|
||||
"usage/analytics/mod.rs should keep explicit analytics owner seam {pattern}"
|
||||
);
|
||||
}
|
||||
for pattern in [
|
||||
"mod parse;",
|
||||
"admin_usage_aggregation_by_model_json",
|
||||
"admin_usage_parse_limit",
|
||||
"admin_usage_matches_search",
|
||||
] {
|
||||
assert!(
|
||||
!analytics_mod.contains(pattern),
|
||||
"usage/analytics/mod.rs should not keep pure crate forwarders {pattern}"
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
!workspace_file_exists(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/usage/analytics.rs"
|
||||
),
|
||||
"usage/analytics.rs should be removed once analytics is directoryized"
|
||||
);
|
||||
|
||||
let analytics_routes = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/usage/analytics_routes/mod.rs",
|
||||
);
|
||||
assert!(
|
||||
analytics_routes.contains("mod aggregation;"),
|
||||
"usage/analytics_routes/mod.rs should register aggregation owner"
|
||||
);
|
||||
assert!(
|
||||
analytics_routes.contains("mod cache_affinity_hit_analysis;"),
|
||||
"usage/analytics_routes/mod.rs should register cache_affinity_hit_analysis owner"
|
||||
);
|
||||
assert!(
|
||||
analytics_routes.contains("mod cache_affinity_interval_timeline;"),
|
||||
"usage/analytics_routes/mod.rs should register cache_affinity_interval_timeline owner"
|
||||
);
|
||||
assert!(
|
||||
analytics_routes.contains("mod cache_affinity_ttl_analysis;"),
|
||||
"usage/analytics_routes/mod.rs should register cache_affinity_ttl_analysis owner"
|
||||
);
|
||||
assert!(
|
||||
analytics_routes.contains("mod heatmap;"),
|
||||
"usage/analytics_routes/mod.rs should register heatmap owner"
|
||||
);
|
||||
assert!(
|
||||
analytics_routes.contains("aggregation::build_admin_usage_aggregation_stats_response"),
|
||||
"usage/analytics_routes/mod.rs should delegate aggregation handling to aggregation owner"
|
||||
);
|
||||
assert!(
|
||||
!workspace_file_exists(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/usage/analytics_routes.rs"
|
||||
),
|
||||
"usage/analytics_routes.rs should stay removed after directory split"
|
||||
);
|
||||
|
||||
let summary_routes = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/usage/summary_routes.rs",
|
||||
);
|
||||
assert!(
|
||||
summary_routes.contains("use super::analytics::admin_usage_provider_key_names;"),
|
||||
"usage/summary_routes.rs should keep only the local stateful analytics lookup"
|
||||
);
|
||||
assert!(
|
||||
summary_routes.contains("use aether_admin::observability::usage::{"),
|
||||
"usage/summary_routes.rs should depend on crate-owned usage helpers directly"
|
||||
);
|
||||
|
||||
let detail_routes = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/usage/detail_routes.rs",
|
||||
);
|
||||
assert!(
|
||||
detail_routes.contains("use super::analytics::admin_usage_provider_key_names;"),
|
||||
"usage/detail_routes.rs should keep only the local stateful analytics lookup"
|
||||
);
|
||||
assert!(
|
||||
detail_routes.contains("use aether_admin::observability::usage::{"),
|
||||
"usage/detail_routes.rs should depend on crate-owned usage helpers directly"
|
||||
);
|
||||
|
||||
let replay =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/observability/usage/replay.rs");
|
||||
assert!(
|
||||
replay.contains("use aether_admin::observability::usage::{"),
|
||||
"usage/replay.rs should depend on crate-owned usage helpers directly"
|
||||
);
|
||||
|
||||
let analytics_aggregations = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/usage/analytics/aggregations.rs",
|
||||
);
|
||||
assert!(
|
||||
analytics_aggregations
|
||||
.contains("pub(in super::super) async fn admin_usage_aggregation_by_user_json("),
|
||||
"usage/analytics/aggregations.rs should keep only the local user aggregation owner"
|
||||
);
|
||||
let analytics_cache_affinity = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/usage/analytics/cache_affinity.rs",
|
||||
);
|
||||
assert!(
|
||||
analytics_cache_affinity
|
||||
.contains("pub(in super::super) async fn list_usage_cache_affinity_intervals("),
|
||||
"usage/analytics/cache_affinity.rs should own cache-affinity analytics helpers"
|
||||
);
|
||||
let analytics_filters = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/usage/analytics/filters.rs",
|
||||
);
|
||||
assert!(
|
||||
analytics_filters.contains("pub(in super::super) async fn admin_usage_provider_key_names("),
|
||||
"usage/analytics/filters.rs should keep only the local provider key lookup"
|
||||
);
|
||||
assert!(
|
||||
!workspace_file_exists(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/usage/helpers.rs"
|
||||
),
|
||||
"usage/helpers.rs should stay removed after crate split"
|
||||
);
|
||||
assert!(
|
||||
!workspace_file_exists(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/usage/analytics/parse.rs"
|
||||
),
|
||||
"usage/analytics/parse.rs should stay removed after crate split"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn admin_monitoring_snapshots_stay_app_local() {
|
||||
let monitoring_cache_types = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/cache_types.rs",
|
||||
);
|
||||
for pattern in [
|
||||
"pub(super) struct AdminMonitoringCacheSnapshot",
|
||||
"pub(super) struct AdminMonitoringCacheAffinityRecord",
|
||||
] {
|
||||
assert!(
|
||||
monitoring_cache_types.contains(pattern),
|
||||
"monitoring/cache_types.rs should own {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
let monitoring_resilience = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/resilience/mod.rs",
|
||||
);
|
||||
assert!(
|
||||
monitoring_resilience.contains("mod history;"),
|
||||
"monitoring/resilience/mod.rs should register history owner"
|
||||
);
|
||||
assert!(
|
||||
monitoring_resilience.contains("mod snapshot;"),
|
||||
"monitoring/resilience/mod.rs should register snapshot owner"
|
||||
);
|
||||
assert!(
|
||||
monitoring_resilience.contains("mod status;"),
|
||||
"monitoring/resilience/mod.rs should register status owner"
|
||||
);
|
||||
assert!(
|
||||
monitoring_resilience.contains("mod reset;"),
|
||||
"monitoring/resilience/mod.rs should register reset owner"
|
||||
);
|
||||
assert!(
|
||||
!workspace_file_exists(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/resilience.rs"
|
||||
),
|
||||
"monitoring/resilience.rs should stay removed after directory split"
|
||||
);
|
||||
|
||||
let resilience_snapshot = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/resilience/snapshot.rs",
|
||||
);
|
||||
assert!(
|
||||
resilience_snapshot.contains("AdminMonitoringResilienceSnapshot"),
|
||||
"monitoring/resilience/snapshot.rs should keep resilience snapshot ownership locally"
|
||||
);
|
||||
assert!(
|
||||
resilience_snapshot.contains("pub(super) struct AdminMonitoringResilienceSnapshot"),
|
||||
"monitoring/resilience/snapshot.rs should define AdminMonitoringResilienceSnapshot locally"
|
||||
);
|
||||
|
||||
let data_system = read_workspace_file("crates/aether-data/runtime/src/repository/system.rs");
|
||||
assert!(
|
||||
!data_system.contains("AdminMonitoringCacheSnapshot")
|
||||
&& !data_system.contains("AdminMonitoringResilienceSnapshot"),
|
||||
"monitoring snapshots are admin view DTOs and should not move into aether-data"
|
||||
);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,615 @@
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn admin_system_build_version_contract_uses_explicit_local_build_arg() {
|
||||
let build_rs = read_workspace_file("apps/aether-gateway/build.rs");
|
||||
for pattern in [
|
||||
"cargo:rerun-if-env-changed=AETHER_BUILD_VERSION",
|
||||
"env::var(\"AETHER_BUILD_VERSION\")",
|
||||
] {
|
||||
assert!(
|
||||
build_rs.contains(pattern),
|
||||
"apps/aether-gateway/build.rs should consume explicit build version pattern {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
let dockerfile = read_workspace_file("Dockerfile.app.local");
|
||||
for pattern in [
|
||||
"ARG AETHER_BUILD_VERSION",
|
||||
"ENV AETHER_BUILD_VERSION=${AETHER_BUILD_VERSION}",
|
||||
"AETHER_VERSION=${AETHER_BUILD_VERSION}",
|
||||
] {
|
||||
assert!(
|
||||
dockerfile.contains(pattern),
|
||||
"Dockerfile.app.local should pass explicit build version pattern {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
let deploy = read_workspace_file("deploy.sh");
|
||||
for pattern in [
|
||||
"detect_build_version()",
|
||||
"git describe --tags --match 'v[0-9]*' --always --dirty",
|
||||
"AETHER_BUILD_VERSION=\"${AETHER_BUILD_VERSION:-$(detect_build_version)}\"",
|
||||
"--build-arg \"AETHER_BUILD_VERSION=$AETHER_BUILD_VERSION\"",
|
||||
">>> AETHER_BUILD_VERSION",
|
||||
] {
|
||||
assert!(
|
||||
deploy.contains(pattern),
|
||||
"deploy.sh should pass deterministic local build version pattern {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
let vite_config = read_workspace_file("frontend/vite.config.ts");
|
||||
for pattern in [
|
||||
"process.env.AETHER_BUILD_VERSION",
|
||||
"process.env.AETHER_VERSION",
|
||||
"git describe --tags --match \"v[0-9]*\" --always --dirty",
|
||||
"trimmed.startsWith('tunnel-v')",
|
||||
] {
|
||||
assert!(
|
||||
vite_config.contains(pattern),
|
||||
"frontend/vite.config.ts should consume local build version pattern {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
let core_api = read_workspace_file("apps/aether-gateway/src/api/core.rs");
|
||||
for pattern in [
|
||||
"option_env!(\"AETHER_BUILD_VERSION\")",
|
||||
"\"version\": current_gateway_version()",
|
||||
] {
|
||||
assert!(
|
||||
core_api.contains(pattern),
|
||||
"api/core.rs should expose build version pattern {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
let build_rs = read_workspace_file("apps/aether-gateway/build.rs");
|
||||
for pattern in [
|
||||
"\"--match\"",
|
||||
"\"v[0-9]*\"",
|
||||
"trimmed.starts_with(\"tunnel-v\")",
|
||||
] {
|
||||
assert!(
|
||||
build_rs.contains(pattern),
|
||||
"apps/aether-gateway/build.rs should ignore tunnel release tags for gateway version pattern {pattern}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn admin_system_and_endpoint_roots_stay_thin() {
|
||||
let system_mod = read_workspace_file("apps/aether-gateway/src/handlers/admin/system/mod.rs");
|
||||
for pattern in [
|
||||
"pub(super) use super::auth::{",
|
||||
"pub(super) use super::model::{",
|
||||
"pub(super) use super::provider::{",
|
||||
] {
|
||||
assert!(
|
||||
!system_mod.contains(pattern),
|
||||
"handlers/admin/system/mod.rs should not act as a cross-domain re-export layer for {pattern}"
|
||||
);
|
||||
}
|
||||
for pattern in [
|
||||
"mod routes;",
|
||||
"pub(super) use self::routes::maybe_build_local_admin_system_response;",
|
||||
] {
|
||||
assert!(
|
||||
system_mod.contains(pattern),
|
||||
"handlers/admin/system/mod.rs should stay as a thin system subdomain router for {pattern}"
|
||||
);
|
||||
}
|
||||
for forbidden in [
|
||||
"pub(crate) use self::adaptive::maybe_build_local_admin_adaptive_response;",
|
||||
"pub(crate) use self::core::maybe_build_local_admin_core_response;",
|
||||
"pub(crate) use self::management_tokens::maybe_build_local_admin_management_tokens_response;",
|
||||
"pub(crate) use self::modules::maybe_build_local_admin_modules_response;",
|
||||
"pub(crate) use self::proxy_nodes::maybe_build_local_admin_proxy_nodes_response;",
|
||||
"pub(crate) use crate::handlers::admin::provider::pool_admin::maybe_build_local_admin_pool_response;",
|
||||
] {
|
||||
assert!(
|
||||
!system_mod.contains(forbidden),
|
||||
"handlers/admin/system/mod.rs should not remain a public owner export hub for {forbidden}"
|
||||
);
|
||||
}
|
||||
|
||||
assert!(
|
||||
!workspace_file_exists("apps/aether-gateway/src/handlers/admin/system/pool/mod.rs"),
|
||||
"handlers/admin/system/pool/mod.rs should be deleted once system root delegates pool admin directly to provider::pool_admin"
|
||||
);
|
||||
|
||||
let endpoint_mod =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/endpoint/mod.rs");
|
||||
for pattern in [
|
||||
"mod routes;",
|
||||
"pub(super) use self::routes::maybe_build_local_admin_endpoints_response;",
|
||||
] {
|
||||
assert!(
|
||||
endpoint_mod.contains(pattern),
|
||||
"handlers/admin/endpoint/mod.rs should stay as a thin endpoint router for {pattern}"
|
||||
);
|
||||
}
|
||||
for pattern in [
|
||||
"use self::extractors::{",
|
||||
"use self::health_builders::{",
|
||||
"use self::payloads::{",
|
||||
] {
|
||||
assert!(
|
||||
!endpoint_mod.contains(pattern),
|
||||
"handlers/admin/endpoint/mod.rs should not re-export local helper seam {pattern}"
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
endpoint_mod.contains(
|
||||
"pub(crate) use self::health_builders::build_admin_endpoint_health_status_payload;"
|
||||
),
|
||||
"handlers/admin/endpoint/mod.rs should keep only the crate-facing health status payload seam"
|
||||
);
|
||||
|
||||
let system_core_mod =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/system/core/mod.rs");
|
||||
for pattern in [
|
||||
"super::management_tokens::maybe_build_local_admin_management_tokens_response",
|
||||
"maybe_build_local_admin_oauth_response",
|
||||
"super::modules::maybe_build_local_admin_modules_response",
|
||||
"maybe_build_local_admin_model_catalog_response",
|
||||
] {
|
||||
assert!(
|
||||
system_core_mod.contains(pattern),
|
||||
"handlers/admin/system/core/mod.rs should call the real owner {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
let system_routes =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/system/routes.rs");
|
||||
for pattern in [
|
||||
"core::maybe_build_local_admin_core_response(",
|
||||
"adaptive::maybe_build_local_admin_adaptive_response(",
|
||||
"pool_admin::maybe_build_local_admin_pool_response(",
|
||||
"proxy_nodes::maybe_build_local_admin_proxy_nodes_response(",
|
||||
] {
|
||||
assert!(
|
||||
system_routes.contains(pattern),
|
||||
"handlers/admin/system/routes.rs should dispatch through specific system owner {pattern}"
|
||||
);
|
||||
}
|
||||
for path in [
|
||||
"apps/aether-gateway/src/handlers/admin/system/core/management_tokens_routes.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/system/core/model_routes.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/system/core/modules_routes.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/system/core/oauth_routes.rs",
|
||||
] {
|
||||
assert!(
|
||||
!workspace_file_exists(path),
|
||||
"{path} should be deleted once system/core/mod.rs dispatches directly to real owners"
|
||||
);
|
||||
}
|
||||
|
||||
let system_routes =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/system/core/system_routes.rs");
|
||||
assert!(
|
||||
!system_routes.contains("use crate::handlers::public::{"),
|
||||
"handlers/admin/system/core/system_routes.rs should not borrow system-owned route helpers from handlers/public"
|
||||
);
|
||||
assert!(
|
||||
!system_routes.contains("crate::handlers::admin::auth::build_proxy_error_response")
|
||||
&& !system_routes.contains("use crate::handlers::admin::auth::build_proxy_error_response;"),
|
||||
"handlers/admin/system/core/system_routes.rs should not borrow proxy error builder from auth"
|
||||
);
|
||||
for pattern in [
|
||||
"build_admin_email_template_payload",
|
||||
"build_admin_email_templates_payload",
|
||||
"preview_admin_email_template",
|
||||
"reset_admin_email_template",
|
||||
] {
|
||||
assert!(
|
||||
system_routes.contains(pattern),
|
||||
"handlers/admin/system/core/system_routes.rs should keep delegating through admin system shared helper {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
let endpoint_routes =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/endpoint/routes.rs");
|
||||
assert!(
|
||||
endpoint_routes.contains(
|
||||
"endpoint_keys::maybe_build_local_admin_endpoints_keys_response"
|
||||
),
|
||||
"handlers/admin/endpoint/routes.rs should dispatch provider key management directly to provider::endpoint_keys"
|
||||
);
|
||||
|
||||
assert!(
|
||||
endpoint_routes.contains(
|
||||
"endpoints_admin::maybe_build_local_admin_endpoints_routes_response"
|
||||
),
|
||||
"handlers/admin/endpoint/routes.rs should dispatch provider endpoint CRUD directly to provider::endpoints_admin"
|
||||
);
|
||||
{
|
||||
let path = "apps/aether-gateway/src/handlers/admin/endpoint/keys.rs";
|
||||
assert!(
|
||||
!workspace_file_exists(path),
|
||||
"{path} should be deleted once endpoint root dispatches directly to provider-owned handlers"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn admin_model_root_owns_model_catalog_routes() {
|
||||
let model_mod = read_workspace_file("apps/aether-gateway/src/handlers/admin/model/mod.rs");
|
||||
assert!(
|
||||
model_mod.contains("mod catalog_routes;"),
|
||||
"handlers/admin/model/mod.rs should register catalog_routes owner"
|
||||
);
|
||||
assert!(
|
||||
model_mod.contains(
|
||||
"pub(super) use self::catalog_routes::maybe_build_local_admin_model_catalog_response;"
|
||||
),
|
||||
"handlers/admin/model/mod.rs should expose model catalog route seam"
|
||||
);
|
||||
|
||||
let model_catalog_routes =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/model/catalog_routes.rs");
|
||||
for pattern in [
|
||||
"build_admin_model_catalog_payload",
|
||||
"read_admin_external_models_cache",
|
||||
"clear_admin_external_models_cache",
|
||||
"ADMIN_MODEL_CATALOG_DATA_UNAVAILABLE_DETAIL",
|
||||
] {
|
||||
assert!(
|
||||
model_catalog_routes.contains(pattern),
|
||||
"handlers/admin/model/catalog_routes.rs should own {pattern}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn admin_system_owns_admin_module_helpers() {
|
||||
let public_modules_helpers =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/public/system_modules_helpers.rs");
|
||||
for pattern in [
|
||||
"admin_module_by_name",
|
||||
"admin_module_name_from_enabled_path",
|
||||
"admin_module_name_from_status_path",
|
||||
"build_admin_module_runtime_state",
|
||||
"build_admin_module_status_payload",
|
||||
"build_admin_module_validation_result",
|
||||
"build_admin_modules_status_payload",
|
||||
"AdminSetModuleEnabledRequest",
|
||||
] {
|
||||
assert!(
|
||||
!public_modules_helpers.contains(pattern),
|
||||
"handlers/public/system_modules_helpers.rs should not re-export admin module helper {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
let public_modules = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/public/system_modules_helpers/modules.rs",
|
||||
);
|
||||
for pattern in [
|
||||
"pub(crate) struct AdminModuleDefinition",
|
||||
"pub(crate) struct AdminSetModuleEnabledRequest",
|
||||
"pub(crate) struct AdminModuleRuntimeState",
|
||||
"pub(crate) fn admin_module_by_name",
|
||||
"pub(crate) async fn build_admin_module_runtime_state",
|
||||
"pub(crate) fn build_admin_module_validation_result",
|
||||
"pub(crate) async fn build_admin_module_status_payload",
|
||||
"pub(crate) async fn build_admin_modules_status_payload",
|
||||
"pub(crate) fn admin_module_name_from_status_path",
|
||||
"pub(crate) fn admin_module_name_from_enabled_path",
|
||||
] {
|
||||
assert!(
|
||||
!public_modules.contains(pattern),
|
||||
"handlers/public/system_modules_helpers/modules.rs should not own admin module helper {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
let system_shared_modules =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/system/shared/modules.rs");
|
||||
for pattern in [
|
||||
"pub(crate) struct AdminModuleDefinition",
|
||||
"pub(crate) struct AdminSetModuleEnabledRequest",
|
||||
"pub(crate) struct AdminModuleRuntimeState",
|
||||
"pub(crate) fn admin_module_by_name",
|
||||
"pub(crate) async fn build_admin_module_runtime_state",
|
||||
"pub(crate) fn build_admin_module_validation_result",
|
||||
"pub(crate) async fn build_admin_module_status_payload",
|
||||
"pub(crate) async fn build_admin_modules_status_payload",
|
||||
"pub(crate) fn admin_module_name_from_status_path",
|
||||
"pub(crate) fn admin_module_name_from_enabled_path",
|
||||
] {
|
||||
assert!(
|
||||
system_shared_modules.contains(pattern),
|
||||
"handlers/admin/system/shared/modules.rs should own {pattern}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn admin_system_owns_system_route_helpers() {
|
||||
let public_system_helpers =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/public/system_modules_helpers.rs");
|
||||
for pattern in [
|
||||
"current_aether_version",
|
||||
"build_admin_system_check_update_payload",
|
||||
"build_admin_system_stats_payload",
|
||||
"build_admin_system_settings_payload",
|
||||
"apply_admin_system_settings_update",
|
||||
"build_admin_api_formats_payload",
|
||||
"build_admin_system_config_export_payload",
|
||||
"build_admin_system_users_export_payload",
|
||||
"build_admin_system_data_export_payload",
|
||||
"build_admin_system_configs_payload",
|
||||
"build_admin_system_config_detail_payload",
|
||||
"apply_admin_system_config_update",
|
||||
"delete_admin_system_config",
|
||||
"serialize_admin_system_users_export_wallet",
|
||||
"module_available_from_env",
|
||||
"system_config_bool",
|
||||
"system_config_string",
|
||||
"read_admin_email_template_payload",
|
||||
"escape_admin_email_template_html",
|
||||
"render_admin_email_template_html",
|
||||
] {
|
||||
assert!(
|
||||
!public_system_helpers.contains(pattern),
|
||||
"handlers/public/system_modules_helpers.rs should not re-export admin system helper {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
let public_mod = read_workspace_file("apps/aether-gateway/src/handlers/public/mod.rs");
|
||||
for pattern in [
|
||||
"current_aether_version",
|
||||
"build_admin_system_check_update_payload",
|
||||
"build_admin_system_stats_payload",
|
||||
"build_admin_system_settings_payload",
|
||||
"apply_admin_system_settings_update",
|
||||
"build_admin_api_formats_payload",
|
||||
"build_admin_system_config_export_payload",
|
||||
"build_admin_system_users_export_payload",
|
||||
"build_admin_system_data_export_payload",
|
||||
"build_admin_system_configs_payload",
|
||||
"build_admin_system_config_detail_payload",
|
||||
"apply_admin_system_config_update",
|
||||
"delete_admin_system_config",
|
||||
"serialize_admin_system_users_export_wallet",
|
||||
"module_available_from_env",
|
||||
"system_config_bool",
|
||||
"system_config_string",
|
||||
"read_admin_email_template_payload",
|
||||
"escape_admin_email_template_html",
|
||||
"render_admin_email_template_html",
|
||||
] {
|
||||
assert!(
|
||||
!public_mod.contains(pattern),
|
||||
"handlers/public/mod.rs should not re-export admin system helper {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
let public_system_file = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/public/system_modules_helpers/system.rs",
|
||||
);
|
||||
for pattern in [
|
||||
"pub(crate) fn current_aether_version",
|
||||
"pub(crate) fn build_admin_system_check_update_payload",
|
||||
"pub(crate) async fn build_admin_system_stats_payload",
|
||||
"pub(crate) async fn build_admin_system_settings_payload",
|
||||
"pub(crate) async fn build_admin_system_config_export_payload",
|
||||
"pub(crate) async fn build_admin_system_users_export_payload",
|
||||
"pub(crate) async fn build_admin_system_data_export_payload",
|
||||
"pub(crate) fn build_admin_system_configs_payload",
|
||||
"pub(crate) async fn build_admin_system_config_detail_payload",
|
||||
"pub(crate) async fn apply_admin_system_config_update",
|
||||
"pub(crate) async fn delete_admin_system_config",
|
||||
"pub(crate) fn serialize_admin_system_users_export_wallet",
|
||||
"pub(crate) fn module_available_from_env",
|
||||
"pub(crate) fn system_config_bool",
|
||||
"pub(crate) fn system_config_string",
|
||||
"pub(crate) async fn read_admin_email_template_payload",
|
||||
"pub(crate) fn escape_admin_email_template_html",
|
||||
"pub(crate) fn render_admin_email_template_html",
|
||||
] {
|
||||
assert!(
|
||||
!public_system_file.contains(pattern),
|
||||
"handlers/public/system_modules_helpers/system.rs should not own shared/admin system helper {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
let shared_mod = read_workspace_file("apps/aether-gateway/src/handlers/shared/mod.rs");
|
||||
for pattern in [
|
||||
"mod email_templates;",
|
||||
"mod system_config_values;",
|
||||
"pub(crate) use self::email_templates::{",
|
||||
"pub(crate) use self::system_config_values::{",
|
||||
] {
|
||||
assert!(
|
||||
shared_mod.contains(pattern),
|
||||
"handlers/shared/mod.rs should wire shared system helper owner {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
let shared_system_config_values =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/shared/system_config_values.rs");
|
||||
for pattern in [
|
||||
"pub(crate) fn module_available_from_env",
|
||||
"pub(crate) fn system_config_bool",
|
||||
"pub(crate) fn system_config_string",
|
||||
] {
|
||||
assert!(
|
||||
shared_system_config_values.contains(pattern),
|
||||
"handlers/shared/system_config_values.rs should own {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
let shared_email_templates =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/shared/email_templates.rs");
|
||||
for pattern in [
|
||||
"pub(crate) fn admin_email_template_definition",
|
||||
"pub(crate) fn admin_email_template_subject_key",
|
||||
"pub(crate) fn admin_email_template_html_key",
|
||||
"pub(crate) async fn read_admin_email_template_payload",
|
||||
"pub(crate) fn escape_admin_email_template_html",
|
||||
"pub(crate) fn render_admin_email_template_html",
|
||||
] {
|
||||
assert!(
|
||||
shared_email_templates.contains(pattern),
|
||||
"handlers/shared/email_templates.rs should own {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
let system_shared_mod =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/system/shared/mod.rs");
|
||||
for pattern in [
|
||||
"pub(crate) mod configs;",
|
||||
"pub(crate) mod export;",
|
||||
"pub(crate) mod modules;",
|
||||
"pub(crate) mod paths;",
|
||||
"pub(crate) mod settings;",
|
||||
] {
|
||||
assert!(
|
||||
system_shared_mod.contains(pattern),
|
||||
"handlers/admin/system/shared/mod.rs should wire system helper owner {pattern}"
|
||||
);
|
||||
}
|
||||
for forbidden in [
|
||||
"pub(crate) use self::configs::*;",
|
||||
"pub(crate) use self::email_templates::{",
|
||||
"pub(crate) use self::modules::*;",
|
||||
"pub(crate) use self::paths::*;",
|
||||
"pub(crate) use self::settings::*;",
|
||||
] {
|
||||
assert!(
|
||||
!system_shared_mod.contains(forbidden),
|
||||
"handlers/admin/system/shared/mod.rs should not remain a re-export hub for {forbidden}"
|
||||
);
|
||||
}
|
||||
|
||||
assert!(
|
||||
!workspace_file_exists("apps/aether-gateway/src/handlers/admin/system/shared/system.rs"),
|
||||
"handlers/admin/system/shared/system.rs should be replaced by email_templates.rs"
|
||||
);
|
||||
|
||||
let system_shared_settings =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/system/shared/settings.rs");
|
||||
for pattern in [
|
||||
"pub(crate) fn current_aether_version",
|
||||
"pub(crate) fn build_admin_system_check_update_payload",
|
||||
"pub(crate) async fn build_admin_system_stats_payload",
|
||||
"pub(crate) async fn build_admin_system_settings_payload",
|
||||
"pub(crate) async fn apply_admin_system_settings_update",
|
||||
"pub(crate) fn build_admin_api_formats_payload",
|
||||
] {
|
||||
assert!(
|
||||
system_shared_settings.contains(pattern),
|
||||
"handlers/admin/system/shared/settings.rs should own {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
let system_shared_configs =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/system/shared/configs.rs");
|
||||
for pattern in [
|
||||
"pub(crate) fn build_admin_system_configs_payload",
|
||||
"pub(crate) async fn build_admin_system_config_detail_payload",
|
||||
"pub(crate) async fn apply_admin_system_config_update",
|
||||
"pub(crate) async fn delete_admin_system_config",
|
||||
] {
|
||||
assert!(
|
||||
system_shared_configs.contains(pattern),
|
||||
"handlers/admin/system/shared/configs.rs should own {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
let request_system =
|
||||
read_workspace_module_tree("apps/aether-gateway/src/handlers/admin/request/system/mod.rs");
|
||||
for pattern in [
|
||||
"pub(crate) async fn build_admin_email_templates_payload",
|
||||
"pub(crate) async fn build_admin_email_template_payload",
|
||||
"pub(crate) async fn apply_admin_email_template_update",
|
||||
"pub(crate) async fn preview_admin_email_template",
|
||||
"pub(crate) async fn reset_admin_email_template",
|
||||
"pub(crate) async fn build_admin_system_config_export_payload",
|
||||
"pub(crate) async fn build_admin_system_users_export_payload",
|
||||
"pub(crate) async fn build_admin_system_data_export_payload",
|
||||
] {
|
||||
assert!(
|
||||
request_system.contains(pattern),
|
||||
"handlers/admin/request/system/mod.rs should own {pattern}"
|
||||
);
|
||||
}
|
||||
for path in [
|
||||
"apps/aether-gateway/src/handlers/admin/system/shared/email_templates.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/system/shared/users_export.rs",
|
||||
] {
|
||||
assert!(
|
||||
!workspace_file_exists(path),
|
||||
"{path} should be deleted once request/system/mod.rs owns system email/export route wrappers"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn admin_system_shared_configs_split_export_owners() {
|
||||
let system_shared_mod =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/system/shared/mod.rs");
|
||||
for pattern in ["pub(crate) mod configs;", "pub(crate) mod export;"] {
|
||||
assert!(
|
||||
system_shared_mod.contains(pattern),
|
||||
"handlers/admin/system/shared/mod.rs should register explicit system shared owner {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
let system_shared_configs =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/system/shared/configs.rs");
|
||||
for forbidden in [
|
||||
"build_admin_system_config_export_payload(",
|
||||
"build_admin_system_users_export_payload(",
|
||||
"serialize_admin_system_users_export_wallet(",
|
||||
] {
|
||||
assert!(
|
||||
!system_shared_configs.contains(forbidden),
|
||||
"handlers/admin/system/shared/configs.rs should stay focused on config CRUD, not export owner {forbidden}"
|
||||
);
|
||||
}
|
||||
|
||||
assert!(
|
||||
!workspace_file_exists("apps/aether-gateway/src/handlers/admin/system/shared/export.rs"),
|
||||
"handlers/admin/system/shared/export.rs should be replaced by export/ directory owners"
|
||||
);
|
||||
|
||||
let system_shared_export =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/system/shared/export/mod.rs");
|
||||
for pattern in [
|
||||
"pub(crate) use self::providers::build_admin_system_export_providers_payload;",
|
||||
"decrypt_admin_system_export_secret",
|
||||
"ADMIN_SYSTEM_CONFIG_EXPORT_VERSION",
|
||||
"ADMIN_SYSTEM_EXPORT_PAGE_LIMIT",
|
||||
] {
|
||||
assert!(
|
||||
system_shared_export.contains(pattern),
|
||||
"handlers/admin/system/shared/export/mod.rs should own {pattern}"
|
||||
);
|
||||
}
|
||||
let request_system =
|
||||
read_workspace_module_tree("apps/aether-gateway/src/handlers/admin/request/system/mod.rs");
|
||||
for pattern in [
|
||||
"pub(crate) async fn build_admin_system_config_export_payload(",
|
||||
"pub(crate) async fn build_admin_system_users_export_payload(",
|
||||
"pub(crate) async fn build_admin_system_data_export_payload(",
|
||||
] {
|
||||
assert!(
|
||||
request_system.contains(pattern),
|
||||
"handlers/admin/request/system/mod.rs should own {pattern}"
|
||||
);
|
||||
}
|
||||
for path in [
|
||||
"apps/aether-gateway/src/handlers/admin/system/shared/export/support.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/system/shared/export/providers.rs",
|
||||
] {
|
||||
assert!(
|
||||
workspace_file_exists(path),
|
||||
"{path} should exist once system export owner is split into specific modules"
|
||||
);
|
||||
}
|
||||
|
||||
assert!(
|
||||
!workspace_file_exists("apps/aether-gateway/src/handlers/admin/system/shared/users_export.rs"),
|
||||
"handlers/admin/system/shared/users_export.rs should be deleted once request/system/mod.rs owns users export wrapper"
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
use super::{read_workspace_file, workspace_file_exists};
|
||||
|
||||
#[test]
|
||||
fn admin_users_lifecycle_mod_stays_thin() {
|
||||
let lifecycle_mod =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/users/lifecycle/mod.rs");
|
||||
for pattern in [
|
||||
"mod create;",
|
||||
"mod delete;",
|
||||
"mod reads;",
|
||||
"mod support;",
|
||||
"mod update;",
|
||||
] {
|
||||
assert!(
|
||||
lifecycle_mod.contains(pattern),
|
||||
"users/lifecycle/mod.rs should keep explicit owner seam {pattern}"
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
!workspace_file_exists("apps/aether-gateway/src/handlers/admin/users/lifecycle/core.rs"),
|
||||
"users/lifecycle/core.rs should be removed once lifecycle is split into explicit owners"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn admin_users_api_key_responses_mod_stays_wrapped() {
|
||||
let responses_mod = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/users/api_keys/responses/mod.rs",
|
||||
);
|
||||
for pattern in [
|
||||
"mod create;",
|
||||
"mod delete;",
|
||||
"mod list;",
|
||||
"mod reveal;",
|
||||
"mod toggle_lock;",
|
||||
"mod update;",
|
||||
"pub(in super::super::super) use create::build_admin_create_user_api_key_response;",
|
||||
"pub(in super::super::super) use update::build_admin_update_user_api_key_response;",
|
||||
] {
|
||||
assert!(
|
||||
responses_mod.contains(pattern),
|
||||
"users/api_keys/responses/mod.rs should keep wrapped response seam {pattern}"
|
||||
);
|
||||
}
|
||||
for forbidden in [
|
||||
"pub mod create;",
|
||||
"pub mod delete;",
|
||||
"pub mod list;",
|
||||
"pub mod reveal;",
|
||||
"pub mod toggle_lock;",
|
||||
"pub mod update;",
|
||||
] {
|
||||
assert!(
|
||||
!responses_mod.contains(forbidden),
|
||||
"users/api_keys/responses/mod.rs should not expose raw public response module seam {forbidden}"
|
||||
);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,227 @@
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
// 架构守卫在独立 integration test 中是顶层模块;helper 统一 pub(crate),
|
||||
// 子模块经 `use super::*` / `use super::{...}` 访问(与原 lib 内布局一致)。
|
||||
pub(crate) fn collect_rust_files(root: &Path, files: &mut Vec<PathBuf>) {
|
||||
for entry in fs::read_dir(root).expect("directory should be readable") {
|
||||
let entry = entry.expect("directory entry should be readable");
|
||||
let path = entry.path();
|
||||
if path.is_dir() {
|
||||
collect_rust_files(&path, files);
|
||||
continue;
|
||||
}
|
||||
if path.extension().and_then(|value| value.to_str()) == Some("rs") {
|
||||
files.push(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn assert_no_sqlx_queries(root_relative_path: &str) {
|
||||
let root = Path::new(env!("CARGO_MANIFEST_DIR")).join(root_relative_path);
|
||||
let mut files = Vec::new();
|
||||
collect_rust_files(&root, &mut files);
|
||||
|
||||
let patterns = [
|
||||
"sqlx::query(",
|
||||
"sqlx::query_scalar",
|
||||
"sqlx::postgres::PgRow",
|
||||
"sqlx::Row",
|
||||
"PostgresPoolFactory",
|
||||
"PostgresPool",
|
||||
"query_scalar::<",
|
||||
"QueryBuilder<",
|
||||
];
|
||||
let violations = files
|
||||
.into_iter()
|
||||
.filter_map(|path| {
|
||||
let source = fs::read_to_string(&path).expect("source file should be readable");
|
||||
let hits = patterns
|
||||
.iter()
|
||||
.filter(|pattern| source_contains_sql_pattern(&source, pattern))
|
||||
.copied()
|
||||
.collect::<Vec<_>>();
|
||||
if hits.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(format!("{} -> {}", path.display(), hits.join(", ")))
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
assert!(
|
||||
violations.is_empty(),
|
||||
"disallowed SQL ownership violations:\n{}",
|
||||
violations.join("\n")
|
||||
);
|
||||
}
|
||||
|
||||
fn source_contains_sql_pattern(source: &str, pattern: &str) -> bool {
|
||||
if pattern == "PostgresPool" {
|
||||
source
|
||||
.split(|character: char| !character.is_ascii_alphanumeric() && character != '_')
|
||||
.any(|identifier| identifier == pattern)
|
||||
} else {
|
||||
source.contains(pattern)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sql_pool_scan_distinguishes_pool_types_from_repository_names() {
|
||||
assert!(source_contains_sql_pattern(
|
||||
"pool: PostgresPool",
|
||||
"PostgresPool"
|
||||
));
|
||||
assert!(source_contains_sql_pattern(
|
||||
"PostgresPool::connect(url)",
|
||||
"PostgresPool"
|
||||
));
|
||||
assert!(!source_contains_sql_pattern(
|
||||
"PostgresPoolMemberScoreRepository::new(pool)",
|
||||
"PostgresPool"
|
||||
));
|
||||
}
|
||||
|
||||
pub(crate) fn assert_no_sensitive_log_patterns(root_relative_path: &str, patterns: &[&str]) {
|
||||
let root = Path::new(env!("CARGO_MANIFEST_DIR")).join(root_relative_path);
|
||||
let mut files = Vec::new();
|
||||
collect_rust_files(&root, &mut files);
|
||||
|
||||
let violations = files
|
||||
.into_iter()
|
||||
.filter_map(|path| {
|
||||
let source = fs::read_to_string(&path).expect("source file should be readable");
|
||||
let hits = patterns
|
||||
.iter()
|
||||
.filter(|pattern| source.contains(**pattern))
|
||||
.copied()
|
||||
.collect::<Vec<_>>();
|
||||
if hits.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(format!("{} -> {}", path.display(), hits.join(", ")))
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
assert!(
|
||||
violations.is_empty(),
|
||||
"disallowed sensitive logging patterns:\n{}",
|
||||
violations.join("\n")
|
||||
);
|
||||
}
|
||||
|
||||
pub(crate) fn assert_no_module_dependency_patterns(root_relative_path: &str, patterns: &[&str]) {
|
||||
let root = Path::new(env!("CARGO_MANIFEST_DIR")).join(root_relative_path);
|
||||
let mut files = Vec::new();
|
||||
collect_rust_files(&root, &mut files);
|
||||
|
||||
let violations = files
|
||||
.into_iter()
|
||||
.filter_map(|path| {
|
||||
let source = fs::read_to_string(&path).expect("source file should be readable");
|
||||
let hits = patterns
|
||||
.iter()
|
||||
.filter(|pattern| source.contains(**pattern))
|
||||
.copied()
|
||||
.collect::<Vec<_>>();
|
||||
if hits.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(format!("{} -> {}", path.display(), hits.join(", ")))
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
assert!(
|
||||
violations.is_empty(),
|
||||
"disallowed module dependency patterns:\n{}",
|
||||
violations.join("\n")
|
||||
);
|
||||
}
|
||||
|
||||
pub(crate) fn workspace_file_exists(root_relative_path: &str) -> bool {
|
||||
Path::new(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("../..")
|
||||
.join(root_relative_path)
|
||||
.exists()
|
||||
}
|
||||
|
||||
pub(crate) fn workspace_files_with_extension(
|
||||
root_relative_path: &str,
|
||||
extension: &str,
|
||||
) -> Vec<PathBuf> {
|
||||
let root = Path::new(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("../..")
|
||||
.join(root_relative_path);
|
||||
let mut files = fs::read_dir(root)
|
||||
.expect("workspace directory should be readable")
|
||||
.filter_map(Result::ok)
|
||||
.map(|entry| entry.path())
|
||||
.filter(|path| path.extension().and_then(|value| value.to_str()) == Some(extension))
|
||||
.collect::<Vec<_>>();
|
||||
files.sort();
|
||||
files
|
||||
}
|
||||
|
||||
pub(crate) fn collect_workspace_rust_files(root_relative_path: &str) -> Vec<PathBuf> {
|
||||
let root = Path::new(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("../..")
|
||||
.join(root_relative_path);
|
||||
let mut files = Vec::new();
|
||||
collect_rust_files(&root, &mut files);
|
||||
files.sort();
|
||||
files
|
||||
}
|
||||
|
||||
pub(crate) fn read_workspace_file(path: &str) -> String {
|
||||
let workspace_root = Path::new(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("../..")
|
||||
.canonicalize()
|
||||
.expect("workspace root should resolve");
|
||||
fs::read_to_string(workspace_root.join(path)).expect("source file should be readable")
|
||||
}
|
||||
|
||||
pub(crate) fn read_workspace_module_tree(path: &str) -> String {
|
||||
let workspace_root = Path::new(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("../..")
|
||||
.canonicalize()
|
||||
.expect("workspace root should resolve");
|
||||
let root_path = workspace_root.join(path);
|
||||
let mut contents =
|
||||
vec![fs::read_to_string(&root_path).expect("source file should be readable")];
|
||||
|
||||
let module_dir = if root_path.file_name().and_then(|value| value.to_str()) == Some("mod.rs") {
|
||||
root_path
|
||||
.parent()
|
||||
.expect("mod.rs should have parent module directory")
|
||||
.to_path_buf()
|
||||
} else if root_path.extension().and_then(|value| value.to_str()) == Some("rs") {
|
||||
root_path.with_extension("")
|
||||
} else {
|
||||
root_path.clone()
|
||||
};
|
||||
if module_dir.is_dir() {
|
||||
let mut files = Vec::new();
|
||||
collect_rust_files(&module_dir, &mut files);
|
||||
files.sort();
|
||||
for file in files {
|
||||
contents.push(fs::read_to_string(file).expect("source file should be readable"));
|
||||
}
|
||||
}
|
||||
|
||||
contents.join("\n")
|
||||
}
|
||||
|
||||
mod admin_billing;
|
||||
mod admin_model;
|
||||
mod admin_observability;
|
||||
mod admin_provider;
|
||||
mod admin_shared;
|
||||
mod admin_system;
|
||||
mod admin_users;
|
||||
mod ai_serving;
|
||||
mod runtime_and_security;
|
||||
mod sql_and_data;
|
||||
mod usage;
|
||||
mod workspace_tiers;
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,264 @@
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn usage_runtime_paths_depend_on_shared_crates_not_app_runtime_shims() {
|
||||
assert!(
|
||||
!workspace_file_exists("apps/aether-gateway/src/usage/runtime.rs"),
|
||||
"usage/runtime.rs should stay removed after collapsing the runtime shim into usage/mod.rs"
|
||||
);
|
||||
for path in [
|
||||
"apps/aether-gateway/src/usage/config.rs",
|
||||
"apps/aether-gateway/src/usage/queue.rs",
|
||||
"apps/aether-gateway/src/usage/event.rs",
|
||||
] {
|
||||
assert!(
|
||||
!workspace_file_exists(path),
|
||||
"{path} should stay removed after collapsing usage shim modules into usage/mod.rs"
|
||||
);
|
||||
}
|
||||
|
||||
for path in [
|
||||
"apps/aether-gateway/src/usage/mod.rs",
|
||||
"apps/aether-gateway/src/usage/worker.rs",
|
||||
"apps/aether-gateway/src/async_task/runtime.rs",
|
||||
] {
|
||||
let source = read_workspace_file(path);
|
||||
assert!(
|
||||
source.contains("aether_usage_runtime"),
|
||||
"{path} should depend on aether_usage_runtime"
|
||||
);
|
||||
assert!(
|
||||
!source.contains("wallet_runtime"),
|
||||
"{path} should not depend on wallet_runtime"
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
let path = "apps/aether-gateway/src/async_task/runtime.rs";
|
||||
let source = read_workspace_file(path);
|
||||
assert!(
|
||||
source.contains("aether_billing"),
|
||||
"{path} should depend on aether_billing"
|
||||
);
|
||||
assert!(
|
||||
!source.contains("billing_runtime::enrich_usage_event_with_billing"),
|
||||
"{path} should not depend on billing_runtime compat re-export"
|
||||
);
|
||||
assert!(
|
||||
!source.contains("settlement_runtime::settle_usage_if_needed"),
|
||||
"{path} should not depend on settlement_runtime compat re-export"
|
||||
);
|
||||
}
|
||||
|
||||
let usage_runtime = read_workspace_file("apps/aether-gateway/src/usage/mod.rs");
|
||||
assert!(
|
||||
!usage_runtime.contains("GatewayDataState"),
|
||||
"usage/mod.rs should not own GatewayDataState integration impls anymore"
|
||||
);
|
||||
assert!(
|
||||
!usage_runtime.contains("UsageBillingEventEnricher"),
|
||||
"usage/mod.rs should not own UsageBillingEventEnricher impl anymore"
|
||||
);
|
||||
assert!(
|
||||
!usage_runtime.contains("UsageRuntimeAccess"),
|
||||
"usage/mod.rs should not own UsageRuntimeAccess impl anymore"
|
||||
);
|
||||
assert!(
|
||||
usage_runtime.contains("pub(crate) use aether_usage_runtime::UsageRuntime;"),
|
||||
"usage/mod.rs should expose UsageRuntime directly from aether_usage_runtime"
|
||||
);
|
||||
for pattern in [
|
||||
"UsageRuntimeConfig",
|
||||
"UsageQueue",
|
||||
"UsageEvent",
|
||||
"UsageEventData",
|
||||
"UsageEventType",
|
||||
"USAGE_EVENT_VERSION",
|
||||
"now_ms",
|
||||
] {
|
||||
assert!(
|
||||
usage_runtime.contains(pattern),
|
||||
"usage/mod.rs should expose usage runtime seam {pattern} directly"
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
!usage_runtime.contains("mod runtime;"),
|
||||
"usage/mod.rs should not keep a local runtime shim module"
|
||||
);
|
||||
for forbidden in ["mod config;", "mod queue;", "mod event;"] {
|
||||
assert!(
|
||||
!usage_runtime.contains(forbidden),
|
||||
"usage/mod.rs should not keep deleted shim module {forbidden}"
|
||||
);
|
||||
}
|
||||
|
||||
let usage_worker = read_workspace_file("apps/aether-gateway/src/usage/worker.rs");
|
||||
let runtime_usage_worker = usage_worker
|
||||
.split("#[cfg(test)]")
|
||||
.next()
|
||||
.unwrap_or(usage_worker.as_str());
|
||||
assert!(
|
||||
!runtime_usage_worker.contains("GatewayDataState"),
|
||||
"usage/worker.rs runtime path should not own GatewayDataState integration impls anymore"
|
||||
);
|
||||
assert!(
|
||||
!runtime_usage_worker.contains("UsageRecordWriter"),
|
||||
"usage/worker.rs runtime path should not own UsageRecordWriter impl anymore"
|
||||
);
|
||||
|
||||
let integrations = read_workspace_file("apps/aether-gateway/src/data/state/integrations.rs");
|
||||
for pattern in [
|
||||
"UsageBillingEventEnricher for GatewayDataState",
|
||||
"UsageRuntimeAccess for GatewayDataState",
|
||||
"UsageRecordWriter for GatewayDataState",
|
||||
"UsageSettlementWriter for GatewayDataState",
|
||||
] {
|
||||
assert!(
|
||||
integrations.contains(pattern),
|
||||
"data/state/integrations.rs should centralize {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
let usage_reporting_context =
|
||||
read_workspace_file("apps/aether-gateway/src/usage/reporting/context.rs");
|
||||
assert!(
|
||||
usage_reporting_context.contains("aether_usage_runtime"),
|
||||
"usage/reporting/context.rs should depend on aether_usage_runtime"
|
||||
);
|
||||
assert!(
|
||||
usage_reporting_context.contains("resolve_video_task_report_lookup"),
|
||||
"usage/reporting/context.rs should depend on shared video task report lookup helper"
|
||||
);
|
||||
for pattern in [
|
||||
"build_locally_actionable_report_context_from_video_task",
|
||||
"report_context_is_locally_actionable",
|
||||
] {
|
||||
assert!(
|
||||
usage_reporting_context.contains(pattern),
|
||||
"usage/reporting/context.rs should depend on shared usage helper {pattern}"
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
usage_reporting_context.contains("VideoTaskReportLookup::TaskIdOrExternal"),
|
||||
"usage/reporting/context.rs should keep app-local external task fallback orchestration"
|
||||
);
|
||||
for pattern in [
|
||||
"build_locally_actionable_report_context_from_request_candidate",
|
||||
"read_request_candidates_by_request_id(",
|
||||
"resolve_locally_actionable_report_context_from_request_candidates(",
|
||||
] {
|
||||
assert!(
|
||||
!usage_reporting_context.contains(pattern),
|
||||
"usage/reporting/context.rs should not own request-candidate resolver details {pattern}"
|
||||
);
|
||||
}
|
||||
for pattern in [
|
||||
"context\n .get(\"local_task_id\")",
|
||||
"context\n .get(\"local_short_id\")",
|
||||
"context\n .get(\"task_id\")",
|
||||
"VideoTaskLookupKey::ShortId(short_id)",
|
||||
"fn insert_missing_string_value(",
|
||||
"fn insert_missing_optional_string_value(",
|
||||
"fn has_non_empty_str(",
|
||||
"fn has_u64(",
|
||||
] {
|
||||
assert!(
|
||||
!usage_reporting_context.contains(pattern),
|
||||
"usage/reporting/context.rs should not own video task report lookup parsing {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
let usage_reporting_mod = read_workspace_file("apps/aether-gateway/src/usage/reporting/mod.rs");
|
||||
assert!(
|
||||
usage_reporting_mod.contains("aether_usage_runtime"),
|
||||
"usage/reporting/mod.rs should depend on aether_usage_runtime"
|
||||
);
|
||||
for pattern in [
|
||||
"is_local_ai_sync_report_kind",
|
||||
"is_local_ai_stream_report_kind",
|
||||
"sync_report_represents_failure",
|
||||
"report_request_id",
|
||||
"should_handle_local_sync_report",
|
||||
"should_handle_local_stream_report",
|
||||
"apply_local_report_effect",
|
||||
"LocalReportEffect",
|
||||
] {
|
||||
assert!(
|
||||
usage_reporting_mod.contains(pattern),
|
||||
"usage/reporting/mod.rs should depend on shared usage helper {pattern}"
|
||||
);
|
||||
}
|
||||
for pattern in [
|
||||
"fn is_local_ai_sync_report_kind(",
|
||||
"fn is_local_ai_stream_report_kind(",
|
||||
"fn sync_report_represents_failure(",
|
||||
"fn extract_gemini_file_mapping_entries(",
|
||||
"fn maybe_push_local_gemini_file_mapping_entry(",
|
||||
"fn extract_sync_report_body_json(",
|
||||
"fn content_type_starts_with(",
|
||||
"fn normalize_file_name(",
|
||||
"const GEMINI_FILE_MAPPING_TTL_SECONDS",
|
||||
"const GEMINI_FILE_MAPPING_CACHE_PREFIX",
|
||||
"fn gemini_file_mapping_cache_key(",
|
||||
"fn report_request_id(",
|
||||
"fn should_handle_local_sync_report(",
|
||||
"fn should_handle_local_stream_report(",
|
||||
"\"openai_video_delete_sync_success\" && payload.status_code == 404",
|
||||
"sync_codex_quota_from_response_headers(",
|
||||
"apply_local_gemini_file_mapping_report_effect(",
|
||||
"pub(crate) async fn store_local_gemini_file_mapping(",
|
||||
] {
|
||||
assert!(
|
||||
!usage_reporting_mod.contains(pattern),
|
||||
"usage/reporting/mod.rs should not own local report classification logic {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
let report_effects =
|
||||
read_workspace_file("apps/aether-gateway/src/orchestration/report_effects.rs");
|
||||
assert!(
|
||||
report_effects.contains("aether_usage_runtime"),
|
||||
"orchestration/report_effects.rs should depend on aether_usage_runtime"
|
||||
);
|
||||
for pattern in [
|
||||
"extract_gemini_file_mapping_entries",
|
||||
"gemini_file_mapping_cache_key",
|
||||
"normalize_gemini_file_name",
|
||||
"report_request_id",
|
||||
"GEMINI_FILE_MAPPING_TTL_SECONDS",
|
||||
"sync_codex_quota_from_response_headers",
|
||||
"store_local_gemini_file_mapping",
|
||||
"delete_local_gemini_file_mapping",
|
||||
"GatewaySyncReportRequest",
|
||||
"GatewayStreamReportRequest",
|
||||
] {
|
||||
assert!(
|
||||
report_effects.contains(pattern),
|
||||
"orchestration/report_effects.rs should own local report effect detail {pattern}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn handlers_do_not_depend_on_raw_state_records() {
|
||||
assert_no_sensitive_log_patterns(
|
||||
"src/handlers",
|
||||
&[
|
||||
"StoredUserSessionRecord",
|
||||
"StoredUserPreferenceRecord",
|
||||
"AdminPaymentCallbackRecord",
|
||||
],
|
||||
);
|
||||
|
||||
let state_types = read_workspace_file("apps/aether-gateway/src/state/types.rs");
|
||||
for pattern in [
|
||||
"pub(crate) struct GatewayUserSessionView",
|
||||
"pub(crate) struct GatewayUserPreferenceView",
|
||||
"pub(crate) struct GatewayAdminPaymentCallbackView",
|
||||
] {
|
||||
assert!(
|
||||
state_types.contains(pattern),
|
||||
"state/types.rs should keep handler-facing state view {pattern}"
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,249 @@
|
||||
use super::{collect_workspace_rust_files, read_workspace_file, workspace_file_exists};
|
||||
|
||||
fn assert_manifest_excludes(manifest_path: &str, forbidden: &[&str]) {
|
||||
let manifest = read_workspace_file(manifest_path);
|
||||
let violations = forbidden
|
||||
.iter()
|
||||
.filter(|dependency| manifest.contains(**dependency))
|
||||
.copied()
|
||||
.collect::<Vec<_>>();
|
||||
assert!(
|
||||
violations.is_empty(),
|
||||
"{manifest_path} crosses its dependency tier through: {}",
|
||||
violations.join(", ")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pure_policy_crates_do_not_depend_on_runtime_adapters() {
|
||||
let pure_manifests = [
|
||||
"crates/aether-admission-core/Cargo.toml",
|
||||
"crates/aether-provider/core/Cargo.toml",
|
||||
"crates/aether-task/core/Cargo.toml",
|
||||
"crates/aether-usage/core/Cargo.toml",
|
||||
];
|
||||
let forbidden = [
|
||||
"axum",
|
||||
"sqlx",
|
||||
"redis",
|
||||
"reqwest",
|
||||
"wreq",
|
||||
"tokio",
|
||||
"aether-data =",
|
||||
"aether-gateway",
|
||||
];
|
||||
|
||||
for manifest in pure_manifests {
|
||||
assert_manifest_excludes(manifest, &forbidden);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn database_adapters_are_independent_driver_boundaries() {
|
||||
let path = "crates/aether-data/adapters/postgres/Cargo.toml";
|
||||
let manifest = read_workspace_file(path);
|
||||
assert!(manifest.contains("aether-data-contracts.workspace = true"));
|
||||
assert!(manifest.contains("features = [\"postgres\""));
|
||||
assert_manifest_excludes(path, &["aether-gateway", "axum"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn data_facade_preserves_legacy_driver_paths_without_owning_driver_code() {
|
||||
let source = read_workspace_file("crates/aether-data/runtime/src/driver/postgres.rs");
|
||||
assert!(source.contains("pub use aether_data_postgres::*;"));
|
||||
assert!(!source.contains("sqlx::"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gateway_runtime_components_keep_focused_dependency_surfaces() {
|
||||
assert_manifest_excludes(
|
||||
"crates/aether-gateway/frontdoor/Cargo.toml",
|
||||
&[
|
||||
"aether-data",
|
||||
"aether-provider-transport",
|
||||
"aether-gateway-workers",
|
||||
"sqlx",
|
||||
"redis",
|
||||
],
|
||||
);
|
||||
assert_manifest_excludes(
|
||||
"crates/aether-gateway/workers/Cargo.toml",
|
||||
&[
|
||||
"axum",
|
||||
"aether-gateway-frontdoor",
|
||||
"aether-provider-transport",
|
||||
],
|
||||
);
|
||||
assert_manifest_excludes(
|
||||
"crates/aether-gateway/execution/Cargo.toml",
|
||||
&[
|
||||
"axum",
|
||||
"sqlx",
|
||||
"redis",
|
||||
"aether-data",
|
||||
"aether-gateway-frontdoor",
|
||||
"aether-gateway-workers",
|
||||
],
|
||||
);
|
||||
assert_manifest_excludes(
|
||||
"crates/aether-gateway/control/Cargo.toml",
|
||||
&[
|
||||
"sqlx",
|
||||
"redis",
|
||||
"reqwest",
|
||||
"aether-data",
|
||||
"aether-provider-transport",
|
||||
"aether-gateway-workers",
|
||||
],
|
||||
);
|
||||
assert_manifest_excludes(
|
||||
"crates/aether-gateway/tunnel/Cargo.toml",
|
||||
&[
|
||||
"axum",
|
||||
"sqlx",
|
||||
"redis",
|
||||
"reqwest",
|
||||
"wreq",
|
||||
"aether-data",
|
||||
"aether-provider-transport",
|
||||
"aether-gateway-workers",
|
||||
],
|
||||
);
|
||||
assert_manifest_excludes(
|
||||
"crates/aether-testing/loadtools/Cargo.toml",
|
||||
&[
|
||||
"aether-gateway",
|
||||
"aether-testkit",
|
||||
"aether-data",
|
||||
"axum",
|
||||
"redis",
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tunnel_binary_uses_shared_tunnel_boundary_without_gateway_runtime_dependency() {
|
||||
let manifest = read_workspace_file("apps/aether-tunnel/Cargo.toml");
|
||||
let dependencies = manifest
|
||||
.split_once("[dependencies]")
|
||||
.expect("tunnel manifest should declare dependencies")
|
||||
.1
|
||||
.split("[dev-dependencies]")
|
||||
.next()
|
||||
.expect("normal dependency section should exist");
|
||||
|
||||
assert!(dependencies.contains("aether-gateway-tunnel.workspace = true"));
|
||||
assert!(!dependencies.contains("aether-gateway.workspace = true"));
|
||||
|
||||
let protocol_facade = read_workspace_file("apps/aether-tunnel/src/tunnel/protocol.rs");
|
||||
assert!(protocol_facade.contains("aether_gateway_tunnel::protocol::*"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn data_facade_defaults_to_postgres_and_gateway_selects_all_drivers_explicitly() {
|
||||
let data_manifest = read_workspace_file("crates/aether-data/runtime/Cargo.toml");
|
||||
assert!(data_manifest.contains("default = [\"postgres\"]"));
|
||||
assert!(data_manifest.contains("aether-data-postgres = { workspace = true, optional = true }"));
|
||||
assert!(data_manifest.contains("postgres = [\"dep:aether-data-postgres\", \"sqlx/postgres\"]"));
|
||||
assert!(data_manifest.contains("all-drivers = [\"postgres\"]"));
|
||||
|
||||
let gateway_manifest = read_workspace_file("apps/aether-gateway/Cargo.toml");
|
||||
assert!(gateway_manifest
|
||||
.contains("aether-data = { workspace = true, features = [\"all-drivers\"] }"));
|
||||
|
||||
let data_lib = read_workspace_file("crates/aether-data/runtime/src/lib.rs");
|
||||
assert!(data_lib.contains("pub use backend::PostgresBackend;"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn data_query_helpers_belong_to_adapters_not_the_runtime_facade() {
|
||||
let data_manifest = read_workspace_file("crates/aether-data/runtime/Cargo.toml");
|
||||
assert!(
|
||||
!data_manifest.contains("aether-data-query.workspace = true"),
|
||||
"aether-data should not keep a direct query-helper dependency after SQL repositories move to adapters"
|
||||
);
|
||||
|
||||
let manifest = read_workspace_file("crates/aether-data/adapters/postgres/Cargo.toml");
|
||||
assert!(manifest.contains("aether-data-query.workspace = true"));
|
||||
|
||||
let query_helpers = read_workspace_file("crates/aether-data/query/src/lib.rs");
|
||||
assert!(query_helpers.contains("Postgres"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gateway_tunnel_protocol_path_is_a_thin_compatibility_facade() {
|
||||
let source = read_workspace_file("apps/aether-gateway/src/tunnel/embedded/protocol.rs");
|
||||
assert_eq!(
|
||||
source.trim(),
|
||||
"pub use aether_gateway_tunnel::embedded::protocol::*;"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn frontdoor_owns_bounded_request_body_buffering() {
|
||||
let frontdoor = read_workspace_file("crates/aether-gateway/frontdoor/src/body.rs");
|
||||
assert!(frontdoor.contains("acquire_many_owned"));
|
||||
assert!(frontdoor.contains("body.into_data_stream()"));
|
||||
assert!(frontdoor.contains("try_reserve_bytes"));
|
||||
assert!(frontdoor.contains("BodyBufferReservation"));
|
||||
|
||||
let gateway = read_workspace_file("apps/aether-gateway/src/handlers/proxy/body_buffer.rs");
|
||||
assert!(gateway.contains("FrontdoorBodyBufferPolicy"));
|
||||
assert!(!gateway.contains("acquire_many_owned"));
|
||||
assert!(!gateway.contains("request_body_collection_exceeded_limit"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn benchmark_binaries_are_outside_the_reusable_testkit() {
|
||||
let testkit_bin = "crates/aether-testing/testkit/src/bin";
|
||||
assert!(
|
||||
!workspace_file_exists(testkit_bin) || collect_workspace_rust_files(testkit_bin).is_empty(),
|
||||
"aether-testkit must not own benchmark binaries"
|
||||
);
|
||||
assert!(
|
||||
!collect_workspace_rust_files("crates/aether-testing/loadtools/src/bin").is_empty(),
|
||||
"standalone load tools should live in aether-loadtools"
|
||||
);
|
||||
assert!(
|
||||
!collect_workspace_rust_files("crates/aether-testing/integration/src/bin").is_empty(),
|
||||
"gateway-backed scenarios should live in aether-integration-tests"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testkit_gateway_harness_is_opt_in() {
|
||||
let testkit_manifest = read_workspace_file("crates/aether-testing/testkit/Cargo.toml");
|
||||
assert!(
|
||||
testkit_manifest.contains("default = []"),
|
||||
"aether-testkit should keep the default feature set dependency-light"
|
||||
);
|
||||
assert!(
|
||||
testkit_manifest
|
||||
.contains("gateway = [\"dep:aether-gateway\", \"dep:aether-runtime-state\"]"),
|
||||
"gateway harnesses should be behind the explicit gateway feature"
|
||||
);
|
||||
assert!(
|
||||
testkit_manifest.contains("postgres = [\"dep:aether-data\", \"dep:sqlx\"]"),
|
||||
"Postgres schema helpers should be behind the explicit postgres feature"
|
||||
);
|
||||
assert!(testkit_manifest.contains(
|
||||
"aether-gateway = { workspace = true, features = [\"testkit\"], optional = true }"
|
||||
));
|
||||
|
||||
let testkit_lib =
|
||||
read_workspace_file("crates/aether-testing/testkit/src/lib.rs").replace("\r\n", "\n");
|
||||
for module in ["execution_runtime", "gateway", "tunnel"] {
|
||||
assert!(
|
||||
testkit_lib.contains(&format!("#[cfg(feature = \"gateway\")]\nmod {module};")),
|
||||
"aether-testkit::{module} should be feature-gated"
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
testkit_lib.contains("#[cfg(feature = \"postgres\")]\nmod postgres;"),
|
||||
"the Postgres helper should be feature-gated"
|
||||
);
|
||||
|
||||
let integration_manifest = read_workspace_file("crates/aether-testing/integration/Cargo.toml");
|
||||
assert!(integration_manifest
|
||||
.contains("aether-testkit = { workspace = true, features = [\"gateway\", \"postgres\"] }"));
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
//! 架构守卫独立测试目标。
|
||||
//!
|
||||
//! 从 lib 的 `cfg(test)` 巨型编译单元迁出:只做源码/manifest 字符串断言,
|
||||
//! 不启动 AppState、不依赖 gateway 私有类型,用于压低 lib test 编译面与 rustc 峰值。
|
||||
mod architecture;
|
||||
Reference in New Issue
Block a user