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 prism3_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 prism3_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 prism3_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

Hu Haixing

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