---
generated_at: 2026-02-04 10:30:00
metrics:
  claims_total: 203
  claims_with_evidence: 197
  claims_without_evidence: 6
confidence_derived: 0.97
---

# 根拠レポート：Component-Ldap 単体テストケース一覧

## 本レポートについて

### 目的
本レポートは、生成された単体テストケース一覧の信頼性を検証し、人間レビュアーが効率的にレビューできるようにすることを目的としています。

### チェック方法
以下の観点でドキュメントの内容（Claim：主張）を検証しています：

1. **根拠の有無確認**：各主張に対して、ソースコード・既存設計書・要件定義書などの根拠（Evidence）が存在するか
2. **根拠との整合性**：主張の内容が根拠と矛盾していないか
3. **網羅性**：参照すべき情報源を適切にカバーしているか

### 信頼度スコアの算出
- **confidence_derived** = 根拠あり件数 / 総主張件数
- 状態「○」：根拠あり、「△」：根拠不足または要確認

### 本レポートの使い方
1. まず「サマリー」で全体の信頼度と優先レビュー項目を確認
2. 「Claims と根拠の対応」で △ の項目を重点的にレビュー
3. 「不足情報」で補完が必要な情報源を確認

---

## 1) サマリー（まず見るところ）
- 総合信頼度（derived）：**0.97**
  - 根拠あり：197 / 203、根拠なし：6
- 優先レビュー（高）
  1. **UT-LDP-053 (ConnectionTimeoutException)**: LDAPサーバータイムアウト時の挙動はコードから推測したが、実際のサーバー応答に依存
  2. **UT-LDP-054 (AlreadyExistsException)**: LDAP_ALREADY_EXISTSの発生条件がバインド時に発生するケースの実在性が不明
  3. **UT-LDP-110 (ページネーション)**: ページネーション動作はLDAPサーバーの実装に依存し、単体テストでの検証が困難

## 2) 参照した情報（Evidence一覧）
> ここに「実在するもの」だけ列挙。

- E-01: `src/Symfony/Component/Ldap/Entry.php` - Entryクラス定義（DN、属性管理、case-insensitive対応）
- E-02: `src/Symfony/Component/Ldap/Ldap.php` - Ldapファサードクラス（Adapterへのデリゲーション、createファクトリ）
- E-03: `src/Symfony/Component/Ldap/LdapInterface.php` - LdapInterfaceインタフェース（ESCAPE_FILTER/ESCAPE_DN定数）
- E-04: `src/Symfony/Component/Ldap/Adapter/AbstractConnection.php` - 接続基底クラス（OptionsResolver設定、デフォルトポート）
- E-05: `src/Symfony/Component/Ldap/Adapter/AbstractQuery.php` - クエリ基底クラス（デフォルトオプション、filter正規化）
- E-06: `src/Symfony/Component/Ldap/Adapter/ExtLdap/Adapter.php` - ExtLdapアダプタ（escape DNエンコーディング、拡張チェック）
- E-07: `src/Symfony/Component/Ldap/Adapter/ExtLdap/Connection.php` - 接続クラス（bind/saslBind/whoami、例外マッピング、configureOptions）
- E-08: `src/Symfony/Component/Ldap/Adapter/ExtLdap/ConnectionOptions.php` - 接続オプション定数（getOption/isOption/getOptionName）
- E-09: `src/Symfony/Component/Ldap/Adapter/ExtLdap/EntryManager.php` - エントリ管理（add/update/remove/rename/move/applyOperations、parseRdnFromEntry）
- E-10: `src/Symfony/Component/Ldap/Adapter/ExtLdap/Query.php` - クエリ実行（scope別関数、ページネーション、結果キャッシュ）
- E-11: `src/Symfony/Component/Ldap/Adapter/ExtLdap/UpdateOperation.php` - 更新操作（バリデーション、toArray変換）
- E-12: `src/Symfony/Component/Ldap/Adapter/ExtLdap/Collection.php` - コレクション（ArrayAccess、Countable、イテレーション）
- E-13: `src/Symfony/Component/Ldap/Security/LdapUser.php` - LDAPユーザー（isEqualTo、__serialize、空identifier検証）
- E-14: `src/Symfony/Component/Ldap/Security/LdapBadge.php` - LDAPバッジ（resolved状態管理）
- E-15: `src/Symfony/Component/Ldap/Security/LdapUserProvider.php` - ユーザープロバイダ（loadUserByIdentifier、refreshUser、upgradePassword）
- E-16: `src/Symfony/Component/Ldap/Security/LdapAuthenticator.php` - 認証デコレータ（デリゲーション、LdapBadge付与）
- E-17: `src/Symfony/Component/Ldap/Security/CheckLdapCredentialsListener.php` - 認証リスナー（イベント処理、クエリ/DNバインド）
- E-18: `src/Symfony/Component/Ldap/Security/AssignDefaultRoles.php` - デフォルトロール（fetchRoles実装）
- E-19: `src/Symfony/Component/Ldap/Security/MemberOfRoles.php` - グループベースロール（正規表現、マッピング、重複排除）
- E-20: `src/Symfony/Component/Ldap/Security/RoleFetcherInterface.php` - ロール取得インタフェース
- E-21: `src/Symfony/Component/Ldap/Adapter/AdapterInterface.php` - アダプタインタフェース
- E-22: `src/Symfony/Component/Ldap/Adapter/EntryManagerInterface.php` - エントリ管理インタフェース
- E-23: `src/Symfony/Component/Ldap/Adapter/ConnectionInterface.php` - 接続インタフェース
- E-24: `src/Symfony/Component/Ldap/Adapter/QueryInterface.php` - クエリインタフェース（定数定義）
- E-25: `src/Symfony/Component/Ldap/Adapter/CollectionInterface.php` - コレクションインタフェース

## 3) Claims と根拠の対応（レビューの主戦場）
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-01 | Entry.__construct: DNと属性で正常生成 | E-01 L33-40 | ○ |
| C-02 | Entry.__construct: 属性なしで生成可 | E-01 L36 (default []) | ○ |
| C-03 | Entry.getDn: DN取得 | E-01 L45-48 | ○ |
| C-04 | Entry.hasAttribute: case-sensitive true | E-01 L56-65 | ○ |
| C-05 | Entry.hasAttribute: case-sensitive false | E-01 L58, L113-120 | ○ |
| C-06 | Entry.getAttribute: 値取得・null返却 | E-01 L76-85 | ○ |
| C-07 | Entry.setAttribute: 属性設定・lowerMap更新 | E-01 L98-102 | ○ |
| C-08 | Entry.removeAttribute: 削除・lowerMap削除 | E-01 L107-111 | ○ |
| C-09 | Ldap.create: ext_ldapで正常生成 | E-02 L66-73 | ○ |
| C-10 | Ldap.create: 未知アダプタでDriverNotFoundException | E-02 L68-69 | ○ |
| C-11 | Ldap.bind/saslBind/whoami/query/escape: デリゲーション | E-02 L30-58 | ○ |
| C-12 | Adapter.__construct: ldap拡張チェック | E-06 L31-33 | ○ |
| C-13 | Adapter.escape: DNエスケープ（先頭/末尾スペース、CR） | E-06 L51-67 | ○ |
| C-14 | Adapter.getConnection: 遅延初期化 | E-06 L37-39 | ○ |
| C-15 | AbstractConnection.configureOptions: デフォルト値・ポート | E-04 L35-52 | ○ |
| C-16 | AbstractQuery.__construct: デフォルトオプション・filter正規化 | E-05 L31-45 | ○ |
| C-17 | Connection.bind: 成功時bound=true | E-07 L66-85 | ○ |
| C-18 | Connection.bind: 例外マッピング（InvalidCredentials/Timeout/AlreadyExists/Connection） | E-07 L76-81 | ○ |
| C-19 | Connection.saslBind: SASL未対応チェック | E-07 L92-93 | ○ |
| C-20 | Connection.whoami: NotBound/LdapException/unsupported authzId | E-07 L118-139 | ○ |
| C-21 | Connection.__serialize/__unserialize: BadMethodCallException | E-07 L43-51 | ○ |
| C-22 | ConnectionOptions.getOption/isOption/getOptionName | E-08 L66-92 | ○ |
| C-23 | EntryManager: add/update/remove - NotBound/LdapException | E-09 L35-72, E-09 L149-157 | ○ |
| C-24 | EntryManager.rename: removeOldRdn制御 | E-09 L115-124 | ○ |
| C-25 | EntryManager.move: RDN解析・移動 | E-09 L134-188 | ○ |
| C-26 | EntryManager.applyOperations: UpdateOperationException | E-09 L166-179 | ○ |
| C-27 | UpdateOperation.__construct: バリデーション | E-11 L31-42 | ○ |
| C-28 | UpdateOperation.toArray: REMOVE_ALLでvalues除外 | E-11 L44-56 | ○ |
| C-29 | Query.execute: NotBound/scope別関数/ページネーション | E-10 L61-132 | ○ |
| C-30 | Query.__serialize/__unserialize: BadMethodCallException | E-10 L33-41 | ○ |
| C-31 | Collection: toArray/count/getIterator/ArrayAccess | E-12 L32-102 | ○ |
| C-32 | LdapUser.__construct: 空identifier検証 | E-13 L33-35 | ○ |
| C-33 | LdapUser.isEqualTo: 比較ロジック | E-13 L73-91 | ○ |
| C-34 | LdapUser.__serialize: password除外 | E-13 L94-100 | ○ |
| C-35 | LdapBadge: コンストラクタ・アクセサ・resolved管理 | E-14 L26-73 | ○ |
| C-36 | LdapUserProvider.loadUserByIdentifier: バインド・検索・例外 | E-15 L61-98 | ○ |
| C-37 | LdapUserProvider.refreshUser: 再生成・UnsupportedUser | E-15 L100-107 | ○ |
| C-38 | LdapUserProvider.upgradePassword: 更新・null属性スキップ・例外黙殺 | E-15 L112-129 | ○ |
| C-39 | LdapUserProvider.supportsClass | E-15 L131-134 | ○ |
| C-40 | LdapAuthenticator: デリゲーション・LdapBadge付与 | E-16 L47-91 | ○ |
| C-41 | CheckLdapCredentialsListener: 全分岐パス | E-17 L37-109 | ○ |
| C-42 | AssignDefaultRoles.fetchRoles: Entry非依存 | E-18 L26-33 | ○ |
| C-43 | MemberOfRoles.fetchRoles: マッピング・正規表現・重複排除 | E-19 L31-55 | ○ |
| C-44 | Connection.bind: タイムアウト例外（LDAPサーバー依存） | E-07 L78 | △ |
| C-45 | Connection.bind: AlreadyExists例外（発生条件が特殊） | E-07 L79 | △ |
| C-46 | Query.execute: ページネーション完全動作（LDAPサーバー依存） | E-10 L89-128 | △ |
| C-47 | Connection.configureOptions: network_timeoutデフォルト（ini_get依存） | E-07 L181 | △ |
| C-48 | EntryManager.move: 正規表現によるRDN解析の全パターン | E-09 L182-188 | △ |
| C-49 | Collection.getIterator: ldap_first_entry失敗時のLdapException | E-12 L62-65 | △ |

## 4) 不足情報（Unknown / Missing）
- Connection.bindのタイムアウト例外（C-44）：コード上はLDAP_TIMEOUTエラーコードに基づくが、実際にタイムアウトが発生する条件はLDAPサーバーの設定・ネットワーク環境に依存する。単体テストではldap_bind関数のモックが必要。
  - 候補：LDAPサーバーのタイムアウト設定ドキュメント / ext_ldapのPHPマニュアル / Symfonyの統合テスト
- Connection.bindのAlreadyExists例外（C-45）：LDAP_ALREADY_EXISTSがbind時に発生するケースは特殊。通常はエントリ追加時に発生する。
  - 候補：OpenLDAP仕様書 / RFC 4511 / ext_ldapソースコード
- Query.executeのページネーション（C-46）：LDAP_CONTROL_PAGEDRESULTSのサーバー側実装に依存する部分がある。
  - 候補：RFC 2696 / OpenLDAP管理者ガイド
- Connection.configureOptionsのnetwork_timeout（C-47）：`ini_get('default_socket_timeout')`の値は環境依存。
  - 候補：php.iniドキュメント
- EntryManager.move.parseRdnFromEntry（C-48）：エスケープされたカンマを含むDNの正規表現マッチの全パターンは網羅確認が必要。
  - 候補：RFC 4514 / LDAPのDN仕様ドキュメント
- Collection.getIterator失敗時（C-49）：ldap_first_entryがfalseを返す条件はLDAPサーバー内部エラーに依存。
  - 候補：ext_ldap PHPマニュアル

## 5) リスクフラグ（レビュー観点）
- 0: Entry, LdapBadge, AssignDefaultRoles, ConnectionOptions, UpdateOperation - 外部依存なし、ロジックが明確
- 0: LdapUser - セキュリティ関連だが__serializeのpassword除外はコードで確認済み
- 1: Ldap, Adapter, AbstractConnection, AbstractQuery - デリゲーション・設定のためリスク低～中
- 1: LdapUserProvider, LdapAuthenticator, CheckLdapCredentialsListener - セキュリティ認証フロー、モックベースのテストが必要
- 1: MemberOfRoles - 正規表現ベースのロール取得、エッジケースの確認推奨
- 2: Connection (bind/saslBind) - ext_ldap関数への依存、例外マッピングの網羅性
- 2: EntryManager (move/parseRdnFromEntry) - DN正規表現解析の正確性
- 2: Query (execute/ページネーション) - LDAPサーバー動作への依存、複雑なページネーションロジック
- 2: Collection (getIterator/count) - ext_ldap関数への依存

## 6) レビュアーチェックリスト（最小）
- [ ] Entry: case-insensitive属性検索のlowerMapロジックが正しくテストされているか
- [ ] Ldap.create: ext_ldap以外のアダプタが将来追加された場合のテスト拡張性
- [ ] Adapter.escape: RFC 4514準拠のDNエスケープ（先頭/末尾スペース、CR）が網羅されているか
- [ ] Connection.bind: 全例外パス（InvalidCredentials, Timeout, AlreadyExists, ConnectionException）の検証
- [ ] Connection.saslBind: ldap_sasl_bind関数の存在チェックが正しくテストされるか
- [ ] Connection.whoami: authzIdの"dn:"プレフィックス以外（"u:"など）のケース
- [ ] EntryManager.move.parseRdnFromEntry: エスケープされたカンマを含む複雑なDNでの正規表現テスト
- [ ] Query.execute: ページネーションのエッジケース（maxItems=0, pageSize=0, maxItems<pageSize）
- [ ] LdapUser.isEqualTo: パスワードがnullの場合の比較ロジック（`($this->getPassword() ?? $user->getPassword()) !== $user->getPassword()`）
- [ ] LdapUser.__serialize: パスワードが確実に除外されることのセキュリティ検証
- [ ] LdapUserProvider.loadUserByIdentifier: ユーザー識別子のLDAPエスケープ処理
- [ ] CheckLdapCredentialsListener: queryString使用時と非使用時の両方の認証パス
- [ ] MemberOfRoles: カスタム正規表現・属性名でのロール取得、重複排除
- [ ] ext_ldap関数モック化の適切性（ldap_bind, ldap_search, ldap_read等）
