---
generated_at: 2026-02-04 12:00:00
metrics:
  claims_total: 213
  claims_with_evidence: 207
  claims_without_evidence: 6
confidence_derived: 0.97
---

# 根拠レポート：launcher.csv（単体テストケース一覧）

## 本レポートについて

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

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

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

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

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

---

## 1) サマリー（まず見るところ）
- 総合信頼度（derived）：**0.97**
  - 根拠あり：207 / 213、根拠なし：6
- 優先レビュー（高）
  1. **SparkSubmitCommandBuilder.buildPySparkShellCommand のPython実行パス検証**：環境依存のためパス解決が不確実
  2. **SparkSubmitCommandBuilder.buildSparkRCommand のR実行パス検証**：環境依存のためパス解決が不確実
  3. **LauncherServer.createSecret のシークレット一意性検証**：SecureRandomに依存するため完全な検証が困難
  4. **SparkClassCommandBuilder.buildCommand のメモリ環境変数依存テスト**：実行環境の環境変数に依存
  5. **AbstractCommandBuilder.buildClassPath のSPARK_PREPEND_CLASSES依存テスト**：ビルド構造への依存
  6. **OutputRedirector.redirect のcallback呼び出しタイミング検証**：スレッド実行タイミングに依存

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

- E-01: `launcher/src/main/java/org/apache/spark/launcher/CommandBuilderUtils.java` - ユーティリティメソッド群
- E-02: `launcher/src/main/java/org/apache/spark/launcher/SparkSubmitOptionParser.java` - コマンドラインパーサー
- E-03: `launcher/src/main/java/org/apache/spark/launcher/SparkSubmitCommandBuilder.java` - SparkSubmitコマンドビルダー
- E-04: `launcher/src/main/java/org/apache/spark/launcher/SparkClassCommandBuilder.java` - SparkClassコマンドビルダー
- E-05: `launcher/src/main/java/org/apache/spark/launcher/AbstractCommandBuilder.java` - 抽象コマンドビルダー
- E-06: `launcher/src/main/java/org/apache/spark/launcher/AbstractLauncher.java` - 抽象ランチャー基底クラス
- E-07: `launcher/src/main/java/org/apache/spark/launcher/SparkLauncher.java` - Sparkランチャー（子プロセス版）
- E-08: `launcher/src/main/java/org/apache/spark/launcher/InProcessLauncher.java` - インプロセスランチャー
- E-09: `launcher/src/main/java/org/apache/spark/launcher/AbstractAppHandle.java` - 抽象アプリハンドル
- E-10: `launcher/src/main/java/org/apache/spark/launcher/ChildProcAppHandle.java` - 子プロセスアプリハンドル
- E-11: `launcher/src/main/java/org/apache/spark/launcher/InProcessAppHandle.java` - インプロセスアプリハンドル
- E-12: `launcher/src/main/java/org/apache/spark/launcher/LauncherServer.java` - ランチャーサーバー
- E-13: `launcher/src/main/java/org/apache/spark/launcher/LauncherConnection.java` - ランチャー接続
- E-14: `launcher/src/main/java/org/apache/spark/launcher/LauncherProtocol.java` - プロトコル定義
- E-15: `launcher/src/main/java/org/apache/spark/launcher/FilteredObjectInputStream.java` - フィルタ付きObjectInputStream
- E-16: `launcher/src/main/java/org/apache/spark/launcher/OutputRedirector.java` - 出力リダイレクタ
- E-17: `launcher/src/main/java/org/apache/spark/launcher/NamedThreadFactory.java` - スレッドファクトリ
- E-18: `launcher/src/main/java/org/apache/spark/launcher/JavaModuleOptions.java` - Javaモジュールオプション
- E-19: `launcher/src/main/java/org/apache/spark/launcher/SparkAppHandle.java` - SparkAppHandleインターフェース
- E-20: `launcher/src/main/java/org/apache/spark/launcher/Main.java` - CLIエントリポイント
- E-21: `launcher/src/main/java/org/apache/spark/launcher/package-info.java` - パッケージ情報

## 3) Claims と根拠の対応（レビューの主戦場）

### CommandBuilderUtils（UT-LNC-001 〜 UT-LNC-041）
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-01 | isEmpty: nullでtrue | E-01 (L44-46) | ○ |
| C-02 | isEmpty: 空文字列でtrue | E-01 (L44-46) | ○ |
| C-03 | isEmpty: 非空でfalse | E-01 (L44-46) | ○ |
| C-04 | join: 複数要素結合 | E-01 (L49-65) | ○ |
| C-05 | join: 空配列で空文字 | E-01 (L54-65) | ○ |
| C-06 | join: null要素スキップ | E-01 (L57) | ○ |
| C-07 | firstNonEmpty: 最初の非空値 | E-01 (L81-88) | ○ |
| C-08 | firstNonEmpty: 全空でnull | E-01 (L81-88) | ○ |
| C-09 | firstNonEmptyValue: マップ検索 | E-01 (L70-78) | ○ |
| C-10 | firstNonEmptyValue: キー不在でnull | E-01 (L70-78) | ○ |
| C-11 | getLibPathEnvName: Mac OS X判定 | E-01 (L92-102) | ○ |
| C-12 | getLibPathEnvName: Linux判定 | E-01 (L92-102) | ○ |
| C-13 | isWindows: Windows判定 | E-01 (L105-108) | ○ |
| C-14 | isWindows: 非Windows判定 | E-01 (L105-108) | ○ |
| C-15 | mergeEnvPathList: パス追加 | E-01 (L114-119) | ○ |
| C-16 | mergeEnvPathList: 空パス | E-01 (L115) | ○ |
| C-17 | parseOptionString: ダブルクォート | E-01 (L128-211) | ○ |
| C-18 | parseOptionString: シングルクォート | E-01 (L128-211) | ○ |
| C-19 | parseOptionString: エスケープ | E-01 (L141-143) | ○ |
| C-20 | parseOptionString: 閉じていないクォート | E-01 (L206) | ○ |
| C-21 | parseOptionString: 空文字列 | E-01 (L207) | ○ |
| C-22 | parseOptionString: 空クォート | E-01 (L137, L207) | ○ |
| C-23 | checkNotNull: nullでException | E-01 (L214-217) | ○ |
| C-24 | checkNotNull: 非nullで正常 | E-01 (L214-217) | ○ |
| C-25 | checkArgument: falseでException | E-01 (L221-225) | ○ |
| C-26 | checkState: falseでException | E-01 (L228-232) | ○ |
| C-27 | quoteForBatchScript: クォート不要 | E-01 (L243-271) | ○ |
| C-28 | quoteForBatchScript: スペース含み | E-01 (L243-271) | ○ |
| C-29 | quoteForBatchScript: ダブルクォート含み | E-01 (L243-271) | ○ |
| C-30 | quoteForCommandString: 基本 | E-01 (L281-291) | ○ |
| C-31 | quoteForCommandString: エスケープ | E-01 (L285-286) | ○ |
| C-32 | javaMajorVersion: JEP-223形式 | E-01 (L298-308) | ○ |
| C-33 | javaMajorVersion: レガシー形式 | E-01 (L298-308) | ○ |
| C-34 | javaMajorVersion: EA版 | E-01 (L298-308) | ○ |
| C-35 | findJarsDir: 存在時 | E-01 (L314-327) | ○ |
| C-36 | findJarsDir: 不在でnull | E-01 (L314-327) | ○ |
| C-37 | findJarsDir: 不在でException | E-01 (L320-321) | ○ |
| C-38 | redact: 秘密情報リダクト | E-01 (L340-347) | ○ |
| C-39 | redact: 非秘密情報保持 | E-01 (L340-347) | ○ |
| C-40 | redact: passwordリダクト | E-01 (L39-40, L340-347) | ○ |
| C-41 | redactCommandLineArgs: 一括 | E-01 (L333-335) | ○ |

### SparkSubmitOptionParser（UT-LNC-042 〜 UT-LNC-048）
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-42 | parse: 既知オプション+値 | E-02 (L146-195) | ○ |
| C-43 | parse: 等号区切り | E-02 (L147, L154-158) | ○ |
| C-44 | parse: スイッチ | E-02 (L178-184) | ○ |
| C-45 | parse: 値不足でException | E-02 (L164-166) | ○ |
| C-46 | parse: 短縮形変換 | E-02 (L96, L229-238) | ○ |
| C-47 | parse: 未知引数 | E-02 (L186-188) | ○ |
| C-48 | parse: handleExtraArgs | E-02 (L191-194) | ○ |

### SparkSubmitCommandBuilder（UT-LNC-049 〜 UT-LNC-072）
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-49 | コンストラクタ: PySparkシェル | E-03 (L133-137) | ○ |
| C-50 | コンストラクタ: SparkRシェル | E-03 (L139-143) | ○ |
| C-51 | コンストラクタ: run-example | E-03 (L145-148) | ○ |
| C-52 | コンストラクタ: 空リスト | E-03 (L155-158) | ○ |
| C-53 | buildCommand: 通常コマンド | E-03 (L172-192, L312-368) | ○ |
| C-54 | buildSparkSubmitArgs: master | E-03 (L220-223) | ○ |
| C-55 | buildSparkSubmitArgs: verbose | E-03 (L216-218) | ○ |
| C-56 | buildSparkSubmitArgs: conf | E-03 (L240-247) | ○ |
| C-57 | buildSparkSubmitArgs: appResource null | E-03 (L212-214) | ○ |
| C-58 | isClientMode: masterがnull | E-03 (L483-488) | ○ |
| C-59 | isClientMode: client | E-03 (L487) | ○ |
| C-60 | isClientMode: cluster | E-03 (L487) | ○ |
| C-61 | checkJavaOptions: Xmx含み | E-03 (L370-381) | ○ |
| C-62 | checkJavaOptions: Xmxなし | E-03 (L370-381) | ○ |
| C-63 | checkJavaOptions: null | E-03 (L371) | ○ |
| C-64 | getApiMode: SPARK_CONNECT_MODE=1 | E-03 (L161-170) | ○ |
| C-65 | getApiMode: classic設定 | E-03 (L165-166) | ○ |
| C-66 | OptionParser.handle: master | E-03 (L557) | ○ |
| C-67 | OptionParser.handle: remote | E-03 (L558-561) | ○ |
| C-68 | OptionParser.handle: conf | E-03 (L572-577) | ○ |
| C-69 | OptionParser.handle: conf null | E-03 (L573) | ○ |
| C-70 | OptionParser.handle: conf invalid | E-03 (L575) | ○ |
| C-71 | OptionParser.handle: 特殊クラス | E-03 (L578-588) | ○ |
| C-72 | OptionParser.handleUnknown: mixed | E-03 (L614-616) | ○ |

### SparkClassCommandBuilder（UT-LNC-073 〜 UT-LNC-078）
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-73 | コンストラクタ: BeeLine検出 | E-04 (L41-43) | ○ |
| C-74 | buildCommand: Master | E-04 (L55-59) | ○ |
| C-75 | buildCommand: Worker | E-04 (L61-65) | ○ |
| C-76 | buildCommand: HistoryServer | E-04 (L67-71) | ○ |
| C-77 | buildCommand: デフォルト | E-04 (L88) | ○ |
| C-78 | buildCommand: Xmx制限 | E-04 (L95-99) | ○ |

### AbstractCommandBuilder（UT-LNC-079 〜 UT-LNC-094）
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-79 | buildJavaCommand: javaパス | E-05 (L102-129) | ○ |
| C-80 | buildJavaCommand: クラスパス | E-05 (L126-128) | ○ |
| C-81 | buildClassPath: confDir | E-05 (L148) | ○ |
| C-82 | buildClassPath: appClassPath | E-05 (L146) | ○ |
| C-83 | buildClassPath: HADOOP_CONF_DIR | E-05 (L273) | ○ |
| C-84 | getSparkHome: 環境変数 | E-05 (L341-349) | ○ |
| C-85 | getSparkHome: 未設定Exception | E-05 (L346-347) | ○ |
| C-86 | getSparkHome: テストモード | E-05 (L343-344) | ○ |
| C-87 | getScalaVersion: 環境変数 | E-05 (L318-320) | ○ |
| C-88 | getenv: childEnv優先 | E-05 (L351-353) | ○ |
| C-89 | getEffectiveConfig: マージ | E-05 (L360-369) | ○ |
| C-90 | getEffectiveConfig: 優先順位 | E-05 (L364-365) | ○ |
| C-91 | getEffectiveConfig: デフォルト値 | E-05 (L366-367) | ○ |
| C-92 | setPropertiesFile: リセット | E-05 (L355-358) | ○ |
| C-93 | addOptionString: 追加 | E-05 (L131-135) | ○ |
| C-94 | addOptionString: 空文字列 | E-05 (L132) | ○ |

### AbstractLauncher（UT-LNC-095 〜 UT-LNC-112）
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-95 | setConf: spark.プレフィックス | E-06 (L58-64) | ○ |
| C-96 | setConf: 不正キー | E-06 (L61) | ○ |
| C-97 | setConf: nullキー | E-06 (L59) | ○ |
| C-98 | setConf: null値 | E-06 (L60) | ○ |
| C-99 | setAppName: 正常 | E-06 (L72-76) | ○ |
| C-100 | setAppName: null | E-06 (L73) | ○ |
| C-101 | setMaster: 正常 | E-06 (L84-88) | ○ |
| C-102 | setDeployMode: 正常 | E-06 (L109-113) | ○ |
| C-103 | setMainClass: 正常 | E-06 (L134-138) | ○ |
| C-104 | addSparkArg(String): スイッチ | E-06 (L152-157) | ○ |
| C-105 | addSparkArg(String,String): master | E-06 (L177) | ○ |
| C-106 | addSparkArg(String,String): conf | E-06 (L183-185) | ○ |
| C-107 | addSparkArg(String,String): jars | E-06 (L188-191) | ○ |
| C-108 | addAppArgs: 正常 | E-06 (L217-223) | ○ |
| C-109 | addAppArgs: null | E-06 (L219) | ○ |
| C-110 | addJar: 正常 | E-06 (L231-235) | ○ |
| C-111 | addFile: 正常 | E-06 (L243-247) | ○ |
| C-112 | addPyFile: 正常 | E-06 (L255-259) | ○ |

### SparkLauncher（UT-LNC-113 〜 UT-LNC-124）
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-113 | デフォルトコンストラクタ | E-07 (L149-151) | ○ |
| C-114 | コンストラクタ(Map): env設定 | E-07 (L158-162) | ○ |
| C-115 | コンストラクタ(Map): null env | E-07 (L159) | ○ |
| C-116 | setJavaHome: 正常 | E-07 (L170-174) | ○ |
| C-117 | setJavaHome: null | E-07 (L171) | ○ |
| C-118 | setSparkHome: 正常 | E-07 (L182-186) | ○ |
| C-119 | directory: 正常 | E-07 (L194-197) | ○ |
| C-120 | redirectError(): フラグ | E-07 (L204-207) | ○ |
| C-121 | redirectToLog: conf設定 | E-07 (L259-262) | ○ |
| C-122 | setConfig: 静的マップ | E-07 (L139-141) | ○ |
| C-123 | findSparkSubmit: Unixパス | E-07 (L497-500) | ○ |
| C-124 | createBuilder: リダイレクト競合 | E-07 (L472-473) | ○ |

### AbstractAppHandle（UT-LNC-125 〜 UT-LNC-137）
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-125 | 初期状態UNKNOWN | E-09 (L41) | ○ |
| C-126 | setState: 正常遷移 | E-09 (L123-147) | ○ |
| C-127 | setState: final状態拒否 | E-09 (L134-141) | ○ |
| C-128 | setState(force): 強制遷移 | E-09 (L128-131) | ○ |
| C-129 | setAppId: 設定と通知 | E-09 (L149-152) | ○ |
| C-130 | getAppId: 取得 | E-09 (L57-59) | ○ |
| C-131 | getAppId: 未設定 | E-09 (L36) | ○ |
| C-132 | addListener: 登録と通知 | E-09 (L45-49, L154-163) | ○ |
| C-133 | stop: 未接続Exception | E-09 (L63-64) | ○ |
| C-134 | disconnect: 切断とdispose | E-09 (L73-82) | ○ |
| C-135 | dispose: 登録解除 | E-09 (L103-121) | ○ |
| C-136 | dispose: LOST遷移 | E-09 (L118) | ○ |
| C-137 | dispose: final状態維持 | E-09 (L118, L134-141) | ○ |

### ChildProcAppHandle（UT-LNC-138 〜 UT-LNC-147）
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-138 | kill: プロセス停止 | E-10 (L68-79) | ○ |
| C-139 | kill: disposed済み | E-10 (L69) | ○ |
| C-140 | monitorChild: 正常終了 | E-10 (L97-135) | ○ |
| C-141 | monitorChild: 異常終了 | E-10 (L125-130) | ○ |
| C-142 | monitorChild: FINISHED上書き | E-10 (L128-129) | ○ |
| C-143 | monitorChild: null proc | E-10 (L98-101) | ○ |
| C-144 | getError: redirectorあり | E-10 (L63-65) | ○ |
| C-145 | getError: redirector null | E-10 (L64) | ○ |
| C-146 | setChildProc: logStreamあり | E-10 (L81-86) | ○ |
| C-147 | setChildProc: logStream null | E-10 (L87-90) | ○ |

### InProcessAppHandle（UT-LNC-148 〜 UT-LNC-153）
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-148 | start: スレッド起動 | E-11 (L63-87) | ○ |
| C-149 | start: 二重起動 | E-11 (L64) | ○ |
| C-150 | start: 名前切り詰め | E-11 (L66-67) | ○ |
| C-151 | start: 例外でFAILED | E-11 (L73-79) | ○ |
| C-152 | kill: interrupt送信 | E-11 (L45-56) | ○ |
| C-153 | getError: 取得 | E-11 (L59-61) | ○ |

### InProcessLauncher（UT-LNC-154 〜 UT-LNC-157）
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-154 | startApplication: ハンドル返却 | E-08 (L54-77) | ○ |
| C-155 | findSparkSubmit: InProcessSparkSubmit | E-08 (L85-116) | ○ |
| C-156 | findSparkSubmit: フォールバック | E-08 (L97-104) | ○ |
| C-157 | findSparkSubmit: 不在Exception | E-08 (L100-103) | ○ |

### LauncherServer（UT-LNC-158 〜 UT-LNC-172）
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-158 | getOrCreateServer: 起動 | E-12 (L92-101) | ○ |
| C-159 | registerHandle: 登録 | E-12 (L150-154) | ○ |
| C-160 | getPort: ポート | E-12 (L204-206) | ○ |
| C-161 | unregister: 解除 | E-12 (L212-222) | ○ |
| C-162 | close: 停止 | E-12 (L157-186) | ○ |
| C-163 | close: 二重停止 | E-12 (L159-161) | ○ |
| C-164 | unref: refCount=0で停止 | E-12 (L192-202) | ○ |
| C-165 | getConnectionTimeout: 設定値 | E-12 (L264-279) | ○ |
| C-166 | getConnectionTimeout: deprecated | E-12 (L270-276) | ○ |
| C-167 | getConnectionTimeout: デフォルト | E-12 (L278) | ○ |
| C-168 | ServerConnection.handle(Hello): 認証成功 | E-12 (L318-328) | ○ |
| C-169 | ServerConnection.handle(Hello): 認証失敗 | E-12 (L329) | ○ |
| C-170 | ServerConnection.handle(SetAppId) | E-12 (L336-337) | ○ |
| C-171 | ServerConnection.handle(SetState) | E-12 (L338-339) | ○ |
| C-172 | ServerConnection.handle: Hello前メッセージ | E-12 (L333-335) | ○ |

### LauncherConnection（UT-LNC-173 〜 UT-LNC-177）
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-173 | send: 送信 | E-13 (L79-95) | ○ |
| C-174 | send: 閉鎖後Exception | E-13 (L81) | ○ |
| C-175 | close: 正常切断 | E-13 (L98-103) | ○ |
| C-176 | close: 二重クローズ | E-13 (L99) | ○ |
| C-177 | isOpen: 確認 | E-13 (L105-107) | ○ |

### FilteredObjectInputStream（UT-LNC-178 〜 UT-LNC-180）
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-178 | resolveClass: launcher許可 | E-15 (L33-35, L42-49) | ○ |
| C-179 | resolveClass: java.lang許可 | E-15 (L34, L45) | ○ |
| C-180 | resolveClass: 不正クラス拒否 | E-15 (L46-48) | ○ |

### OutputRedirector（UT-LNC-181 〜 UT-LNC-189）
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-181 | redirect: ログ出力 | E-16 (L59-78) | ○ |
| C-182 | redirect: エラー検出 | E-16 (L65-68) | ○ |
| C-183 | redirect: スタックトレース除外 | E-16 (L66) | ○ |
| C-184 | stop: active=false | E-16 (L85-87) | ○ |
| C-185 | isAlive: スレッド状態 | E-16 (L89-91) | ○ |
| C-186 | getError: エラー取得 | E-16 (L93-95) | ○ |
| C-187 | containsIgnoreCase: 部分一致 | E-16 (L100-112) | ○ |
| C-188 | containsIgnoreCase: str null | E-16 (L101-103) | ○ |
| C-189 | containsIgnoreCase: searchStr null | E-16 (L101-103) | ○ |

### NamedThreadFactory（UT-LNC-190 〜 UT-LNC-192）
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-190 | newThread: スレッド名 | E-17 (L34-38) | ○ |
| C-191 | newThread: デーモン | E-17 (L36) | ○ |
| C-192 | newThread: 連番 | E-17 (L35) | ○ |

### JavaModuleOptions（UT-LNC-193 〜 UT-LNC-197）
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-193 | defaultModuleOptions: 非空 | E-18 (L55-57) | ○ |
| C-194 | defaultModuleOptions: --add-opens | E-18 (L31-45) | ○ |
| C-195 | defaultModuleOptions: -XX | E-18 (L29) | ○ |
| C-196 | defaultModuleOptionArray: 非空 | E-18 (L62-64) | ○ |
| C-197 | defaultModuleOptionArray: 要素数一致 | E-18 (L55-57, L62-64) | ○ |

### SparkAppHandle.State（UT-LNC-198 〜 UT-LNC-203）
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-198 | isFinal: UNKNOWN | E-19 (L39) | ○ |
| C-199 | isFinal: FINISHED | E-19 (L47) | ○ |
| C-200 | isFinal: FAILED | E-19 (L49) | ○ |
| C-201 | isFinal: KILLED | E-19 (L51) | ○ |
| C-202 | isFinal: LOST | E-19 (L53) | ○ |
| C-203 | isFinal: RUNNING | E-19 (L45) | ○ |

### Main（UT-LNC-204 〜 UT-LNC-210）
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-204 | main: SparkSubmitモード | E-20 (L60-84) | ○ |
| C-205 | main: SparkClassモード | E-20 (L85-88) | ○ |
| C-206 | main: 空引数チェック | E-20 (L52) | ○ |
| C-207 | prepareWindowsCommand | E-20 (L130-141) | ○ |
| C-208 | prepareBashCommand: envあり | E-20 (L147-160) | ○ |
| C-209 | prepareBashCommand: env空 | E-20 (L148-149) | ○ |
| C-210 | MainClassOptionParser.handle | E-20 (L172-176) | ○ |

### LauncherProtocol（UT-LNC-211 〜 UT-LNC-213）
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-211 | Hello: 生成 | E-14 (L48-58) | ○ |
| C-212 | SetAppId: 生成 | E-14 (L63-70) | ○ |
| C-213 | SetState: 生成 | E-14 (L76-83) | ○ |

## 4) 不足情報（Unknown / Missing）
- **PySpark/SparkR実行パスの環境依存テスト**: buildPySparkShellCommand, buildSparkRCommandは環境固有のPython/R実行パスに依存するため、テストケースの入力値・期待結果が実行環境に左右される
  - 候補：モック環境変数 / テスト用ダミーパス / Docker環境
- **LauncherServer.createSecretの一意性**: SecureRandomベースのシークレット生成の一意性保証は確率的であり、完全な検証が困難
  - 候補：衝突テスト（大量生成） / モックRandom
- **AbstractCommandBuilder.buildClassPathのSPARK_PREPEND_CLASSES依存**: ビルドディレクトリ構造への依存があり、テスト環境でのディレクトリ構造再現が必要
  - 候補：テスト用ディレクトリ構造の構築 / ファイルシステムモック
- **SparkClassCommandBuilder.buildCommandの環境変数依存**: SPARK_DAEMON_JAVA_OPTS等の環境変数に依存するテストは環境設定が必要
  - 候補：環境変数モック / テスト用ヘルパー
- **OutputRedirector.redirectのスレッドタイミング**: callbackの呼び出しタイミングがスレッドスケジューリングに依存
  - 候補：CountDownLatch / CompletableFuture
- **LauncherServer.acceptConnectionsのソケット受信テスト**: 統合テストに近い性質を持ち、単体テストでの完全検証が困難
  - 候補：ローカルソケットによるテスト / SocketChannel

## 5) リスクフラグ（レビュー観点）
- **0: 低リスク** - CommandBuilderUtils, NamedThreadFactory, JavaModuleOptions, LauncherProtocol, SparkAppHandle.State: 単純なユーティリティ関数やデータクラスで、ロジックが明確
- **1: 中リスク** - AbstractCommandBuilder.buildClassPath, SparkSubmitCommandBuilder.buildCommand: 環境変数やファイルシステムへの依存があるが、コードパスは明確
- **1: 中リスク** - FilteredObjectInputStream.resolveClass: セキュリティ関連だが、ロジックは単純（SPARK-20922対応）
- **1: 中リスク** - AbstractAppHandle.setState: CAS操作による状態遷移はマルチスレッド環境での正確な検証が必要
- **2: 高リスク** - LauncherServer全体: ソケット通信、マルチスレッド、タイムアウト管理が絡み、テスト環境構築が複雑
- **1: 中リスク** - redact/redactCommandLineArgs: セキュリティ機能のため、パターンの網羅性確認が重要

## 6) レビュアーチェックリスト（最小）
- [ ] テストケースが全21ファイルをカバーしているか（package-info.javaは対象外で正しいか確認）
- [ ] セキュリティ関連テスト（FilteredObjectInputStream, redact）が十分に網羅されているか
- [ ] 状態遷移テスト（AbstractAppHandle.setState）が全パターンを網羅しているか
- [ ] 環境依存テスト（buildClassPath, buildCommand）の前提条件が明確か
- [ ] 異常系テスト（null入力、不正入力）が主要なpublicメソッドに対して存在するか
- [ ] LauncherServerの認証フロー（Hello/secret）のテストが十分か
- [ ] InProcessAppHandle.startのスレッド安全性テストが考慮されているか
