Merge commit 'd803bfe2b1fe7f5e219e50ac20d6801a0a58ac75' as 'vendor/ruvector'
This commit is contained in:
268
vendor/ruvector/examples/exo-ai-2025/tests/README.md
vendored
Normal file
268
vendor/ruvector/examples/exo-ai-2025/tests/README.md
vendored
Normal file
@@ -0,0 +1,268 @@
|
||||
# EXO-AI 2025 Integration Tests
|
||||
|
||||
This directory contains comprehensive integration tests for the cognitive substrate platform.
|
||||
|
||||
## Test Organization
|
||||
|
||||
### Test Files
|
||||
|
||||
- **`substrate_integration.rs`** - Complete substrate workflow tests
|
||||
- Pattern storage and retrieval
|
||||
- Manifold deformation
|
||||
- Strategic forgetting
|
||||
- Bulk operations
|
||||
- Filtered queries
|
||||
|
||||
- **`hypergraph_integration.rs`** - Hypergraph substrate tests
|
||||
- Hyperedge creation and querying
|
||||
- Persistent homology computation
|
||||
- Betti number calculation
|
||||
- Sheaf consistency checking
|
||||
- Complex relational queries
|
||||
|
||||
- **`temporal_integration.rs`** - Temporal memory coordinator tests
|
||||
- Causal storage and queries
|
||||
- Light-cone constraints
|
||||
- Memory consolidation
|
||||
- Predictive anticipation
|
||||
- Temporal knowledge graphs
|
||||
|
||||
- **`federation_integration.rs`** - Federated mesh tests
|
||||
- CRDT merge operations
|
||||
- Byzantine consensus
|
||||
- Post-quantum handshakes
|
||||
- Onion-routed queries
|
||||
- Network partition tolerance
|
||||
|
||||
### Test Utilities
|
||||
|
||||
The `common/` directory contains shared testing infrastructure:
|
||||
|
||||
- **`fixtures.rs`** - Test data generators and builders
|
||||
- **`assertions.rs`** - Domain-specific assertion functions
|
||||
- **`helpers.rs`** - Utility functions for testing
|
||||
|
||||
## Running Tests
|
||||
|
||||
### Quick Start
|
||||
|
||||
```bash
|
||||
# Run all tests (currently all ignored until crates implemented)
|
||||
cargo test --workspace
|
||||
|
||||
# Run tests with output
|
||||
cargo test --workspace -- --nocapture
|
||||
|
||||
# Run specific test file
|
||||
cargo test --test substrate_integration
|
||||
|
||||
# Run tests matching a pattern
|
||||
cargo test causal
|
||||
```
|
||||
|
||||
### Using the Test Runner Script
|
||||
|
||||
```bash
|
||||
# Standard test run
|
||||
./scripts/run-integration-tests.sh
|
||||
|
||||
# Verbose output
|
||||
./scripts/run-integration-tests.sh --verbose
|
||||
|
||||
# Parallel execution
|
||||
./scripts/run-integration-tests.sh --parallel
|
||||
|
||||
# Generate coverage report
|
||||
./scripts/run-integration-tests.sh --coverage
|
||||
|
||||
# Run specific tests
|
||||
./scripts/run-integration-tests.sh --filter "causal"
|
||||
```
|
||||
|
||||
## Test-Driven Development (TDD) Workflow
|
||||
|
||||
These integration tests are written **BEFORE** implementation to define expected behavior.
|
||||
|
||||
### Current State
|
||||
|
||||
All tests are marked with `#[ignore]` because the crates don't exist yet.
|
||||
|
||||
### Implementation Workflow
|
||||
|
||||
1. **Implementer selects a test** (e.g., `test_substrate_store_and_retrieve`)
|
||||
2. **Reads the test to understand requirements**
|
||||
3. **Implements the crate to satisfy the test**
|
||||
4. **Removes `#[ignore]` from the test**
|
||||
5. **Runs `cargo test` to verify**
|
||||
6. **Iterates until test passes**
|
||||
|
||||
### Example: Implementing Substrate Storage
|
||||
|
||||
```rust
|
||||
// 1. Read the test in substrate_integration.rs
|
||||
#[tokio::test]
|
||||
#[ignore] // <- Remove this line when implementing
|
||||
async fn test_substrate_store_and_retrieve() {
|
||||
// The test shows expected API:
|
||||
let config = SubstrateConfig::default();
|
||||
let backend = ClassicalBackend::new(config).unwrap();
|
||||
// ... etc
|
||||
}
|
||||
|
||||
// 2. Implement exo-core and exo-backend-classical to match
|
||||
|
||||
// 3. Remove #[ignore] and run:
|
||||
cargo test --test substrate_integration
|
||||
|
||||
// 4. Iterate until passing
|
||||
```
|
||||
|
||||
## Test Requirements for Implementers
|
||||
|
||||
### exo-core
|
||||
|
||||
**Required types:**
|
||||
- `Pattern` - Pattern with embedding, metadata, timestamp, antecedents
|
||||
- `Query` - Query specification
|
||||
- `SubstrateConfig` - Configuration
|
||||
- `SearchResult` - Search result with score
|
||||
- `SubstrateBackend` trait - Backend abstraction
|
||||
- `TemporalContext` trait - Temporal operations
|
||||
|
||||
**Expected methods:**
|
||||
- `SubstrateInstance::new(backend)` - Create substrate
|
||||
- `substrate.store(pattern)` - Store pattern
|
||||
- `substrate.search(query, k)` - Similarity search
|
||||
|
||||
### exo-manifold
|
||||
|
||||
**Required types:**
|
||||
- `ManifoldEngine` - Learned manifold storage
|
||||
- `ManifoldDelta` - Deformation result
|
||||
|
||||
**Expected methods:**
|
||||
- `ManifoldEngine::new(config)` - Initialize
|
||||
- `manifold.retrieve(tensor, k)` - Gradient descent retrieval
|
||||
- `manifold.deform(pattern, salience)` - Continuous deformation
|
||||
- `manifold.forget(region, decay_rate)` - Strategic forgetting
|
||||
|
||||
### exo-hypergraph
|
||||
|
||||
**Required types:**
|
||||
- `HypergraphSubstrate` - Hypergraph storage
|
||||
- `Hyperedge` - Multi-entity relationship
|
||||
- `TopologicalQuery` - Topology query spec
|
||||
- `PersistenceDiagram` - Homology results
|
||||
|
||||
**Expected methods:**
|
||||
- `hypergraph.create_hyperedge(entities, relation)` - Create hyperedge
|
||||
- `hypergraph.persistent_homology(dim, range)` - Compute persistence
|
||||
- `hypergraph.betti_numbers(max_dim)` - Topological invariants
|
||||
- `hypergraph.check_sheaf_consistency(sections)` - Sheaf check
|
||||
|
||||
### exo-temporal
|
||||
|
||||
**Required types:**
|
||||
- `TemporalMemory` - Temporal coordinator
|
||||
- `CausalConeType` - Cone specification
|
||||
- `CausalResult` - Result with causal metadata
|
||||
- `AnticipationHint` - Pre-fetch hint
|
||||
|
||||
**Expected methods:**
|
||||
- `temporal.store(pattern, antecedents)` - Store with causality
|
||||
- `temporal.causal_query(query, time, cone)` - Causal retrieval
|
||||
- `temporal.consolidate()` - Short-term to long-term
|
||||
- `temporal.anticipate(hints)` - Pre-fetch
|
||||
|
||||
### exo-federation
|
||||
|
||||
**Required types:**
|
||||
- `FederatedMesh` - Federation coordinator
|
||||
- `FederationScope` - Query scope
|
||||
- `StateUpdate` - CRDT update
|
||||
- `CommitProof` - Consensus proof
|
||||
|
||||
**Expected methods:**
|
||||
- `mesh.join_federation(peer)` - Federation handshake
|
||||
- `mesh.federated_query(query, scope)` - Distributed query
|
||||
- `mesh.byzantine_commit(update)` - Consensus
|
||||
- `mesh.merge_crdt_state(state)` - CRDT reconciliation
|
||||
|
||||
## Performance Targets
|
||||
|
||||
Integration tests should verify these performance characteristics:
|
||||
|
||||
| Operation | Target Latency | Notes |
|
||||
|-----------|----------------|-------|
|
||||
| Pattern storage | < 1ms | Classical backend |
|
||||
| Similarity search (k=10) | < 10ms | 10K patterns |
|
||||
| Manifold deformation | < 100ms | Single pattern |
|
||||
| Hypergraph query | < 50ms | 1K entities |
|
||||
| Causal query | < 20ms | 10K temporal patterns |
|
||||
| CRDT merge | < 5ms | 100 operations |
|
||||
| Consensus round | < 200ms | 4 nodes, no faults |
|
||||
|
||||
## Test Coverage Goals
|
||||
|
||||
- **Statement coverage**: > 80%
|
||||
- **Branch coverage**: > 75%
|
||||
- **Function coverage**: > 80%
|
||||
|
||||
Run with coverage:
|
||||
```bash
|
||||
cargo tarpaulin --workspace --out Html --output-dir coverage
|
||||
```
|
||||
|
||||
## Debugging Failed Tests
|
||||
|
||||
### Enable Logging
|
||||
|
||||
```bash
|
||||
RUST_LOG=debug cargo test --test substrate_integration -- --nocapture
|
||||
```
|
||||
|
||||
### Run Single Test
|
||||
|
||||
```bash
|
||||
cargo test --test substrate_integration test_substrate_store_and_retrieve -- --nocapture
|
||||
```
|
||||
|
||||
### Use Test Helpers
|
||||
|
||||
```rust
|
||||
use common::helpers::*;
|
||||
|
||||
init_test_logger(); // Enable logging in test
|
||||
|
||||
let (result, duration) = measure_async(async {
|
||||
substrate.search(query, 10).await
|
||||
}).await;
|
||||
|
||||
println!("Query took {:?}", duration);
|
||||
```
|
||||
|
||||
## Contributing Tests
|
||||
|
||||
When adding new integration tests:
|
||||
|
||||
1. **Follow existing patterns** - Use the same structure as current tests
|
||||
2. **Use test utilities** - Leverage `common/` helpers
|
||||
3. **Document expectations** - Comment expected behavior clearly
|
||||
4. **Mark as ignored** - Add `#[ignore]` until implementation ready
|
||||
5. **Add to README** - Document what the test verifies
|
||||
|
||||
## CI/CD Integration
|
||||
|
||||
These tests run in CI on:
|
||||
- Every pull request
|
||||
- Main branch commits
|
||||
- Nightly builds
|
||||
|
||||
CI configuration: `.github/workflows/integration-tests.yml` (to be created)
|
||||
|
||||
## Questions?
|
||||
|
||||
See the main project documentation:
|
||||
- Architecture: `../architecture/ARCHITECTURE.md`
|
||||
- Specification: `../specs/SPECIFICATION.md`
|
||||
- Pseudocode: `../architecture/PSEUDOCODE.md`
|
||||
116
vendor/ruvector/examples/exo-ai-2025/tests/common/assertions.rs
vendored
Normal file
116
vendor/ruvector/examples/exo-ai-2025/tests/common/assertions.rs
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
//! Custom assertions for integration tests
|
||||
//!
|
||||
//! Provides domain-specific assertions for cognitive substrate testing.
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
/// Assert two embeddings are approximately equal (within epsilon)
|
||||
pub fn assert_embeddings_approx_equal(a: &[f32], b: &[f32], epsilon: f32) {
|
||||
assert_eq!(
|
||||
a.len(),
|
||||
b.len(),
|
||||
"Embeddings have different dimensions: {} vs {}",
|
||||
a.len(),
|
||||
b.len()
|
||||
);
|
||||
|
||||
for (i, (av, bv)) in a.iter().zip(b.iter()).enumerate() {
|
||||
let diff = (av - bv).abs();
|
||||
assert!(
|
||||
diff < epsilon,
|
||||
"Embedding mismatch at index {}: |{} - {}| = {} >= {}",
|
||||
i,
|
||||
av,
|
||||
bv,
|
||||
diff,
|
||||
epsilon
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Assert similarity scores are in descending order
|
||||
pub fn assert_scores_descending(scores: &[f32]) {
|
||||
for window in scores.windows(2) {
|
||||
assert!(
|
||||
window[0] >= window[1],
|
||||
"Scores not in descending order: {} < {}",
|
||||
window[0],
|
||||
window[1]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Assert causal ordering is respected
|
||||
pub fn assert_causal_order(results: &[String], expected_order: &[String]) {
|
||||
// TODO: Implement once CausalResult type exists
|
||||
// Verify results respect causal dependencies
|
||||
assert_eq!(results.len(), expected_order.len(), "Result count mismatch");
|
||||
}
|
||||
|
||||
/// Assert CRDT states are convergent
|
||||
pub fn assert_crdt_convergence(state1: &str, state2: &str) {
|
||||
// TODO: Implement once CRDT types exist
|
||||
// Verify eventual consistency
|
||||
assert_eq!(state1, state2, "CRDT states did not converge");
|
||||
}
|
||||
|
||||
/// Assert topological invariants match expected values
|
||||
pub fn assert_betti_numbers(betti: &[usize], expected: &[usize]) {
|
||||
assert_eq!(
|
||||
betti.len(),
|
||||
expected.len(),
|
||||
"Betti number dimension mismatch"
|
||||
);
|
||||
|
||||
for (i, (actual, exp)) in betti.iter().zip(expected.iter()).enumerate() {
|
||||
assert_eq!(
|
||||
actual, exp,
|
||||
"Betti number b_{} mismatch: {} != {}",
|
||||
i, actual, exp
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Assert consensus proof is valid
|
||||
pub fn assert_valid_consensus_proof(proof: &str, threshold: usize) {
|
||||
// TODO: Implement once CommitProof type exists
|
||||
// Verify proof has sufficient signatures
|
||||
assert!(
|
||||
!proof.is_empty(),
|
||||
"Consensus proof is empty (need {} votes)",
|
||||
threshold
|
||||
);
|
||||
}
|
||||
|
||||
/// Assert temporal ordering is consistent
|
||||
pub fn assert_temporal_order(timestamps: &[u64]) {
|
||||
for window in timestamps.windows(2) {
|
||||
assert!(
|
||||
window[0] <= window[1],
|
||||
"Timestamps not in temporal order: {} > {}",
|
||||
window[0],
|
||||
window[1]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Assert pattern is within manifold region
|
||||
pub fn assert_in_manifold_region(embedding: &[f32], center: &[f32], radius: f32) {
|
||||
let distance = euclidean_distance(embedding, center);
|
||||
assert!(
|
||||
distance <= radius,
|
||||
"Pattern outside manifold region: distance {} > radius {}",
|
||||
distance,
|
||||
radius
|
||||
);
|
||||
}
|
||||
|
||||
// Helper: Compute Euclidean distance
|
||||
fn euclidean_distance(a: &[f32], b: &[f32]) -> f32 {
|
||||
assert_eq!(a.len(), b.len());
|
||||
a.iter()
|
||||
.zip(b.iter())
|
||||
.map(|(av, bv)| (av - bv).powi(2))
|
||||
.sum::<f32>()
|
||||
.sqrt()
|
||||
}
|
||||
80
vendor/ruvector/examples/exo-ai-2025/tests/common/fixtures.rs
vendored
Normal file
80
vendor/ruvector/examples/exo-ai-2025/tests/common/fixtures.rs
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
//! Test fixtures and data builders
|
||||
//!
|
||||
//! Provides reusable test data and configuration builders.
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
/// Generate test embeddings with known patterns
|
||||
pub fn generate_test_embeddings(count: usize, dimensions: usize) -> Vec<Vec<f32>> {
|
||||
// TODO: Implement once exo-core types are available
|
||||
// Generate diverse embeddings for testing
|
||||
// Use deterministic seed for reproducibility
|
||||
|
||||
(0..count)
|
||||
.map(|i| {
|
||||
(0..dimensions)
|
||||
.map(|d| ((i * dimensions + d) as f32).sin())
|
||||
.collect()
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Generate clustered embeddings (for testing similarity)
|
||||
pub fn generate_clustered_embeddings(
|
||||
clusters: usize,
|
||||
per_cluster: usize,
|
||||
dimensions: usize,
|
||||
) -> Vec<Vec<f32>> {
|
||||
// TODO: Implement clustering logic
|
||||
// Create distinct clusters in embedding space
|
||||
vec![vec![0.0; dimensions]; clusters * per_cluster]
|
||||
}
|
||||
|
||||
/// Create a test pattern with default values
|
||||
pub fn create_test_pattern(embedding: Vec<f32>) -> String {
|
||||
// TODO: Return actual Pattern once exo-core exists
|
||||
// For now, return placeholder
|
||||
format!("TestPattern({:?})", &embedding[..embedding.len().min(3)])
|
||||
}
|
||||
|
||||
/// Create a test hypergraph with known topology
|
||||
pub fn create_test_hypergraph() -> String {
|
||||
// TODO: Build test hypergraph once exo-hypergraph exists
|
||||
// Should include:
|
||||
// - Multiple connected components
|
||||
// - Some 1-dimensional holes (cycles)
|
||||
// - Some 2-dimensional holes (voids)
|
||||
"TestHypergraph".to_string()
|
||||
}
|
||||
|
||||
/// Create a causal chain for testing temporal memory
|
||||
pub fn create_causal_chain(length: usize) -> Vec<String> {
|
||||
// TODO: Create linked patterns once exo-temporal exists
|
||||
// Returns pattern IDs in causal order
|
||||
(0..length).map(|i| format!("pattern_{}", i)).collect()
|
||||
}
|
||||
|
||||
/// Create a federation of test nodes
|
||||
pub async fn create_test_federation(node_count: usize) -> Vec<String> {
|
||||
// TODO: Implement once exo-federation exists
|
||||
// Returns federation node handles
|
||||
(0..node_count)
|
||||
.map(|i| format!("node_{}", i))
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Default test configuration
|
||||
pub fn default_test_config() -> TestConfig {
|
||||
TestConfig {
|
||||
timeout_ms: 5000,
|
||||
log_level: "info".to_string(),
|
||||
seed: 42,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TestConfig {
|
||||
pub timeout_ms: u64,
|
||||
pub log_level: String,
|
||||
pub seed: u64,
|
||||
}
|
||||
130
vendor/ruvector/examples/exo-ai-2025/tests/common/helpers.rs
vendored
Normal file
130
vendor/ruvector/examples/exo-ai-2025/tests/common/helpers.rs
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
//! Test helper functions
|
||||
//!
|
||||
//! Provides utility functions for integration testing.
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
use std::time::Duration;
|
||||
use tokio::time::timeout;
|
||||
|
||||
/// Run async test with timeout
|
||||
pub async fn with_timeout<F, T>(duration: Duration, future: F) -> Result<T, String>
|
||||
where
|
||||
F: std::future::Future<Output = T>,
|
||||
{
|
||||
match timeout(duration, future).await {
|
||||
Ok(result) => Ok(result),
|
||||
Err(_) => Err(format!("Test timed out after {:?}", duration)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Initialize test logger
|
||||
pub fn init_test_logger() {
|
||||
// Initialize tracing/logging for tests
|
||||
// Only initialize once
|
||||
let _ = env_logger::builder()
|
||||
.is_test(true)
|
||||
.filter_level(log::LevelFilter::Info)
|
||||
.try_init();
|
||||
}
|
||||
|
||||
/// Generate deterministic random data for testing
|
||||
pub fn deterministic_random_vec(seed: u64, len: usize) -> Vec<f32> {
|
||||
// Simple LCG for deterministic "random" numbers
|
||||
let mut state = seed;
|
||||
(0..len)
|
||||
.map(|_| {
|
||||
state = state.wrapping_mul(1103515245).wrapping_add(12345);
|
||||
((state / 65536) % 32768) as f32 / 32768.0
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Measure execution time of a function
|
||||
pub async fn measure_async<F, T>(f: F) -> (T, Duration)
|
||||
where
|
||||
F: std::future::Future<Output = T>,
|
||||
{
|
||||
let start = std::time::Instant::now();
|
||||
let result = f.await;
|
||||
let duration = start.elapsed();
|
||||
(result, duration)
|
||||
}
|
||||
|
||||
/// Compare vectors with tolerance
|
||||
pub fn vectors_approx_equal(a: &[f32], b: &[f32], tolerance: f32) -> bool {
|
||||
if a.len() != b.len() {
|
||||
return false;
|
||||
}
|
||||
|
||||
a.iter()
|
||||
.zip(b.iter())
|
||||
.all(|(av, bv)| (av - bv).abs() < tolerance)
|
||||
}
|
||||
|
||||
/// Cosine similarity
|
||||
pub fn cosine_similarity(a: &[f32], b: &[f32]) -> f32 {
|
||||
assert_eq!(a.len(), b.len());
|
||||
|
||||
let dot_product: f32 = a.iter().zip(b.iter()).map(|(av, bv)| av * bv).sum();
|
||||
let norm_a: f32 = a.iter().map(|av| av * av).sum::<f32>().sqrt();
|
||||
let norm_b: f32 = b.iter().map(|bv| bv * bv).sum::<f32>().sqrt();
|
||||
|
||||
if norm_a == 0.0 || norm_b == 0.0 {
|
||||
0.0
|
||||
} else {
|
||||
dot_product / (norm_a * norm_b)
|
||||
}
|
||||
}
|
||||
|
||||
/// Wait for async condition to become true
|
||||
pub async fn wait_for_condition<F>(
|
||||
mut condition: F,
|
||||
timeout_duration: Duration,
|
||||
check_interval: Duration,
|
||||
) -> Result<(), String>
|
||||
where
|
||||
F: FnMut() -> bool,
|
||||
{
|
||||
let start = std::time::Instant::now();
|
||||
|
||||
while start.elapsed() < timeout_duration {
|
||||
if condition() {
|
||||
return Ok(());
|
||||
}
|
||||
tokio::time::sleep(check_interval).await;
|
||||
}
|
||||
|
||||
Err(format!(
|
||||
"Condition not met within {:?}",
|
||||
timeout_duration
|
||||
))
|
||||
}
|
||||
|
||||
/// Create a temporary test directory
|
||||
pub fn create_temp_test_dir() -> std::io::Result<std::path::PathBuf> {
|
||||
let temp_dir = std::env::temp_dir().join(format!("exo-test-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&temp_dir)?;
|
||||
Ok(temp_dir)
|
||||
}
|
||||
|
||||
/// Clean up test resources
|
||||
pub async fn cleanup_test_resources(path: &std::path::Path) -> std::io::Result<()> {
|
||||
if path.exists() {
|
||||
tokio::fs::remove_dir_all(path).await?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Mock UUID for tests (replace with actual uuid crate when available)
|
||||
mod uuid {
|
||||
pub struct Uuid;
|
||||
impl Uuid {
|
||||
pub fn new_v4() -> String {
|
||||
format!("{:016x}", std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_nanos())
|
||||
}
|
||||
}
|
||||
}
|
||||
12
vendor/ruvector/examples/exo-ai-2025/tests/common/mod.rs
vendored
Normal file
12
vendor/ruvector/examples/exo-ai-2025/tests/common/mod.rs
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
//! Common test utilities and helpers for integration tests
|
||||
//!
|
||||
//! This module provides shared functionality across all integration tests.
|
||||
|
||||
pub mod fixtures;
|
||||
pub mod assertions;
|
||||
pub mod helpers;
|
||||
|
||||
// Re-export commonly used items
|
||||
pub use fixtures::*;
|
||||
pub use assertions::*;
|
||||
pub use helpers::*;
|
||||
246
vendor/ruvector/examples/exo-ai-2025/tests/federation_integration.rs
vendored
Normal file
246
vendor/ruvector/examples/exo-ai-2025/tests/federation_integration.rs
vendored
Normal file
@@ -0,0 +1,246 @@
|
||||
//! Integration Tests: Federated Cognitive Mesh
|
||||
//!
|
||||
//! These tests verify distributed substrate capabilities including:
|
||||
//! - Post-quantum key exchange
|
||||
//! - CRDT reconciliation
|
||||
//! - Byzantine fault tolerant consensus
|
||||
//! - Federated query routing
|
||||
|
||||
#[cfg(test)]
|
||||
mod federation_tests {
|
||||
// Note: These imports will be available once crates are implemented
|
||||
// use exo_federation::{FederatedMesh, FederationScope, StateUpdate};
|
||||
// use exo_core::{Query, Pattern};
|
||||
|
||||
/// Test: CRDT merge operations for conflict-free reconciliation
|
||||
///
|
||||
/// Flow:
|
||||
/// 1. Create two federated nodes
|
||||
/// 2. Each node stores different patterns
|
||||
/// 3. Merge CRDT states
|
||||
/// 4. Verify both nodes have consistent view
|
||||
#[tokio::test]
|
||||
#[ignore] // Remove when exo-federation exists
|
||||
async fn test_crdt_merge_reconciliation() {
|
||||
// TODO: Implement once exo-federation exists
|
||||
|
||||
// Expected API:
|
||||
// let node1 = FederatedMesh::new("node1").await.unwrap();
|
||||
// let node2 = FederatedMesh::new("node2").await.unwrap();
|
||||
//
|
||||
// // Node 1 stores pattern A
|
||||
// let pattern_a = Pattern { embedding: vec![1.0, 0.0], ... };
|
||||
// node1.store(pattern_a.clone()).await.unwrap();
|
||||
//
|
||||
// // Node 2 stores pattern B
|
||||
// let pattern_b = Pattern { embedding: vec![0.0, 1.0], ... };
|
||||
// node2.store(pattern_b.clone()).await.unwrap();
|
||||
//
|
||||
// // Export CRDT states
|
||||
// let state1 = node1.export_crdt_state().await.unwrap();
|
||||
// let state2 = node2.export_crdt_state().await.unwrap();
|
||||
//
|
||||
// // Merge states (commutative, associative, idempotent)
|
||||
// node1.merge_crdt_state(state2).await.unwrap();
|
||||
// node2.merge_crdt_state(state1).await.unwrap();
|
||||
//
|
||||
// // Verify convergence: both nodes have A and B
|
||||
// let results1 = node1.list_all_patterns().await.unwrap();
|
||||
// let results2 = node2.list_all_patterns().await.unwrap();
|
||||
//
|
||||
// assert_eq!(results1.len(), 2);
|
||||
// assert_eq!(results2.len(), 2);
|
||||
// assert_eq!(results1, results2); // Identical state
|
||||
|
||||
panic!("Implement this test once exo-federation crate exists");
|
||||
}
|
||||
|
||||
/// Test: Byzantine fault tolerant consensus
|
||||
///
|
||||
/// Verifies consensus can tolerate f Byzantine faults for n=3f+1 nodes.
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
async fn test_byzantine_consensus() {
|
||||
// TODO: Implement once exo-federation exists
|
||||
|
||||
// Expected behavior:
|
||||
// - Create 4 nodes (tolerate 1 Byzantine fault)
|
||||
// - Propose state update
|
||||
// - Simulate 1 Byzantine node sending conflicting votes
|
||||
// - Verify honest majority reaches consensus
|
||||
|
||||
// Expected API:
|
||||
// let nodes = create_federation(4).await;
|
||||
//
|
||||
// let update = StateUpdate { ... };
|
||||
//
|
||||
// // Honest nodes (0, 1, 2)
|
||||
// let votes = vec![
|
||||
// nodes[0].vote_on_update(&update).await.unwrap(),
|
||||
// nodes[1].vote_on_update(&update).await.unwrap(),
|
||||
// nodes[2].vote_on_update(&update).await.unwrap(),
|
||||
// ];
|
||||
//
|
||||
// // Byzantine node sends conflicting vote
|
||||
// let byzantine_vote = create_conflicting_vote(&update);
|
||||
//
|
||||
// // Collect all votes
|
||||
// let all_votes = [votes, vec![byzantine_vote]].concat();
|
||||
//
|
||||
// // Verify consensus reached despite Byzantine node
|
||||
// let proof = nodes[0].finalize_consensus(&all_votes).await.unwrap();
|
||||
// assert!(proof.is_valid());
|
||||
|
||||
panic!("Implement this test once exo-federation crate exists");
|
||||
}
|
||||
|
||||
/// Test: Post-quantum key exchange and encrypted channel
|
||||
///
|
||||
/// Verifies CRYSTALS-Kyber key exchange for federation handshake.
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
async fn test_post_quantum_handshake() {
|
||||
// TODO: Implement once exo-federation exists
|
||||
|
||||
// Expected API:
|
||||
// let node1 = FederatedMesh::new("node1").await.unwrap();
|
||||
// let node2 = FederatedMesh::new("node2").await.unwrap();
|
||||
//
|
||||
// // Node 1 initiates federation
|
||||
// let token = node1.join_federation(&node2.address()).await.unwrap();
|
||||
//
|
||||
// // Verify encrypted channel established
|
||||
// assert!(token.channel.is_encrypted());
|
||||
// assert_eq!(token.channel.crypto_algorithm(), "CRYSTALS-Kyber");
|
||||
//
|
||||
// // Send encrypted message
|
||||
// let message = "test message";
|
||||
// token.channel.send(message).await.unwrap();
|
||||
//
|
||||
// // Node 2 receives and decrypts
|
||||
// let received = node2.receive().await.unwrap();
|
||||
// assert_eq!(received, message);
|
||||
|
||||
panic!("Implement this test once exo-federation crate exists");
|
||||
}
|
||||
|
||||
/// Test: Federated query with onion routing
|
||||
///
|
||||
/// Verifies privacy-preserving query routing across federation.
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
async fn test_onion_routed_federated_query() {
|
||||
// TODO: Implement once exo-federation exists
|
||||
|
||||
// Expected API:
|
||||
// let federation = create_federation(5).await;
|
||||
//
|
||||
// // Store pattern on node 4
|
||||
// let pattern = Pattern { ... };
|
||||
// federation.nodes[4].store(pattern.clone()).await.unwrap();
|
||||
//
|
||||
// // Node 0 queries through onion network
|
||||
// let query = Query::from_embedding(pattern.embedding.clone());
|
||||
// let scope = FederationScope::Full;
|
||||
// let results = federation.nodes[0].federated_query(&query, scope).await.unwrap();
|
||||
//
|
||||
// // Should find pattern without revealing query origin
|
||||
// assert_eq!(results.len(), 1);
|
||||
// assert_eq!(results[0].pattern.id, pattern.id);
|
||||
//
|
||||
// // Verify intermediate nodes don't know query origin
|
||||
// // (This would require instrumentation/logging)
|
||||
|
||||
panic!("Implement this test once exo-federation crate exists");
|
||||
}
|
||||
|
||||
/// Test: CRDT concurrent updates
|
||||
///
|
||||
/// Verifies CRDTs handle concurrent conflicting updates correctly.
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
async fn test_crdt_concurrent_updates() {
|
||||
// TODO: Implement once exo-federation exists
|
||||
|
||||
// Scenario:
|
||||
// - Two nodes concurrently update same pattern
|
||||
// - Verify CRDT reconciliation produces consistent result
|
||||
// - Test all CRDT types: G-Set, LWW-Register, Counter
|
||||
|
||||
panic!("Implement this test once exo-federation crate exists");
|
||||
}
|
||||
|
||||
/// Test: Federation with partial connectivity
|
||||
///
|
||||
/// Verifies system handles network partitions gracefully.
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
async fn test_network_partition_tolerance() {
|
||||
// TODO: Implement once exo-federation exists
|
||||
|
||||
// Expected:
|
||||
// - Create 6-node federation
|
||||
// - Partition into two groups (3 + 3)
|
||||
// - Verify each partition continues operation
|
||||
// - Heal partition
|
||||
// - Verify eventual consistency after healing
|
||||
|
||||
panic!("Implement this test once exo-federation crate exists");
|
||||
}
|
||||
|
||||
/// Test: Consensus timeout and retry
|
||||
///
|
||||
/// Verifies consensus protocol handles slow/unresponsive nodes.
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
async fn test_consensus_timeout_handling() {
|
||||
// TODO: Implement once exo-federation exists
|
||||
|
||||
// Expected:
|
||||
// - Create federation with one slow node
|
||||
// - Propose update with timeout
|
||||
// - Verify consensus either succeeds without slow node or retries
|
||||
|
||||
panic!("Implement this test once exo-federation crate exists");
|
||||
}
|
||||
|
||||
/// Test: Federated query aggregation
|
||||
///
|
||||
/// Verifies query results are correctly aggregated from multiple nodes.
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
async fn test_federated_query_aggregation() {
|
||||
// TODO: Implement once exo-federation exists
|
||||
|
||||
// Expected:
|
||||
// - Multiple nodes store different patterns
|
||||
// - Query aggregates top-k results from all nodes
|
||||
// - Verify ranking is correct across federation
|
||||
|
||||
panic!("Implement this test once exo-federation crate exists");
|
||||
}
|
||||
|
||||
/// Test: Cryptographic sovereignty boundaries
|
||||
///
|
||||
/// Verifies federation respects cryptographic access control.
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
async fn test_cryptographic_sovereignty() {
|
||||
// TODO: Implement once exo-federation exists
|
||||
|
||||
// Expected:
|
||||
// - Node stores pattern with access control
|
||||
// - Unauthorized node attempts query
|
||||
// - Verify access denied
|
||||
// - Authorized node with correct key succeeds
|
||||
|
||||
panic!("Implement this test once exo-federation crate exists");
|
||||
}
|
||||
|
||||
// Helper function to create test federation
|
||||
#[allow(dead_code)]
|
||||
async fn create_federation(_node_count: usize) {
|
||||
// TODO: Implement helper to build test federation
|
||||
panic!("Helper not implemented yet");
|
||||
}
|
||||
}
|
||||
58
vendor/ruvector/examples/exo-ai-2025/tests/full_stack_test.rs
vendored
Normal file
58
vendor/ruvector/examples/exo-ai-2025/tests/full_stack_test.rs
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
//! Full-stack integration tests: All components together
|
||||
|
||||
#[cfg(test)]
|
||||
mod full_stack_integration {
|
||||
use super::*;
|
||||
// use exo_core::*;
|
||||
// use exo_manifold::*;
|
||||
// use exo_hypergraph::*;
|
||||
// use exo_temporal::*;
|
||||
// use exo_federation::*;
|
||||
// use exo_backend_classical::*;
|
||||
|
||||
#[test]
|
||||
#[tokio::test]
|
||||
async fn test_complete_cognitive_substrate() {
|
||||
// Test complete system: manifold + hypergraph + temporal + federation
|
||||
//
|
||||
// // Setup
|
||||
// let backend = ClassicalBackend::new(config);
|
||||
// let manifold = ManifoldEngine::new(backend.clone());
|
||||
// let hypergraph = HypergraphSubstrate::new(backend.clone());
|
||||
// let temporal = TemporalMemory::new();
|
||||
// let federation = FederatedMesh::new(fed_config);
|
||||
//
|
||||
// // Scenario: Multi-agent collaborative memory
|
||||
// // 1. Store patterns with temporal context
|
||||
// let p1 = temporal.store(pattern1, &[]).unwrap();
|
||||
//
|
||||
// // 2. Deform manifold
|
||||
// manifold.deform(&pattern1, 0.8);
|
||||
//
|
||||
// // 3. Create hypergraph relationships
|
||||
// hypergraph.create_hyperedge(&[p1, p2], &relation).unwrap();
|
||||
//
|
||||
// // 4. Query with causal constraints
|
||||
// let results = temporal.causal_query(&query, now, CausalConeType::Past);
|
||||
//
|
||||
// // 5. Federate query
|
||||
// let fed_results = federation.federated_query(&query, FederationScope::Global).await;
|
||||
//
|
||||
// // Verify all components work together
|
||||
// assert!(!results.is_empty());
|
||||
// assert!(!fed_results.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[tokio::test]
|
||||
async fn test_agent_memory_lifecycle() {
|
||||
// Test complete memory lifecycle:
|
||||
// Storage -> Consolidation -> Retrieval -> Forgetting -> Federation
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[tokio::test]
|
||||
async fn test_cross_component_consistency() {
|
||||
// Test that all components maintain consistent state
|
||||
}
|
||||
}
|
||||
172
vendor/ruvector/examples/exo-ai-2025/tests/hypergraph_integration.rs
vendored
Normal file
172
vendor/ruvector/examples/exo-ai-2025/tests/hypergraph_integration.rs
vendored
Normal file
@@ -0,0 +1,172 @@
|
||||
//! Integration Tests: Hypergraph Substrate
|
||||
//!
|
||||
//! These tests verify higher-order relational reasoning capabilities
|
||||
//! including hyperedge creation, topological queries, and sheaf consistency.
|
||||
|
||||
#[cfg(test)]
|
||||
mod hypergraph_tests {
|
||||
// Note: These imports will be available once crates are implemented
|
||||
// use exo_hypergraph::{HypergraphSubstrate, Hyperedge, TopologicalQuery};
|
||||
// use exo_core::{EntityId, Relation, Pattern};
|
||||
|
||||
/// Test: Create entities and hyperedges, then query topology
|
||||
///
|
||||
/// Flow:
|
||||
/// 1. Create multiple entities in the substrate
|
||||
/// 2. Create hyperedges spanning multiple entities
|
||||
/// 3. Query the hypergraph topology
|
||||
/// 4. Verify hyperedge relationships
|
||||
#[tokio::test]
|
||||
#[ignore] // Remove when exo-hypergraph exists
|
||||
async fn test_hyperedge_creation_and_query() {
|
||||
// TODO: Implement once exo-hypergraph exists
|
||||
|
||||
// Expected API:
|
||||
// let mut hypergraph = HypergraphSubstrate::new();
|
||||
//
|
||||
// // Create entities
|
||||
// let entity1 = hypergraph.create_entity(Pattern { ... }).await.unwrap();
|
||||
// let entity2 = hypergraph.create_entity(Pattern { ... }).await.unwrap();
|
||||
// let entity3 = hypergraph.create_entity(Pattern { ... }).await.unwrap();
|
||||
//
|
||||
// // Create hyperedge spanning 3 entities
|
||||
// let relation = Relation::new("collaborates_on");
|
||||
// let hyperedge_id = hypergraph.create_hyperedge(
|
||||
// &[entity1, entity2, entity3],
|
||||
// &relation
|
||||
// ).await.unwrap();
|
||||
//
|
||||
// // Query hyperedges containing entity1
|
||||
// let edges = hypergraph.get_hyperedges_for_entity(entity1).await.unwrap();
|
||||
// assert!(edges.contains(&hyperedge_id));
|
||||
//
|
||||
// // Verify all entities are in the hyperedge
|
||||
// let hyperedge = hypergraph.get_hyperedge(hyperedge_id).await.unwrap();
|
||||
// assert_eq!(hyperedge.entities.len(), 3);
|
||||
// assert!(hyperedge.entities.contains(&entity1));
|
||||
// assert!(hyperedge.entities.contains(&entity2));
|
||||
// assert!(hyperedge.entities.contains(&entity3));
|
||||
|
||||
panic!("Implement this test once exo-hypergraph crate exists");
|
||||
}
|
||||
|
||||
/// Test: Persistent homology computation
|
||||
///
|
||||
/// Verifies topological feature extraction across scales.
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
async fn test_persistent_homology() {
|
||||
// TODO: Implement once exo-hypergraph exists
|
||||
|
||||
// Expected API:
|
||||
// let hypergraph = build_test_hypergraph();
|
||||
//
|
||||
// // Compute 1-dimensional persistent features (loops/cycles)
|
||||
// let persistence_diagram = hypergraph.persistent_homology(
|
||||
// dimension=1,
|
||||
// epsilon_range=(0.0, 1.0)
|
||||
// ).await.unwrap();
|
||||
//
|
||||
// // Verify persistence pairs
|
||||
// assert!(!persistence_diagram.pairs.is_empty());
|
||||
//
|
||||
// // Check for essential features (never die)
|
||||
// let essential = persistence_diagram.pairs.iter()
|
||||
// .filter(|(birth, death)| death.is_infinite())
|
||||
// .count();
|
||||
// assert!(essential > 0);
|
||||
|
||||
panic!("Implement this test once exo-hypergraph crate exists");
|
||||
}
|
||||
|
||||
/// Test: Betti numbers (topological invariants)
|
||||
///
|
||||
/// Verifies computation of connected components and holes.
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
async fn test_betti_numbers() {
|
||||
// TODO: Implement once exo-hypergraph exists
|
||||
|
||||
// Expected API:
|
||||
// let hypergraph = build_test_hypergraph_with_holes();
|
||||
//
|
||||
// // Compute Betti numbers up to dimension 2
|
||||
// let betti = hypergraph.betti_numbers(max_dim=2).await.unwrap();
|
||||
//
|
||||
// // b0 = connected components
|
||||
// // b1 = 1-dimensional holes (loops)
|
||||
// // b2 = 2-dimensional holes (voids)
|
||||
// assert_eq!(betti.len(), 3);
|
||||
// assert!(betti[0] > 0); // At least one connected component
|
||||
|
||||
panic!("Implement this test once exo-hypergraph crate exists");
|
||||
}
|
||||
|
||||
/// Test: Sheaf consistency check
|
||||
///
|
||||
/// Verifies local-to-global coherence across hypergraph sections.
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
async fn test_sheaf_consistency() {
|
||||
// TODO: Implement once exo-hypergraph exists with sheaf support
|
||||
|
||||
// Expected API:
|
||||
// let hypergraph = HypergraphSubstrate::with_sheaf();
|
||||
//
|
||||
// // Create overlapping sections
|
||||
// let section1 = hypergraph.create_section(entities=[e1, e2], data=...);
|
||||
// let section2 = hypergraph.create_section(entities=[e2, e3], data=...);
|
||||
//
|
||||
// // Check consistency
|
||||
// let result = hypergraph.check_sheaf_consistency(&[section1, section2]).await.unwrap();
|
||||
//
|
||||
// match result {
|
||||
// SheafConsistencyResult::Consistent => { /* expected */ },
|
||||
// SheafConsistencyResult::Inconsistent(errors) => {
|
||||
// panic!("Sheaf inconsistency: {:?}", errors);
|
||||
// },
|
||||
// _ => panic!("Unexpected result"),
|
||||
// }
|
||||
|
||||
panic!("Implement this test once exo-hypergraph sheaf support exists");
|
||||
}
|
||||
|
||||
/// Test: Complex relational query
|
||||
///
|
||||
/// Verifies ability to query complex multi-entity relationships.
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
async fn test_complex_relational_query() {
|
||||
// TODO: Implement once exo-hypergraph exists
|
||||
|
||||
// Scenario:
|
||||
// - Create a knowledge graph with multiple relation types
|
||||
// - Query for patterns like "all entities related to X through Y"
|
||||
// - Verify transitive relationships
|
||||
|
||||
panic!("Implement this test once exo-hypergraph crate exists");
|
||||
}
|
||||
|
||||
/// Test: Hypergraph with temporal evolution
|
||||
///
|
||||
/// Verifies hypergraph can track changes over time.
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
async fn test_temporal_hypergraph() {
|
||||
// TODO: Implement once exo-hypergraph + exo-temporal integrated
|
||||
|
||||
// Expected:
|
||||
// - Create hyperedges at different timestamps
|
||||
// - Query hypergraph state at specific time points
|
||||
// - Verify temporal consistency
|
||||
|
||||
panic!("Implement this test once temporal integration exists");
|
||||
}
|
||||
|
||||
// Helper function for building test hypergraphs
|
||||
#[allow(dead_code)]
|
||||
fn build_test_hypergraph() {
|
||||
// TODO: Implement helper to build standard test topology
|
||||
panic!("Helper not implemented yet");
|
||||
}
|
||||
}
|
||||
53
vendor/ruvector/examples/exo-ai-2025/tests/manifold_hypergraph_test.rs
vendored
Normal file
53
vendor/ruvector/examples/exo-ai-2025/tests/manifold_hypergraph_test.rs
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
//! Integration tests: Manifold Engine + Hypergraph Substrate
|
||||
|
||||
#[cfg(test)]
|
||||
mod manifold_hypergraph_integration {
|
||||
use super::*;
|
||||
// use exo_manifold::*;
|
||||
// use exo_hypergraph::*;
|
||||
// use exo_backend_classical::ClassicalBackend;
|
||||
|
||||
#[test]
|
||||
fn test_manifold_with_hypergraph_structure() {
|
||||
// Test querying manifold with hypergraph topological constraints
|
||||
// let backend = ClassicalBackend::new(config);
|
||||
// let mut manifold = ManifoldEngine::new(backend.clone());
|
||||
// let mut hypergraph = HypergraphSubstrate::new(backend);
|
||||
//
|
||||
// // Store patterns in manifold
|
||||
// let p1 = manifold.deform(pattern1, 0.8);
|
||||
// let p2 = manifold.deform(pattern2, 0.7);
|
||||
// let p3 = manifold.deform(pattern3, 0.9);
|
||||
//
|
||||
// // Create hyperedges linking patterns
|
||||
// let relation = Relation::new("semantic_cluster");
|
||||
// hypergraph.create_hyperedge(&[p1, p2, p3], &relation).unwrap();
|
||||
//
|
||||
// // Query manifold and verify hypergraph structure
|
||||
// let results = manifold.retrieve(query, 10);
|
||||
//
|
||||
// // Verify results respect hypergraph topology
|
||||
// for result in results {
|
||||
// let edges = hypergraph.hyperedges_containing(result.id);
|
||||
// assert!(!edges.is_empty()); // Should be connected
|
||||
// }
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_persistent_homology_on_manifold() {
|
||||
// Test computing persistent homology on learned manifold
|
||||
// let manifold = setup_manifold_with_patterns();
|
||||
// let hypergraph = setup_hypergraph_from_manifold(&manifold);
|
||||
//
|
||||
// let diagram = hypergraph.persistent_homology(1, (0.0, 1.0));
|
||||
//
|
||||
// // Verify topological features detected
|
||||
// assert!(diagram.num_features() > 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hypergraph_guided_retrieval() {
|
||||
// Test using hypergraph structure to guide manifold retrieval
|
||||
// Retrieve patterns, then expand via hyperedge traversal
|
||||
}
|
||||
}
|
||||
137
vendor/ruvector/examples/exo-ai-2025/tests/substrate_integration.rs
vendored
Normal file
137
vendor/ruvector/examples/exo-ai-2025/tests/substrate_integration.rs
vendored
Normal file
@@ -0,0 +1,137 @@
|
||||
//! Integration Tests: Complete Substrate Workflow
|
||||
//!
|
||||
//! These tests verify the end-to-end functionality of the cognitive substrate,
|
||||
//! from pattern storage through querying and retrieval.
|
||||
|
||||
#[cfg(test)]
|
||||
mod substrate_tests {
|
||||
// Note: These imports will be available once crates are implemented
|
||||
// use exo_core::{Pattern, Query, SubstrateConfig};
|
||||
// use exo_backend_classical::ClassicalBackend;
|
||||
// use exo_manifold::ManifoldEngine;
|
||||
|
||||
/// Test: Complete substrate workflow
|
||||
///
|
||||
/// Steps:
|
||||
/// 1. Initialize substrate with classical backend
|
||||
/// 2. Store multiple patterns with embeddings
|
||||
/// 3. Query with similarity search
|
||||
/// 4. Verify results match expected patterns
|
||||
#[tokio::test]
|
||||
#[ignore] // Remove this when crates are implemented
|
||||
async fn test_substrate_store_and_retrieve() {
|
||||
// TODO: Implement once exo-core and exo-backend-classical exist
|
||||
|
||||
// Expected API usage:
|
||||
// let config = SubstrateConfig::default();
|
||||
// let backend = ClassicalBackend::new(config).unwrap();
|
||||
// let substrate = SubstrateInstance::new(backend);
|
||||
|
||||
// // Store patterns
|
||||
// let pattern1 = Pattern {
|
||||
// embedding: vec![1.0, 0.0, 0.0, 0.0],
|
||||
// metadata: Metadata::new(),
|
||||
// timestamp: SubstrateTime::now(),
|
||||
// antecedents: vec![],
|
||||
// };
|
||||
//
|
||||
// let id1 = substrate.store(pattern1.clone()).await.unwrap();
|
||||
//
|
||||
// let pattern2 = Pattern {
|
||||
// embedding: vec![0.9, 0.1, 0.0, 0.0],
|
||||
// metadata: Metadata::new(),
|
||||
// timestamp: SubstrateTime::now(),
|
||||
// antecedents: vec![],
|
||||
// };
|
||||
//
|
||||
// let id2 = substrate.store(pattern2.clone()).await.unwrap();
|
||||
//
|
||||
// // Query
|
||||
// let query = Query::from_embedding(vec![1.0, 0.0, 0.0, 0.0]);
|
||||
// let results = substrate.search(query, 2).await.unwrap();
|
||||
//
|
||||
// // Verify
|
||||
// assert_eq!(results.len(), 2);
|
||||
// assert_eq!(results[0].id, id1); // Closest match
|
||||
// assert!(results[0].score > results[1].score);
|
||||
|
||||
panic!("Implement this test once exo-core crate exists");
|
||||
}
|
||||
|
||||
/// Test: Manifold deformation (continuous learning)
|
||||
///
|
||||
/// Verifies that the learned manifold can be deformed to incorporate
|
||||
/// new patterns without explicit insert operations.
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
async fn test_manifold_deformation() {
|
||||
// TODO: Implement once exo-manifold exists
|
||||
|
||||
// Expected API:
|
||||
// let manifold = ManifoldEngine::new(config);
|
||||
//
|
||||
// // Initial query should find nothing
|
||||
// let query = Tensor::from_floats(&[0.5, 0.5, 0.0, 0.0]);
|
||||
// let before = manifold.retrieve(query.clone(), 1);
|
||||
// assert!(before.is_empty());
|
||||
//
|
||||
// // Deform manifold with new pattern
|
||||
// let pattern = Pattern { embedding: vec![0.5, 0.5, 0.0, 0.0], ... };
|
||||
// manifold.deform(pattern, salience=1.0);
|
||||
//
|
||||
// // Now query should find the pattern
|
||||
// let after = manifold.retrieve(query, 1);
|
||||
// assert_eq!(after.len(), 1);
|
||||
|
||||
panic!("Implement this test once exo-manifold crate exists");
|
||||
}
|
||||
|
||||
/// Test: Strategic forgetting
|
||||
///
|
||||
/// Verifies that low-salience patterns decay over time.
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
async fn test_strategic_forgetting() {
|
||||
// TODO: Implement once exo-manifold exists
|
||||
|
||||
// Expected behavior:
|
||||
// 1. Store high-salience and low-salience patterns
|
||||
// 2. Trigger forgetting
|
||||
// 3. Verify low-salience patterns are forgotten
|
||||
// 4. Verify high-salience patterns remain
|
||||
|
||||
panic!("Implement this test once exo-manifold crate exists");
|
||||
}
|
||||
|
||||
/// Test: Batch operations and performance
|
||||
///
|
||||
/// Verifies substrate can handle bulk operations efficiently.
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
async fn test_bulk_operations() {
|
||||
// TODO: Implement performance test
|
||||
|
||||
// Expected:
|
||||
// - Store 10,000 patterns
|
||||
// - Batch query 1,000 times
|
||||
// - Verify latency < 10ms per query (classical backend)
|
||||
|
||||
panic!("Implement this test once exo-core crate exists");
|
||||
}
|
||||
|
||||
/// Test: Filter-based queries
|
||||
///
|
||||
/// Verifies metadata filtering during similarity search.
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
async fn test_filtered_search() {
|
||||
// TODO: Implement once exo-core exists
|
||||
|
||||
// Expected:
|
||||
// - Store patterns with different metadata tags
|
||||
// - Query with metadata filter
|
||||
// - Verify only matching patterns returned
|
||||
|
||||
panic!("Implement this test once exo-core crate exists");
|
||||
}
|
||||
}
|
||||
47
vendor/ruvector/examples/exo-ai-2025/tests/temporal_federation_test.rs
vendored
Normal file
47
vendor/ruvector/examples/exo-ai-2025/tests/temporal_federation_test.rs
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
//! Integration tests: Temporal Memory + Federation
|
||||
|
||||
#[cfg(test)]
|
||||
mod temporal_federation_integration {
|
||||
use super::*;
|
||||
// use exo_temporal::*;
|
||||
// use exo_federation::*;
|
||||
|
||||
#[test]
|
||||
#[tokio::test]
|
||||
async fn test_federated_temporal_query() {
|
||||
// Test temporal queries across federation
|
||||
// let node1 = setup_federated_node_with_temporal(config1);
|
||||
// let node2 = setup_federated_node_with_temporal(config2);
|
||||
//
|
||||
// // Join federation
|
||||
// node1.join_federation(&node2.address()).await.unwrap();
|
||||
//
|
||||
// // Store temporal patterns on node1
|
||||
// let p1 = node1.temporal_memory.store(pattern1, &[]).unwrap();
|
||||
// let p2 = node1.temporal_memory.store(pattern2, &[p1]).unwrap();
|
||||
//
|
||||
// // Query from node2 with causal constraints
|
||||
// let query = Query::new("test");
|
||||
// let results = node2.federated_temporal_query(
|
||||
// &query,
|
||||
// SubstrateTime::now(),
|
||||
// CausalConeType::Past,
|
||||
// FederationScope::Global
|
||||
// ).await;
|
||||
//
|
||||
// // Should receive results from node1
|
||||
// assert!(!results.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[tokio::test]
|
||||
async fn test_distributed_memory_consolidation() {
|
||||
// Test memory consolidation across federated nodes
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[tokio::test]
|
||||
async fn test_causal_graph_federation() {
|
||||
// Test causal graph spanning multiple nodes
|
||||
}
|
||||
}
|
||||
227
vendor/ruvector/examples/exo-ai-2025/tests/temporal_integration.rs
vendored
Normal file
227
vendor/ruvector/examples/exo-ai-2025/tests/temporal_integration.rs
vendored
Normal file
@@ -0,0 +1,227 @@
|
||||
//! Integration Tests: Temporal Memory Coordinator
|
||||
//!
|
||||
//! These tests verify causal memory architecture including:
|
||||
//! - Causal link tracking
|
||||
//! - Causal cone queries
|
||||
//! - Memory consolidation
|
||||
//! - Predictive anticipation
|
||||
|
||||
#[cfg(test)]
|
||||
mod temporal_tests {
|
||||
// Note: These imports will be available once crates are implemented
|
||||
// use exo_temporal::{TemporalMemory, CausalConeType, AnticipationHint};
|
||||
// use exo_core::{Pattern, SubstrateTime, PatternId};
|
||||
|
||||
/// Test: Store patterns with causal links, then verify causal queries
|
||||
///
|
||||
/// Flow:
|
||||
/// 1. Store patterns with explicit causal antecedents
|
||||
/// 2. Build causal graph
|
||||
/// 3. Query with causal cone constraints
|
||||
/// 4. Verify only causally-connected patterns returned
|
||||
#[tokio::test]
|
||||
#[ignore] // Remove when exo-temporal exists
|
||||
async fn test_causal_storage_and_query() {
|
||||
// TODO: Implement once exo-temporal exists
|
||||
|
||||
// Expected API:
|
||||
// let mut temporal_memory = TemporalMemory::new();
|
||||
//
|
||||
// // Store pattern A (no antecedents)
|
||||
// let pattern_a = Pattern { embedding: vec![1.0, 0.0, 0.0], ... };
|
||||
// let id_a = temporal_memory.store(pattern_a, antecedents=&[]).await.unwrap();
|
||||
//
|
||||
// // Store pattern B (caused by A)
|
||||
// let pattern_b = Pattern { embedding: vec![0.0, 1.0, 0.0], ... };
|
||||
// let id_b = temporal_memory.store(pattern_b, antecedents=&[id_a]).await.unwrap();
|
||||
//
|
||||
// // Store pattern C (caused by B)
|
||||
// let pattern_c = Pattern { embedding: vec![0.0, 0.0, 1.0], ... };
|
||||
// let id_c = temporal_memory.store(pattern_c, antecedents=&[id_b]).await.unwrap();
|
||||
//
|
||||
// // Query: causal past of C
|
||||
// let query = Query::from_id(id_c);
|
||||
// let results = temporal_memory.causal_query(
|
||||
// &query,
|
||||
// reference_time=SubstrateTime::now(),
|
||||
// cone_type=CausalConeType::Past
|
||||
// ).await.unwrap();
|
||||
//
|
||||
// // Should find B and A (causal ancestors)
|
||||
// assert_eq!(results.len(), 2);
|
||||
// let ids: Vec<_> = results.iter().map(|r| r.pattern.id).collect();
|
||||
// assert!(ids.contains(&id_a));
|
||||
// assert!(ids.contains(&id_b));
|
||||
//
|
||||
// // Causal distances should be correct
|
||||
// let result_a = results.iter().find(|r| r.pattern.id == id_a).unwrap();
|
||||
// assert_eq!(result_a.causal_distance, 2); // A -> B -> C
|
||||
|
||||
panic!("Implement this test once exo-temporal crate exists");
|
||||
}
|
||||
|
||||
/// Test: Causal cone with light-cone constraints
|
||||
///
|
||||
/// Verifies relativistic causal constraints on retrieval.
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
async fn test_light_cone_query() {
|
||||
// TODO: Implement once exo-temporal exists
|
||||
|
||||
// Expected behavior:
|
||||
// - Store patterns at different spacetime coordinates
|
||||
// - Query with light-cone velocity constraint
|
||||
// - Verify only patterns within light-cone returned
|
||||
|
||||
// Expected API:
|
||||
// let cone_type = CausalConeType::LightCone { velocity: 1.0 };
|
||||
// let results = temporal_memory.causal_query(
|
||||
// &query,
|
||||
// reference_time,
|
||||
// cone_type
|
||||
// ).await.unwrap();
|
||||
//
|
||||
// for result in results {
|
||||
// let spatial_dist = distance(query.origin, result.pattern.origin);
|
||||
// let temporal_dist = (result.timestamp - reference_time).abs();
|
||||
// assert!(spatial_dist <= velocity * temporal_dist);
|
||||
// }
|
||||
|
||||
panic!("Implement this test once exo-temporal crate exists");
|
||||
}
|
||||
|
||||
/// Test: Memory consolidation from short-term to long-term
|
||||
///
|
||||
/// Flow:
|
||||
/// 1. Fill short-term buffer with patterns of varying salience
|
||||
/// 2. Trigger consolidation
|
||||
/// 3. Verify high-salience patterns moved to long-term
|
||||
/// 4. Verify low-salience patterns forgotten
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
async fn test_memory_consolidation() {
|
||||
// TODO: Implement once exo-temporal exists
|
||||
|
||||
// Expected API:
|
||||
// let mut temporal_memory = TemporalMemory::new();
|
||||
//
|
||||
// // Store high-salience patterns
|
||||
// for _ in 0..10 {
|
||||
// let pattern = Pattern { salience: 0.9, ... };
|
||||
// temporal_memory.store(pattern, &[]).await.unwrap();
|
||||
// }
|
||||
//
|
||||
// // Store low-salience patterns
|
||||
// for _ in 0..10 {
|
||||
// let pattern = Pattern { salience: 0.1, ... };
|
||||
// temporal_memory.store(pattern, &[]).await.unwrap();
|
||||
// }
|
||||
//
|
||||
// // Trigger consolidation
|
||||
// temporal_memory.consolidate().await.unwrap();
|
||||
//
|
||||
// // Verify short-term buffer cleared
|
||||
// assert_eq!(temporal_memory.short_term_count(), 0);
|
||||
//
|
||||
// // Verify long-term contains ~10 patterns (high-salience)
|
||||
// assert!(temporal_memory.long_term_count() >= 8); // Allow some variance
|
||||
|
||||
panic!("Implement this test once exo-temporal crate exists");
|
||||
}
|
||||
|
||||
/// Test: Predictive anticipation and pre-fetching
|
||||
///
|
||||
/// Verifies substrate can predict future queries and pre-fetch results.
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
async fn test_predictive_anticipation() {
|
||||
// TODO: Implement once exo-temporal exists
|
||||
|
||||
// Expected API:
|
||||
// let mut temporal_memory = TemporalMemory::new();
|
||||
//
|
||||
// // Establish sequential pattern: A -> B -> C
|
||||
// let id_a = store_pattern_a();
|
||||
// let id_b = store_pattern_b(antecedents=[id_a]);
|
||||
// let id_c = store_pattern_c(antecedents=[id_b]);
|
||||
//
|
||||
// // Train sequential pattern
|
||||
// temporal_memory.learn_sequential_pattern(&[id_a, id_b, id_c]);
|
||||
//
|
||||
// // Query A
|
||||
// temporal_memory.query(id_a).await.unwrap();
|
||||
//
|
||||
// // Provide anticipation hint
|
||||
// let hint = AnticipationHint::SequentialPattern;
|
||||
// temporal_memory.anticipate(&[hint]).await.unwrap();
|
||||
//
|
||||
// // Verify B and C are now cached (predicted)
|
||||
// assert!(temporal_memory.is_cached(id_b));
|
||||
// assert!(temporal_memory.is_cached(id_c));
|
||||
|
||||
panic!("Implement this test once exo-temporal crate exists");
|
||||
}
|
||||
|
||||
/// Test: Temporal knowledge graph integration
|
||||
///
|
||||
/// Verifies integration with temporal knowledge graph structures.
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
async fn test_temporal_knowledge_graph() {
|
||||
// TODO: Implement once exo-temporal TKG support exists
|
||||
|
||||
// Expected:
|
||||
// - Store facts with temporal validity periods
|
||||
// - Query facts at specific time points
|
||||
// - Verify temporal reasoning (fact true at t1, false at t2)
|
||||
|
||||
panic!("Implement this test once TKG integration exists");
|
||||
}
|
||||
|
||||
/// Test: Causal graph distance computation
|
||||
///
|
||||
/// Verifies correct computation of causal distances.
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
async fn test_causal_distance() {
|
||||
// TODO: Implement once exo-temporal exists
|
||||
|
||||
// Build causal chain: A -> B -> C -> D -> E
|
||||
// Query causal distance from A to E
|
||||
// Expected: 4 (number of hops)
|
||||
|
||||
panic!("Implement this test once exo-temporal crate exists");
|
||||
}
|
||||
|
||||
/// Test: Concurrent causal updates
|
||||
///
|
||||
/// Verifies thread-safety of causal graph updates.
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
async fn test_concurrent_causal_updates() {
|
||||
// TODO: Implement once exo-temporal exists
|
||||
|
||||
// Expected:
|
||||
// - Spawn multiple tasks storing patterns concurrently
|
||||
// - Verify no race conditions in causal graph
|
||||
// - Verify all causal links preserved
|
||||
|
||||
panic!("Implement this test once exo-temporal crate exists");
|
||||
}
|
||||
|
||||
/// Test: Memory decay and forgetting
|
||||
///
|
||||
/// Verifies strategic forgetting mechanisms.
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
async fn test_strategic_forgetting() {
|
||||
// TODO: Implement once exo-temporal exists
|
||||
|
||||
// Expected:
|
||||
// - Store patterns with low access frequency
|
||||
// - Advance time and trigger decay
|
||||
// - Verify low-salience patterns removed
|
||||
|
||||
panic!("Implement this test once exo-temporal crate exists");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user