11//! ai_provider.rs 单测(AAA 模式)。
22//!
3- //! @ai-context: 覆盖:预设模板完整性(4 Provider)、配置校验(合法/非法 URL
4- //! 与空模型)、JSON roundtrip(顺序与默认保持)、幽灵 id 回退、
5- //! 旧版单 Provider 配置迁移(SiliconFlow)。
3+ //! @ai-context: 覆盖:预设模板完整性(4 Provider)、配置校验(合法/非法 URL、
4+ //! 空模型、默认模型不在列表/空白)、JSON roundtrip(顺序与默认
5+ //! 保持)、幽灵 id 回退(含全禁用边界)、旧版单 Provider 配置
6+ //! 迁移(SiliconFlow,含非法配置回退预设)。
67
78use crate :: ai_provider:: * ;
89
@@ -33,6 +34,11 @@ fn provider_validate_rejects_bad_url_and_empty_model() {
3334 p. base_url = "https://ok" . to_string ( ) ;
3435 p. models . clear ( ) ;
3536 assert ! ( p. validate( ) . is_err( ) ) ;
37+ p. models = vec ! [ "m" . to_string( ) ] ;
38+ p. default_model = "not-in-list" . to_string ( ) ;
39+ assert ! ( p. validate( ) . is_err( ) ) ;
40+ p. default_model = " " . to_string ( ) ;
41+ assert ! ( p. validate( ) . is_err( ) ) ;
3642}
3743
3844#[ test]
@@ -53,14 +59,16 @@ fn store_roundtrip_keeps_order_and_default() {
5359}
5460
5561#[ test]
56- fn store_missing_default_falls_back_to_first_enabled ( ) {
62+ fn store_ghost_default_falls_back_to_first_enabled ( ) {
5763 let mut store = AiProviderStore :: default ( ) ;
5864 let mut a = preset_templates ( ) . remove ( 0 ) ;
5965 a. id = "a" . to_string ( ) ;
60- a. enabled = true ;
6166 store. providers . push ( a) ;
6267 store. default_provider_id = Some ( "ghost" . to_string ( ) ) ;
6368 assert_eq ! ( store. effective_default_id( ) , Some ( "a" . to_string( ) ) ) ;
69+ // 全部禁用 → 无生效默认
70+ store. providers [ 0 ] . enabled = false ;
71+ assert_eq ! ( store. effective_default_id( ) , None ) ;
6472}
6573
6674#[ test]
@@ -76,4 +84,18 @@ fn migrate_from_legacy_creates_siliconflow() {
7684 assert_eq ! ( providers[ 0 ] . base_url, s. base_url) ;
7785 assert_eq ! ( providers[ 0 ] . default_model, s. model) ;
7886 assert_eq ! ( default_id, Some ( providers[ 0 ] . id. clone( ) ) ) ;
87+ }
88+
89+ #[ test]
90+ fn migrate_from_legacy_falls_back_on_invalid_config ( ) {
91+ let s = crate :: ai_settings:: AiSettings {
92+ base_url : "ftp://bad" . to_string ( ) ,
93+ model : String :: new ( ) ,
94+ ..Default :: default ( )
95+ } ;
96+ let ( providers, default_id) = migrate_from_legacy ( & s) ;
97+ assert_eq ! ( providers. len( ) , 1 ) ;
98+ assert_eq ! ( providers[ 0 ] . id, "legacy-siliconflow" ) ;
99+ assert ! ( providers[ 0 ] . validate( ) . is_ok( ) ) ;
100+ assert_eq ! ( default_id, Some ( "legacy-siliconflow" . to_string( ) ) ) ;
79101}
0 commit comments