Skip to content

Commit

Permalink
tests
Browse files Browse the repository at this point in the history
  • Loading branch information
carolynzech committed Dec 30, 2024
1 parent 1f135c9 commit d4a8fc0
Show file tree
Hide file tree
Showing 6 changed files with 187 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
assertion\
- Status: FAILURE\
- Description: "|result| old(*add_two_ptr + 1) == *add_two_ptr"

assertion\
- Status: SUCCESS\
- Description: "|result| old(*add_one_ptr + 1) == *add_one_ptr"

VERIFICATION:- FAILED
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright Kani Contributors
// SPDX-License-Identifier: Apache-2.0 OR MIT
// kani-flags: -Zfunction-contracts -Zcontracts-as-assertions

// Test -Zcontracts-as-assertions for postconditions.

#[kani::requires(*add_three_ptr < 100)]
#[kani::modifies(add_three_ptr)]
fn add_three(add_three_ptr: &mut u32) {
*add_three_ptr += 1;
add_two(add_three_ptr);
}

#[kani::ensures(|result| old(*add_two_ptr + 1) == *add_two_ptr)] // incorrect -- should be old(*add_two_ptr + 1)
fn add_two(add_two_ptr: &mut u32) {
*add_two_ptr += 1;
add_one(add_two_ptr)
}

#[kani::requires(*add_one_ptr < 102)]
#[kani::modifies(add_one_ptr)]
#[kani::ensures(|result| old(*add_one_ptr + 1) == *add_one_ptr)] // correct -- assertion should always succeed
fn add_one(add_one_ptr: &mut u32) {
*add_one_ptr += 1;
}

// -Zcontracts-as-assertions introduces this failure; without it, add_two's and add_one's contracts are ignored.
#[kani::proof_for_contract(add_three)]
fn prove_add_three() {
let mut i = kani::any();
add_three(&mut i);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
assertion\
- Status: SUCCESS\
- Description: "*ptr < 100"\

assertion\
- Status: FAILURE\
- Description: "*ptr == 1"

assertion\
- Status: FAILURE\
- Description: "*ptr < 100"

assertion\
- Status: FAILURE\
- Description: "*ptr == 1"

Summary:
Verification failed for - should_fail::prove_add_three_contract
Verification failed for - should_fail::prove_add_one
Verification failed for - should_fail::prove_add_three
Complete - 1 successfully verified harnesses, 3 failures, 4 total.
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Copyright Kani Contributors
// SPDX-License-Identifier: Apache-2.0 OR MIT
// kani-flags: -Zfunction-contracts -Zcontracts-as-assertions

// Test -Zcontracts-as-assertions for preconditions.

#[kani::requires(*ptr < 100)]
#[kani::ensures(|result| old(*ptr + 3) == *ptr)]
#[kani::modifies(ptr)]
fn add_three(ptr: &mut u32) {
*ptr += 1;
add_two(ptr);
}

#[kani::requires(*ptr < 101)]
#[kani::ensures(|result| old(*ptr + 2) == *ptr)]
fn add_two(ptr: &mut u32) {
*ptr += 1;
add_one(ptr);
}

#[kani::requires(*ptr == 1)]
#[kani::modifies(ptr)]
fn add_one(ptr: &mut u32) {
*ptr += 1;
}

mod should_fail {
use crate::*;

// add_three and add_one's preconditions are asserted, causing failure.
#[kani::proof]
fn prove_add_three() {
let mut i = kani::any();
add_three(&mut i);
}

// add_three's precondition is asserted, causing failure.
#[kani::proof_for_contract(add_one)]
fn prove_add_one() {
let mut i = kani::any();
add_three(&mut i);
}

// Since add_three is the target of the proof_for_contract, its precondition gets assumed.
// However, add_one's precondition is still asserted, causing failure.
#[kani::proof_for_contract(add_three)]
fn prove_add_three_contract() {
let mut i = kani::any();
add_three(&mut i);
}
}

mod should_pass {
use crate::*;
// Same as should_fail::prove_add_one, with the added assumption of add_three's precondition.
// Note that add_one's precondition gets assumed since it's the target of the proof_for_contract.
#[kani::proof_for_contract(add_one)]
fn prove_add_one() {
let mut i = kani::any();
kani::assume(i < 100);
add_three(&mut i);
}
}
13 changes: 13 additions & 0 deletions tests/expected/function-contract/as-assertions/precedence.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
assertion\
- Status: UNREACHABLE\
- Description: "*add_one_ptr == 1"

assertion\
- Status: UNREACHABLE\
- Description: "|result| old(*add_one_ptr + 1) == *add_one_ptr"

assertion\
- Status: UNREACHABLE\
- Description: "|result| old(*add_one_ptr + 1) == *add_one_ptr"

Complete - 2 successfully verified harnesses, 0 failures, 2 total.
48 changes: 48 additions & 0 deletions tests/expected/function-contract/as-assertions/precedence.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright Kani Contributors
// SPDX-License-Identifier: Apache-2.0 OR MIT
// kani-flags: -Zfunction-contracts -Zcontracts-as-assertions

// If a function is the target of a proof_for_contract or stub_verified, we should defer to the contract handling for those modes.
// i.e., test that -Zcontracts-as-assertions does not override the contract handling for proof_for_contract and stub_verified.

#[kani::modifies(add_three_ptr)]
#[kani::requires(*add_three_ptr < 100)]
fn add_three(add_three_ptr: &mut u32) {
*add_three_ptr += 1;
add_two(add_three_ptr);
}

#[kani::requires(*add_two_ptr < 101)]
#[kani::ensures(|result| old(*add_two_ptr + 2) == *add_two_ptr)]
fn add_two(add_two_ptr: &mut u32) {
*add_two_ptr += 1;
add_one(add_two_ptr);
}

#[kani::modifies(add_one_ptr)]
#[kani::requires(*add_one_ptr == 1)]
#[kani::ensures(|result| old(*add_one_ptr + 1) == *add_one_ptr)]
fn add_one(add_one_ptr: &mut u32) {
*add_one_ptr += 1;
}

// Test that proof_for_contract takes precedence over the assert mode, i.e.
// that the target of the proof for contract still has its preconditions assumed.
#[kani::proof_for_contract(add_one)]
fn proof_for_contract_takes_precedence() {
let mut i = kani::any();
// if add_one's precondition was asserted, verification would fail,
// but since it's assumed, we get a vacuously successful proof instead.
kani::assume(i == 2);
add_one(&mut i);
}

// Test that stub_verified takes precedence over the assert mode.
// Verification should succeed because we stub add_two by its contract,
// meaning we never reach add_one's contract.
#[kani::proof_for_contract(add_three)]
#[kani::stub_verified(add_two)]
fn stub_verified_takes_precedence() {
let mut i = kani::any();
add_three(&mut i);
}

0 comments on commit d4a8fc0

Please sign in to comment.