Skip to content

Commit

Permalink
feat: add a way to specify expected revert code to forc-test (FuelL…
Browse files Browse the repository at this point in the history
…abs#4554)

## Description
closes FuelLabs#3544.

Enables users to provide a specified revert code with their
`should_revert` tests.
  • Loading branch information
kayagokalp authored May 18, 2023
1 parent 639ae5c commit 81731c5
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 8 deletions.
9 changes: 9 additions & 0 deletions docs/book/src/testing/unit-testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,15 @@ fn test_meaning_of_life() {
}
```

It is also possible to specify an expected revert code, like the following example.

```sway
#[test(should_revert = "18446744073709486084")]
fn test_meaning_of_life() {
assert(6 * 6 == 42);
}
```

Tests with `#[test(should_revert)]` considered to be passing if they are reverting.

## Calling Contracts
Expand Down
27 changes: 22 additions & 5 deletions forc-pkg/src/pkg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ pub enum PkgEntryKind {
/// The possible conditions for a test result to be considered "passing".
#[derive(Debug, Clone)]
pub enum TestPassCondition {
ShouldRevert,
ShouldRevert(Option<u64>),
ShouldNotRevert,
}

Expand Down Expand Up @@ -1949,18 +1949,35 @@ impl PkgTestEntry {
let span = decl_ref.span();
let test_function_decl = decl_engine.get_function(&decl_ref);

let test_args: HashSet<String> = test_function_decl
const FAILING_TEST_KEYWORD: &str = "should_revert";

let test_args: HashMap<String, Option<String>> = test_function_decl
.attributes
.get(&AttributeKind::Test)
.expect("test declaration is missing test attribute")
.iter()
.flat_map(|attr| attr.args.iter().map(|arg| arg.name.to_string()))
.flat_map(|attr| attr.args.iter())
.map(|arg| {
(
arg.name.to_string(),
arg.value
.as_ref()
.map(|val| val.span().as_str().to_string()),
)
})
.collect();

let pass_condition = if test_args.is_empty() {
anyhow::Ok(TestPassCondition::ShouldNotRevert)
} else if test_args.get("should_revert").is_some() {
anyhow::Ok(TestPassCondition::ShouldRevert)
} else if let Some(args) = test_args.get(FAILING_TEST_KEYWORD) {
let expected_revert_code = args
.as_ref()
.map(|arg| {
let arg_str = arg.replace('"', "");
arg_str.parse::<u64>()
})
.transpose()?;
anyhow::Ok(TestPassCondition::ShouldRevert(expected_revert_code))
} else {
let test_name = &test_function_decl.name;
bail!("Invalid test argument(s) for test: {test_name}.")
Expand Down
7 changes: 4 additions & 3 deletions forc-test/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -491,9 +491,10 @@ impl TestResult {
/// Whether or not the test passed.
pub fn passed(&self) -> bool {
match &self.condition {
TestPassCondition::ShouldRevert => {
matches!(self.state, vm::state::ProgramState::Revert(_))
}
TestPassCondition::ShouldRevert(revert_code) => match revert_code {
Some(revert_code) => self.state == vm::state::ProgramState::Revert(*revert_code),
None => matches!(self.state, vm::state::ProgramState::Revert(_)),
},
TestPassCondition::ShouldNotRevert => {
!matches!(self.state, vm::state::ProgramState::Revert(_))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,8 @@ library;
fn should_revert_test() {
assert(0 == 1)
}

#[test(should_revert = "18446744073709486084")]
fn should_revert_test_with_exact_code() {
assert(0 == 1)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
category = "unit_tests_pass"

0 comments on commit 81731c5

Please sign in to comment.