لsphinx.addnodesdocument)}( rawsourcechildren]( translations LanguagesNode)}(hhh](h pending_xref)}(hhh]docutils.nodesTextEnglish}parenthsba attributes}(ids]classes]names]dupnames]backrefs] refdomainstdreftypedoc reftarget /rust/testingmodnameN classnameN refexplicitutagnamehhh ubh)}(hhh]hChinese (Traditional)}hh2sbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget /translations/zh_TW/rust/testingmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hItalian}hhFsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget /translations/it_IT/rust/testingmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hJapanese}hhZsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget /translations/ja_JP/rust/testingmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hKorean}hhnsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget /translations/ko_KR/rust/testingmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hPortuguese (Brazilian)}hhsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget /translations/pt_BR/rust/testingmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hSpanish}hhsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget /translations/sp_SP/rust/testingmodnameN classnameN refexplicituh1hhh ubeh}(h]h ]h"]h$]h&]current_languageChinese (Simplified)uh1h hh _documenthsourceNlineNubhcomment)}(h SPDX-License-Identifier: GPL-2.0h]h SPDX-License-Identifier: GPL-2.0}hhsbah}(h]h ]h"]h$]h&] xml:spacepreserveuh1hhhhhhM/var/lib/git/docbuild/linux/Documentation/translations/zh_CN/rust/testing.rsthKubhnote)}(hX{此文件的目的是为让中文读者更容易阅读和理解,而不是作为一个分支。 因此, 如果您对此文件有任何意见或更新,请先尝试更新原始英文文件。 如果您发现本文档与原始文件有任何不同或者有翻译问题,请发建议或者补丁给 该文件的译者,或者请求中文文档维护者和审阅者的帮助。h]h paragraph)}(hX{此文件的目的是为让中文读者更容易阅读和理解,而不是作为一个分支。 因此, 如果您对此文件有任何意见或更新,请先尝试更新原始英文文件。 如果您发现本文档与原始文件有任何不同或者有翻译问题,请发建议或者补丁给 该文件的译者,或者请求中文文档维护者和审阅者的帮助。h]hX{此文件的目的是为让中文读者更容易阅读和理解,而不是作为一个分支。 因此, 如果您对此文件有任何意见或更新,请先尝试更新原始英文文件。 如果您发现本文档与原始文件有任何不同或者有翻译问题,请发建议或者补丁给 该文件的译者,或者请求中文文档维护者和审阅者的帮助。}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hh5Documentation/translations/zh_CN/disclaimer-zh_CN.rsthKhhubah}(h]h ]h"]h$]h&]uh1hhhhhhhhNubh field_list)}(hhh](hfield)}(hhh](h field_name)}(hOriginalh]hOriginal}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhhhKubh field_body)}(hDocumentation/rust/testing.rst h]h)}(hDocumentation/rust/testing.rsth]hDocumentation/rust/testing.rst}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1hhhubeh}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(hhh](h)}(h翻译h]h翻译}(hj"hhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhKubj)}(h$郭杰 Ben Guo h]h)}(h#郭杰 Ben Guo h](h郭杰 Ben Guo <}(hj4hhhNhNubh reference)}(hbenx.guo@gmail.comh]hbenx.guo@gmail.com}(hj>hhhNhNubah}(h]h ]h"]h$]h&]refurimailto:benx.guo@gmail.comuh1j<hj4ubh>}(hj4hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhj0ubah}(h]h ]h"]h$]h&]uh1hhjubeh}(h]h ]h"]h$]h&]uh1hhhhKhhhhubeh}(h]h ]h"]h$]h&]uh1hhhhhhhhKubhsection)}(hhh](htitle)}(h测试h]h测试}(hjqhhhNhNubah}(h]h ]h"]h$]h&]uh1johjlhhhhhK ubh)}(h6本文介绍了如何在内核中测试 Rust 代码。h]h6本文介绍了如何在内核中测试 Rust 代码。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK hjlhhubh)}(h有三种测试类型:h]h有三种测试类型:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjlhhubh bullet_list)}(hhh](h list_item)}(h KUnit 测试h]h)}(hjh]h KUnit 测试}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhjhhhhhNubj)}(h``#[test]`` 测试h]h)}(hjh](hliteral)}(h ``#[test]``h]h#[test]}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh 测试}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhjhhhhhNubj)}(h Kselftests h]h)}(h Kselftestsh]h Kselftests}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhjhhhhhNubeh}(h]h ]h"]h$]h&]bullet-uh1jhhhKhjlhhubjk)}(hhh](jp)}(h KUnit 测试h]h KUnit 测试}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1johjhhhhhKubh)}(hR这些测试来自 Rust 文档中的示例。它们会被转换为 KUnit 测试。h]hR这些测试来自 Rust 文档中的示例。它们会被转换为 KUnit 测试。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubjk)}(hhh](jp)}(h使用h]h使用}(hj"hhhNhNubah}(h]h ]h"]h$]h&]uh1johjhhhhhKubh)}(hl这些测试可以通过 KUnit 运行。例如,在命令行中使用 ``kunit_tool`` ( ``kunit.py`` )::h](hG这些测试可以通过 KUnit 运行。例如,在命令行中使用 }(hj0hhhNhNubj)}(h``kunit_tool``h]h kunit_tool}(hj8hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj0ubh ( }(hj0hhhNhNubj)}(h ``kunit.py``h]hkunit.py}(hjJhhhNhNubah}(h]h ]h"]h$]h&]uh1jhj0ubh ):}(hj0hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh literal_block)}(hb./tools/testing/kunit/kunit.py run --make_options LLVM=1 --arch x86_64 --kconfig_add CONFIG_RUST=yh]hb./tools/testing/kunit/kunit.py run --make_options LLVM=1 --arch x86_64 --kconfig_add CONFIG_RUST=y}hjdsbah}(h]h ]h"]h$]h&]hhuh1jbhhhKhjhhubh)}(hX或者,KUnit 也可以在内核启动时以内置方式运行。获取更多 KUnit 信息,请参阅 Documentation/dev-tools/kunit/index.rst。 关于内核内置与命令行测试的详细信息,请参阅 Documentation/dev-tools/kunit/architecture.rst。h]hX或者,KUnit 也可以在内核启动时以内置方式运行。获取更多 KUnit 信息,请参阅 Documentation/dev-tools/kunit/index.rst。 关于内核内置与命令行测试的详细信息,请参阅 Documentation/dev-tools/kunit/architecture.rst。}(hjrhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK!hjhhubh)}(hQ要使用这些 KUnit 文档测试,需要在内核配置中启用以下选项::h]hP要使用这些 KUnit 文档测试,需要在内核配置中启用以下选项:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK%hjhhubjc)}(hCONFIG_KUNIT Kernel hacking -> Kernel Testing and Coverage -> KUnit - Enable support for unit tests CONFIG_RUST_KERNEL_DOCTESTS Kernel hacking -> Rust hacking -> Doctests for the `kernel` crateh]hCONFIG_KUNIT Kernel hacking -> Kernel Testing and Coverage -> KUnit - Enable support for unit tests CONFIG_RUST_KERNEL_DOCTESTS Kernel hacking -> Rust hacking -> Doctests for the `kernel` crate}hjsbah}(h]h ]h"]h$]h&]hhuh1jbhhhK'hjhhubeh}(h]id2ah ]h"]使用ah$]h&]uh1jjhjhhhhhKubjk)}(hhh](jp)}(hKUnit 测试即文档测试h]hKUnit 测试即文档测试}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1johjhhhhhK-ubh)}(h`文档测试( *doctests* )一般用于展示函数、结构体或模块等的使用方法。h](h文档测试( }(hjhhhNhNubhemphasis)}(h *doctests*h]hdoctests}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubhF )一般用于展示函数、结构体或模块等的使用方法。}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhK/hjhhubh)}(hB它们非常方便,因为它们就写在文档旁边。例如:h]hB它们非常方便,因为它们就写在文档旁边。例如:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK1hjhhubjc)}(h/// 求和两个数字。 /// /// ``` /// assert_eq!(mymod::f(10, 20), 30); /// ``` pub fn f(a: i32, b: i32) -> i32 { a + b }h]h/// 求和两个数字。 /// /// ``` /// assert_eq!(mymod::f(10, 20), 30); /// ``` pub fn f(a: i32, b: i32) -> i32 { a + b }}hjsbah}(h]h ]h"]h$]h&]hhƌforcelanguagerusthighlight_args}uh1jbhhhK3hjhhubh)}(hX在用户空间中,这些测试由 ``rustdoc`` 负责收集并运行。单独使用这个工具已经很有价值, 因为它可以验证示例能否成功编译(确保和代码保持同步), 同时还可以运行那些不依赖内核 API 的示例。h](h%在用户空间中,这些测试由 }(hjhhhNhNubj)}(h ``rustdoc``h]hrustdoc}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh 负责收集并运行。单独使用这个工具已经很有价值, 因为它可以验证示例能否成功编译(确保和代码保持同步), 同时还可以运行那些不依赖内核 API 的示例。}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhK>hjhhubh)}(h然而,在内核中,这些测试会转换成 KUnit 测试套件。 这意味着文档测试会被编译成 Rust 内核对象,从而可以在构建的内核环境中运行。h]h然而,在内核中,这些测试会转换成 KUnit 测试套件。 这意味着文档测试会被编译成 Rust 内核对象,从而可以在构建的内核环境中运行。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKBhjhhubh)}(hx通过与 KUnit 集成,Rust 的文档测试可以复用内核现有的测试设施。 例如,内核日志会显示::h]hw通过与 KUnit 集成,Rust 的文档测试可以复用内核现有的测试设施。 例如,内核日志会显示:}(hj&hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKEhjhhubjc)}(hXKTAP version 1 1..1 KTAP version 1 # Subtest: rust_doctests_kernel 1..59 # rust_doctest_kernel_build_assert_rs_0.location: rust/kernel/build_assert.rs:13 ok 1 rust_doctest_kernel_build_assert_rs_0 # rust_doctest_kernel_build_assert_rs_1.location: rust/kernel/build_assert.rs:56 ok 2 rust_doctest_kernel_build_assert_rs_1 # rust_doctest_kernel_init_rs_0.location: rust/kernel/init.rs:122 ok 3 rust_doctest_kernel_init_rs_0 ... # rust_doctest_kernel_types_rs_2.location: rust/kernel/types.rs:150 ok 59 rust_doctest_kernel_types_rs_2 # rust_doctests_kernel: pass:59 fail:0 skip:0 total:59 # Totals: pass:59 fail:0 skip:0 total:59 ok 1 rust_doctests_kernelh]hXKTAP version 1 1..1 KTAP version 1 # Subtest: rust_doctests_kernel 1..59 # rust_doctest_kernel_build_assert_rs_0.location: rust/kernel/build_assert.rs:13 ok 1 rust_doctest_kernel_build_assert_rs_0 # rust_doctest_kernel_build_assert_rs_1.location: rust/kernel/build_assert.rs:56 ok 2 rust_doctest_kernel_build_assert_rs_1 # rust_doctest_kernel_init_rs_0.location: rust/kernel/init.rs:122 ok 3 rust_doctest_kernel_init_rs_0 ... # rust_doctest_kernel_types_rs_2.location: rust/kernel/types.rs:150 ok 59 rust_doctest_kernel_types_rs_2 # rust_doctests_kernel: pass:59 fail:0 skip:0 total:59 # Totals: pass:59 fail:0 skip:0 total:59 ok 1 rust_doctests_kernel}hj4sbah}(h]h ]h"]h$]h&]hhuh1jbhhhKHhjhhubh)}(h文档测试中,也可以正常使用 `? `_ 运算符,例如:h](h(文档测试中,也可以正常使用 }(hjBhhhNhNubj=)}(hd`? `_h]h?}(hjJhhhNhNubah}(h]h ]h"]h$]h&]name?refuri]https://doc.rust-lang.org/reference/expressions/operator-expr.html#the-question-mark-operatoruh1j<hjBubhtarget)}(h` h]h}(h]id4ah ]h"]?ah$]h&]refurij[uh1j\ referencedKhjBubh 运算符,例如:}(hjBhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKZhjhhubjc)}(h/// ``` /// # use kernel::{spawn_work_item, workqueue}; /// spawn_work_item!(workqueue::system(), || pr_info!("x\n"))?; /// # Ok::<(), Error>(()) /// ```h]h/// ``` /// # use kernel::{spawn_work_item, workqueue}; /// spawn_work_item!(workqueue::system(), || pr_info!("x\n"))?; /// # Ok::<(), Error>(()) /// ```}hjvsbah}(h]h ]h"]h$]h&]hhjjrustj}uh1jbhhhK\hjhhubh)}(h这些测试和普通代码一样,也可以在 ``CLIPPY=1`` 条件下通过 Clippy 进行编译, 因此可以从额外的 lint 检查中获益。h](h1这些测试和普通代码一样,也可以在 }(hjhhhNhNubj)}(h ``CLIPPY=1``h]hCLIPPY=1}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubhX 条件下通过 Clippy 进行编译, 因此可以从额外的 lint 检查中获益。}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKdhjhhubh)}(h为了便于开发者定位文档测试出错的具体行号,日志会输出一条 KTAP 诊断信息。 其中标明了原始测试的文件和行号(不是 ``rustdoc`` 生成的临时 Rust 文件位置)::h](h为了便于开发者定位文档测试出错的具体行号,日志会输出一条 KTAP 诊断信息。 其中标明了原始测试的文件和行号(不是 }(hjhhhNhNubj)}(h ``rustdoc``h]hrustdoc}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh& 生成的临时 Rust 文件位置):}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKghjhhubjc)}(hC# rust_doctest_kernel_types_rs_2.location: rust/kernel/types.rs:150h]hC# rust_doctest_kernel_types_rs_2.location: rust/kernel/types.rs:150}hjsbah}(h]h ]h"]h$]h&]hhuh1jbhhhKjhjhhubh)}(hXRust 测试中常用的断言宏是来自 Rust 标准库( ``core`` )中的 ``assert!`` 和 ``assert_eq!`` 宏。 内核提供了一个定制版本,这些宏的调用会被转发到 KUnit。 和 KUnit 测试不同的是,这些宏不需要传递上下文参数( ``struct kunit *`` )。 这使得它们更易于使用,同时文档的读者无需关心底层用的是什么测试框架。 此外,这种方式未来也许可以让我们更容易测试第三方代码。h](h`_ 运算符。 更多背景信息,请参阅:h](hd作为文档中的测试示例,应当像 “实际代码” 一样编写。 例如:不要使用 }(hj8hhhNhNubj)}(h ``unwrap()``h]hunwrap()}(hj@hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj8ubh 或 }(hj8hhhNhNubj)}(h ``expect()``h]hexpect()}(hjRhhhNhNubah}(h]h ]h"]h$]h&]uh1jhj8ubh ,请使用 }(hj8hhhNhNubj=)}(hd`? `_h]h?}(hjdhhhNhNubah}(h]h ]h"]h$]h&]namejYjZ]https://doc.rust-lang.org/reference/expressions/operator-expr.html#the-question-mark-operatoruh1j<hj8ubj])}(h` h]h}(h]id5ah ]h"]h$]?ah&]refurijsuh1j\jkKhj8ubh/ 运算符。 更多背景信息,请参阅:}(hj8hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKvhjhhubh block_quote)}(hUhttps://rust.docs.kernel.org/kernel/error/type.Result.html#error-codes-in-c-and-rust h]h)}(hThttps://rust.docs.kernel.org/kernel/error/type.Result.html#error-codes-in-c-and-rusth]j=)}(hjh]hThttps://rust.docs.kernel.org/kernel/error/type.Result.html#error-codes-in-c-and-rust}(hjhhhNhNubah}(h]h ]h"]h$]h&]refurijuh1j<hjubah}(h]h ]h"]h$]h&]uh1hhhhKzhjubah}(h]h ]h"]h$]h&]uh1jhhhKzhjhhubeh}(h]id3ah ]h"]kunit 测试即文档测试ah$]h&]uh1jjhjhhhhhK-ubeh}(h]kunitah ]h"] kunit 测试ah$]h&]uh1jjhjlhhhhhKubjk)}(hhh](jp)}(h``#[test]`` 测试h](j)}(h ``#[test]``h]h#[test]}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh 测试}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1johjhhhhhK}ubh)}(h此外,还有 ``#[test]`` 测试。与文档测试类似,这些测试与用户空间中的测试方式也非常相近,并且同样会映射到 KUnit。h](h此外,还有 }(hjhhhNhNubj)}(h ``#[test]``h]h#[test]}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh 测试。与文档测试类似,这些测试与用户空间中的测试方式也非常相近,并且同样会映射到 KUnit。}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh)}(hb这些测试通过 ``kunit_tests`` 过程宏引入,该宏将测试套件的名称作为参数。h](h这些测试通过 }(hjhhhNhNubj)}(h``kunit_tests``h]h kunit_tests}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh@ 过程宏引入,该宏将测试套件的名称作为参数。}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh)}(h例如,假设想要测试前面文档测试示例中的函数 ``f``,我们可以在定义该函数的同一文件中编写:h](h@例如,假设想要测试前面文档测试示例中的函数 }(hjhhhNhNubj)}(h``f``h]hf}(hj&hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh<,我们可以在定义该函数的同一文件中编写:}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjhhubjc)}(h#[kunit_tests(rust_kernel_mymod)] mod tests { use super::*; #[test] fn test_f() { assert_eq!(f(10, 20), 30); } }h]h#[kunit_tests(rust_kernel_mymod)] mod tests { use super::*; #[test] fn test_f() { assert_eq!(f(10, 20), 30); } }}hj>sbah}(h]h ]h"]h$]h&]hhjjrustj}uh1jbhhhKhjhhubh)}(h8如果我们执行这段代码,内核日志会显示::h]h7如果我们执行这段代码,内核日志会显示:}(hjNhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubjc)}(h KTAP version 1 # Subtest: rust_kernel_mymod # speed: normal 1..1 # test_f.speed: normal ok 1 test_f ok 1 rust_kernel_mymodh]h KTAP version 1 # Subtest: rust_kernel_mymod # speed: normal 1..1 # test_f.speed: normal ok 1 test_f ok 1 rust_kernel_mymod}hj\sbah}(h]h ]h"]h$]h&]hhuh1jbhhhKhjhhubh)}(hXa与文档测试类似, ``assert!`` 和 ``assert_eq!`` 宏被映射回 KUnit 并且不会发生 panic。 同样,支持 `? `_ 运算符, 测试函数可以什么都不返回(单元类型 ``()``)或 ``Result`` (任何 ``Result``)。例如:h](h与文档测试类似, }(hjjhhhNhNubj)}(h ``assert!``h]hassert!}(hjrhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjjubh 和 }(hjjhhhNhNubj)}(h``assert_eq!``h]h assert_eq!}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjjubhC 宏被映射回 KUnit 并且不会发生 panic。 同样,支持 }(hjjhhhNhNubj=)}(hd`? `_h]h?}(hjhhhNhNubah}(h]h ]h"]h$]h&]namejYjZ]https://doc.rust-lang.org/reference/expressions/operator-expr.html#the-question-mark-operatoruh1j<hjjubj])}(h` h]h}(h]id6ah ]h"]h$]?ah&]refurijuh1j\jkKhjjubhB 运算符, 测试函数可以什么都不返回(单元类型 }(hjjhhhNhNubj)}(h``()``h]h()}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjjubh)或 }(hjjhhhNhNubj)}(h ``Result``h]hResult}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjjubh (任何 }(hjjhhhNhNubj)}(h``Result``h]h Result}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjjubh)。例如:}(hjjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjhhubjc)}(h#[kunit_tests(rust_kernel_mymod)] mod tests { use super::*; #[test] fn test_g() -> Result { let x = g()?; assert_eq!(x, 30); Ok(()) } }h]h#[kunit_tests(rust_kernel_mymod)] mod tests { use super::*; #[test] fn test_g() -> Result { let x = g()?; assert_eq!(x, 30); Ok(()) } }}hjsbah}(h]h ]h"]h$]h&]hhjjrustj}uh1jbhhhKhjhhubh)}(hQ如果我们运行测试并且调用 ``g`` 失败,那么内核日志会显示::h](h%如果我们运行测试并且调用 }(hjhhhNhNubj)}(h``g``h]hg}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh& 失败,那么内核日志会显示:}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjhhubjc)}(hX KTAP version 1 # Subtest: rust_kernel_mymod # speed: normal 1..1 # test_g: ASSERTION FAILED at rust/kernel/lib.rs:335 Expected is_test_result_ok(test_g()) to be true, but is false # test_g.speed: normal not ok 1 test_g not ok 1 rust_kernel_mymodh]hX KTAP version 1 # Subtest: rust_kernel_mymod # speed: normal 1..1 # test_g: ASSERTION FAILED at rust/kernel/lib.rs:335 Expected is_test_result_ok(test_g()) to be true, but is false # test_g.speed: normal not ok 1 test_g not ok 1 rust_kernel_mymod}hj#sbah}(h]h ]h"]h$]h&]hhuh1jbhhhKhjhhubh)}(h如果 ``#[test]`` 测试可以对用户起到示例作用,那就应该改用文档测试。 即使是 API 的边界情况,例如错误或边界问题,放在示例中展示也同样有价值。h](h如果 }(hj1hhhNhNubj)}(h ``#[test]``h]h#[test]}(hj9hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj1ubh 测试可以对用户起到示例作用,那就应该改用文档测试。 即使是 API 的边界情况,例如错误或边界问题,放在示例中展示也同样有价值。}(hj1hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjhhubeh}(h]testah ]h"]#[test] 测试ah$]h&]uh1jjhjlhhhhhK}ubjk)}(hhh](jp)}(h``rusttest`` 宿主机测试h](j)}(h ``rusttest``h]hrusttest}(hj`hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj\ubh 宿主机测试}(hj\hhhNhNubeh}(h]h ]h"]h$]h&]uh1johjYhhhhhKubh)}(hs这类测试运行在用户空间,可以通过 ``rusttest`` 目标在构建内核的宿主机中编译并运行::h](h1这类测试运行在用户空间,可以通过 }(hjxhhhNhNubj)}(h ``rusttest``h]hrusttest}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjxubh5 目标在构建内核的宿主机中编译并运行:}(hjxhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjYhhubjc)}(hmake LLVM=1 rusttesth]hmake LLVM=1 rusttest}hjsbah}(h]h ]h"]h$]h&]hhuh1jbhhhKhjYhhubh)}(h'当前操作需要内核 ``.config``。h](h当前操作需要内核 }(hjhhhNhNubj)}(h ``.config``h]h.config}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh。}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjYhhubh)}(h?目前,它们主要用于测试 ``macros`` crate 的示例。h](h"目前,它们主要用于测试 }(hjhhhNhNubj)}(h ``macros``h]hmacros}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh crate 的示例。}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjYhhubeh}(h]rusttestah ]h"]rusttest 宿主机测试ah$]h&]uh1jjhjlhhhhhKubjk)}(hhh](jp)}(h Kselftestsh]h Kselftests}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1johjhhhhhKubh)}(hKKselftests 可以在 ``tools/testing/selftests/rust`` 文件夹中找到。h](hKselftests 可以在 }(hjhhhNhNubj)}(h ``tools/testing/selftests/rust``h]htools/testing/selftests/rust}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh 文件夹中找到。}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh)}(h测试所需的内核配置选项列在 ``tools/testing/selftests/rust/config`` 文件中, 可以借助 ``merge_config.sh`` 脚本合并到现有配置中::h](h(测试所需的内核配置选项列在 }(hjhhhNhNubj)}(h'``tools/testing/selftests/rust/config``h]h#tools/testing/selftests/rust/config}(hj'hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh 文件中, 可以借助 }(hjhhhNhNubj)}(h``merge_config.sh``h]hmerge_config.sh}(hj9hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh 脚本合并到现有配置中:}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjhhubjc)}(hM./scripts/kconfig/merge_config.sh .config tools/testing/selftests/rust/configh]hM./scripts/kconfig/merge_config.sh .config tools/testing/selftests/rust/config}hjQsbah}(h]h ]h"]h$]h&]hhuh1jbhhhKhjhhubh)}(hhKselftests 会在内核源码树中构建,以便在运行相同版本内核的系统上执行测试。h]hhKselftests 会在内核源码树中构建,以便在运行相同版本内核的系统上执行测试。}(hj_hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh)}(he一旦安装并启动了与源码树匹配的内核,测试即可通过以下命令编译并执行::h]hd一旦安装并启动了与源码树匹配的内核,测试即可通过以下命令编译并执行:}(hjmhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubjc)}(hmake TARGETS="rust" kselftesth]hmake TARGETS="rust" kselftest}hj{sbah}(h]h ]h"]h$]h&]hhuh1jbhhhKhjhhubh)}(hN请参阅 Documentation/dev-tools/kselftest.rst 文档以获取更多信息。h]hN请参阅 Documentation/dev-tools/kselftest.rst 文档以获取更多信息。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubeh}(h] kselftestsah ]h"] kselftestsah$]h&]uh1jjhjlhhhhhKubeh}(h]id1ah ]h"]测试ah$]h&]uh1jjhhhhhhhK ubeh}(h]h ]h"]h$]h&]sourcehuh1hcurrent_sourceN current_lineNsettingsdocutils.frontendValues)}(joN generatorN datestampN source_linkN source_urlN toc_backlinksentryfootnote_backlinksK sectnum_xformKstrip_commentsNstrip_elements_with_classesN strip_classesN report_levelK halt_levelKexit_status_levelKdebugNwarning_streamN tracebackinput_encoding utf-8-siginput_encoding_error_handlerstrictoutput_encodingutf-8output_encoding_error_handlerjerror_encodingutf-8error_encoding_error_handlerbackslashreplace language_codeenrecord_dependenciesNconfigN id_prefixhauto_id_prefixid dump_settingsNdump_internalsNdump_transformsNdump_pseudo_xmlNexpose_internalsNstrict_visitorN_disable_configN_sourcehnj _destinationN _config_files]7/var/lib/git/docbuild/linux/Documentation/docutils.confafile_insertion_enabled raw_enabledKline_length_limitM'pep_referencesN pep_base_urlhttps://peps.python.org/pep_file_url_templatepep-%04drfc_referencesN rfc_base_url&https://datatracker.ietf.org/doc/html/ tab_widthKtrim_footnote_reference_spacesyntax_highlightlong smart_quotessmartquotes_locales]character_level_inline_markupdoctitle_xform docinfo_xformKsectsubtitle_xform image_loadinglinkembed_stylesheetcloak_email_addressessection_self_linkenvNubreporterNindirect_targets]substitution_defs}substitution_names}refnames}refids}nameids}(jjjjjjjjjgjdjVjSjjjju nametypes}(jjjjjgjVjjuh}(jjljjjjjjjdj^jzjtjSjjjjjYjju footnote_refs} citation_refs} autofootnotes]autofootnote_refs]symbol_footnotes]symbol_footnote_refs] footnotes] citations]autofootnote_startKsymbol_footnote_startK id_counter collectionsCounter}jKsRparse_messages](hsystem_message)}(hhh]h)}(h$Duplicate explicit target name: "?".h]h(Duplicate explicit target name: “?”.}(hj1hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj.ubah}(h]h ]h"]h$]h&]jzalevelKtypeINFOsourcehnjlineK uh1j,hjhhhhhKxubj-)}(hhh]h)}(h$Duplicate explicit target name: "?".h]h(Duplicate explicit target name: “?”.}(hjMhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjJubah}(h]h ]h"]h$]h&]jalevelKtypejGsourcehnjlineK uh1j,hjhhhhhKubetransform_messages] transformerN include_log]1Documentation/translations/zh_CN/rust/testing.rst(NNNNta decorationNhhub.