use elicitation::contracts::{And, Established, Prop, both};
macro_rules! assert_prop_zero_sized {
($name:ident) => {
#[derive(elicitation::Prop)]
struct $name;
assert!(
std::mem::size_of::<$name>() == 0,
"{} must be zero-sized",
stringify!($name)
);
assert!(
std::mem::size_of::<Established<$name>>() == 0,
"Established<{}> must be zero-sized",
stringify!($name)
);
};
}
#[cfg(feature = "tokio-types")]
#[kani::proof]
fn verify_time_props_zero_sized() {
assert_prop_zero_sized!(SleepCompleted);
assert_prop_zero_sized!(TimeoutResolved);
}
#[cfg(feature = "tokio-types")]
#[kani::proof]
fn verify_sleep_completed_axiom() {
let duration_ms: u64 = kani::any();
let sleep_returned_ok: bool = kani::any();
kani::assume(sleep_returned_ok);
assert!(
sleep_returned_ok,
"tokio::time::sleep axiom: returns when duration elapsed"
);
}
#[cfg(feature = "tokio-types")]
#[kani::proof]
fn verify_timeout_resolved_axiom() {
let timed_out: bool = kani::any();
let resolved = true; assert!(
resolved,
"tokio::time::timeout axiom: always resolves to Ok or Elapsed"
);
let _ = timed_out;
}
#[cfg(feature = "tokio-types")]
#[kani::proof]
fn verify_sync_props_zero_sized() {
assert_prop_zero_sized!(PermitAcquired);
assert_prop_zero_sized!(NotificationReceived);
assert_prop_zero_sized!(BarrierReached);
}
#[cfg(feature = "tokio-types")]
#[kani::proof]
fn verify_permit_acquired_axiom() {
let permits_available: u32 = kani::any();
kani::assume(permits_available > 0);
let acquired = true;
assert!(
acquired,
"tokio::sync::Semaphore::acquire axiom: Ok => permit decremented"
);
}
#[cfg(feature = "tokio-types")]
#[kani::proof]
fn verify_notification_received_axiom() {
let notified: bool = kani::any();
kani::assume(notified);
assert!(
notified,
"tokio::sync::Notify::notified axiom: returns when notify_one/waiters called"
);
}
#[cfg(feature = "tokio-types")]
#[kani::proof]
fn verify_barrier_reached_axiom() {
let all_arrived: bool = kani::any();
kani::assume(all_arrived);
assert!(
all_arrived,
"tokio::sync::Barrier::wait axiom: returns when all parties arrive"
);
}
#[cfg(feature = "tokio-types")]
#[kani::proof]
fn verify_net_props_zero_sized() {
assert_prop_zero_sized!(ListenerBound);
assert_prop_zero_sized!(ConnectionAccepted);
assert_prop_zero_sized!(StreamConnected);
assert_prop_zero_sized!(DataReceived);
}
#[cfg(feature = "tokio-types")]
#[kani::proof]
fn verify_listener_bound_axiom() {
let bind_ok: bool = kani::any();
kani::assume(bind_ok);
assert!(
bind_ok,
"tokio::net::TcpListener::bind axiom: Ok => socket bound"
);
}
#[cfg(feature = "tokio-types")]
#[kani::proof]
fn verify_connection_accepted_axiom() {
let accept_ok: bool = kani::any();
kani::assume(accept_ok);
assert!(
accept_ok,
"tokio::net::TcpListener::accept axiom: Ok => connection stream ready"
);
}
#[cfg(feature = "tokio-types")]
#[kani::proof]
fn verify_stream_connected_axiom() {
let connect_ok: bool = kani::any();
kani::assume(connect_ok);
assert!(
connect_ok,
"tokio::net::TcpStream::connect axiom: Ok => TCP handshake complete"
);
}
#[cfg(feature = "tokio-types")]
#[kani::proof]
fn verify_data_received_axiom() {
let bytes: usize = kani::any();
kani::assume(bytes > 0);
assert!(
bytes > 0,
"AsyncReadExt::read axiom: Ok(n > 0) => bytes available"
);
}
#[cfg(feature = "tokio-types")]
#[kani::proof]
fn verify_fs_props_zero_sized() {
assert_prop_zero_sized!(FileRead);
assert_prop_zero_sized!(FileWritten);
assert_prop_zero_sized!(DirCreated);
}
#[cfg(feature = "tokio-types")]
#[kani::proof]
fn verify_file_read_axiom() {
let read_ok: bool = kani::any();
kani::assume(read_ok);
assert!(
read_ok,
"tokio::fs::read axiom: Ok => file contents available"
);
}
#[cfg(feature = "tokio-types")]
#[kani::proof]
fn verify_file_written_axiom() {
let write_ok: bool = kani::any();
kani::assume(write_ok);
assert!(
write_ok,
"tokio::fs::write axiom: Ok => all bytes flushed to disk"
);
}
#[cfg(feature = "tokio-types")]
#[kani::proof]
fn verify_dir_created_axiom() {
let mkdir_ok: bool = kani::any();
kani::assume(mkdir_ok);
assert!(
mkdir_ok,
"tokio::fs::create_dir_all axiom: Ok => directory path exists"
);
}
#[cfg(feature = "tokio-types")]
#[kani::proof]
fn verify_process_props_zero_sized() {
assert_prop_zero_sized!(ProcessSpawned);
assert_prop_zero_sized!(ProcessExited);
assert_prop_zero_sized!(StdinWritten);
}
#[cfg(feature = "tokio-types")]
#[kani::proof]
fn verify_process_spawned_axiom() {
let spawn_ok: bool = kani::any();
kani::assume(spawn_ok);
assert!(
spawn_ok,
"tokio::process::Command::spawn axiom: Ok => OS process is running"
);
}
#[cfg(feature = "tokio-types")]
#[kani::proof]
fn verify_process_exited_axiom() {
let wait_ok: bool = kani::any();
kani::assume(wait_ok);
assert!(
wait_ok,
"tokio::process::Child::wait axiom: Ok => child process has exited"
);
}
#[cfg(feature = "tokio-types")]
#[kani::proof]
fn verify_stdin_written_axiom() {
let write_ok: bool = kani::any();
kani::assume(write_ok);
assert!(
write_ok,
"AsyncWriteExt::write_all(stdin) axiom: Ok => all bytes written to pipe"
);
}
#[cfg(feature = "tokio-types")]
#[kani::proof]
fn verify_channel_props_zero_sized() {
assert_prop_zero_sized!(MessageSent);
assert_prop_zero_sized!(MessageReceived);
assert_prop_zero_sized!(ChannelClosed);
}
#[cfg(feature = "tokio-types")]
#[kani::proof]
fn verify_message_sent_axiom() {
let send_ok: bool = kani::any();
kani::assume(send_ok);
assert!(
send_ok,
"tokio channel send axiom: Ok => value enqueued for receiver(s)"
);
}
#[cfg(feature = "tokio-types")]
#[kani::proof]
fn verify_message_received_axiom() {
let recv_some: bool = kani::any();
kani::assume(recv_some);
assert!(
recv_some,
"tokio channel recv axiom: Some(v)/Ok(v) => value was sent"
);
}
#[cfg(feature = "tokio-types")]
#[kani::proof]
fn verify_channel_closed_axiom() {
let close_ok: bool = kani::any();
kani::assume(close_ok);
assert!(
close_ok,
"tokio channel close axiom: drop/remove => endpoint closed"
);
}
#[cfg(feature = "tokio-types")]
#[kani::proof]
fn verify_signal_props_zero_sized() {
assert_prop_zero_sized!(CtrlCReceived);
assert_prop_zero_sized!(SignalHandlerRegistered);
assert_prop_zero_sized!(SignalReceived);
}
#[cfg(feature = "tokio-types")]
#[kani::proof]
fn verify_ctrl_c_received_axiom() {
let ctrl_c_ok: bool = kani::any();
kani::assume(ctrl_c_ok);
assert!(
ctrl_c_ok,
"tokio::signal::ctrl_c axiom: Ok => SIGINT received"
);
}
#[cfg(feature = "tokio-types")]
#[kani::proof]
fn verify_signal_handler_registered_axiom() {
let register_ok: bool = kani::any();
kani::assume(register_ok);
assert!(
register_ok,
"tokio::signal::unix::signal axiom: Ok => OS handler registered"
);
}
#[cfg(feature = "tokio-types")]
#[kani::proof]
fn verify_signal_received_axiom() {
let sig_some: bool = kani::any();
kani::assume(sig_some);
assert!(
sig_some,
"Signal::recv axiom: Some(()) => registered signal was delivered"
);
}
#[cfg(feature = "tokio-types")]
#[kani::proof]
fn verify_io_props_zero_sized() {
assert_prop_zero_sized!(DuplexCreated);
assert_prop_zero_sized!(BytesCopied);
}
#[cfg(feature = "tokio-types")]
#[kani::proof]
fn verify_duplex_created_axiom() {
let created = true;
assert!(
created,
"tokio::io::duplex axiom: always returns a connected (a, b) pair"
);
}
#[cfg(feature = "tokio-types")]
#[kani::proof]
fn verify_bytes_copied_axiom() {
let copy_ok: bool = kani::any();
kani::assume(copy_ok);
let n: u64 = kani::any();
assert!(
copy_ok,
"tokio::io::copy axiom: Ok(n) => n bytes transferred reader→writer"
);
let _ = n;
}
#[cfg(feature = "tokio-types")]
#[kani::proof]
fn verify_task_props_zero_sized() {
assert_prop_zero_sized!(TaskYielded);
assert_prop_zero_sized!(TaskSpawned);
assert_prop_zero_sized!(TaskJoined);
assert_prop_zero_sized!(TaskAborted);
}
#[cfg(feature = "tokio-types")]
#[kani::proof]
fn verify_task_yielded_axiom() {
let yielded = true; assert!(
yielded,
"tokio::task::yield_now axiom: always returns after yielding"
);
}
#[cfg(feature = "tokio-types")]
#[kani::proof]
fn verify_task_spawned_axiom() {
let spawn_ok = true; assert!(
spawn_ok,
"tokio::spawn axiom: JoinHandle returned => task accepted by scheduler"
);
}
#[cfg(feature = "tokio-types")]
#[kani::proof]
fn verify_task_joined_axiom() {
let join_ok: bool = kani::any();
kani::assume(join_ok);
assert!(
join_ok,
"JoinHandle::await axiom: Ok => task completed without panic"
);
}
#[cfg(feature = "tokio-types")]
#[kani::proof]
fn verify_task_aborted_axiom() {
let abort_scheduled = true; assert!(
abort_scheduled,
"JoinHandle::abort axiom: schedules cancellation (infallible)"
);
}
#[cfg(feature = "tokio-types")]
#[kani::proof]
fn verify_runtime_props_zero_sized() {
assert_prop_zero_sized!(RuntimeFlavored);
}
#[cfg(feature = "tokio-types")]
#[kani::proof]
fn verify_runtime_flavored_axiom() {
let flavor_known = true; assert!(
flavor_known,
"Handle::runtime_flavor axiom: always returns when called inside runtime"
);
}
#[cfg(all(feature = "tokio-types", unix))]
#[kani::proof]
fn verify_unix_props_zero_sized() {
assert_prop_zero_sized!(UnixListenerBound);
assert_prop_zero_sized!(UnixConnectionAccepted);
assert_prop_zero_sized!(UnixStreamConnected);
assert_prop_zero_sized!(UnixDataReceived);
}
#[cfg(all(feature = "tokio-types", unix))]
#[kani::proof]
fn verify_unix_listener_bound_axiom() {
let bind_ok: bool = kani::any();
kani::assume(bind_ok);
assert!(
bind_ok,
"tokio::net::UnixListener::bind axiom: Ok => socket file created"
);
}
#[cfg(all(feature = "tokio-types", unix))]
#[kani::proof]
fn verify_unix_connection_accepted_axiom() {
let accept_ok: bool = kani::any();
kani::assume(accept_ok);
assert!(
accept_ok,
"tokio::net::UnixListener::accept axiom: Ok => client stream ready"
);
}
#[cfg(all(feature = "tokio-types", unix))]
#[kani::proof]
fn verify_unix_stream_connected_axiom() {
let connect_ok: bool = kani::any();
kani::assume(connect_ok);
assert!(
connect_ok,
"tokio::net::UnixStream::connect axiom: Ok => connected to socket"
);
}
#[cfg(all(feature = "tokio-types", unix))]
#[kani::proof]
fn verify_unix_data_received_axiom() {
let bytes: usize = kani::any();
kani::assume(bytes > 0);
assert!(
bytes > 0,
"UnixStream::read axiom: Ok(n > 0) => bytes available"
);
}
#[cfg(feature = "tokio-types")]
#[kani::proof]
fn verify_established_zero_sized_general() {
use std::mem::size_of;
#[derive(elicitation::Prop)]
struct AnyProp;
assert!(size_of::<Established<AnyProp>>() == 0);
}
#[cfg(feature = "tokio-types")]
#[kani::proof]
fn verify_and_combinator_zero_sized() {
use std::mem::size_of;
#[derive(elicitation::Prop)]
struct P;
#[derive(elicitation::Prop)]
struct Q;
assert!(size_of::<And<P, Q>>() == 0);
}
#[cfg(feature = "tokio-types")]
#[kani::proof]
fn verify_both_composition_zero_sized() {
use std::mem::size_of;
#[derive(elicitation::Prop)]
struct P;
#[derive(elicitation::Prop)]
struct Q;
let p: Established<P> = Established::assert();
let q: Established<Q> = Established::assert();
let _combined: Established<And<P, Q>> = both(p, q);
assert!(size_of::<Established<And<P, Q>>>() == 0);
}
#[cfg(feature = "tokio-types")]
#[kani::proof]
fn verify_three_way_composition_zero_sized() {
use std::mem::size_of;
#[derive(elicitation::Prop)]
struct Bound;
#[derive(elicitation::Prop)]
struct Accepted;
#[derive(elicitation::Prop)]
struct Connected;
let p: Established<Bound> = Established::assert();
let q: Established<Accepted> = Established::assert();
let r: Established<Connected> = Established::assert();
let pq: Established<And<Bound, Accepted>> = both(p, q);
let _pqr: Established<And<And<Bound, Accepted>, Connected>> = both(pq, r);
assert!(size_of::<Established<And<And<Bound, Accepted>, Connected>>>() == 0);
}