test
目的
- stdlib と tutorials で共通に使う
assert_*/check_*/finish_checksを提供し、失敗 を trap ではなくResult<(),str>として表現 します。 単発 の検査 と、複数 検査 を継続 実行 する collectable な検査 の両方 を同 じモジュールで扱 います。
実装
単発 のassert_*は対応 するcheck_*の結果 を受 け、ErrのときだけFAIL:形式 の表示 を行 ったうえでResult::Errを返 します。集約 検査 はVec<Result<(),str>>を保持 し、finish_checksは表示 せずにResult<(),str>へ畳 みます。表示 が必要 な test case はchecks_print_machine/checks_print_humanを明示的 に呼 びます。
注意
失敗 の最終 判定 はresult_exit_codeやchecks_exit_codeのような helper で i32 に落 とし、runner側 で比較 する前提 です。表示 は#target stdのときだけ行 います。std以外の target ではResultだけが返 ります。- reboot
後 は「明示的 に print する」方針 とし、checks_exit_codeは stdout を汚 しません。 - doctest は
使 い方 の保証 が目的であり、境界条件や回帰確認はtests/stdlib/*側で行います。
計算量
assert_*とcheck_*の単体判定は O(1) か、比較対象の長さに応じた O(n) です。- 集約 API は summary
文字列 構築 を含 むため、finish_checks全体 では O(n^2) になりえます。
test_str_eq
目的
- a と b の内容が同じなら true を返します。
実装
- 長さ一致を確認し、バイト単位で比較します。
注意
- UTF-8 のバイト列として比較します。
計算量
時間 : O(n)空間 : O(n)(再帰呼び出しぶん)
test_str_eq_loop
目的
- i を進めながら各バイトを比較します。
実装
- 一致なら再帰、差異があれば false を返します。
注意
- 呼び出し側で長さ一致を確認している前提です。
計算量
時間 : O(n)空間 : O(n)(再帰呼び出しぶん)
test_print_fail
目的
- msg を赤色で標準出力へ表示します。
実装
- ANSI 赤色コードで色付けして出力します。
注意
#target stdの表示 helper です。- 端末が ANSI に対応している必要があります。
計算量
時間 : O(n)空間 : O(n)
test_checked
目的
- "Checked "
付 きの成功 ログを色付 きで表示 し、Result::Ok ()を返 します。
実装
- 文字列を連結し、ansi_green で出力します。
注意
#target stdの表示 helper です。- 端末が ANSI に対応している必要があります。
計算量
時間 : O(n)空間 : O(n)
test_fail
Result::Err を
目的
- msg を
FAIL:形式 で表示 し、安全 にResult::Errとして失敗 を返 します。
実装
#target stdではtest_print_failを呼 び、そのあとResult::Err msgを返 します。
注意
- この helper
自体 は trap しません。最終 判定 は呼 び出 し側 が行 います。
計算量
時間 : O(n)空間 : O(n)
checks_new
目的
finish_checksに渡すVec<Result<(),str>>を空の状態で作ります。pushの型引数を毎回書かずに collectable な検査列を組み立てる入口として使います。
実装
new<Result<(),str>>を呼び、検査結果専用の空ベクタを返します。
注意
- 返り値は
Result<(),str>専用です。 - 以後の追加は
checks_pushを使うと型引数を書かずに済みます。
計算量
時間 : O(1)空間 : O(1)
使い方
#entry main
#target std
#import "std/test" as *
fn main <()*>i32> ():
let checks <Vec<Result<(),str>>> checks_new;
checks_exit_code checkschecks_push
目的
Result<(),str>をVec<Result<(),str>>に追加し、pipe で連結しやすい形を提供します。
実装
vec_push<Result<(),str>>を固定して呼び、pushの型推論詳細を利用者へ露出させません。
注意
- 検査そのものは
check_*側で評価済みであり、この関数は格納しかしません。 - 返り値は同じベクタなので、
|> checks_push ... |> checks_push ...と連結できます。
計算量
時間 : 償却 O(1)最悪 時間 : O(n)(再確保が起きる場合)空間 : 償却 O(1)
使い方
#entry main
#target std
#import "std/test" as *
fn main <()*>i32> ():
let checks <Vec<Result<(),str>>>:
checks_new
|> checks_push check true
|> checks_push check true
checks_exit_code checkscheck
Result<(),str> として
目的
assertと同じ条件判定を行い、その場で停止せずResult<(),str>として返します。- 複数の検査を
Vec<Result<(),str>>に集約して最後にまとめて判定したいときに使います。
実装
okが true ならOk(())、false なら固定メッセージ付きのErrを返します。
注意
- 失敗時に詳細な説明が必要なら、この関数ではなく
check_eq_i32やcheck_str_eqのような専用版を使ってください。 - この関数自体は何も表示しません。表示と最終失敗判定は
finish_checksが担当します。
計算量
時間 : O(1)空間 : O(1)
使い方
#entry main
#target std
#import "std/test" as *
fn main <()*>i32> ():
let checks <Vec<Result<(),str>>>:
checks_new
|> checks_push check true
|> checks_push check true
checks_exit_code checkscheck_eq_i32
i32 のResult<(),str> として
目的
expectedとactualの比較結果を即時停止ではなく値として返します。
実装
- 等しければ
Ok(())、異なればexpectedとactualを文字列化したメッセージ付きErrを返します。
注意
assert_eq_i32はこの関数の結果を受けてただちに失敗終了する薄いラッパです。- 失敗を複数件まとめたいときはこの関数を
Vec<Result<(),str>>に積んでください。
計算量
時間 : O(1)空間 : O(1)
使い方
#entry main
#target std
#import "std/test" as *
fn main <()*>i32> ():
let checks <Vec<Result<(),str>>>:
checks_new
|> checks_push check_eq_i32 10 add 4 6
|> checks_push check_eq_i32 3 sub 8 5
checks_exit_code checkscheck_ne
bool がResult<(),str> として
目的
aとbが同じなら詳細メッセージ付きErr、違えばOk(())を返します。
実装
- bool の組み合わせを分岐し、一致時だけ値を文字列化して失敗メッセージを組み立てます。
注意
- bool 専用です。
- true/false のどちらで一致したかを失敗メッセージに含めます。
計算量
時間 : O(1)空間 : O(1)
check_str_eq
Result<(),str> として
目的
- 文字列比較の結果を、直ちに停止せずに後段へ渡せる形で返します。
実装
test_str_eqで UTF-8 バイト列を比較し、不一致時だけ詳細メッセージを組み立てます。
注意
- 比較単位は Unicode の文字数ではなく UTF-8 のバイト列です。
- 長い文字列では、失敗メッセージ自体の生成にも連結コストがかかります。
計算量
時間 : O(n)空間 : O(n)(失敗時メッセージ生成ぶん)
使い方
#entry main
#target std
#import "std/test" as *
fn main <()*>i32> ():
let checks <Vec<Result<(),str>>>:
checks_new
|> checks_push check_str_eq "hello" concat "he" "llo"
checks_exit_code checkscheck_ok_i32
Result<i32,i32> が Ok であることを
目的
Result::Okを期待する検査を集約可能なResult<(),str>に変換します。
実装
matchでOk/Errを分け、Errの場合だけ失敗メッセージを返します。
注意
Result<i32,i32>専用です。Okの中身は返さず、成功・失敗だけを返します。
計算量
時間 : O(1)空間 : O(1)
check_err_i32
Result<i32,i32> が Err であることを
目的
Result::Errを期待する検査を集約可能なResult<(),str>に変換します。
実装
matchでOk/Errを分け、Okの場合だけ失敗メッセージを返します。
注意
Result<i32,i32>専用です。Errの中身は返さず、成功・失敗だけを返します。
計算量
時間 : O(1)空間 : O(1)
check_status_str
目的
Result<(),str>をok/err <msg>の安定 した summary片 へ変換 し、machine側 でも追跡 しやすくします。
実装
Okはokを返 し、Err msgはerrと msg を連結 して返 します。
注意
checks_summaryの内部 helper です。- msg をそのまま summary に
含 めるため、非常 に長 い失敗 文 は summary行 も長 くなります。
計算量
時間 : O(1)空間 : O(1)
checks_has_err_loop
Err を
目的
集約 済 み検査列 に失敗 があるかを線形 走査 で判定 します。
実装
Vecの backing store を 1回 だけ取 り出 し、raw data を添字 で走査 します。最初 のErrが見 つかった時点 で true を返 します。
注意
内部 helper です。checks_dataはVec<Result<(),str>>の data pointer、nは長 さです。
計算量
時間 : O(n)空間 : O(n)(再帰 )
checks_has_err
Err が
目的
最終 失敗 判定 の前 に、少 なくとも 1件 の失敗 があるかを調 べます。
実装
Vec<Result<(),str>>を temporary memory に保存 し、長さと data pointer を 1回 だけ取 り出 してchecks_has_err_loopへ渡 します。
注意
失敗 の詳細 は返 しません。詳細 表示 にはfinish_checksを使 ってください。
計算量
時間 : O(n)空間 : O(n)(再帰 )
checks_summary_loop
[ok,err <msg>,...]
目的
集約 済 み検査列 を、okとerr <msg>が並 ぶ summary文字列 へ変換 します。
実装
Vecの raw data を先頭 から順 に走査 し、check_status_strの結果 を必要 な区切 りとともに連結 します。
注意
失敗 件数 だけでなく、summary行 だけで各 失敗 理由 まで追 いたい場面 を想定 した helper です。
計算量
時間 : O(n^2)(文字列 連結 を繰 り返 すため)空間 : O(n)
checks_summary
[ok,err <msg>,...]
目的
複数 の検査 結果 を安定 した 1行 の文字列表現 へ畳 み、runner や log側 で扱 いやすくします。
実装
Vec<Result<(),str>>を temporary memory に保存 し、[から始 めてchecks_summary_loopで連結 します。
注意
- これは machine / log
向 けの安定 表現 です。人間 向 けの色付 き表示 はchecks_print_humanを使 います。
計算量
時間 : O(n^2)(文字列 連結 を繰 り返 すため)空間 : O(n)
checks_print_human_line
1
目的
[index] okまたは[index] err <msg>の形 で、1件 の検査 結果 を見 やすく表示 します。
実装
添字 部分 は灰色、okは緑、err <msg>は赤で表示 します。
注意
標準 出力 への表示 は#target stdのときだけ行 います。
計算量
時間 : O(m)(m は msg の長 さ)空間 : O(m)
checks_print_human_loop
Vec<Result<(),str>> を
目的
集約 済 み検査列 の全要素 を人間 向 けに並 べて表示 します。
実装
- raw data を
順 に走査 し、checks_print_human_lineへ 1件 ずつ渡 します。
注意
成功 case でも失敗 case でも全件 を表示 します。
計算量
時間 : O(n + s)(s は全 ての msg長 さの合計 )空間 : O(n)(再帰 )
checks_print_human
Vec<Result<(),str>> を
目的
Vec<Result<(),str>>を[index] ok / err <msg>の形 で全件 表示 し、人間 が成功 と失敗 を即座 に読 めるようにします。表示 後 も同 じVec<Result<(),str>>を返 し、その後 のchecks_exit_codeや追加 helper と合成 できるようにします。
実装
checksを temporary memory に保存 し、raw data をchecks_print_human_loopへ渡 したあと、同 じVec<Result<(),str>>を読 み戻 して返 します。
注意
#target std専用 です。- machine
向 けの安定 表現 が必要 ならchecks_summaryを使 います。
計算量
時間 : O(n + s)(s は全 ての msg長 さの合計 )空間 : O(n)(再帰 )
checks_print_machine
Vec<Result<(),str>> を machine
目的
- test case
側 で summary だけを stdout へ明示的 に出 したいときに使 います。 表示 後 も同 じVec<Result<(),str>>を返 し、その後 の処理 へ繋 げられるようにします。
実装
checksを temporary memory に保存 し、checks_summaryを計算 して失敗 があるときはFAIL:付き 、なければChecked付き で 1行 表示 します。最後 に同 じVec<Result<(),str>>を読 み戻 して返 します。
注意
finish_checksやchecks_exit_codeは自動 で表示 しません。stdout が必要 な test case ではこの helper を明示的 に呼 んでください。#target std専用 です。
計算量
時間 : O(n^2)(checks_summaryの構築 を含 む)空間 : O(n)
checks_print_report
test
目的
checks_push中 には何 も print せず、test本体 の末尾 で 1回 だけ明示的 に結果 を出 したい場合 の標準 helper を提供 します。
実装
checks_print_machineの後 にchecks_print_humanを呼 び、同 じVec<Result<(),str>>を返 します。
注意
checks_exit_codeとは別 です。stdout が必要 な test case だけ、return直前 でこの helper を呼 んでください。#target std専用 です。
計算量
checks_print_machineとchecks_print_humanの合計 に準 じます。
finish_checks
Result<(),str> に
目的
Vec<Result<(),str>>として集約 した検査 を最後 にまとめて評価 します。途中 の検査 は継続 しつつ、最後 に表示 なしで成功 /失敗 を値 として得 られます。
実装
checks_summaryで machine向 け summary を作 ります。失敗 が 1件 でもあればResult::Err summary、なければResult::Ok ()を返 します。- move model に
合 わせ、入力 のVec<Result<(),str>>は 1回 だけ memory に保存 してから helper へ渡 します。
注意
想定 用途 は<Vec<Result<(),str>>> new |> push check_* ...のような段階的 収集 です。- stdout へ
出 したい場合 はchecks_print_reportなどを test case側 で明示的 に呼 んでください。 - runner
連携 で終了 code が必要 な場合 はchecks_exit_codeを使 います。
計算量
時間 : O(n^2)(summary文字列 構築 を含 む)空間 : O(n)
使い方
#entry main
#target std
#import "std/test" as *
#import "core/math" as *
fn main <()*>i32> ():
let checks <Vec<Result<(),str>>>:
checks_new
|> checks_push check_eq_i32 3 add 1 2
|> checks_push check_str_eq "ok" "ok"
|> checks_push check_ok_i32 Result::Ok 7
checks_exit_code checksresult_exit_code
Result<(),str> を i32 の
目的
安全 なResult<(),str>表現 を、runner が比較 できる i32 に落 とします。
実装
Okなら 0、Errなら 1 を返 します。
注意
詳細 な失敗 内容 の表示 はtest_failやchecks_print_*helper が担当 します。
計算量
時間 : O(1)空間 : O(1)
checks_exit_code
目的
finish_checksの結果 をそのままmainの返 り値 へ繋 げられるようにします。
実装
finish_checksを呼 んでからresult_exit_codeへ渡 します。
注意
- stdout を
伴 う表示 は行 いません。必要なら test case側 でchecks_print_machine/checks_print_humanを呼 んでください。
計算量
finish_checksに準 じます。
assert
目的
- ok が false なら
FAIL:表示 つきのResult::Errを返 します。
実装
- if で分岐し、false なら test_fail を呼びます。
注意
- ok は bool である必要があります。
計算量
時間 : O(1)空間 : O(1)
使い方
#entry main
#target std
#import "std/test" as *
fn main <()*>i32> ():
let checks <Vec<Result<(),str>>>:
checks_new
|> checks_push assert true
|> checks_push assert eq 3 add 1 2
checks_exit_code checksassert_eq_i32
i32 の
目的
- expected と actual が等しいことを保証します。
実装
- eq の結果が false なら詳細メッセージを作って test_fail します。
注意
- i32 専用です。
計算量
時間 : O(1)空間 : O(1)
使い方
#entry main
#target std
#import "std/test" as *
#import "core/math" as *
fn main <()*>i32> ():
let checks <Vec<Result<(),str>>>:
checks_new
|> checks_push assert_eq_i32 6 add 1 5
|> checks_push assert_eq_i32 3 sub 10 7
checks_exit_code checksassert_ne
bool が
目的
- a と b が同じなら詳細メッセージを作って test_fail します。
実装
- a の値で分岐し、b との一致を確認します。
注意
- bool 専用です。
計算量
時間 : O(1)空間 : O(1)
使い方
#entry main
#target std
#import "std/test" as *
fn main <()*>i32> ():
let checks <Vec<Result<(),str>>>:
checks_new
|> checks_push assert_ne true false
|> checks_push assert_ne false true
checks_exit_code checksassert_str_eq
目的
- expected と actual が同じであることを保証します。
実装
- test_str_eq で比較し、false なら詳細メッセージを作って test_fail します。
注意
- UTF-8 のバイト列として比較します。
計算量
時間 : O(n)空間 : O(n)
使い方
#entry main
#target std
#import "std/test" as *
#import "alloc/string" as *
fn main <()*>i32> ():
let checks <Vec<Result<(),str>>>:
checks_new
|> checks_push assert_str_eq "prefix-suffix" concat "prefix-" "suffix"
|> checks_push assert_str_eq "true" from_bool true
checks_exit_code checksassert_ok_i32
Result が Ok であることを
目的
- Result::Ok を受け付け、Err なら詳細メッセージを作って test_fail します。
実装
- match で Ok/Err を分岐します。
注意
- Result<i32,i32> 専用です。
計算量
時間 : O(1)空間 : O(1)
使い方
#entry main
#target std
#import "std/test" as *
#import "core/result" as *
fn main <()*>i32> ():
result_exit_code assert_ok_i32 Result<i32,i32>::Ok 42assert_err_i32
Result が Err であることを
目的
- Result::Err を受け付け、Ok なら詳細メッセージを作って test_fail します。
実装
- match で Ok/Err を分岐します。
注意
- Result<i32,i32> 専用です。
計算量
時間 : O(1)空間 : O(1)
使い方
#entry main
#target std
#import "std/test" as *
#import "core/result" as *
fn main <()*>i32> ():
result_exit_code assert_err_i32 Result<i32,i32>::Err 7