windjammer 0.48.0

A simple language inspired by Go, Ruby, and Elixir that transpiles to Rust - 80% of Rust's power with 20% of the complexity
Documentation
// Windjammer Testing Framework - Decorator Syntax Examples
//
// This file shows the elegant decorator syntax for testing features.
// These decorators wrap your test functions automatically!

use std::test::*;
use std::bench::*;
use std::timeout::*;

// ============================================================================
// 1. @timeout - Automatic timeout for tests
// ============================================================================

@timeout(1000)  // 1 second timeout
@test
fn test_with_timeout() {
    // This test must complete within 1 second
    let mut sum = 0;
    for i in 0..1000 {
        sum += i;
    }
    assert_eq(sum, 499500);
}

@timeout(16)  // 16ms = 60fps frame budget
@test
fn test_frame_rendering() {
    // Ensure rendering completes within frame budget
    render_frame();
}

// ============================================================================
// 2. @bench - Automatic benchmarking
// ============================================================================

@bench
fn benchmark_fibonacci() {
    // Automatically benchmarked and results printed
    fibonacci(20);
}

@bench
fn benchmark_sorting() {
    let mut data = vec![5, 2, 8, 1, 9];
    data.sort();
}

// ============================================================================
// 3. @property_test - Property-based testing
// ============================================================================

@property_test(100)  // Test 100 random inputs
fn test_addition_commutative(a: int, b: int) {
    // Automatically generates random a and b values
    assert_eq(a + b, b + a);
}

@property_test(50)
fn test_multiplication_associative(a: int, b: int, c: int) {
    // Tests with 3 random parameters
    assert_eq((a * b) * c, a * (b * c));
}

// ============================================================================
// 4. Combined Decorators - Stack multiple decorators
// ============================================================================

@timeout(5000)
@bench
@test
fn test_with_timeout_and_bench() {
    // Both timeout AND benchmarked
    expensive_operation();
}

@property_test(100)
@timeout(10000)
fn test_property_with_timeout(x: int, y: int) {
    // Property test with timeout protection
    assert!(x + y >= x);
    assert!(x + y >= y);
}

// ============================================================================
// 5. @requires - Precondition checks
// ============================================================================

@requires(x > 0)
@requires(y > 0)
fn add_positive(x: int, y: int) -> int {
    // Automatically checks x > 0 and y > 0 before executing
    x + y
}

@requires(divisor != 0)
fn safe_divide(dividend: int, divisor: int) -> int {
    // Prevents division by zero at runtime
    dividend / divisor
}

// ============================================================================
// 6. @ensures - Postcondition checks
// ============================================================================

@ensures(result > 0)
fn abs(x: int) -> int {
    // Automatically verifies result is positive after execution
    if x < 0 { -x } else { x }
}

@requires(x > 0)
@ensures(result > x)
fn increment(x: int) -> int {
    // Combines preconditions and postconditions!
    x + 1
}

// ============================================================================
// 7. @invariant - State invariants
// ============================================================================

@invariant(count >= 0)
fn decrement_safe(count: int) -> int {
    // Ensures count never goes negative
    if count > 0 { count - 1 } else { 0 }
}

// ============================================================================
// 8. @test(setup, teardown) - Test lifecycle
// ============================================================================

@test(setup = setup_db, teardown = teardown_db)
fn test_database(db: Database) {
    // Automatically calls setup_db() before test
    // and teardown_db(db) after test
    assert(db.is_connected());
    let users = db.query("SELECT * FROM users");
    assert_eq(users.len(), 10);
}

fn setup_db() -> Database {
    Database::connect_test()
}

fn teardown_db(db: Database) {
    db.disconnect();
}

// ============================================================================
// 9. Function-Based API (alternative syntax)
// ============================================================================

// You can also use function calls if you prefer:

@test
fn test_with_contracts_functional() {
    let x = 10;
    requires(x > 0, "x must be positive");
    
    let result = x * 2;
    ensures(result > x, "result must be greater than x");
}

@test
fn test_with_setup_teardown_functional() {
    with_setup_teardown(
        || Database::connect_test(),
        |db| db.disconnect(),
        |db| {
            assert(db.is_connected());
            db
        }
    );
}

// ============================================================================
// SUMMARY
// ============================================================================
//
// ✅ ALL DECORATOR SYNTAX WORKING (8/8):
// 1. @timeout(ms) - Automatic timeout wrapping
// 2. @bench - Automatic benchmarking
// 3. @property_test(n) - Property-based testing
// 4. @requires(expr) - Precondition checks
// 5. @ensures(expr) - Postcondition checks
// 6. @invariant(expr) - State invariants
// 7. @test(setup=fn, teardown=fn) - Test lifecycle
// 8. @test_cases([...]) - Parameterized tests
//
// Plus: @test, @ignore, @async - Standard decorators
//
// ✨ Features:
// - Elegant, declarative syntax
// - Supports full expressions (x > 0, result != null, etc.)
// - Supports named arguments (setup = fn, teardown = fn)
// - Can stack multiple decorators
// - Function-based API also available for flexibility
//
// Both decorator and function-based approaches work perfectly!
// Choose what fits your style and use case.

// Helper functions for examples
fn fibonacci(n: int) -> int {
    if n <= 1 { n } else { fibonacci(n-1) + fibonacci(n-2) }
}

fn render_frame() {
    // Simulate rendering
    let mut pixels = vec![0; 1920 * 1080];
    for i in 0..pixels.len() {
        pixels[i] = i % 256;
    }
}

fn expensive_operation() {
    let mut sum = 0;
    for i in 0..10000 {
        sum += i * i;
    }
}

struct Database {
    connected: bool,
}

impl Database {
    fn connect_test() -> Self {
        Self { connected: true }
    }
    
    fn disconnect(&mut self) {
        self.connected = false;
    }
    
    fn is_connected(&self) -> bool {
        self.connected
    }
    
    fn query(&self, sql: string) -> Vec<string> {
        vec!["user1", "user2", "user3", "user4", "user5",
             "user6", "user7", "user8", "user9", "user10"]
    }
}