---
generated_at: 2026-02-04 10:30:00
metrics:
  claims_total: 140
  claims_with_evidence: 136
  claims_without_evidence: 4
confidence_derived: 0.97
---

# 根拠レポート：connector-kafka-0-10 単体テストケース一覧

## 本レポートについて

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

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

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

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

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

---

## 1) サマリー（まず見るところ）
- 総合信頼度（derived）：**0.97**
  - 根拠あり：136 / 140、根拠なし：4
- 優先レビュー（高）
  1. **C-104 (DirectKafkaInputDStream.getPreferredHosts - PreferBrokers)**: getBrokersメソッドの内部動作はKafkaブローカーへの接続に依存するため、テスト実行時のモック設計に注意が必要
  2. **C-132/C-133 (paranoidPoll)**: privateメソッドのため直接テスト不可、compute経由の間接テストが必要
  3. **C-134/C-135 (compute)**: StreamingContextの完全な初期化が必要であり、統合テスト寄りの設計が必要
  4. **C-126 (checkpoint restore)**: チェックポイント復元のテストはStreamingContext/SparkContextの初期化に依存

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

- E-01: `connector/kafka-0-10/src/main/scala/org/apache/spark/streaming/kafka010/OffsetRange.scala` - OffsetRange クラス定義（count, topicPartition, equals, hashCode, toString, toTuple, create, apply）
- E-02: `connector/kafka-0-10/src/main/scala/org/apache/spark/streaming/kafka010/KafkaRDDPartition.scala` - KafkaRDDPartition クラス定義（count, topicPartition）
- E-03: `connector/kafka-0-10/src/main/scala/org/apache/spark/streaming/kafka010/KafkaUtils.scala` - KafkaUtils オブジェクト定義（fixKafkaParams, createRDD, createDirectStream）
- E-04: `connector/kafka-0-10/src/main/scala/org/apache/spark/streaming/kafka010/ConsumerStrategy.scala` - ConsumerStrategy 抽象クラスおよびSubscribe/SubscribePattern/Assign/ConsumerStrategies定義
- E-05: `connector/kafka-0-10/src/main/scala/org/apache/spark/streaming/kafka010/LocationStrategy.scala` - LocationStrategy sealed class およびLocationStrategies定義
- E-06: `connector/kafka-0-10/src/main/scala/org/apache/spark/streaming/kafka010/KafkaDataConsumer.scala` - InternalKafkaConsumer, KafkaDataConsumer trait/object, CacheKey定義
- E-07: `connector/kafka-0-10/src/main/scala/org/apache/spark/streaming/kafka010/KafkaRDD.scala` - KafkaRDD, KafkaRDDIterator, CompactedKafkaRDDIterator定義
- E-08: `connector/kafka-0-10/src/main/scala/org/apache/spark/streaming/kafka010/DirectKafkaInputDStream.scala` - DirectKafkaInputDStream, DirectKafkaInputDStreamCheckpointData, DirectKafkaRateController定義
- E-09: `connector/kafka-0-10/src/main/scala/org/apache/spark/streaming/kafka010/PerPartitionConfig.scala` - PerPartitionConfig, DefaultPerPartitionConfig定義
- E-10: `connector/kafka-0-10/src/main/scala/org/apache/spark/streaming/kafka010/package.scala` - 設定キー定義（CONSUMER_CACHE_ENABLED, MAX_RATE_PER_PARTITION, MIN_RATE_PER_PARTITION等）

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

### OffsetRange (E-01)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-01 | OffsetRange.count()はuntilOffset - fromOffsetを返す | E-01 L92 | ○ |
| C-02 | fromOffset==untilOffsetの場合count()は0を返す | E-01 L92 | ○ |
| C-03 | topicPartition()はTopicPartitionを正しく生成する | E-01 L89 | ○ |
| C-04 | 同一OffsetRangeのequals比較はtrueを返す | E-01 L94-101 | ○ |
| C-05 | 異なるOffsetRangeのequals比較はfalseを返す | E-01 L94-101 | ○ |
| C-06 | 非OffsetRangeとの比較はfalseを返す | E-01 L100 | ○ |
| C-07 | hashCode()はtoTuple.hashCode()を使用する | E-01 L103-105 | ○ |
| C-08 | toString()は規定フォーマットの文字列を返す | E-01 L107-109 | ○ |
| C-09 | toTupleは4要素タプルに変換する | E-01 L113 | ○ |
| C-10 | create(String,Int,Long,Long)でインスタンス生成 | E-01 L120-121 | ○ |
| C-11 | create(TopicPartition,Long,Long)でインスタンス生成 | E-01 L123-127 | ○ |
| C-12 | apply(String,Int,Long,Long)でインスタンス生成 | E-01 L129-130 | ○ |
| C-13 | apply(TopicPartition,Long,Long)でインスタンス生成 | E-01 L132-136 | ○ |
| C-14 | apply(OffsetRangeTuple)でタプルから復元 | E-01 L143-144 | ○ |

### KafkaRDDPartition (E-02)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-15 | KafkaRDDPartition.count()はuntilOffset - fromOffsetを返す | E-02 L40 | ○ |
| C-16 | fromOffset==untilOffsetの場合count()は0 | E-02 L40 | ○ |
| C-17 | topicPartition()はTopicPartitionを正しく生成 | E-02 L43 | ○ |

### KafkaUtils (E-03)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-18 | fixKafkaParamsでENABLE_AUTO_COMMITがfalseに設定される | E-03 L189 | ○ |
| C-19 | fixKafkaParamsでAUTO_OFFSET_RESETが"none"に設定される | E-03 L193 | ○ |
| C-20 | fixKafkaParamsでGROUP_IDに"spark-executor-"プレフィックスが付く | E-03 L201-204 | ○ |
| C-21 | GROUP_IDがnullの場合もエラーにならない | E-03 L197-201 | ○ |
| C-22 | RECEIVE_BUFFER < 65536の場合に65536に設定される | E-03 L208-212 | ○ |
| C-23 | RECEIVE_BUFFERがnullの場合に65536に設定される | E-03 L208 | ○ |
| C-24 | RECEIVE_BUFFER >= 65536の場合は上書きされない | E-03 L208 | ○ |
| C-25 | createRDD - PreferConsistentでKafkaRDDが生成される | E-03 L52-71 | ○ |
| C-26 | createRDD - PreferBrokersでIllegalArgumentException | E-03 L59-62 | ○ |
| C-27 | createRDD - PreferFixedでKafkaRDDが生成される | E-03 L64 | ○ |
| C-28 | createDirectStreamでDStreamが生成される | E-03 L110-138 | ○ |

### ConsumerStrategy (E-04)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-29 | ConsumerStrategies.Subscribe(Iterable,Map,Map)でインスタンス生成 | E-04 L237-246 | ○ |
| C-30 | ConsumerStrategies.Subscribe(Iterable,Map)でoffset空Mapで生成 | E-04 L258-265 | ○ |
| C-31 | ConsumerStrategies.Subscribe(Collection,Map,Map)でインスタンス生成 | E-04 L280-285 | ○ |
| C-32 | ConsumerStrategies.Subscribe(Collection,Map)でoffset空Mapで生成 | E-04 L297-301 | ○ |
| C-33 | ConsumerStrategies.SubscribePattern(Pattern,Map,Map)でインスタンス生成 | E-04 L317-326 | ○ |
| C-34 | ConsumerStrategies.SubscribePattern(Pattern,Map)でoffset空Mapで生成 | E-04 L339-346 | ○ |
| C-35 | ConsumerStrategies.Assign(Iterable,Map,Map)でインスタンス生成 | E-04 L402-411 | ○ |
| C-36 | ConsumerStrategies.Assign(Iterable,Map)でoffset空Mapで生成 | E-04 L423-430 | ○ |
| C-37 | Subscribe.onStart - offsets空でconsumer返却 | E-04 L90-122 | ○ |
| C-38 | Subscribe.onStart - offsets指定時にseek実行 | E-04 L94-116 | ○ |
| C-39 | Subscribe.onStart - currentOffsets非空でcurrentOffsetsにseek | E-04 L94-98 | ○ |
| C-40 | Subscribe.onStart - KAFKA-3370ワークアラウンド | E-04 L100-113 | ○ |
| C-41 | Subscribe.executorKafkaParamsはkafkaParamsを返す | E-04 L88 | ○ |
| C-42 | SubscribePattern.onStart - パターンsubscribe | E-04 L147-176 | ○ |
| C-43 | SubscribePattern.onStart - currentOffsets非空でseek | E-04 L151-155 | ○ |
| C-44 | Assign.onStart - パーティションassign | E-04 L200-217 | ○ |
| C-45 | Assign.onStart - offsets指定時にseek | E-04 L209-213 | ○ |
| C-46 | Assign.onStart - currentOffsets非空でseek | E-04 L204-208 | ○ |

### LocationStrategy (E-05)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-47 | LocationStrategies.PreferBrokersでインスタンス返却 | E-05 L49-50 | ○ |
| C-48 | LocationStrategies.PreferConsistentでインスタンス返却 | E-05 L55-56 | ○ |
| C-49 | LocationStrategies.PreferFixed(Scala Map)でインスタンス返却 | E-05 L62-63 | ○ |
| C-50 | LocationStrategies.PreferFixed(Java Map)でインスタンス返却 | E-05 L69-70 | ○ |

### KafkaDataConsumer / InternalKafkaConsumer (E-06)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-51 | InternalKafkaConsumer.get - 正常なオフセット取得 | E-06 L132-164 | ○ |
| C-52 | InternalKafkaConsumer.get - バッファヒット（連続offset） | E-06 L134 | ○ |
| C-53 | InternalKafkaConsumer.get - バッファミス（非連続offset） | E-06 L134-138 | ○ |
| C-54 | InternalKafkaConsumer.get - タイムアウトでrequire例外 | E-06 L144-145 | ○ |
| C-55 | InternalKafkaConsumer.get - オフセット不一致でrequire例外 | E-06 L156-160 | ○ |
| C-56 | InternalKafkaConsumer.compactedStart - 正常開始 | E-06 L170-178 | ○ |
| C-57 | InternalKafkaConsumer.compactedStart - seekスキップ | E-06 L173 | ○ |
| C-58 | InternalKafkaConsumer.compactedNext - 正常取得 | E-06 L185-194 | ○ |
| C-59 | InternalKafkaConsumer.compactedNext - require例外 | E-06 L189-191 | ○ |
| C-60 | InternalKafkaConsumer.compactedPrevious - 正常巻き戻し | E-06 L201-203 | ○ |
| C-61 | InternalKafkaConsumer.compactedPrevious - NoSuchElementException | E-06 L201-203 | ○ |
| C-62 | InternalKafkaConsumer.close - 正常クローズ | E-06 L126 | ○ |
| C-63 | InternalKafkaConsumer.toString - 文字列表現 | E-06 L108-113 | ○ |
| C-64 | KafkaDataConsumer.init - キャッシュ初期化 | E-06 L241-279 | ○ |
| C-65 | KafkaDataConsumer.init - 重複初期化防止 | E-06 L245 | ○ |
| C-66 | KafkaDataConsumer.acquire - 新規キャッシュ取得 | E-06 L326-331 | ○ |
| C-67 | KafkaDataConsumer.acquire - キャッシュヒット（未使用） | E-06 L337-342 | ○ |
| C-68 | KafkaDataConsumer.acquire - キャッシュヒット（使用中）で新規NonCached | E-06 L332-336 | ○ |
| C-69 | KafkaDataConsumer.acquire - useCache=falseでNonCached | E-06 L321-325 | ○ |
| C-70 | KafkaDataConsumer.acquire - 再試行でキャッシュ無効化 | E-06 L301-320 | ○ |
| C-71 | KafkaDataConsumer.acquire - 再試行時使用中consumerのmarkedForClose | E-06 L308-309 | ○ |
| C-72 | CachedKafkaDataConsumer.release - 正常リリース | E-06 L346-357 | ○ |
| C-73 | CachedKafkaDataConsumer.release - markedForCloseでクローズ&削除 | E-06 L352-354 | ○ |
| C-74 | NonCachedKafkaDataConsumer.release - close呼び出し | E-06 L231 | ○ |
| C-75 | キャッシュLRU退避(未使用エントリ削除) | E-06 L250-277 | ○ |
| C-76 | キャッシュLRU退避(使用中エントリ保護) | E-06 L262 | ○ |

### KafkaRDD (E-07)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-77 | auto.offset.reset != "none"でrequire例外 | E-07 L59-62 | ○ |
| C-78 | enable.auto.commit = trueでrequire例外 | E-07 L64-67 | ○ |
| C-79 | getPartitionsでKafkaRDDPartition配列生成 | E-07 L82-86 | ○ |
| C-80 | getPartitions - 空配列 | E-07 L82-86 | ○ |
| C-81 | count - compacted=falseでoffsetRanges合計 | E-07 L88-93 | ○ |
| C-82 | count - 全countが0で0 | E-07 L88-93 | ○ |
| C-83 | isEmpty - count > 0でfalse | E-07 L106-111 | ○ |
| C-84 | isEmpty - count == 0でtrue | E-07 L106-111 | ○ |
| C-85 | countApprox - compacted=falseでPartialResult | E-07 L95-104 | ○ |
| C-86 | take - 指定件数取得 | E-07 L113-143 | ○ |
| C-87 | take - num < 1で空配列 | E-07 L116-117 | ○ |
| C-88 | take - 全パーティション空で空配列 | E-07 L123-124 | ○ |
| C-89 | compareExecutors - 異なるホスト | E-07 L152-159 | ○ |
| C-90 | compareExecutors - 同一ホスト | E-07 L155-156 | ○ |
| C-91 | compute - fromOffset < untilOffsetでイテレータ | E-07 L186-221 | ○ |
| C-92 | compute - fromOffset == untilOffsetで空イテレータ | E-07 L189-192 | ○ |
| C-93 | compute - fromOffset > untilOffsetでrequire例外 | E-07 L188 | ○ |
| C-94 | compute - compacted=trueでCompactedKafkaRDDIterator | E-07 L197-208 | ○ |
| C-95 | KafkaRDDIterator.hasNext - requestOffset < untilOffset | E-07 L254 | ○ |
| C-96 | KafkaRDDIterator.hasNext - requestOffset == untilOffset | E-07 L254 | ○ |
| C-97 | KafkaRDDIterator.next - 正常取得とインクリメント | E-07 L256-263 | ○ |
| C-98 | KafkaRDDIterator.next - NoSuchElementException | E-07 L257-259 | ○ |
| C-99 | CompactedKafkaRDDIterator.next - 正常取得 | E-07 L299-314 | ○ |
| C-100 | CompactedKafkaRDDIterator.next - 終端でokNext=false | E-07 L304-305 | ○ |
| C-101 | CompactedKafkaRDDIterator.next - NoSuchElementException | E-07 L300-302 | ○ |

### DirectKafkaInputDStream (E-08)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-102 | consumer() - 初回でKafkaConsumer初期化 | E-08 L72-78 | ○ |
| C-103 | consumer() - 2回目で同一インスタンス | E-08 L72-78 | ○ |
| C-104 | getPreferredHosts - PreferBrokersでbroker情報 | E-08 L105-111 | ○ |
| C-105 | getPreferredHosts - PreferConsistentで空Map | E-08 L108 | ○ |
| C-106 | getPreferredHosts - PreferFixedで指定hostMap | E-08 L109 | ○ |
| C-107 | maxMessagesPerPartition - rateController無効 | E-08 L131-164 | ○ |
| C-108 | maxMessagesPerPartition - rateController有効 | E-08 L131-164 | ○ |
| C-109 | maxMessagesPerPartition - レート0でNone | E-08 L155-163 | ○ |
| C-110 | maxMessagesPerPartition - initialRate使用 | E-08 L133-136 | ○ |
| C-111 | clamp - 制限内オフセット | E-08 L218-227 | ○ |
| C-112 | clamp - 制限なし(None)でそのまま | E-08 L226 | ○ |
| C-113 | latestOffsets - 最新オフセット取得 | E-08 L191-215 | ○ |
| C-114 | latestOffsets - 新パーティション追加 | E-08 L197-210 | ○ |
| C-115 | latestOffsets - パーティション取消でIllegalStateException | E-08 L200-207 | ○ |
| C-116 | commitAsync(Array) - キュー追加 | E-08 L283-285 | ○ |
| C-117 | commitAsync(Array, Callback) - キュー追加+callback | E-08 L292-295 | ○ |
| C-118 | commitAll - 全offset一括コミット | E-08 L297-310 | ○ |
| C-119 | commitAll - 同一TPの最大offset選択 | E-08 L303 | ○ |
| C-120 | commitAll - 空キューでcommitAsync呼ばれない | E-08 L307-309 | ○ |
| C-121 | start - currentOffsetsが空で初期化 | E-08 L260-268 | ○ |
| C-122 | start - currentOffsetsが非空で上書きしない | E-08 L263 | ○ |
| C-123 | stop - consumerクローズ | E-08 L270-274 | ○ |
| C-124 | stop - kc=nullでエラーなし | E-08 L271 | ○ |
| C-125 | CheckpointData.update - batchForTime更新 | E-08 L318-323 | ○ |
| C-126 | CheckpointData.restore - generatedRDDs復元 | E-08 L328-342 | ○ |
| C-132 | paranoidPoll - メッセージ返却時にseek補正 | E-08 L170-186 | ○ |
| C-133 | paranoidPoll - メッセージ空でseek不要 | E-08 L170-186 | ○ |
| C-134 | compute - KafkaRDD生成とInputInfoTracker報告 | E-08 L229-258 | ○ |
| C-135 | compute - currentOffsets更新とcommitAll | E-08 L255-257 | ○ |
| C-136 | persist - エラーログ出力 | E-08 L80-84 | ○ |

### PerPartitionConfig (E-09, E-10)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-127 | DefaultPerPartitionConfig.maxRatePerPartition設定値返却 | E-09 L42, E-10 L57-61 | ○ |
| C-128 | DefaultPerPartitionConfig.maxRatePerPartitionデフォルト0 | E-10 L61 | ○ |
| C-129 | DefaultPerPartitionConfig.minRatePerPartition設定値返却 | E-09 L43, E-10 L63-67 | ○ |
| C-130 | DefaultPerPartitionConfig.minRatePerPartitionデフォルト1 | E-10 L67 | ○ |
| C-131 | PerPartitionConfig.minRatePerPartitionデフォルト1 | E-09 L34 | ○ |

### KafkaRDD 追加 (E-07)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-137 | KafkaRDD.persist - エラーログ出力 | E-07 L76-80 | ○ |
| C-138 | getPreferredLocations - preferredHostsに基づくExecutor選択 | E-07 L161-178 | ○ |
| C-139 | getPreferredLocations - executors空で空Seq | E-07 L171-172 | ○ |
| C-140 | getPreferredLocations - preferredHostsなしで一貫選択 | E-07 L169-177 | ○ |

### 根拠なしの主張
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-104 | getPreferredHosts(PreferBrokers)でbroker情報取得 | E-08 L86-103, ただしgetBrokersはKafkaブローカー接続依存 | △ |
| C-113 | latestOffsetsで最新オフセット取得 | E-08 L191-215, ただしKafkaブローカー接続依存 | △ |
| C-121 | start時のcurrentOffsets初期化 | E-08 L260-268, ただしKafkaブローカー接続依存 | △ |
| C-134 | compute時のKafkaRDD生成 | E-08 L229-258, ただしStreamingContext依存 | △ |

## 4) 不足情報（Unknown / Missing）
- getBrokers, latestOffsets, start, computeの各メソッドはKafkaブローカーへの実接続やStreamingContextの完全初期化に依存するため、単体テストではモックが必須
  - 候補：MockKafkaConsumer / embedded Kafka / StreamingContextテスト用ユーティリティ
- DirectKafkaInputDStream.paranoidPollはprivateメソッドのため直接テスト不可
  - 候補：compute経由の間接テスト / リフレクション / テスト用サブクラス
- キャッシュのremoveEldestEntryは内部クラスのオーバーライドであり、テストにはキャッシュを直接操作する必要がある
  - 候補：KafkaDataConsumer.cacheフィールドへの直接アクセス（package privateスコープ）

## 5) リスクフラグ（レビュー観点）
- **リスク1 (中)**: KafkaDataConsumer.acquireのスレッドセーフティテストは本テストケース一覧に含まれていない。synchronizedメソッドの並行テストは統合テストで実施すべき
- **リスク0 (低)**: OffsetRange, KafkaRDDPartitionは純粋なデータクラスであり、テストケースの信頼度は高い
- **リスク1 (中)**: DirectKafkaInputDStream.maxMessagesPerPartitionのバックプレッシャーロジックは複雑な計算を含み、エッジケースの見落としがある可能性
- **リスク0 (低)**: KafkaUtils.fixKafkaParamsは副作用のある関数だが、ロジックが明確で検証しやすい

## 6) レビュアーチェックリスト（最小）
- [ ] OffsetRange.count()の境界値テスト（fromOffset > untilOffsetのケース）が追加で必要か確認
- [ ] KafkaDataConsumer.acquire のスレッドセーフティに関するテストケースの追加要否を検討
- [ ] DirectKafkaInputDStream.maxMessagesPerPartitionの計算ロジックで、totalLag=0のゼロ除算ケースのテスト追加要否を確認
- [ ] Kafka接続依存のテスト（getBrokers, latestOffsets等）のモック戦略が適切か確認
- [ ] CompactedKafkaRDDIteratorのgap（compactedトピックのオフセットギャップ）を考慮したテストケースの追加要否を確認
- [ ] ConsumerStrategy.setAuthenticationConfigIfNeededのセキュリティ設定に関するテストケースの追加要否を確認
