Skip to main content

Module tester

Module tester 

Source
Expand description

§Tester Type

Provides tester implementations that test conditions or states and return boolean values, without accepting input parameters.

§Overview

Tester is a functional abstraction for testing conditions or states without accepting input. It can check system status, wait for conditions, or perform health checks.

This module implements Option 3 from the design document: a unified Tester trait with multiple concrete implementations optimized for different ownership and concurrency scenarios.

§Core Design Principles

  1. Returns boolean: Tester returns bool to indicate test results
  2. Uses &self: Tester is only responsible for “judgment”, not “state management”
  3. No TesterOnce: Very limited use cases, lacks practical examples
  4. State management is caller’s responsibility: Tester only reads state, does not modify state

§Three Implementations

  • BoxTester: Single ownership using Box<dyn Fn() -> bool>. Zero overhead, cannot be cloned. Best for one-time use and builder patterns.

  • ArcTester: Thread-safe shared ownership using Arc<dyn Fn() -> bool + Send + Sync>. Can be cloned and sent across threads. Lock-free overhead.

  • RcTester: Single-threaded shared ownership using Rc<dyn Fn() -> bool>. Can be cloned but cannot be sent across threads. Lower overhead than ArcTester.

§Comparison with Other Functional Abstractions

TypeInputOutputselfModify?Use Cases
TesterNonebool&selfNoState Check
Predicate&Tbool&selfNoFilter
SupplierNoneT&mutYesFactory

§Examples

§Basic State Checking

use qubit_function::{BoxTester, Tester};
use std::sync::{Arc, atomic::{AtomicUsize, Ordering}};

// State managed externally
let count = Arc::new(AtomicUsize::new(0));
let count_clone = Arc::clone(&count);

let tester = BoxTester::new(move || {
    count_clone.load(Ordering::Relaxed) <= 3
});

assert!(tester.test());  // true (0)
count.fetch_add(1, Ordering::Relaxed);
assert!(tester.test());  // true (1)
count.fetch_add(1, Ordering::Relaxed);
assert!(tester.test());  // true (2)
count.fetch_add(1, Ordering::Relaxed);
assert!(tester.test());  // true (3)
count.fetch_add(1, Ordering::Relaxed);
assert!(!tester.test()); // false (4)

§Logical Combination

use qubit_function::{BoxTester, Tester};
use std::sync::{Arc, atomic::{AtomicUsize, AtomicBool, Ordering}};

// Simulate microservice health check scenario
let cpu_usage = Arc::new(AtomicUsize::new(0));
let memory_usage = Arc::new(AtomicUsize::new(0));
let is_healthy = Arc::new(AtomicBool::new(true));
let is_ready = Arc::new(AtomicBool::new(false));
let max_cpu = 80;
let max_memory = 90;

let cpu_clone = Arc::clone(&cpu_usage);
let memory_clone = Arc::clone(&memory_usage);
let health_clone = Arc::clone(&is_healthy);
let ready_clone = Arc::clone(&is_ready);

// System resource check: CPU and memory within safe limits
let resources_ok = BoxTester::new(move || {
    cpu_clone.load(Ordering::Relaxed) < max_cpu
})
.and(move || {
    memory_clone.load(Ordering::Relaxed) < max_memory
});

// Service status check: healthy or ready
let service_ok = BoxTester::new(move || {
    health_clone.load(Ordering::Relaxed)
})
.or(move || {
    ready_clone.load(Ordering::Relaxed)
});

// Combined condition: resources normal and service available
let can_accept_traffic = resources_ok.and(service_ok);

// Test different state combinations
// Initial state: resources normal and service healthy
cpu_usage.store(50, Ordering::Relaxed);
memory_usage.store(60, Ordering::Relaxed);
assert!(can_accept_traffic.test()); // resources normal and service healthy

// Service unhealthy but ready
is_healthy.store(false, Ordering::Relaxed);
is_ready.store(true, Ordering::Relaxed);
assert!(can_accept_traffic.test()); // resources normal and service ready

// CPU usage too high
cpu_usage.store(95, Ordering::Relaxed);
assert!(!can_accept_traffic.test()); // resources exceeded

// Service unhealthy but ready
is_healthy.store(false, Ordering::Relaxed);
cpu_usage.store(50, Ordering::Relaxed);
assert!(can_accept_traffic.test()); // still ready

§Thread-Safe Sharing

use qubit_function::{ArcTester, Tester};
use std::thread;

let shared = ArcTester::new(|| true);
let clone = shared.clone();

let handle = thread::spawn(move || {
    clone.test()
});

assert!(handle.join().unwrap());

§Author

Haixing Hu

Structs§

ArcTester
Thread-safe shared ownership Tester implemented using Arc
BoxTester
Single ownership Tester implemented using Box
RcTester
Single-threaded shared ownership Tester implemented using Rc

Traits§

FnTesterOps
Extension trait providing logical composition methods for closures
Tester
Tests whether a state or condition holds