internal/conformance の設計
設計目標
4 つのコーパスフロントエンドは、まったく異なるデータ(10 進の行、区間の文、MPFR の行、TestFloat のベクトル)について結果を報告し、Python のツール群はそれらをプロセスをまたいで集計します。「ケース」「合格」「スキップ」「シャード」が何を意味するかについて一致していなければ、公表される合計は比較できなくなります。internal/conformance はその語彙を一度だけ定めます。ケースごとの処理区分、恒等式が固定されたカウンタ、そして 1 つのシャード規則です。
数学的背景
結果とカウンタ
結果は組 であり、処理区分 (executable、diagnostic、legacy、unsupported)、合格ビット 、メッセージ からなります。結果のリスト に対し、カウンタベクトルを次のように定義します。
ここで は の単位ベクトルです。RunSummary::from_results は と を正確に計算し、呼び出し側から与えられた合計 を格納します。
シャード
と に対し、シャード は序数 を選択します。
設計上の判断
4 つの処理区分と 1 つの失敗の概念
失敗し得るのは executable の結果のみです。diagnostic、legacy、unsupported のスキップを区別することで、レポートは行が実行されなかった理由を示せます。diagnostic の行はテストではなく(失われる主張はない)、unsupported の行は欠けている機能であり(主張が失われる)、legacy の行は廃止された規約に従っています。success() は「失敗した executable のケースがない」ことを意味します。より厳格な判定は呼び出し側がその上に重ねます(ITL フロントエンドは診断でも失敗し、CLI はオプションで unsupported の行でも失敗します)。
ラウンドロビン方式のシャード
序数 をシャード に割り当てる方式は、合計を知る必要がなく、ストリーミング中に決定でき、隣接する(多くの場合コストが似た)ケースをシャード間に分散させます。検証(try_new)は使用から分離されているため、selects は 1 回の比較で済みます。
total は外部から与え、merge は最大値をとる
シャーディング前のケース数を知っているのは呼び出し側であり、シャードの結果リストではありません。1 回の実行のすべてのシャードは同じ合計 を報告するため、merge で最大値をとれば分割数にかかわらず が返りますが、総和をとると 回数えてしまいます。
1 始まりの位置
SourceLocation は行と列を 1 以上に切り詰めるため、整形された診断(file:line:column: message)は、「不明」を表すために 0 を渡す呼び出し側に対しても、常にエディタで有効な位置になります。
正しさ/不変条件
カウンタの恒等式。 すべてのサマリーについて、、、 が成り立ちます。 の各加数は各恒等式のちょうど一方の辺に 1 を加えるため、これらは from_results に対して成り立ちます。merge はカウンタを成分ごとに加算し、これは線形な恒等式を保存します。
シャードは序数を分割する。 すべての は を法としてちょうど 1 つの剰余を持つため、 は互いに素で を覆います。最初の 個の序数のうち、シャード が受け取る数は
であり、したがってシャードのサイズの差は高々 1 です。
シャードを統合すると逐次実行のカウンタが得られる。 は、連結に関するリストから へのモノイド準同型です。 であり、同様に です。各シャードの結果が逐次実行の結果を に制限したものであれば(ケースの結果が他のケースに依存しない限り常に成り立ちます)、
はカウンタも合計も等しくなります。異なるのは結果リストの順序(シャードごとにまとめられる)だけです。
不変性。 サマリーは構築時と results() の呼び出し時に結果の配列をコピーするため、呼び出し側が後からサマリーを変更することはできません。
却下した代替案
- 単一の「skipped」カウンタ。 テストでないものと欠けている機能の違いが隠れてしまいますが、それこそ適合性の主張が明示しなければならないものです。
- 連続した範囲のシャード。 事前に合計が必要であり、コストの高いファイルが 1 つのシャードに集中します。
- フロントエンドの公開 API でこれらの型を使うこと。 フロントエンドはこれらをラップするので、このパッケージは公開 API を壊さずに進化できます。
境界
- コーパスの解析、実行、IO、JSON は扱いません。それらはフロントエンドと internal/runner_cli の役割です。
- 時間計測や性能のデータは扱いません。
- 結果の
passedビットがその処理区分と一致しているかは検査しません。 - 内部用です。
Luna-Flow/floatingの外部からはインポートできず、安定性の約束もありません。