This document describes the comprehensive three-layer testing strategy for the Dist Agent Language (DAL).
┌─────────────────────────────────────────────────────────────┐
│ Layer 1: Rust Unit Tests (example_tests.rs) │
│ Purpose: Syntax & Parse-time Validation │
│ Tools: cargo test, parse_source(), execute_source() │
│ Runs: CI/CD, pre-commit, development │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ Layer 2: Semantic Validators (stdlib/test.rs) │
│ Purpose: Attribute, Type & Rule Validation │
│ Tools: expect_valid_trust_model(), expect_type(), etc. │
│ Runs: Within DAL tests, programmatic validation │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ Layer 3: DAL Test Files (*.test.dal) │
│ Purpose: Runtime Behavior & Integration Testing │
│ Tools: describe(), it(), expect(), deploy_service() │
│ Runs: dist_agent_lang test, user-written tests │
└─────────────────────────────────────────────────────────────┘
Location:
/dist_agent_lang/tests/example_tests.rs
Validate that all DAL example files can be parsed and executed without errors.
@ attributes are
properly formatted#[test]
fn test_token_contract_parses() {
let source = r#"
@trust("hybrid")
@chain("ethereum")
service TokenContract {
balance: map<string, float>;
fn transfer(to: string, amount: float) {
balance[to] = balance[to] + amount;
}
}
"#;
// Layer 1: Parse validation
parse_source(&source).unwrap();
}cargo test (local development)Syntax Validation (Parse-time)
Semantic Validation (Parse-time)
Runtime Behavior (Layer 3)
.test.dal)Key Feature: The
test_all_examples_with_semantic_validation() test combines
syntax and semantic validation in a single fast test run!
Location:
/dist_agent_lang/src/stdlib/test.rs
Provide semantic validation helpers that go beyond syntax checking.
// Validate trust model
expect_valid_trust_model("hybrid") // ✅ Pass
expect_valid_trust_model("invalid") // ❌ Fail
// Validate blockchain
expect_valid_chain("ethereum") // ✅ Pass
expect_valid_chain("fake_chain") // ❌ Fail
// Check attribute compatibility
expect_compatible_attributes(vec!["trust"]) // ✅ Pass
expect_compatible_attributes(vec!["trust", "chain"]) // ✅ Pass
expect_compatible_attributes(vec!["secure", "public"]) // ❌ Fail (exclusive)// Validate value type
let balance = Value::Number(100.0);
expect_type(&balance, "number") // ✅ Pass
expect_type(&balance, "string") // ❌ Fail
// Validate range
let amount = Value::Number(50.0);
expect_in_range(amount, 0.0, 100.0) // ✅ Pass
expect_in_range(amount, 200.0, 300.0) // ❌ Fail// Validate length
let name = Value::String("Alice".to_string());
expect_length(name, 5) // ✅ Pass
// Validate not empty
let items = Value::Vector(vec![Value::Number(1.0)]);
expect_not_empty(items) // ✅ Pass
// Validate map keys
let config = Value::Map(hashmap!{"host" => Value::String("localhost")});
expect_has_key(config, "host") // ✅ Passexpect_contains("hello world", "world") // ✅ Pass
expect_starts_with("0x123abc", "0x") // ✅ Pass#[test]
fn test_token_contract_semantics() {
let source = r#"
@trust("hybrid")
@chain("ethereum")
service TokenContract { }
"#;
// Layer 1: Parse validation
let ast = parse_source(&source).unwrap();
// Layer 2: Semantic validation
if let Statement::Service(service) = &ast.statements[0] {
let attrs: Vec<&str> = service.attributes.iter()
.map(|a| a.name.as_str())
.collect();
// Validate attribute compatibility
expect_compatible_attributes(attrs).unwrap();
// Validate specific attribute values
for attr in &service.attributes {
if attr.name == "trust" {
if let Expression::Literal(Literal::String(model)) = &attr.parameters[0] {
expect_valid_trust_model(model).unwrap();
}
}
if attr.name == "chain" {
if let Expression::Literal(Literal::String(chain)) = &attr.parameters[0] {
expect_valid_chain(chain).unwrap();
}
}
}
}
}Location:
/dist_agent_lang/examples/*.test.dal
Runtime behavior testing and integration testing, written in DAL itself.
*.test.dal - Test filesdist_agent_lang testFile: token_contract.test.dal
// Import the service to test
use token_contract::TokenContract;
// Test suite using Hardhat-style syntax
describe("TokenContract", fn() {
let contract;
let owner = "alice";
let recipient = "bob";
beforeEach(fn() {
// Deploy a fresh contract for each test
contract = deploy_service("TokenContract", {
"initial_supply": 1000.0
});
});
it("should initialize with correct supply", fn() {
let supply = contract.total_supply();
// Layer 2: Semantic validation
expect_type(&supply, "number");
expect_in_range(supply, 0.0, 1000000.0);
// Layer 3: Runtime behavior
expect(supply).to_equal(1000.0);
});
it("should transfer tokens correctly", fn() {
// Arrange
let initial_balance = contract.balance_of(recipient);
let transfer_amount = 100.0;
// Act
contract.transfer(recipient, transfer_amount);
// Assert - Runtime behavior
let new_balance = contract.balance_of(recipient);
expect(new_balance).to_equal(initial_balance + transfer_amount);
// Assert - Semantic validation
expect_in_range(new_balance, 0.0, 1000.0);
});
it("should validate trust model attribute", fn() {
// Layer 2: Semantic validation
expect_valid_trust_model("hybrid");
expect_valid_chain("ethereum");
// Verify attribute compatibility
expect_compatible_attributes(["trust", "chain"]);
});
it("should reject invalid transfers", fn() {
expect_throws(fn() {
contract.transfer(recipient, -100.0);
}, "negative amounts not allowed");
});
it("should handle edge cases", fn() {
// Test boundary conditions
let zero_transfer = 0.0;
expect_in_range(zero_transfer, 0.0, 1000.0);
contract.transfer(recipient, zero_transfer);
expect(contract.balance_of(recipient)).to_equal(zero_transfer);
});
});
describe("TokenContract attribute validation", fn() {
it("should have required attributes", fn() {
// Semantic validation
expect_has_attribute("TokenContract", "trust");
expect_has_attribute("TokenContract", "chain");
});
it("should enforce attribute rules", fn() {
// These should pass
expect_compatible_attributes(["trust", "chain"]);
// This should fail
expect_throws(fn() {
expect_compatible_attributes(["secure", "public"]);
}, "mutually exclusive");
});
});
# Run all test files
dist_agent_lang test
# Run specific test file
dist_agent_lang test token_contract.test.dal
# Run with verbose output
dist_agent_lang test --verbose
# Run with coverage
dist_agent_lang test --coveragedist_agent_lang test command1. Write the implementation
// token_contract.dal
@trust("hybrid")
@chain("ethereum")
service TokenContract {
balance: map<string, float>;
total_supply: float;
fn transfer(to: string, amount: float) {
if amount < 0.0 {
error("negative amounts not allowed");
}
balance[to] = balance[to] + amount;
}
}
2. Layer 1: Add to example tests (automatic)
# Runs automatically if file is in examples/
cargo test3. Layer 2: Add semantic validation (if needed)
// In tests/example_tests.rs
#[test]
fn test_token_contract_semantics() {
let source = read_file("examples/token_contract.dal");
let ast = parse_source(&source).unwrap();
// Extract and validate attributes
// (see Layer 2 examples above)
}4. Layer 3: Write DAL test file
# Create token_contract.test.dal
# (see Layer 3 example above)
# Run tests
dist_agent_lang test token_contract.test.dalWhen adding new DAL features, ensure:
For mutation testing (fault injection against the Rust test suite), see the mutation testing runbook and Mutation analysis for run scripts, reliable long-run practices, and enterprise-oriented test policy.
AST-aware semantic validation
expect_has_attribute()Test coverage reporting
Property-based testing
Visual test reporting
| Layer | Purpose | Tools | Speed | Coverage |
|---|---|---|---|---|
| 1. Rust Unit Tests | Syntax validation | cargo test, parse_source() |
⚡ Fast | Syntax |
| 2. Semantic Validators | Rule enforcement | expect_*() functions |
🚀 Medium | Semantics |
| 3. DAL Test Files | Runtime behavior | describe(), it() |
🐌 Slower | Logic |
Key Principle: Each layer builds on the previous one, providing increasingly sophisticated validation while maintaining fast feedback for common errors.