Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
マイコンでもRustのtestがしたい その2/KernelVM Tokyo 18
Search
Toshifumi NISHINAGA
August 09, 2025
Programming
2.7k
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
マイコンでもRustのtestがしたい その2/KernelVM Tokyo 18
Toshifumi NISHINAGA
August 09, 2025
More Decks by Toshifumi NISHINAGA
See All by Toshifumi NISHINAGA
マイコンでもRustのtestがしたい/KernelVM Kansai 11
tnishinaga
1
1.9k
BareMetalで遊ぶRaspberry Pi 5 PCIe編/KernelVM Tokyo17
tnishinaga
2
3.9k
probe-rsの紹介と最近の貢献紹介/CELF-02-03
tnishinaga
1
850
SecurityCamp2023基板作るコース講義資料/Security Camp 2023 Lecture Materials
tnishinaga
8
2.8k
RP2040のPIOを使う話/KernelVM Hokuriku 6
tnishinaga
4
9.1k
JTAGでArmプロセッサをデバッグする方法のつづき/KernelVM_Tokyo16
tnishinaga
0
760
CMSIS-DAPの概要と使い方/KernelVM Online5
tnishinaga
1
2.5k
JTAGでarmプロセッサをデバッグする話/KernelVM Online4
tnishinaga
5
4k
ARM入門/arm introduction
tnishinaga
14
14k
Other Decks in Programming
See All in Programming
Workers Cache を知る
syumai
0
130
LoopHub - ローカルで動く GitHub で、AI と共同開発
jugyo
1
560
Verilogで学ぶCPU自作入門.pdf
uyuki234
1
390
WebAssembly in Android Apps 〜 WASMはJNIの夢を見るか
keiji
1
110
App Storeの外へ──日本のiOSサイドローディング入門 for iOSDC Japan 2026
yuukiw00w
0
230
そのリトライ、死んだコネクションを使い回していませんか ── GoのHTTPクライアントとHTTP/2を実プロダクト障害から学び直す
myus4a
0
200
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
250
AWS DevOps Agentで インシデント対応をAIに任せたい
honmarkhunt
7
3.1k
iOSDC Japan 2026 - Swiftで作って学ぼう!データベース自作入門
kaseken
2
280
市販E-Readerを乗っ取れ 〜Embedded Swiftで電子ペーパーガジェットを制御する〜
trickart
0
200
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
270
setup-vp GitLab対応の裏側
naokihaba
0
120
Featured
See All Featured
Leveraging LLMs for student feedback in introductory data science courses - posit::conf(2025)
minecr
1
400
What the history of the web can teach us about the future of AI
inesmontani
PRO
1
700
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
130k
GraphQLの誤解/rethinking-graphql
sonatard
75
12k
Claude Code どこまでも/ Claude Code Everywhere
nwiizo
67
58k
Building the Perfect Custom Keyboard
takai
2
880
Highjacked: Video Game Concept Design
rkendrick25
PRO
1
460
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
2
560
Visual Storytelling: How to be a Superhuman Communicator
reverentgeek
2
670
Ruling the World: When Life Gets Gamed
codingconduct
0
340
Odyssey Design
rkendrick25
PRO
2
810
For a Future-Friendly Web
brad_frost
183
10k
Transcript
マイコンでも Rustのtestがしたい その2 @tnishinaga(CVついなちゃん) 2025/08/09 KernelVM@Tokyo 18 2025/05/11 1
前回のおさらい • マイコン(no_std)でもRustのテストをしたいなら、embedded- testを使うと良い • probe-rs + embedded-test • https://crates.io/crates/embedded-test
• いいところ • std環境のtestとほぼ同じ書き方ができる • panicするテスト(should panic)が書ける 2025/05/11 2
今日の目的 • 大目的 • no_std環境でもstd環境のcargo test並のテストがしたい • 中目的 • std環境のcargo
testがどのような仕組みで動いているかを知る • no_std環境では今最もstd環境に近いtestが実現できるprobe-rs+embedded- testがどうやってその機能を実現しているかを深堀りする • 小目的 • cargo testはどうやってテストの成否を判定しているのか • probe-rsとembedded-testはそれぞれ何をやっているか • なぜshould_panicテストができるのか • custom test harness では使えないのになぜ使えるの? 2025/05/11 3
cargo testはどうやってテスト の成否を判定しているのか 2025/05/11 4
cargo testはどうやってテストの成否を判 定しているのか • embedded-testの詳細を理解するために、まずはcargo testが何 をしているかを知る 2025/05/11 5
std Rustのテスト • unit test • ソースコード内に testコードを追記 するだけ •
integration test • tests/*.rs にテスト を書く • doc test • コードのドキュメ ント内にテストが かける(!?) • 今回は省略 参考: https://doc.rust-lang.org/rust-by- example/testing/integration_testing.html unit test integration test 2025/05/11 6 コード: https://github.com/tnishinaga/20250511_kernelvm_kansai_sample/tree/main/no01_std_tests
cargo test実行の様子 2025/05/11 7
cargo test実行結果 unit test 部分 integration test 部分 結果発表 成功時に
0を返す 2025/05/11 8
cargo testを実行すると何が起こるのか • テスト用バイナリを生成する • rustcにtest用オプション(--test)を渡してビルド(※) • テスト用バイナリを実行する • 個別のテストの成否はここで集計
• report形式の変更等もテスト用バイナリの担当 • テスト用バイナリの終了コードを見てTestの成否を判断 • cargo testは各ユニットテストの実行や集計等には関与していない • テスト用バイナリ(正確にはtest crate) の機能 • 前回のK/VMで紹介した内容は誤り 2025/05/11 9 ※: cargo build --tests --lib -vvv するとコンパイルオプションが取れる
cargo testのコード確認 1. run_tests内で run_unit_testが呼ばれる 2. run_unit_test内ではtest 用バイナリをビルドし てexecしているだけ 2025/05/11
10 https://github.com/rust- lang/cargo/blob/c24e1064277fe51ab7 2011e2612e556ac56addf7/src/cargo/o ps/cargo_test.rs#L76 ① ②
cargo testの動作確認 • 目的 • cargo testがテストの実行と終了コードの確認しかしてないことを確認 する • 方法
• runnerにexit 0を実行するshell scriptを登録してcargo testを実行する • cargoにはrunnerがセットされている場合はrunnerを使ってバイナリを実行する仕 組みがあるので、これを使う • 例: cargo run時にprobe-rsを使ってプログラムを書き込んで実行させるとか • cargo testの実装から読み取った挙動 • 何もテストが実行されていなくてもTestにPassしたと出てくるはず • exit 1に書き換えればFailするはず 2025/05/11 11
動作確認結果 • exit 0を返すだけの shell scriptを動かす とtestが成功する • exit 1を返すと失敗に
なる • よって、cargo testは 終了コードしか見て いない 2025/05/11 12
テスト用バイナリ単体の実行結果確認 • cargo test実行時にビルドされる バイナリを直接実行してみる • テストの集計等をテスト用バイナ リ側がやってるとわかるはず • 実行結果
• テスト用バイナリがテストの実施 ・集計等を担っていた 2025/05/11 13
テスト用バイナリの生成機序 • cargo testがrustcに `--test` オプションを渡してビルドしている • rustcは `--test` オプションを渡されると以下を行う
• cfg(test)を有効化する • https://github.com/rust- lang/rust/blob/6b00bc3880198600130e1cf62b8f8a93494488cc/compiler/rustc_session /src/config/cfg.rs#L295-L298 • testを実行するmain関数を展開 • 多分このあたりでやっている • https://github.com/rust- lang/rust/blob/master/compiler/rustc_builtin_macros/src/test_harness.rs#L287 • cfg(test)よりmod testsが有効化される • mod tests内の `#[test]` マクロが展開され、test実行用の定義が追加 される 2025/05/11 14
テスト用マクロ展開 実 行 ハーネスを生成 (cargo expand --lib --tests) マクロ展開部 生成されたtest
harness 2025/05/11 15
展開されたコードとtest crateがやること • 展開されたコード • 各unit test用関数に対応したTestDescAndFn型の定義を作る • HarnessはTestDescAndFnのsliceをtest_main_static関数に渡して実行する •
libtest側 • 受け取ったsliceを元にunit testの関数を呼び出して順次実行する • 実態はこのあたり • https://github.com/rust- lang/rust/blob/e05ab47e6c418fb2b9faa2eae9a7e70c65c98eaa/library/test/src/lib.rs#L284 • 引数が与えられると各種機能を提供する • 各unit testの一覧表示とか、出力形式の変更とか • IDE側のテストの単体実行などを実現する際に使われている • この機能を実装すると、各種IDE側との親和性が高まる(= libtest compatibleになる) 2025/05/11 16
この節のまとめ • cargo testはテストバイナリのビルドと実行を行っている • テストの実態はtest crateが担っている 2025/05/11 17
probe-rs+embedded-testのテス トの仕組み 2025/05/11 18
前回のおさらい • no_std環境ではstd環境のテストができない • test時に生成されるハーネスがstdに依存しているため • custom test frameworksを使えばno_std環境でもテストはできる が、一部機能が使えない
• panicするテストとか • probe-rs+embedded-testを使えばno_std環境でもstd環境並みの テストができる • panicするテストも書ける • なぜ? 2025/05/11 19
probe-rsを使ったcargo testのOverview 2025/05/11 20 cargo test (1) probe-rs run \
<test options> probe-rs (test mode) マイコン (2) イメージ書き込み (3) 実行 & 結果(json) (4) 成否判定 集計 表示 (5) exit codeを返す (0)テストコードのビルド probe-rsとマイコン間の文字入出力や終了コードのやり取りにはsemihostingを用いる
probe-rsを使ったcargo testのOverview 2025/05/11 21 cargo test (1) probe-rs run \
<test options> probe-rs (test mode) マイコン (2) イメージ書き込み (3) 実行 & 結果(json) (4) 成否判定 集計 表示 (5) exit codeを返す (0)テストコードのビルド probe-rsとマイコン間の文字入出力や終了コードのやり取りにはsemihostingを用いる
マイコンで動くプログラムの動作 • 以下の機能をembedded-test crateが提供している • semihosting経由で受け取った引数に応じて以下を行う • テストのリストを返す(list) • 指定されたテストを実行する(run)
• テストの成否等をsemihosting経由で返す 2025/05/11 22
embedded-test crateの機能 • ビルド時 • マクロ展開をしてno_stdで動くテスト用バイナリを作る • 説明省略 • テストの実行は
embedded_test::export::run_testsで行う • 動作時(embedded_test::export::run_testsの機能) • 引数に応じて以下の2機能を提供する • list • 各テストの一覧をsemihosting経由で出力する • run <テスト名> • 指定されたテストを実行し、成否をsemihostingで返す • 各コマンド実行後は終了する • 複数のテストを実行する機能はない。そこは外部のプログラムだより。 2025/05/11 23
マクロ展開 2025/05/11 24 • #[embedded_test::tests] マクロが以下の展開を行 う • #[init] •
#[test] • #[should_panic] • #[ignore] • #[timeout] • 展開コードはこのあたり • https://github.com/probe- rs/embedded- test/blob/81857b62554196 724ea81d0a9d1020e7bc60 41a0/macros/src/lib.rs#L1 18-L138
マクロ展開されたコードがやっているこ と • 以下の定義を生成 • テスト用main関数 • __embedded_test_entry と、そこから呼ばれる __embedded_test_start
• おもしろポイント • リンカスクリプトに定義されたシンボル経由で__embedded_test_startを呼ぶこと でembedded-test.xの不足をコンパイル時に検出している • 最後に embedded_test::export::run_testsでテストを実行する • 各種テスト用情報の入ったheapless::vec::Vec • 関数名とか関数ポインタとか 2025/05/11 25
embedded_test::export::run_testsの機能 • semihosting経由で引数を受け取って出力を返す • 実行結果(成功・失敗)をsemihosting経由で伝える • 成功時はexit(0)を返す • https://github.com/probe-rs/embedded- test/blob/81857b62554196724ea81d0a9d1020e7bc6041a0/src/export.rs#L84C12-
L84C30 • 失敗時または異常終了時はabortが返る • 失敗時(各テストは check_outcome関数経由で実行され、結果が返る) • https://github.com/probe-rs/embedded- test/blob/81857b62554196724ea81d0a9d1020e7bc6041a0/src/export.rs#L105-L113 • 異常終了時(panic) • https://github.com/probe-rs/embedded- test/blob/81857b62554196724ea81d0a9d1020e7bc6041a0/src/lib.rs#L18 2025/05/11 26
probe-rsを使ったcargo testのOverview 2025/05/11 27 cargo test (1) probe-rs run \
<test options> probe-rs (test mode) マイコン (2) イメージ書き込み (3) 実行 & 結果(json) (4) 成否判定 集計 表示 (5) exit codeを返す (0)テストコードのビルド probe-rsとマイコン間の文字入出力や終了コードのやり取りにはsemihostingを用いる
probe-rs run(test mode)の機能 • probe-rs runにtest用オプションを与えるとtest modeで動作する • https://github.com/probe-rs/probe- rs/blob/c6dae5f3e0db1af0e159f6e6aff12df33d8ab447/probe-rs-
tools/src/bin/probe-rs/cmd/run.rs#L285 • test modeでは以下の機能を提供する • テストの実行・制御 • テスト結果の収集・表示 2025/05/11 28
テストモードのoverview 1. マイコンへのプログラムの書き込み & 実行 2. マイコン側からテストの一覧を取得 1. semihosting経由で list
コマンドを実行してテスト関数一覧を取得 • SessionInterface::list_testsとlist_tests_impl関数が担当 3. テスト一覧に対し、以下を繰り返し行う(foreach) 1. マイコンをリセット • https://github.com/probe-rs/probe-rs/blob/71d09fd6807353c49fddd98f28966e0d7e94b67e/probe-rs- tools/src/bin/probe-rs/rpc/functions/test.rs#L229 2. semihosting経由で run <テスト名> を実行 • https://github.com/probe-rs/probe-rs/blob/71d09fd6807353c49fddd98f28966e0d7e94b67e/probe-rs- tools/src/bin/probe-rs/rpc/functions/test.rs#L260 3. 実行結果を取得し、成否を画面に表示 4. 実行結果をexit codeとして返す • 成功時は0, 失敗時はそれ以外 • cargo testはこの値を元に成否を判定 2025/05/11 29
ここで気になったこと • どうやってstd環境のtestのような表示を実現しているか • panicするテストはどうやって実現しているか 2025/05/11 30
テストの実行と画面表示の方法 • probe-rsはlibtest_mimicを用いて cargo test とほぼ同じ出力を提供し ている • 右図参照 •
probe-rsのやっていること • テストの処理をclosureにしてTrial型の リストを作成 • https://github.com/probe-rs/probe- rs/blob/c6dae5f3e0db1af0e159f6e6aff12 df33d8ab447/probe-rs- tools/src/bin/probe-rs/util/cli.rs#L591- L623 • libtest_mimic::runで全テストを実行・ 結果表示 • https://github.com/probe-rs/probe- rs/blob/c6dae5f3e0db1af0e159f6e6aff12 df33d8ab447/probe-rs- tools/src/bin/probe-rs/util/cli.rs#L540 2025/05/11 31
panicするテスト(should_panic)の実現方法 • 通常はマイコン側がpanicしたらprobe-rsはテスト失敗 判定をする • マイコン側はsemihosting経由でabortを返す • probe-rsは以下の機序でpanic時にテストが失敗したと判定 • handle_halt関数はabortを受け取ったらTestOutcome::Panicを返す
• https://github.com/probe-rs/probe- rs/blob/c6dae5f3e0db1af0e159f6e6aff12df33d8ab447/probe-rs- tools/src/bin/probe-rs/rpc/functions/test.rs#L395-L397 • outcomeが期待通り(outcome == expected_outcome(Pass))でないな ら失敗 • https://github.com/probe-rs/probe- rs/blob/c6dae5f3e0db1af0e159f6e6aff12df33d8ab447/probe-rs- tools/src/bin/probe-rs/rpc/functions/test.rs#L265-L268 • マイコン側の関数に#[should_panic]がついている場合は 成功にする • should_panicがtrueの場合はexpected_outcomeがPanicにな る • (outcome == expected_outcome) が true になるので成功とな る 2025/05/11 32 probe-rsのテスト成否判定部分 outcomeが期待通りの場合は成功
should_panicの情報はどうやってマイコン からprobe-rs側に渡るの? • マイコン側のlistコマンド実行結果経由でprobe-rsに渡る • 出力例 • INFO tests available:
[Test { name: "tests::test_add", function: 0xe5, should_panic: false, ignored: false, timeout: None }] 2025/05/11 33
probe-rs+embedded-testのテストの仕組み • マイコン側(embedded-test)は以下の2機能のみを提供する • テストの一覧表示 • 指定されたテストの実行 • probe-rs(とlibtest_mimic)がその他の部分をすべて担当する •
テスト一覧(と詳細情報)取得 • 各テストの実行 • 実行結果取得 • 画面表示(libtest_mimicの機能) • 終了コード出力 • マイコン・probe-rs間の通信にsemihostingを用いる 2025/05/11 34
今回のまとめ • cargo testは以下しか行っていない • テスト用バイナリのビルド • 上記バイナリの実行と終了コードのチェック • 各テストの実行制御や結果の表示・集計はtest
crate側で行っている • probe-rs + embedded-testは協力してstd環境のcargo test相当の 機能を提供している • embedded-test • マイコン側でテストリストの出力、指定されたテストの実行を行う • probe-rs • テストの実行・実行後のリセット・結果の集計等を行う 2025/05/11 35
おまけ 2025/05/11 36
probe-rs + embedded_testが使えない環境 でこの機能を実現するには? • x86_64環境でのOS開発ではprobe-rs+embedded_testが使えない • semihosting機能がないため • x86_64+qemuならexit
deviceを使って模擬できるかも • マイコン側の機能はcustom test flameworksで対応できるかも • probe-rs側の機能は新規開発が必要そう • コストとメリットを天秤にかけて要検討 • コスト • 様々な開発が必要 • メリット • should_panicテスト等ができる • テスト結果の表示がきれいになる 2025/05/11 37
probe-rs + embedded_testが使えない環境 でこの機能を実現するには? 2 • 実機のx86_64マシンで自作OS等をテストするには? • 以下の仕組みを用意して、制御ソフトを作ればできるかも? •
リセット機能 • IoTコンセントとか? • プログラムのロード機能 • uefiのhttp bootとか? • 入出力 • UARTとか? (UART使えるお手頃x86マシンって今もあるのだろうか?) 2025/05/11 38