mirror of https://codeberg.org/topola/topola.git
170 lines
3.5 KiB
Rust
170 lines
3.5 KiB
Rust
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
//! Testing of simple functions.
|
|
|
|
use contracts::*;
|
|
|
|
#[cfg(feature = "mirai_assertions")]
|
|
mod mirai_assertion_mocks;
|
|
|
|
#[test]
|
|
fn test_a_thing() {
|
|
#[requires(x > 10, x < 20, "x must be in valid range")]
|
|
#[ensures(ret > x, "result will be bigger than input")]
|
|
fn a(x: usize) -> usize {
|
|
x + 1
|
|
}
|
|
|
|
a(15);
|
|
}
|
|
|
|
#[test]
|
|
fn test_sort() {
|
|
fn is_sorted(input: &[usize]) -> bool {
|
|
if input.len() < 2 {
|
|
return true;
|
|
}
|
|
|
|
for i in 1..input.len() {
|
|
if input[i - 1] > input[i] {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
true
|
|
}
|
|
|
|
#[ensures(ret.len() == input.len())]
|
|
#[test_ensures(is_sorted(&ret))]
|
|
fn sort(input: &[usize]) -> Vec<usize> {
|
|
let mut vec = input.to_owned();
|
|
|
|
vec.sort_unstable();
|
|
|
|
vec
|
|
}
|
|
|
|
let input = vec![31, 234, 34, 0, 4234, 85];
|
|
|
|
sort(&input);
|
|
}
|
|
|
|
#[test]
|
|
fn test_invariant() {
|
|
#[invariant(*val <= 10)]
|
|
fn add_to_10(val: &mut usize) {
|
|
if *val >= 10 {
|
|
return;
|
|
}
|
|
*val += 1;
|
|
}
|
|
|
|
let mut val = 8;
|
|
|
|
add_to_10(&mut val);
|
|
add_to_10(&mut val);
|
|
add_to_10(&mut val);
|
|
add_to_10(&mut val);
|
|
add_to_10(&mut val);
|
|
}
|
|
|
|
#[test]
|
|
#[should_panic(expected = "Post-condition of abs violated")]
|
|
fn test_early_return() {
|
|
// make sure that post-conditions are executed even if an early return happened.
|
|
|
|
#[ensures(ret >= 0)]
|
|
#[ensures(ret == x || ret == -x)]
|
|
#[ensures(ret * ret == x * x)]
|
|
fn abs(x: isize) -> isize {
|
|
if x < 0 {
|
|
// this implementation does not respect the contracts!
|
|
return 0;
|
|
}
|
|
x
|
|
}
|
|
|
|
abs(-4);
|
|
}
|
|
|
|
#[test]
|
|
fn test_mut_ref_and_lifetimes() {
|
|
#[requires(i < s.len())]
|
|
#[ensures(*ret == 0)]
|
|
fn insert_zero<'a>(s: &'a mut [u8], i: usize) -> &'a mut u8 {
|
|
s[i] = 0;
|
|
&mut s[i]
|
|
}
|
|
|
|
insert_zero(&mut [4, 2], 1);
|
|
}
|
|
|
|
#[test]
|
|
fn test_pattern_match() {
|
|
#[ensures(ret > a && ret > b)]
|
|
fn add((a, b): (u8, u8)) -> u8 {
|
|
a.saturating_add(b)
|
|
}
|
|
|
|
assert_eq!(add((4, 2)), 6);
|
|
}
|
|
|
|
#[test]
|
|
fn test_impl_trait_return() {
|
|
// make sure that compiling functions that return existentially
|
|
// qualified types works properly.
|
|
|
|
#[requires(x >= 10)]
|
|
#[ensures(Clone::clone(&ret) == ret)]
|
|
#[allow(unused_variables)]
|
|
fn impl_test(x: isize) -> impl Clone + PartialEq + std::fmt::Debug {
|
|
"it worked"
|
|
}
|
|
|
|
let x = impl_test(200);
|
|
let y = x.clone();
|
|
assert_eq!(
|
|
format!("{:?} and {:?}", x, y),
|
|
r#""it worked" and "it worked""#
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_impl_trait_arg() {
|
|
#[requires(Clone::clone(&x) == x)]
|
|
#[ensures(Clone::clone(&ret) == ret)]
|
|
fn impl_test(x: impl Clone + PartialEq + std::fmt::Debug) -> &'static str {
|
|
"it worked"
|
|
}
|
|
|
|
let x = impl_test(200);
|
|
let y = Clone::clone(&x);
|
|
assert_eq!(
|
|
format!("{:?} and {:?}", x, y),
|
|
r#""it worked" and "it worked""#
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
#[deny(clippy::used_underscore_binding)]
|
|
fn test_unbound_parameters_clippy() {
|
|
#[requires(__y == 3)]
|
|
#[ensures(ret)]
|
|
fn param_test(_x: i32, __y: i32) -> bool {
|
|
true
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
#[deny(non_fmt_panics)]
|
|
fn test_braced_condition_expression_clippy() {
|
|
#[requires(if __y == 3 {
|
|
__y != 0
|
|
} else {
|
|
false
|
|
})]
|
|
fn param_test(_x: i32, __y: i32) {}
|
|
}
|