blob: 85a96d7f2d45bfaf15cd5a1371f696e6a187549b [file]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
pub use futures::FutureExt;
use futures::future::BoxFuture;
use std::string::String;
use std::vec::Vec;
pub use teaclave_test_utils_proc_macro::{async_test_case, test_case};
pub struct TestCase(pub String, pub fn() -> ());
pub struct AsyncTestCase(pub String, pub fn() -> BoxFuture<'static, ()>);
inventory::collect!(TestCase);
inventory::collect!(AsyncTestCase);
use std::time::Instant;
#[cfg(feature = "mesalock_sgx")]
#[allow(unused_imports)]
use std::untrusted::time::InstantEx;
#[macro_export]
macro_rules! run_inventory_tests {
($predicate:expr) => {{
teaclave_test_utils::test_start();
let mut ntestcases: u64 = 0u64;
let mut failurecases: Vec<String> = Vec::new();
for t in inventory::iter::<teaclave_test_utils::TestCase>.into_iter() {
if $predicate(&t.0) {
teaclave_test_utils::test(&mut ntestcases, &mut failurecases, t.1, &t.0);
}
}
for t in inventory::iter::<teaclave_test_utils::AsyncTestCase>.into_iter() {
if $predicate(&t.0) {
teaclave_test_utils::async_test(&mut ntestcases, &mut failurecases, t.1, &t.0);
}
}
teaclave_test_utils::test_end(ntestcases, failurecases)
}};
() => {
run_inventory_tests!(|_| true);
};
}
#[macro_export]
macro_rules! should_panic {
($fmt:expr) => {{
match ::std::panic::catch_unwind(|| $fmt).is_err() {
true => {
println!(
"{} {} ... {}!",
"testing_should_panic",
stringify!($fmt),
"\x1B[1;32mok\x1B[0m"
);
}
false => ::std::rt::begin_panic($fmt),
}
}};
}
#[macro_export]
macro_rules! check_all_passed {
(
$($f : expr),* $(,)?
) => {
{
let mut v: Vec<bool> = Vec::new();
$(
v.push($f);
)*
v.iter().all(|&x| x)
}
}
}
#[macro_export]
macro_rules! run_tests {
(
$($f : expr),* $(,)?
) => {
{
teaclave_test_utils::test_start();
let mut ntestcases : u64 = 0u64;
let mut failurecases : Vec<String> = Vec::new();
$(teaclave_test_utils::test(&mut ntestcases, &mut failurecases, $f,stringify!($f));)*
teaclave_test_utils::test_end(ntestcases, failurecases)
}
}
}
#[macro_export]
macro_rules! run_async_tests {
(
$($f : expr),* $(,)?
) => {
{
teaclave_test_utils::test_start();
let mut ntestcases : u64 = 0u64;
let mut failurecases : Vec<String> = Vec::new();
use $crate::FutureExt;
$(teaclave_test_utils::async_test(&mut ntestcases, &mut failurecases, || async {$f().await}.boxed(),stringify!($f));)*
teaclave_test_utils::test_end(ntestcases, failurecases)
}
}
}
pub fn test_start() {
println!("\nstart running tests");
}
pub fn test_end(ntestcases: u64, failurecases: Vec<String>) -> bool {
let ntotal = ntestcases as usize;
let nsucc = ntestcases as usize - failurecases.len();
if !failurecases.is_empty() {
print!("\nfailures: ");
println!(
" {}",
failurecases
.iter()
.fold(String::new(), |s, per| s + "\n " + per)
);
}
if ntotal == nsucc {
print!("\ntest result \x1B[1;32mok\x1B[0m. ");
} else {
print!("\ntest result \x1B[1;31mFAILED\x1B[0m. ");
}
println!(
"{} tested, {} passed, {} failed",
ntotal,
nsucc,
ntotal - nsucc
);
failurecases.is_empty()
}
#[allow(clippy::print_literal)]
fn do_test<F>(f: F, ncases: &mut u64, failurecases: &mut Vec<String>, name: &str)
where
F: FnOnce() -> f64 + std::panic::UnwindSafe,
{
*ncases += 1;
match std::panic::catch_unwind(f) {
Ok(elapsed) => {
println!("{} {} ... {}!", "testing", name, "\x1B[1;32mok\x1B[0m");
if elapsed < 0.5 {
println!(" Elapsed time: {:?}", elapsed);
} else {
println!(" Elapsed time: \x1B[1;31m{:?}\x1B[0m", elapsed);
}
}
Err(_) => {
println!("{} {} ... {}!", "testing", name, "\x1B[1;31mfailed\x1B[0m");
failurecases.push(String::from(name));
}
}
}
pub fn test<F, R>(ncases: &mut u64, failurecases: &mut Vec<String>, f: F, name: &str)
where
F: FnOnce() -> R + std::panic::UnwindSafe,
{
let t = || -> f64 {
let before = Instant::now();
f();
before.elapsed().as_secs_f64()
};
do_test(t, ncases, failurecases, name)
}
pub fn async_test<F>(ncases: &mut u64, failurecases: &mut Vec<String>, f: F, name: &str)
where
F: FnOnce() -> BoxFuture<'static, ()> + std::panic::UnwindSafe,
{
let t = || -> f64 {
let before = Instant::now();
let rt = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.unwrap();
rt.block_on(f());
before.elapsed().as_secs_f64()
};
do_test(t, ncases, failurecases, name)
}