From e870221ea0daf1762bad79b3378cc4d2a1b1723b Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 9 Jun 2025 16:33:44 -0700 Subject: [PATCH 1/4] Unwrap should_panic --- src/attributes/testing.md | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/attributes/testing.md b/src/attributes/testing.md index ae5f94909..8261d10fb 100644 --- a/src/attributes/testing.md +++ b/src/attributes/testing.md @@ -124,19 +124,13 @@ r[attributes.testing.should_panic] ## The `should_panic` attribute r[attributes.testing.should_panic.intro] -A function annotated with the `test` attribute that returns `()` can also be -annotated with the `should_panic` attribute. +A function annotated with the `test` attribute that returns `()` can also be annotated with the `should_panic` attribute. r[attributes.testing.should_panic.behavior] -The *`should_panic` attribute* -makes the test only pass if it actually panics. +The *`should_panic` attribute* makes the test only pass if it actually panics. r[attributes.testing.should_panic.syntax] -The `should_panic` attribute may optionally take an input string that must -appear within the panic message. If the string is not found in the message, -then the test will fail. The string may be passed using the -[MetaNameValueStr] syntax or the [MetaListNameValueStr] syntax with an -`expected` field. +The `should_panic` attribute may optionally take an input string that must appear within the panic message. If the string is not found in the message, then the test will fail. The string may be passed using the [MetaNameValueStr] syntax or the [MetaListNameValueStr] syntax with an `expected` field. ```rust #[test] From 5789bb73a4dac9384023e3fa5e8033418cba3227 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 9 Jun 2025 16:57:01 -0700 Subject: [PATCH 2/4] Convert should_panic to use the attribute template --- src/attributes/testing.md | 64 +++++++++++++++++++++++++++++++-------- 1 file changed, 52 insertions(+), 12 deletions(-) diff --git a/src/attributes/testing.md b/src/attributes/testing.md index 8261d10fb..15464ed05 100644 --- a/src/attributes/testing.md +++ b/src/attributes/testing.md @@ -124,21 +124,61 @@ r[attributes.testing.should_panic] ## The `should_panic` attribute r[attributes.testing.should_panic.intro] -A function annotated with the `test` attribute that returns `()` can also be annotated with the `should_panic` attribute. +The *`should_panic` [attribute][attributes]* changes a [test function][attributes.testing.test] so that it passes only if it panics. -r[attributes.testing.should_panic.behavior] -The *`should_panic` attribute* makes the test only pass if it actually panics. +> [!EXAMPLE] +> ```rust +> #[test] +> #[should_panic(expected = "values don't match")] +> fn mytest() { +> assert_eq!(1, 2, "values don't match"); +> } +> ``` r[attributes.testing.should_panic.syntax] -The `should_panic` attribute may optionally take an input string that must appear within the panic message. If the string is not found in the message, then the test will fail. The string may be passed using the [MetaNameValueStr] syntax or the [MetaListNameValueStr] syntax with an `expected` field. - -```rust -#[test] -#[should_panic(expected = "values don't match")] -fn mytest() { - assert_eq!(1, 2, "values don't match"); -} -``` +The `should_panic` attribute is specified with one of the following forms: + +- [MetaWord] + > [!EXAMPLE] + > ```rust + > #[test] + > #[should_panic] + > fn mytest() { panic!("some message"); } + > ``` + +- [MetaNameValueStr] --- This indicates that the given string should appear within the panic message. + > [!EXAMPLE] + > ```rust + > #[test] + > #[should_panic = "some message"] + > fn mytest() { panic!("some message"); } + > ``` + +- [MetaListNameValueStr] --- Specified with the key `expected`. Same behavior as [MetaNameValueStr], just with an explicit key. + > [!EXAMPLE] + > ```rust + > #[test] + > #[should_panic(expected = "some message")] + > fn mytest() { panic!("some message"); } + > ``` + +r[attributes.testing.should_panic.allowed-positions] +The `should_panic` attribute may be applied to functions annotated with the `test` attribute. + +> [!NOTE] +> `rustc` currently warns in some other positions. This may become a hard error in the future. + +r[attributes.testing.should_panic.duplicates] +Only the first instance of `should_panic` on a function is honored. Subsequent `should_panic` attributes are ignored. + +> [!NOTE] +> `rustc` currently ignores subsequent duplicate `should_panic` attributes. This may become an error in the future. + +r[attributes.testing.should_panic.expected] +The string specified with the [MetaNameValueStr] form or the `expected` key in [MetaListNameValueStr] indicates that the string must appear somewhere within the panic message. If the string is not found in the message, then the test will fail. + +r[attributes.testing.should_panic.return] +The return type of the test function must be `()`. [`Termination`]: std::process::Termination [`report`]: std::process::Termination::report From 6215cd1586e3993f0e5376215fa4c71f428b293f Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Thu, 3 Jul 2025 23:18:51 +0000 Subject: [PATCH 3/4] Revise editorially The test functions within our code blocks will not actually be run in any case, so let's mark these tests as `no_run`. In the examples, let's demonstrate the behavior that the expected string must be a substring of the panic message. Let's also tighten up some wording. --- src/attributes/testing.md | 41 +++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/src/attributes/testing.md b/src/attributes/testing.md index 15464ed05..8fbceddab 100644 --- a/src/attributes/testing.md +++ b/src/attributes/testing.md @@ -13,9 +13,8 @@ r[attributes.testing.test.intro] The *`test` [attribute][attributes]* marks a function to be executed as a test. > [!EXAMPLE] -> ```rust +> ```rust,no_run > # pub fn add(left: u64, right: u64) -> u64 { left + right } -> > #[test] > fn it_works() { > let result = add(2, 2); @@ -60,7 +59,7 @@ In particular: * Tests that do not terminate neither pass nor fail. > [!EXAMPLE] -> ```rust +> ```rust,no_run > # use std::io; > # fn setup_the_thing() -> io::Result { Ok(1) } > # fn do_the_thing(s: &i32) -> io::Result<()> { Ok(()) } @@ -79,7 +78,7 @@ r[attributes.testing.ignore.intro] The *`ignore` [attribute][attributes]* can be used with the [`test` attribute][attributes.testing.test] to tell the test harness to not execute that function as a test. > [!EXAMPLE] -> ```rust +> ```rust,no_run > #[test] > #[ignore] > fn check_thing() { @@ -97,7 +96,7 @@ r[attributes.testing.ignore.reason] The [MetaNameValueStr] form of the `ignore` attribute provides a way to specify a reason why the test is ignored. > [!EXAMPLE] -> ```rust +> ```rust,no_run > #[test] > #[ignore = "not yet implemented"] > fn mytest() { @@ -124,10 +123,10 @@ r[attributes.testing.should_panic] ## The `should_panic` attribute r[attributes.testing.should_panic.intro] -The *`should_panic` [attribute][attributes]* changes a [test function][attributes.testing.test] so that it passes only if it panics. +The *`should_panic` [attribute][attributes]* causes a test to pass only if the [test function][attributes.testing.test] to which the attribute is applied panics. > [!EXAMPLE] -> ```rust +> ```rust,no_run > #[test] > #[should_panic(expected = "values don't match")] > fn mytest() { @@ -136,46 +135,46 @@ The *`should_panic` [attribute][attributes]* changes a [test function][attribute > ``` r[attributes.testing.should_panic.syntax] -The `should_panic` attribute is specified with one of the following forms: +The `should_panic` attribute has one of the following forms: - [MetaWord] > [!EXAMPLE] - > ```rust + > ```rust,no_run > #[test] > #[should_panic] - > fn mytest() { panic!("some message"); } + > fn mytest() { panic!("error: some message, and more"); } > ``` -- [MetaNameValueStr] --- This indicates that the given string should appear within the panic message. +- [MetaNameValueStr] --- The given string must appear within the panic message for the test to pass. > [!EXAMPLE] - > ```rust + > ```rust,no_run > #[test] > #[should_panic = "some message"] - > fn mytest() { panic!("some message"); } + > fn mytest() { panic!("error: some message, and more"); } > ``` -- [MetaListNameValueStr] --- Specified with the key `expected`. Same behavior as [MetaNameValueStr], just with an explicit key. +- [MetaListNameValueStr] --- As with the [MetaNameValueStr] syntax, the given string must appear within the panic message. > [!EXAMPLE] - > ```rust + > ```rust,no_run > #[test] > #[should_panic(expected = "some message")] - > fn mytest() { panic!("some message"); } + > fn mytest() { panic!("error: some message, and more"); } > ``` r[attributes.testing.should_panic.allowed-positions] -The `should_panic` attribute may be applied to functions annotated with the `test` attribute. +The `should_panic` attribute may only be applied to functions annotated with the `test` attribute. > [!NOTE] -> `rustc` currently warns in some other positions. This may become a hard error in the future. +> `rustc` currently accepts this attribute in other positions with a warning. This may become a hard error in the future. r[attributes.testing.should_panic.duplicates] -Only the first instance of `should_panic` on a function is honored. Subsequent `should_panic` attributes are ignored. +Only the first instance of `should_panic` on a function is honored. > [!NOTE] -> `rustc` currently ignores subsequent duplicate `should_panic` attributes. This may become an error in the future. +> `rustc` currently ignores subsequent `should_panic` attributes and emits a future-compatibility warning. This may become a hard error in the future. r[attributes.testing.should_panic.expected] -The string specified with the [MetaNameValueStr] form or the `expected` key in [MetaListNameValueStr] indicates that the string must appear somewhere within the panic message. If the string is not found in the message, then the test will fail. +When the [MetaNameValueStr] form or the [MetaListNameValueStr] form with the `expected` key is used, the given string must appear somewhere within the panic message for the test to pass. r[attributes.testing.should_panic.return] The return type of the test function must be `()`. From f7b664cfe29f6d1466b1abc6099829c141771cad Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Thu, 3 Jul 2025 23:51:18 +0000 Subject: [PATCH 4/4] Note invalid syntax currently accepted We currently accept invalid syntax between the parentheses with `should_panic(..)`. Let's make a note of that. --- src/attributes/testing.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/attributes/testing.md b/src/attributes/testing.md index 8fbceddab..93fd7de05 100644 --- a/src/attributes/testing.md +++ b/src/attributes/testing.md @@ -161,6 +161,9 @@ The `should_panic` attribute has one of the following forms: > fn mytest() { panic!("error: some message, and more"); } > ``` + > [!NOTE] + > `rustc` currently accepts the [MetaListNameValueStr] form with invalid syntax between the parentheses and emits a future-compatibility warning. This may become a hard error in the future. + r[attributes.testing.should_panic.allowed-positions] The `should_panic` attribute may only be applied to functions annotated with the `test` attribute.