9.0 KiB
テスト妥当性レビュー: provider
- 評価: 概ね良い
確認した範囲
- Crate:
crates/provider - 確認した主な責務:
- provider/model catalog の読み込みと
ModelManifest解決 - auth 参照から
ResolvedAuthへの解決 LlmClient構築エントリポイント- Codex OAuth の auth.json 解析、token refresh、header 生成、error mapping
- provider/model catalog の読み込みと
- 読んだファイル:
crates/provider/Cargo.tomlcrates/provider/README.mdcrates/provider/src/lib.rscrates/provider/src/catalog.rscrates/provider/src/codex_oauth/{mod.rs,auth_json.rs,jwt.rs,refresh.rs,error.rs}resources/providers/builtin.tomlresources/models/builtin.toml
現在のテストがよくカバーしていること
-
Catalog resolution は有用な振る舞いレベルでカバーされている。
- builtin provider/model catalog が parse できる。
ref解決が provider catalog と model catalog のフィールドを merge する。- inline manifest form が
scheme、model_id、authを要求する。 - manifest override が catalog default より優先される。
- unknown provider は hard error になる一方、unknown model は provider default に fallback する。
openrouter/anthropic/claude-sonnet-4.6のような nested model id がカバーされている。- context-window override と backend max clamping がカバーされている。
-
User catalog override の振る舞いには意味のあるカバレッジがある。
YOI_CONFIG_DIRは serial tests で保護されている。- provider override は存在する場合 builtin より優先される。
- override が存在しない場合は builtin に fallback する。
- malformed provider TOML は silent fallback ではなく parse error を返す。
-
Auth resolution tests は重要な local safety property をカバーしている。
SecretRefresolution は injectable resolver を使う。- missing secret は logical id を露出するが、key に見える material は露出しない。
- API key file loading は whitespace を trim する。
- relative auth file path は reject される。
- missing API key は期待される
ApiKeyMissingを返す。 - auth-less Ollama-style construction は成功する。
-
Codex OAuth tests は local integration として十分に強い。
auth.jsonloading は unknown field を保持する。id_tokenJWT からの account id fallback がテストされている。- missing auth file は login-oriented error を報告する。
- persistence は unknown field を保持し、Unix で
0600を強制する。 - JWT parsing は
exp、ChatGPT claims、missingexp、malformed JWT をカバーしている。 - refresh tests は timeout classification と一般的な permanent 401 classifications をカバーしている。
- provider-level tests は fresh-token headers、FedRAMP header、persistence 付き expired-token refresh、permanent refresh login hint、missing auth file を検証している。
不足 / 疑問のあるテスト
-
build_client/build_client_from_configの construction tests は、ほとんどがis_ok()または 1 つの error shape を assert している。構築された transport の effective base URL、選択された scheme、model id、capability fallback、Codex-OAuth-specific OpenAI Responses behavior を検証していない。このため、重要な provider-factory invariant のテストが弱い。 -
Codex OAuth default base URL path は直接テストされていない。
effective_base_urlにはhttps://chatgpt.com/backend-api/codex用の特別なAuthRef::CodexOAuthbranch があるが、誤って OpenAI Responses scheme default に fallback しても検知するテストがない。 -
Codex OAuth 用の OpenAI Responses special case は、
max_output_tokens、temperature、top_pの forwarding を無効化する。これは重要な compatibility invariant だが、provider crate にはそれに対する focused assertion がない。transport internals が opaque なままであれば、狭い test hook か、所有 layer でのより高レベルな request-building test が必要かもしれない。 -
Builtin catalog tests は、正確な provider list と count を assert している箇所がやや脆い:
builtin_has_four_providersload_falls_back_to_builtin_when_override_absent
これは偶発的な catalog drift を捕捉できるため価値があるが、正当な provider を追加すると、invariant-oriented というより一部 snapshot-like なテスト更新が必要になることも意味する。意図的であれば許容できるが、pure behavior testing ではなく catalog contract testing として扱うべき。
-
User model override behavior は provider override behavior よりカバーが薄い。
models.tomloverride precedence に相当するテストがない。- malformed
models.tomlparse-error test がない。 - providers と models は設計上独立して override されるため、対称的なカバレッジが必要。
-
Codex OAuth guarded-reload behavior は文書化されているが、直接テストされていない。
- “file becomes fresh between stale read and refresh” をカバーするテストがない。
- refresh 前に account id が変わり、そのため refresh を skip するケースをカバーするテストがない。
- これらは concurrency/race-safety invariants であり、現在のテストは通常の refresh path は検証しているが、race guards は検証していない。
-
last_refresh + 8 daysによる Codex OAuth staleness fallback は直接テストされていない。現在の provider tests は access-tokenexpを使って fresh/expired cases を強制している。実際の auth file で malformed/non-JWT access token が想定されるなら、この fallback はテストするだけの重要性がある。 -
Refresh HTTP tests は outbound request shape を assert していない。
client_idgrant_type = refresh_tokenrefresh_token- JSON content type
現在の mock は期待される path へ POST が発生したことは証明しているが、Codex-compatible body が正しいことは証明していない。
-
Error conversion のカバレッジは間接的である。
CodexAuthError::to_client_errorの permanent-path behavior は provider-level login-message test を通して部分的にカバーされているが、transient refresh と config-classified errors はClientErrorvariants として直接 assert されていない。 -
CodexAuthProvider::from_default_homeの environment precedence(HOMEよりCODEX_HOME)や missingHOMEに対するテストがない。これは小さいが public construction path である。
追加を提案するテスト
-
Codex OAuth construction invariants に対する provider-factory tests を追加する:
ref = "codex-oauth/gpt-5.5"がAuthRef::CodexOAuthとして resolve/build される。base_urlがない場合、official OpenAI ではなく ChatGPT backend base URL になる。- explicit
base_urlは引き続き優先される。 - 広い internals を露出せずに assert できるなら、Codex OAuth OpenAI Responses が unsupported output/sampling parameters を無効化する。
-
対称的な model catalog override tests を追加する:
load_models()は<config_dir>/models.tomlを優先する。- malformed model override は
CatalogError::Parseを返す。 - provider override と model override は片方だけが存在する場合も独立している。
-
Codex OAuth race-guard tests を追加する。できれば
auth_json::load周辺の小さな test seam を使うか、呼び出し間で temp-file changes を構成する:- stale initial snapshot、fresh pre-refresh snapshot: HTTP refresh しない。
- pre-refresh account id が異なる: HTTP refresh せず、新しい account を採用する。
-
staleness fallback unit tests を追加する:
- invalid/non-JWT access token + recent
last_refreshは stale ではない。 - invalid/non-JWT access token + old
last_refreshは stale。 - invalid/non-JWT access token + missing
last_refreshは stale。
- invalid/non-JWT access token + recent
-
wiremockで request body matching を使って refresh HTTP tests を強化し、偶発的な Codex OAuth request-shape 変更を捕捉できるようにする。 -
catalog churn が想定されるなら、正確な builtin provider-count tests をより contract-focused な checks に置き換えることを検討する:
- required provider ids が存在する
- 各 provider が必要な scheme/auth/default context/capability を持つ
- 各 builtin model が known provider を参照する
正確なリストが意図的に product contract の一部であるなら、現在の snapshot-style assertions で問題ない。
実行したコマンド
cargo test -p provider- Result: passed
- Summary:
47 passed; 0 failed; 0 ignored - Doc tests:
0 passed; 0 failed