1 /* 2 * This file is derived from src/macros/mod.rs in the Rust libcore, used under 3 * the Apache License, Version 2.0. The following is the original copyright 4 * information from the Rust project: 5 * 6 * Copyrights in the Rust project are retained by their contributors. No 7 * copyright assignment is required to contribute to the Rust project. 8 * 9 * Some files include explicit copyright notices and/or license notices. 10 * For full authorship information, see the version control history or 11 * https://thanks.rust-lang.org 12 * 13 * Except as otherwise noted (below and/or in individual files), Rust is 14 * licensed under the Apache License, Version 2.0 <LICENSE-APACHE> or 15 * <http://www.apache.org/licenses/LICENSE-2.0> or the MIT license 16 * <LICENSE-MIT> or <http://opensource.org/licenses/MIT>, at your option. 17 * 18 * 19 * Licensed under the Apache License, Version 2.0 (the "License"); 20 * you may not use this file except in compliance with the License. 21 * You may obtain a copy of the License at 22 * 23 * http://www.apache.org/licenses/LICENSE-2.0 24 * 25 * Unless required by applicable law or agreed to in writing, software 26 * distributed under the License is distributed on an "AS IS" BASIS, 27 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 28 * See the License for the specific language governing permissions and 29 * limitations under the License. 30 */ 31 32 /// Expects two expressions are equal to each other (using 33 /// [std::cmp::PartialEq]). 34 /// 35 /// On failure, this macro will print the values of the expressions with their 36 /// debug representations and signal the failure to the test framework. The test 37 /// will continue past the failure. 38 /// 39 /// Like [`assert!`], this macro has a second form, where a custom 40 /// error message can be provided. 41 /// 42 /// # Examples 43 /// 44 /// ``` 45 /// let a = 3; 46 /// let b = 1 + 2; 47 /// expect_eq!(a, b); 48 /// 49 /// expect_eq!(a, b, "we are testing addition with {} and {}", a, b); 50 /// ``` 51 #[macro_export] 52 macro_rules! expect_eq { 53 ($left:expr, $right:expr $(,)?) => ({ 54 match (&$left, &$right) { 55 (left_val, right_val) => { 56 if !(*left_val == *right_val) { 57 let kind = $crate::__internal_macro_utils::AssertKind::Eq; 58 // The reborrows below are intentional. Without them, the 59 // stack slot for the borrow is initialized even before the 60 // values are compared, leading to a noticeable slow down. 61 $crate::__internal_macro_utils::assert_failed( 62 kind, 63 &*left_val, 64 &*right_val, 65 core::option::Option::None 66 ); 67 } 68 } 69 } 70 }); 71 ($left:expr, $right:expr, $($arg:tt)+) => ({ 72 match (&$left, &$right) { 73 (left_val, right_val) => { 74 if !(*left_val == *right_val) { 75 let kind = $crate::__internal_macro_utils::AssertKind::Eq; 76 // The reborrows below are intentional. Without them, the 77 // stack slot for the borrow is initialized even before the 78 // values are compared, leading to a noticeable slow down. 79 $crate::__internal_macro_utils::assert_failed( 80 kind, 81 &*left_val, 82 &*right_val, 83 core::option::Option::Some(core::format_args!($($arg)+)) 84 ); 85 } 86 } 87 } 88 }); 89 } 90 91 /// Asserts that two expressions are equal to each other (using 92 /// [std::cmp::PartialEq]). 93 /// 94 /// Unlike [`core::assert_eq!`], this macro will not panic, but instead returns 95 /// early from a test function. 96 /// 97 /// Like [`assert!`], this macro has a second form, where a custom 98 /// panic message can be provided. 99 /// 100 /// # Examples 101 /// 102 /// ``` 103 /// let a = 3; 104 /// let b = 1 + 2; 105 /// assert_eq!(a, b); 106 /// 107 /// assert_eq!(a, b, "we are testing addition with {} and {}", a, b); 108 /// ``` 109 #[macro_export] 110 macro_rules! assert_eq { 111 ($left:expr, $right:expr $(,)?) => ({ 112 match (&$left, &$right) { 113 (left_val, right_val) => { 114 if !(*left_val == *right_val) { 115 let kind = $crate::__internal_macro_utils::AssertKind::Eq; 116 // The reborrows below are intentional. Without them, the 117 // stack slot for the borrow is initialized even before the 118 // values are compared, leading to a noticeable slow down. 119 $crate::__internal_macro_utils::assert_failed( 120 kind, 121 &*left_val, 122 &*right_val, 123 core::option::Option::None 124 ); 125 return; 126 } 127 } 128 } 129 }); 130 ($left:expr, $right:expr, $($arg:tt)+) => ({ 131 match (&$left, &$right) { 132 (left_val, right_val) => { 133 if !(*left_val == *right_val) { 134 let kind = $crate::__internal_macro_utils::AssertKind::Eq; 135 // The reborrows below are intentional. Without them, the 136 // stack slot for the borrow is initialized even before the 137 // values are compared, leading to a noticeable slow down. 138 $crate::__internal_macro_utils::assert_failed( 139 kind, 140 &*left_val, 141 &*right_val, 142 core::option::Option::Some(core::format_args!($($arg)+)) 143 ); 144 return; 145 } 146 } 147 } 148 }); 149 } 150 151 /// Expects that two expressions are not equal to each other (using 152 /// [std::cmp::PartialEq]). 153 /// 154 /// On failure, this macro will print the values of the expressions with their 155 /// debug representations and signal the failure to the test framework. The test 156 /// will continue past the failure. 157 /// 158 /// Like [`assert!`], this macro has a second form, where a custom 159 /// panic message can be provided. 160 /// 161 /// # Examples 162 /// 163 /// ``` 164 /// let a = 3; 165 /// let b = 2; 166 /// expect_ne!(a, b); 167 /// 168 /// expect_ne!(a, b, "we are testing that the values are not equal"); 169 /// ``` 170 #[macro_export] 171 macro_rules! expect_ne { 172 ($left:expr, $right:expr $(,)?) => ({ 173 match (&$left, &$right) { 174 (left_val, right_val) => { 175 if *left_val == *right_val { 176 let kind = $crate::__internal_macro_utils::AssertKind::Ne; 177 // The reborrows below are intentional. Without them, the 178 // stack slot for the borrow is initialized even before the 179 // values are compared, leading to a noticeable slow down. 180 $crate::__internal_macro_utils::assert_failed( 181 kind, 182 &*left_val, 183 &*right_val, 184 core::option::Option::None 185 ); 186 } 187 } 188 } 189 }); 190 ($left:expr, $right:expr, $($arg:tt)+) => ({ 191 match (&($left), &($right)) { 192 (left_val, right_val) => { 193 if *left_val == *right_val { 194 let kind = $crate::__internal_macro_utils::AssertKind::Ne; 195 // The reborrows below are intentional. Without them, the 196 // stack slot for the borrow is initialized even before the 197 // values are compared, leading to a noticeable slow down. 198 $crate::__internal_macro_utils::assert_failed( 199 kind, 200 &*left_val, 201 &*right_val, 202 core::option::Option::Some(core::format_args!($($arg)+)) 203 ); 204 } 205 } 206 } 207 }); 208 } 209 210 /// Asserts that two expressions are not equal to each other (using 211 /// [std::cmp::PartialEq]). 212 /// 213 /// Unlike [`core::assert_ne!`], this macro will not panic, but instead returns 214 /// early from a test function. 215 /// 216 /// Like [`assert!`], this macro has a second form, where a custom 217 /// panic message can be provided. 218 /// 219 /// # Examples 220 /// 221 /// ``` 222 /// let a = 3; 223 /// let b = 2; 224 /// assert_ne!(a, b); 225 /// 226 /// assert_ne!(a, b, "we are testing that the values are not equal"); 227 /// ``` 228 #[macro_export] 229 macro_rules! assert_ne { 230 ($left:expr, $right:expr $(,)?) => ({ 231 match (&$left, &$right) { 232 (left_val, right_val) => { 233 if *left_val == *right_val { 234 let kind = $crate::__internal_macro_utils::AssertKind::Ne; 235 // The reborrows below are intentional. Without them, the 236 // stack slot for the borrow is initialized even before the 237 // values are compared, leading to a noticeable slow down. 238 $crate::__internal_macro_utils::assert_failed( 239 kind, 240 &*left_val, 241 &*right_val, 242 core::option::Option::None 243 ); 244 return; 245 } 246 } 247 } 248 }); 249 ($left:expr, $right:expr, $($arg:tt)+) => ({ 250 match (&($left), &($right)) { 251 (left_val, right_val) => { 252 if *left_val == *right_val { 253 let kind = $crate::__internal_macro_utils::AssertKind::Ne; 254 // The reborrows below are intentional. Without them, the 255 // stack slot for the borrow is initialized even before the 256 // values are compared, leading to a noticeable slow down. 257 $crate::__internal_macro_utils::assert_failed( 258 kind, 259 &*left_val, 260 &*right_val, 261 core::option::Option::Some(core::format_args!($($arg)+)) 262 ); 263 return; 264 } 265 } 266 } 267 }); 268 } 269 270 /// Asserts that a `Result` expression is `Ok` 271 /// 272 /// On failure, this macro will print an error message containing the `Err` 273 /// value and signal the failure to the test framework. On success, the macro 274 /// expression will evaluate to the unwrapped `Ok` value. 275 /// 276 /// Like [`assert!`], this macro has a second form, where a custom error 277 /// message can be provided with or without arguments for formatting. See 278 /// [`core::fmt`] for syntax for this form. Expressions used as format arguments 279 /// will only be evaluated if the assertion fails. 280 /// 281 /// Failures will include a best-effort representation of the error value in the 282 /// error message. It will use the [std::fmt::Display], [std::fmt::Debug], or 283 /// [std::any::type_name] in that order of priority, depending on which ones are 284 /// implemented for the error type. (This is implemented with 285 /// [autoderef specialization], so it will work for concrete types, but using it 286 /// for unconstrained generic `T` will always use the [std::any::type_name] 287 /// impl, regardless of what traits the type actually implements. Similarly, if 288 /// the type is declared as `T: Debug`, the [std::fmt::Debug] impl will be 289 /// invoked, even if the concrete type implements [std::fmt::Display] as well.) 290 /// 291 /// # Examples 292 /// 293 /// ``` 294 /// let x: Result<usize, String> = Ok(4); 295 /// let x: usize = assert_ok!(x); 296 /// 297 /// let y: Result<usize, String> = Ok(x); 298 /// assert_ok!(y, "something went wrong; x was {}", x); 299 /// ``` 300 /// 301 /// [autoderef specialization]: https://lukaskalbertodt.github.io/2019/12/05/generalized-autoref-based-specialization.html 302 #[macro_export] 303 macro_rules! assert_ok { 304 ($result:expr $(,)?) => ({ 305 match ($result) { 306 Ok(t) => t, 307 Err(e) => { 308 use $crate::__internal_macro_utils::{ 309 DisplayKind as _, 310 DebugKind as _, 311 TypenameKind as _, 312 }; 313 $crate::__internal_macro_utils::assert_ok_failed( 314 core::stringify!($result), 315 (&&&$crate::__internal_macro_utils::BestEffortDisplay(&e)) 316 .display_kind() 317 .wrap(e), 318 core::option::Option::None 319 ); 320 return; 321 } 322 } 323 }); 324 ($result:expr, $($arg:tt)+) => ({ 325 match ($result) { 326 Ok(t) => t, 327 Err(e) => { 328 use $crate::__internal_macro_utils::{ 329 DisplayKind as _, 330 DebugKind as _, 331 TypenameKind as _, 332 }; 333 $crate::__internal_macro_utils::assert_ok_failed( 334 core::stringify!($result), 335 (&&&$crate::__internal_macro_utils::BestEffortDisplay(&e)) 336 .display_kind() 337 .wrap(e), 338 core::option::Option::Some(core::format_args!($($arg)+)) 339 ); 340 return; 341 } 342 } 343 }); 344 } 345 346 /// Expects that a boolean expression is `true` at runtime. 347 /// 348 /// On failure, this macro will print an error message and signal the failure to 349 /// the test framework. The test will continue past the failure. 350 /// 351 /// # Custom Messages 352 /// 353 /// This macro has a second form, where a custom error message can 354 /// be provided with or without arguments for formatting. See [`core::fmt`] 355 /// for syntax for this form. Expressions used as format arguments will only 356 /// be evaluated if the assertion fails. 357 #[macro_export] 358 macro_rules! expect { 359 ($cond:expr $(,)?) => ({ 360 match (&($cond)) { 361 (cond) => { 362 if (!*cond) { 363 $crate::__internal_macro_utils::simple_assert_failed( 364 core::stringify!($cond), 365 core::option::Option::None 366 ); 367 } 368 } 369 } 370 }); 371 ($cond:expr, $($arg:tt)+) => ({ 372 match (&($cond)) { 373 (cond) => { 374 if (!*cond) { 375 $crate::__internal_macro_utils::simple_assert_failed( 376 core::stringify!($cond), 377 core::option::Option::Some(core::format_args!($($arg)+)) 378 ); 379 } 380 } 381 } 382 }); 383 } 384 385 /// Asserts that a boolean expression is `true` at runtime. 386 /// 387 /// Unlike [`core::assert!`], this macro will not panic, but instead returns 388 /// early from a test function. 389 /// 390 /// # Custom Messages 391 /// 392 /// This macro has a second form, where a custom error message can 393 /// be provided with or without arguments for formatting. See [`core::fmt`] 394 /// for syntax for this form. Expressions used as format arguments will only 395 /// be evaluated if the assertion fails. 396 #[macro_export] 397 macro_rules! assert { 398 ($cond:expr $(,)?) => ({ 399 match (&($cond)) { 400 (cond) => { 401 if (!*cond) { 402 $crate::__internal_macro_utils::simple_assert_failed( 403 core::stringify!($cond), 404 core::option::Option::None 405 ); 406 return; 407 } 408 } 409 } 410 }); 411 ($cond:expr, $($arg:tt)+) => ({ 412 match (&($cond)) { 413 (cond) => { 414 if (!*cond) { 415 $crate::__internal_macro_utils::simple_assert_failed( 416 core::stringify!($cond), 417 core::option::Option::Some(core::format_args!($($arg)+)) 418 ); 419 return; 420 } 421 } 422 } 423 }); 424 } 425 426 /// Fails the test and diverges. 427 /// 428 /// Unlike [`core::panic!`], this macro will not unwind/abort, but instead returns 429 /// early from a test function. 430 /// 431 /// This macro can be used with or without providing a custom error message. 432 /// Formatting is supported; see [`core::fmt`] for syntax. 433 #[macro_export] 434 macro_rules! fail { 435 () => ({ 436 $crate::__internal_macro_utils::simple_assert_failed( 437 "encountered test failure", 438 core::option::Option::None 439 ); 440 return; 441 }); 442 ($($arg:tt)+) => ({ 443 $crate::__internal_macro_utils::simple_assert_failed( 444 "encountered test failure", 445 core::option::Option::Some(core::format_args!($($arg)+)) 446 ); 447 return; 448 }); 449 } 450 451 /// Marks the test as skipped. 452 /// 453 /// This macro can be used with or without providing a custom error message. 454 /// Formatting is supported; see [`core::fmt`] for syntax. 455 #[macro_export] 456 macro_rules! skip { 457 () => ({ 458 $crate::skip(); 459 return; 460 }); 461 ($($arg:tt)+) => ({ 462 std::eprintln!( 463 "test skipped: {}, {}", 464 core::format_args!($($arg)+), 465 std::panic::Location::caller() 466 ); 467 $crate::skip(); 468 return; 469 }); 470 } 471