use crate::{
BroadcastReceiver, BroadcastSender, ConformanceTest, MpscReceiver, MpscSender, OneshotSender,
RuntimeInterface, TestCategory, TestMeta, TestResult, checkpoint,
};
use std::env;
use std::sync::Arc;
use std::sync::atomic::{AtomicU64, Ordering};
use std::time::{Duration, Instant};
pub fn all_tests<RT: RuntimeInterface>() -> Vec<ConformanceTest<RT>> {
let mut tests = Vec::new();
tests.extend(region_negative_tests::<RT>());
tests.extend(channel_negative_tests::<RT>());
tests.extend(budget_negative_tests::<RT>());
tests.extend(time_negative_tests::<RT>());
tests.extend(performance_bounds_tests::<RT>());
tests
}
pub fn negative_only_tests<RT: RuntimeInterface>() -> Vec<ConformanceTest<RT>> {
let mut tests = Vec::new();
tests.extend(region_negative_tests::<RT>());
tests.extend(channel_negative_tests::<RT>());
tests.extend(budget_negative_tests::<RT>());
tests.extend(time_negative_tests::<RT>());
tests
}
pub fn performance_tests<RT: RuntimeInterface>() -> Vec<ConformanceTest<RT>> {
performance_bounds_tests::<RT>()
}
fn region_negative_tests<RT: RuntimeInterface>() -> Vec<ConformanceTest<RT>> {
vec![
neg_rg_001_double_await_handle::<RT>(),
neg_rg_002_spawn_returns_immediately::<RT>(),
neg_rg_003_concurrent_join_same_handle::<RT>(),
]
}
fn neg_rg_001_double_await_handle<RT: RuntimeInterface>() -> ConformanceTest<RT> {
ConformanceTest::new(
TestMeta {
id: "neg-rg-001".to_string(),
name: "Double await on join handle".to_string(),
description:
"Join handles should be consumed on first await (compile-time or runtime check)"
.to_string(),
category: TestCategory::Spawn,
tags: vec![
"negative".to_string(),
"region".to_string(),
"join".to_string(),
"spec:3.1.2".to_string(),
],
expected: "Join handle cannot be awaited twice".to_string(),
},
|rt| {
rt.block_on(async {
let handle = rt.spawn(async { 42i32 });
let result = handle.await;
checkpoint("first_await", serde_json::json!({"result": result}));
if result != 42 {
return TestResult::failed(format!(
"First await should return 42, got {}",
result
));
}
TestResult::passed()
})
},
)
}
fn neg_rg_002_spawn_returns_immediately<RT: RuntimeInterface>() -> ConformanceTest<RT> {
ConformanceTest::new(
TestMeta {
id: "neg-rg-002".to_string(),
name: "Spawn returns immediately".to_string(),
description: "Spawn should return immediately, not block on task completion"
.to_string(),
category: TestCategory::Spawn,
tags: vec![
"negative".to_string(),
"region".to_string(),
"spawn".to_string(),
"spec:3.1.1".to_string(),
],
expected: "Spawn returns in <10ms even for long-running tasks".to_string(),
},
|rt| {
rt.block_on(async {
let start = Instant::now();
let _handle = rt.spawn(async {
for _ in 0..100_000 {
std::hint::black_box(0u64);
}
42
});
let spawn_time = start.elapsed();
checkpoint(
"spawn_returned",
serde_json::json!({"spawn_time_us": spawn_time.as_micros().min(u128::from(u64::MAX)) as u64}),
);
if spawn_time > Duration::from_millis(10) {
return TestResult::failed(format!(
"Spawn took too long: {:?} (expected < 10ms). Spawn must not block.",
spawn_time
));
}
TestResult::passed()
})
},
)
}
fn neg_rg_003_concurrent_join_same_handle<RT: RuntimeInterface>() -> ConformanceTest<RT> {
ConformanceTest::new(
TestMeta {
id: "neg-rg-003".to_string(),
name: "Concurrent join behavior".to_string(),
description: "Multiple concurrent joins on same task should be well-defined"
.to_string(),
category: TestCategory::Spawn,
tags: vec![
"negative".to_string(),
"region".to_string(),
"concurrent".to_string(),
],
expected: "At most one joiner gets the result; others get error or nothing".to_string(),
},
|rt| {
rt.block_on(async {
let (tx, mut rx) = rt.mpsc_channel::<i32>(1);
let handle = rt.spawn(async move {
let _ = tx.send(42).await;
42i32
});
let result = handle.await;
let sent_value = rx.recv().await;
checkpoint(
"join_result",
serde_json::json!({
"handle_result": result,
"sent_value": sent_value
}),
);
if result != 42 {
return TestResult::failed(format!("Expected 42, got {}", result));
}
if sent_value != Some(42) {
return TestResult::failed(format!("Expected Some(42), got {:?}", sent_value));
}
TestResult::passed()
})
},
)
}
fn channel_negative_tests<RT: RuntimeInterface>() -> Vec<ConformanceTest<RT>> {
vec![
neg_ch_001_recv_from_closed::<RT>(),
neg_ch_002_send_to_closed::<RT>(),
neg_ch_003_oneshot_double_send::<RT>(),
neg_ch_004_broadcast_lagged::<RT>(),
neg_ch_005_empty_channel_recv::<RT>(),
]
}
fn neg_ch_001_recv_from_closed<RT: RuntimeInterface>() -> ConformanceTest<RT> {
ConformanceTest::new(
TestMeta {
id: "neg-ch-001".to_string(),
name: "Receive from closed MPSC channel".to_string(),
description: "Receiving from a channel after all senders dropped returns None"
.to_string(),
category: TestCategory::Channels,
tags: vec![
"negative".to_string(),
"channel".to_string(),
"closed".to_string(),
],
expected: "recv() returns None after senders dropped".to_string(),
},
|rt| {
rt.block_on(async {
let (tx, mut rx) = rt.mpsc_channel::<i32>(10);
let _ = tx.send(42).await;
drop(tx);
let first = rx.recv().await;
let second = rx.recv().await;
checkpoint(
"recv_results",
serde_json::json!({
"first": first,
"second": second
}),
);
if first != Some(42) {
return TestResult::failed(format!(
"First recv should be Some(42), got {:?}",
first
));
}
if second.is_some() {
return TestResult::failed(format!(
"Second recv should be None, got {:?}",
second
));
}
TestResult::passed()
})
},
)
}
fn neg_ch_002_send_to_closed<RT: RuntimeInterface>() -> ConformanceTest<RT> {
ConformanceTest::new(
TestMeta {
id: "neg-ch-002".to_string(),
name: "Send to closed MPSC channel".to_string(),
description: "Sending to a channel after receiver dropped returns error".to_string(),
category: TestCategory::Channels,
tags: vec![
"negative".to_string(),
"channel".to_string(),
"closed".to_string(),
],
expected: "send() returns Err after receiver dropped".to_string(),
},
|rt| {
rt.block_on(async {
let (tx, rx) = rt.mpsc_channel::<i32>(10);
drop(rx);
let result = tx.send(42).await;
checkpoint(
"send_result",
serde_json::json!({"is_err": result.is_err()}),
);
if result.is_ok() {
return TestResult::failed(
"Send to closed channel should return Err".to_string(),
);
}
if let Err(value) = result
&& value != 42
{
return TestResult::failed(format!(
"Error should contain original value 42, got {}",
value
));
}
TestResult::passed()
})
},
)
}
fn neg_ch_003_oneshot_double_send<RT: RuntimeInterface>() -> ConformanceTest<RT> {
ConformanceTest::new(
TestMeta {
id: "neg-ch-003".to_string(),
name: "Oneshot double send".to_string(),
description: "Sending twice on oneshot channel should fail (compile-time enforced)"
.to_string(),
category: TestCategory::Channels,
tags: vec![
"negative".to_string(),
"channel".to_string(),
"oneshot".to_string(),
"spec:4.2.1".to_string(),
],
expected: "Second send is prevented by type system".to_string(),
},
|rt| {
rt.block_on(async {
let (tx, rx) = rt.oneshot_channel::<i32>();
let first_result = tx.send(42);
checkpoint(
"first_send",
serde_json::json!({"is_ok": first_result.is_ok()}),
);
let recv_result = rx.await;
match recv_result {
Ok(value) => {
if value != 42 {
return TestResult::failed(format!("Expected 42, got {}", value));
}
TestResult::passed()
}
Err(_) => TestResult::failed("Receiver should get value".to_string()),
}
})
},
)
}
fn neg_ch_004_broadcast_lagged<RT: RuntimeInterface>() -> ConformanceTest<RT> {
ConformanceTest::new(
TestMeta {
id: "neg-ch-004".to_string(),
name: "Broadcast receiver lagged".to_string(),
description: "Slow broadcast receivers should receive lagged errors".to_string(),
category: TestCategory::Channels,
tags: vec![
"negative".to_string(),
"channel".to_string(),
"broadcast".to_string(),
"lagged".to_string(),
],
expected: "Receiver gets BroadcastRecvError::Lagged when behind".to_string(),
},
|rt| {
rt.block_on(async {
let (tx, mut rx) = rt.broadcast_channel::<i32>(2);
for i in 0..10 {
let _ = tx.send(i);
}
let result = rx.recv().await;
checkpoint(
"recv_result",
serde_json::json!({"result": format!("{:?}", result)}),
);
match result {
Err(crate::BroadcastRecvError::Lagged(n)) => {
checkpoint("lagged", serde_json::json!({"missed": n}));
TestResult::passed()
}
Ok(value) => {
checkpoint("got_value", serde_json::json!({"value": value}));
TestResult::passed()
}
Err(crate::BroadcastRecvError::Closed) => {
TestResult::failed("Channel should not be closed".to_string())
}
}
})
},
)
}
fn neg_ch_005_empty_channel_recv<RT: RuntimeInterface>() -> ConformanceTest<RT> {
ConformanceTest::new(
TestMeta {
id: "neg-ch-005".to_string(),
name: "Empty channel blocks".to_string(),
description: "Receiving from empty but open channel should block".to_string(),
category: TestCategory::Channels,
tags: vec![
"negative".to_string(),
"channel".to_string(),
"blocking".to_string(),
],
expected: "recv() blocks until value available or timeout".to_string(),
},
|rt| {
rt.block_on(async {
let (tx, mut rx) = rt.mpsc_channel::<i32>(10);
let start = Instant::now();
let result = rt
.timeout(Duration::from_millis(50), async { rx.recv().await })
.await;
let elapsed = start.elapsed();
checkpoint(
"recv_result",
serde_json::json!({
"timed_out": result.is_err(),
"elapsed_ms": elapsed.as_millis().min(u128::from(u64::MAX)) as u64
}),
);
let _ = tx;
if result.is_ok() {
return TestResult::failed(
"Recv from empty channel should timeout".to_string(),
);
}
TestResult::passed()
})
},
)
}
fn budget_negative_tests<RT: RuntimeInterface>() -> Vec<ConformanceTest<RT>> {
vec![
neg_bd_001_zero_poll_quota::<RT>(),
neg_bd_002_expired_deadline::<RT>(),
neg_bd_003_zero_cost_quota::<RT>(),
]
}
fn neg_bd_001_zero_poll_quota<RT: RuntimeInterface>() -> ConformanceTest<RT> {
ConformanceTest::new(
TestMeta {
id: "neg-bd-001".to_string(),
name: "Zero poll quota behavior".to_string(),
description: "A task with zero poll quota should not be able to make progress"
.to_string(),
category: TestCategory::Cancel,
tags: vec![
"negative".to_string(),
"budget".to_string(),
"poll-quota".to_string(),
"spec:3.2.2".to_string(),
],
expected: "Task with exhausted poll quota cannot proceed".to_string(),
},
|rt| {
rt.block_on(async {
let start = Instant::now();
let result = rt.timeout(Duration::ZERO, async { 42 }).await;
let elapsed = start.elapsed();
checkpoint(
"zero_timeout",
serde_json::json!({
"result": format!("{:?}", result),
"elapsed_us": elapsed.as_micros().min(u128::from(u64::MAX)) as u64
}),
);
TestResult::passed()
})
},
)
}
fn neg_bd_002_expired_deadline<RT: RuntimeInterface>() -> ConformanceTest<RT> {
ConformanceTest::new(
TestMeta {
id: "neg-bd-002".to_string(),
name: "Expired deadline immediate timeout".to_string(),
description: "A deadline that has already passed should timeout immediately"
.to_string(),
category: TestCategory::Time,
tags: vec![
"negative".to_string(),
"budget".to_string(),
"deadline".to_string(),
"spec:3.2.1".to_string(),
],
expected: "Immediate timeout without executing work".to_string(),
},
|rt| {
rt.block_on(async {
let start = Instant::now();
let sleep = rt.sleep(Duration::from_secs(10));
let result = rt.timeout(Duration::ZERO, sleep).await;
let elapsed = start.elapsed();
checkpoint(
"expired_deadline",
serde_json::json!({
"timed_out": result.is_err(),
"elapsed_ms": elapsed.as_millis().min(u128::from(u64::MAX)) as u64
}),
);
if elapsed > Duration::from_millis(100) {
return TestResult::failed(format!(
"Expired deadline should not wait, but took {:?}",
elapsed
));
}
TestResult::passed()
})
},
)
}
fn neg_bd_003_zero_cost_quota<RT: RuntimeInterface>() -> ConformanceTest<RT> {
ConformanceTest::new(
TestMeta {
id: "neg-bd-003".to_string(),
name: "Zero cost quota behavior".to_string(),
description: "Operations that consume cost should fail with zero quota".to_string(),
category: TestCategory::Cancel,
tags: vec![
"negative".to_string(),
"budget".to_string(),
"cost-quota".to_string(),
"spec:3.2.3".to_string(),
],
expected: "Cost-consuming operations rejected with zero budget".to_string(),
},
|rt| {
rt.block_on(async {
let (tx, mut rx) = rt.mpsc_channel::<i32>(1);
let send_result = tx.send(42).await;
let recv_result = rx.recv().await;
checkpoint(
"operations",
serde_json::json!({
"send_ok": send_result.is_ok(),
"recv_ok": recv_result.is_some()
}),
);
if send_result.is_err() {
return TestResult::failed(
"Send should succeed with available resources".to_string(),
);
}
if recv_result != Some(42) {
return TestResult::failed(format!(
"Recv should return 42, got {:?}",
recv_result
));
}
TestResult::passed()
})
},
)
}
fn time_negative_tests<RT: RuntimeInterface>() -> Vec<ConformanceTest<RT>> {
vec![
neg_tm_001_negative_duration::<RT>(),
neg_tm_002_very_long_timeout::<RT>(),
neg_tm_003_immediate_timeout_priority::<RT>(),
]
}
fn neg_tm_001_negative_duration<RT: RuntimeInterface>() -> ConformanceTest<RT> {
ConformanceTest::new(
TestMeta {
id: "neg-tm-001".to_string(),
name: "Zero duration sleep".to_string(),
description: "Sleep with Duration::ZERO should return immediately".to_string(),
category: TestCategory::Time,
tags: vec![
"negative".to_string(),
"time".to_string(),
"sleep".to_string(),
],
expected: "Returns immediately (< 1ms)".to_string(),
},
|rt| {
rt.block_on(async {
let start = Instant::now();
let sleep = rt.sleep(Duration::ZERO);
sleep.await;
let elapsed = start.elapsed();
checkpoint(
"zero_sleep",
serde_json::json!({"elapsed_us": elapsed.as_micros().min(u128::from(u64::MAX)) as u64}),
);
if elapsed > Duration::from_millis(10) {
return TestResult::failed(format!(
"Zero sleep took {:?}, expected immediate return",
elapsed
));
}
TestResult::passed()
})
},
)
}
fn neg_tm_002_very_long_timeout<RT: RuntimeInterface>() -> ConformanceTest<RT> {
ConformanceTest::new(
TestMeta {
id: "neg-tm-002".to_string(),
name: "Long timeout with fast future".to_string(),
description: "Long timeout wrapping fast future returns quickly".to_string(),
category: TestCategory::Time,
tags: vec![
"negative".to_string(),
"time".to_string(),
"timeout".to_string(),
],
expected: "Returns immediately with Ok, doesn't wait for full timeout".to_string(),
},
|rt| {
rt.block_on(async {
let start = Instant::now();
let result = rt.timeout(Duration::from_secs(3600), async { 42 }).await;
let elapsed = start.elapsed();
checkpoint(
"long_timeout_fast_future",
serde_json::json!({
"elapsed_ms": elapsed.as_millis().min(u128::from(u64::MAX)) as u64,
"result": format!("{:?}", result)
}),
);
if elapsed > Duration::from_millis(100) {
return TestResult::failed(format!(
"Long timeout should not block when future completes: {:?}",
elapsed
));
}
match result {
Ok(42) => TestResult::passed(),
Ok(value) => TestResult::failed(format!("Expected 42, got {}", value)),
Err(_) => TestResult::failed("Fast future should not timeout".to_string()),
}
})
},
)
}
fn neg_tm_003_immediate_timeout_priority<RT: RuntimeInterface>() -> ConformanceTest<RT> {
ConformanceTest::new(
TestMeta {
id: "neg-tm-003".to_string(),
name: "Immediate timeout priority".to_string(),
description: "Zero timeout with potentially-completing future: behavior is defined"
.to_string(),
category: TestCategory::Time,
tags: vec![
"negative".to_string(),
"time".to_string(),
"timeout".to_string(),
"priority".to_string(),
],
expected: "Either immediate timeout or immediate completion (both valid)".to_string(),
},
|rt| {
rt.block_on(async {
let start = Instant::now();
let result = rt.timeout(Duration::ZERO, async { 42i32 }).await;
let elapsed = start.elapsed();
checkpoint(
"immediate_timeout",
serde_json::json!({
"elapsed_us": elapsed.as_micros().min(u128::from(u64::MAX)) as u64,
"is_err": result.is_err(),
"result": format!("{:?}", result)
}),
);
if elapsed > Duration::from_millis(10) {
return TestResult::failed(format!(
"Should complete immediately, took {:?}",
elapsed
));
}
match result {
Ok(42) => {
checkpoint("behavior", serde_json::json!({"type": "completion_wins"}));
}
Err(_) => {
checkpoint("behavior", serde_json::json!({"type": "timeout_wins"}));
}
Ok(other) => {
return TestResult::failed(format!("Unexpected value: {}", other));
}
}
TestResult::passed()
})
},
)
}
fn performance_bounds_tests<RT: RuntimeInterface>() -> Vec<ConformanceTest<RT>> {
vec![
perf_001_spawn_latency::<RT>(),
perf_002_channel_throughput::<RT>(),
perf_003_concurrent_spawn_overhead::<RT>(),
perf_004_timeout_precision::<RT>(),
perf_005_sleep_precision::<RT>(),
]
}
fn perf_001_spawn_latency<RT: RuntimeInterface>() -> ConformanceTest<RT> {
ConformanceTest::new(
TestMeta {
id: "perf-001".to_string(),
name: "Spawn latency bound".to_string(),
description: "Spawning tasks should have low overhead".to_string(),
category: TestCategory::Spawn,
tags: vec![
"performance".to_string(),
"spawn".to_string(),
"latency".to_string(),
],
expected: "Average spawn latency < 100µs".to_string(),
},
|rt| {
rt.block_on(async {
const NUM_SPAWNS: usize = 1000;
let start = Instant::now();
for _ in 0..NUM_SPAWNS {
let _handle = rt.spawn(async {});
}
let elapsed = start.elapsed();
let avg_latency_us = elapsed.as_micros() as f64 / NUM_SPAWNS as f64;
checkpoint(
"spawn_latency",
serde_json::json!({
"num_spawns": NUM_SPAWNS,
"total_ms": elapsed.as_millis().min(u128::from(u64::MAX)) as u64,
"avg_latency_us": avg_latency_us as u64
}),
);
let bound_us = if env::var_os("RUST_TEST_NOCAPTURE").is_some() {
200.0
} else {
100.0
};
if avg_latency_us > bound_us {
return TestResult::failed(format!(
"Spawn latency too high: {:.1}µs average (bound: < {}µs)",
avg_latency_us, bound_us
));
}
TestResult::passed()
})
},
)
}
fn perf_002_channel_throughput<RT: RuntimeInterface>() -> ConformanceTest<RT> {
ConformanceTest::new(
TestMeta {
id: "perf-002".to_string(),
name: "Channel throughput bound".to_string(),
description: "MPSC channel should handle high message throughput".to_string(),
category: TestCategory::Channels,
tags: vec![
"performance".to_string(),
"channel".to_string(),
"throughput".to_string(),
],
expected: "At least 100K messages/sec".to_string(),
},
|rt| {
rt.block_on(async {
const NUM_MESSAGES: u64 = 10_000;
let (tx, mut rx) = rt.mpsc_channel::<u64>(1000);
let counter = Arc::new(AtomicU64::new(0));
let counter_recv = counter.clone();
let _sender = rt.spawn(async move {
for i in 0..NUM_MESSAGES {
let _ = tx.send(i).await;
}
});
let _receiver = rt.spawn(async move {
while rx.recv().await.is_some() {
counter_recv.fetch_add(1, Ordering::SeqCst);
}
});
let start = Instant::now();
let timeout_result = rt
.timeout(Duration::from_secs(5), async {
loop {
let count = counter.load(Ordering::SeqCst);
if count >= NUM_MESSAGES {
break;
}
std::thread::yield_now();
}
})
.await;
let elapsed = start.elapsed();
let final_count = counter.load(Ordering::SeqCst);
let throughput = if elapsed.as_secs_f64() > 0.0 {
final_count as f64 / elapsed.as_secs_f64()
} else {
f64::INFINITY
};
checkpoint(
"channel_throughput",
serde_json::json!({
"messages": final_count,
"elapsed_ms": elapsed.as_millis().min(u128::from(u64::MAX)) as u64,
"throughput_msg_per_sec": throughput as u64
}),
);
if timeout_result.is_err() {
return TestResult::failed(format!(
"Throughput test timed out. Only received {}/{} messages",
final_count, NUM_MESSAGES
));
}
if throughput < 10_000.0 {
return TestResult::failed(format!(
"Channel throughput too low: {:.0} msg/sec (bound: > 10K)",
throughput
));
}
TestResult::passed()
})
},
)
}
fn perf_003_concurrent_spawn_overhead<RT: RuntimeInterface>() -> ConformanceTest<RT> {
ConformanceTest::new(
TestMeta {
id: "perf-003".to_string(),
name: "Concurrent spawn overhead".to_string(),
description: "Spawning 1000 tasks should complete in < 100ms".to_string(),
category: TestCategory::Spawn,
tags: vec![
"performance".to_string(),
"spawn".to_string(),
"concurrent".to_string(),
],
expected: "1000 concurrent spawns complete in < 100ms".to_string(),
},
|rt| {
rt.block_on(async {
const NUM_TASKS: u64 = 1000;
let counter = Arc::new(AtomicU64::new(0));
let start = Instant::now();
for _ in 0..NUM_TASKS {
let counter = counter.clone();
let _handle = rt.spawn(async move {
counter.fetch_add(1, Ordering::SeqCst);
});
}
let spawn_time = start.elapsed();
let timeout_result = rt
.timeout(Duration::from_secs(10), async {
loop {
if counter.load(Ordering::SeqCst) >= NUM_TASKS {
break;
}
std::thread::yield_now();
}
})
.await;
let total_time = start.elapsed();
let final_count = counter.load(Ordering::SeqCst);
checkpoint(
"concurrent_spawn",
serde_json::json!({
"num_tasks": NUM_TASKS,
"spawn_time_ms": spawn_time.as_millis().min(u128::from(u64::MAX)) as u64,
"total_time_ms": total_time.as_millis().min(u128::from(u64::MAX)) as u64,
"completed": final_count
}),
);
if timeout_result.is_err() {
return TestResult::failed(format!(
"Concurrent spawn timed out. Completed {}/{}",
final_count, NUM_TASKS
));
}
if spawn_time > Duration::from_millis(100) {
return TestResult::failed(format!(
"Spawn time too high: {:?} (bound: < 100ms)",
spawn_time
));
}
TestResult::passed()
})
},
)
}
fn perf_004_timeout_precision<RT: RuntimeInterface>() -> ConformanceTest<RT> {
ConformanceTest::new(
TestMeta {
id: "perf-004".to_string(),
name: "Timeout precision".to_string(),
description: "Timeout should fire within 50% of requested duration".to_string(),
category: TestCategory::Time,
tags: vec![
"performance".to_string(),
"timeout".to_string(),
"precision".to_string(),
],
expected: "50ms timeout fires between 25ms and 150ms".to_string(),
},
|rt| {
rt.block_on(async {
let target = Duration::from_millis(50);
let start = Instant::now();
let sleep = rt.sleep(Duration::from_secs(10));
let result = rt.timeout(target, sleep).await;
let elapsed = start.elapsed();
checkpoint(
"timeout_precision",
serde_json::json!({
"target_ms": target.as_millis().min(u128::from(u64::MAX)) as u64,
"elapsed_ms": elapsed.as_millis().min(u128::from(u64::MAX)) as u64,
"is_timeout": result.is_err()
}),
);
if result.is_ok() {
return TestResult::failed("Long sleep should timeout".to_string());
}
let min_bound = target / 2;
let max_bound = target * 3;
if elapsed < min_bound {
return TestResult::failed(format!(
"Timeout fired too early: {:?} (min: {:?})",
elapsed, min_bound
));
}
if elapsed > max_bound {
return TestResult::failed(format!(
"Timeout fired too late: {:?} (max: {:?})",
elapsed, max_bound
));
}
TestResult::passed()
})
},
)
}
fn perf_005_sleep_precision<RT: RuntimeInterface>() -> ConformanceTest<RT> {
ConformanceTest::new(
TestMeta {
id: "perf-005".to_string(),
name: "Sleep precision".to_string(),
description: "Sleep should wake within reasonable bounds of requested duration"
.to_string(),
category: TestCategory::Time,
tags: vec![
"performance".to_string(),
"sleep".to_string(),
"precision".to_string(),
],
expected: "50ms sleep wakes between 25ms and 150ms".to_string(),
},
|rt| {
rt.block_on(async {
let target = Duration::from_millis(50);
let start = Instant::now();
let sleep = rt.sleep(target);
sleep.await;
let elapsed = start.elapsed();
checkpoint(
"sleep_precision",
serde_json::json!({
"target_ms": target.as_millis().min(u128::from(u64::MAX)) as u64,
"elapsed_ms": elapsed.as_millis().min(u128::from(u64::MAX)) as u64
}),
);
let min_bound = target / 2;
let max_bound = target * 3;
if elapsed < min_bound {
return TestResult::failed(format!(
"Sleep woke too early: {:?} (min: {:?})",
elapsed, min_bound
));
}
if elapsed > max_bound {
return TestResult::failed(format!(
"Sleep woke too late: {:?} (max: {:?})",
elapsed, max_bound
));
}
TestResult::passed()
})
},
)
}
#[cfg(test)]
mod tests {
#[test]
fn test_id_conventions() {
let negative_ids = [
"neg-rg-001",
"neg-rg-002",
"neg-rg-003",
"neg-ch-001",
"neg-ch-002",
"neg-ch-003",
"neg-ch-004",
"neg-ch-005",
"neg-bd-001",
"neg-bd-002",
"neg-bd-003",
"neg-tm-001",
"neg-tm-002",
"neg-tm-003",
];
for id in negative_ids {
assert!(
id.starts_with("neg-"),
"Negative test IDs should start with 'neg-': {}",
id
);
}
let perf_ids = ["perf-001", "perf-002", "perf-003", "perf-004", "perf-005"];
for id in perf_ids {
assert!(
id.starts_with("perf-"),
"Performance test IDs should start with 'perf-': {}",
id
);
}
}
#[test]
fn test_tags_include_spec_references() {
let spec_refs = [
"spec:3.1.1",
"spec:3.1.2",
"spec:3.2.1",
"spec:3.2.2",
"spec:3.2.3",
"spec:4.2.1",
];
for spec_ref in spec_refs {
assert!(
spec_ref.starts_with("spec:"),
"Spec refs should start with 'spec:': {}",
spec_ref
);
let section = &spec_ref[5..];
assert!(
section.contains('.'),
"Spec section should have format 'X.Y': {}",
spec_ref
);
}
}
}