213 lines
6.7 KiB
Rust
213 lines
6.7 KiB
Rust
//! Integration tests for M3.8 Context Optimizer
|
|||
|
|
//!
|
||
|
|
//! Tests the full 4-stage pipeline: Detection → Compression → CCR → Integration
|
||
|
|
|
||
|
|
use mem_core::{ContextOptimizer, ContextOptimizerConfig, ContentType};
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_optimizer_detects_json() {
|
||
|
|
let optimizer = ContextOptimizer::new().expect("failed to create optimizer");
|
||
|
|
let json = r#"{"status": "success", "count": 42, "items": [1, 2, 3]}"#;
|
||
|
|
|
||
|
|
let result = optimizer.optimize(json).expect("optimize failed");
|
||
|
|
assert_eq!(result.content_type, ContentType::Json);
|
||
|
|
assert!(result.original_tokens > 0);
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_optimizer_detects_log() {
|
||
|
|
let optimizer = ContextOptimizer::new().expect("failed to create optimizer");
|
||
|
|
let log = "ERROR: connection timeout at 2026-08-28T09:15:00Z\n at main.rs:42";
|
||
|
|
|
||
|
|
let result = optimizer.optimize(log).expect("optimize failed");
|
||
|
|
assert_eq!(result.content_type, ContentType::Log);
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_optimizer_detects_code() {
|
||
|
|
let optimizer = ContextOptimizer::new().expect("failed to create optimizer");
|
||
|
|
let code = r#"
|
||
|
|
fn main() {
|
||
|
|
println!("hello");
|
||
|
|
}
|
||
|
|
"#;
|
||
|
|
|
||
|
|
let result = optimizer.optimize(code).expect("optimize failed");
|
||
|
|
assert_eq!(result.content_type, ContentType::Code);
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_optimizer_compresses_npm_logs() {
|
||
|
|
let optimizer = ContextOptimizer::new().expect("failed to create optimizer");
|
||
|
|
|
||
|
|
let npm_log = r#"
|
||
|
|
npm WARN deprecated [email protected]: package no longer supported
|
||
|
|
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: [email protected]
|
||
|
|
npm notice created a lockfile as package-lock.json.
|
||
|
|
npm ERR! 404 Not Found - GET https://registry.npmjs.org/[email protected]
|
||
|
|
npm ERR! 404
|
||
|
|
npm ERR! It is likely you are behind a proxy.
|
||
|
|
npm ERR! A complete log of this error:
|
||
|
|
npm ERR! /home/user/.npm/_logs/error.log
|
||
|
|
"#;
|
||
|
|
|
||
|
|
let result = optimizer.optimize(npm_log).expect("optimize failed");
|
||
|
|
|
||
|
|
// Should detect as log
|
||
|
|
assert_eq!(result.content_type, ContentType::Log);
|
||
|
|
|
||
|
|
// Should compress
|
||
|
|
assert!(result.compressed_tokens < result.original_tokens);
|
||
|
|
|
||
|
|
// Should keep error markers
|
||
|
|
assert!(result.compressed.to_lowercase().contains("npm err!"));
|
||
|
|
assert!(result.compressed.contains("404"));
|
||
|
|
|
||
|
|
// Should drop noise
|
||
|
|
assert!(!result.compressed.contains("WARN deprecated"));
|
||
|
|
assert!(!result.compressed.contains("notice created"));
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_optimizer_handles_json_array() {
|
||
|
|
let optimizer = ContextOptimizer::new().expect("failed to create optimizer");
|
||
|
|
|
||
|
|
let json_array = r#"
|
||
|
|
[
|
||
|
|
{"id": 1, "name": "Alice", "status": "active"},
|
||
|
|
{"id": 2, "name": "Bob", "status": "inactive"},
|
||
|
|
{"id": 3, "name": "Charlie", "status": "active"},
|
||
|
|
{"id": 4, "name": "Diana", "status": "active"}
|
||
|
|
]
|
||
|
|
"#;
|
||
|
|
|
||
|
|
let result = optimizer.optimize(json_array).expect("optimize failed");
|
||
|
|
|
||
|
|
// Should detect JSON
|
||
|
|
assert_eq!(result.content_type, ContentType::Json);
|
||
|
|
assert!(result.original_tokens > 0);
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_optimizer_detects_diff() {
|
||
|
|
let optimizer = ContextOptimizer::new().expect("failed to create optimizer");
|
||
|
|
|
||
|
|
let diff = r#"--- a/config.yaml
|
||
|
|
+++ b/config.yaml
|
||
|
|
@@ -1,3 +1,3 @@
|
||
|
|
server:
|
||
|
|
host: localhost
|
||
|
|
- port: 8080
|
||
|
|
+ port: 9000
|
||
|
|
"#;
|
||
|
|
|
||
|
|
let result = optimizer.optimize(diff).expect("optimize failed");
|
||
|
|
assert_eq!(result.content_type, ContentType::Diff);
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_optimizer_passthrough_when_disabled() {
|
||
|
|
let config = ContextOptimizerConfig {
|
||
|
|
enabled: false,
|
||
|
|
..Default::default()
|
||
|
|
};
|
||
|
|
let optimizer = ContextOptimizer::with_config(config).expect("failed to create optimizer");
|
||
|
|
|
||
|
|
let content = "ERROR: something failed";
|
||
|
|
let result = optimizer.optimize(content).expect("optimize failed");
|
||
|
|
|
||
|
|
// Should be unchanged
|
||
|
|
assert_eq!(result.compressed, content);
|
||
|
|
assert_eq!(result.original_tokens, result.compressed_tokens);
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_optimizer_with_compression_disabled() {
|
||
|
|
let config = ContextOptimizerConfig {
|
||
|
|
enabled: true,
|
||
|
|
compress_logs: false,
|
||
|
|
..Default::default()
|
||
|
|
};
|
||
|
|
let optimizer = ContextOptimizer::with_config(config).expect("failed to create optimizer");
|
||
|
|
|
||
|
|
let log = "ERROR: connection timeout\nWARN: slow response\nINFO: connected";
|
||
|
|
let result = optimizer.optimize(log).expect("optimize failed");
|
||
|
|
|
||
|
|
// Should be unchanged since compression is disabled
|
||
|
|
assert_eq!(result.compressed, log);
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_optimizer_token_counting() {
|
||
|
|
let optimizer = ContextOptimizer::new().expect("failed to create optimizer");
|
||
|
|
|
||
|
|
let short = "hello world";
|
||
|
|
let short_result = optimizer.optimize(short).expect("optimize failed");
|
||
|
|
|
||
|
|
let long = "This is a much longer piece of text with many words to test the token counting. ".repeat(10);
|
||
|
|
let long_result = optimizer.optimize(&long).expect("optimize failed");
|
||
|
|
|
||
|
|
// Longer text should have more tokens
|
||
|
|
assert!(long_result.original_tokens > short_result.original_tokens);
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_optimizer_with_cargo_error() {
|
||
|
|
let optimizer = ContextOptimizer::new().expect("failed to create optimizer");
|
||
|
|
|
||
|
|
let cargo_error = r#"
|
||
|
|
Compiling myapp v0.1.0
|
||
|
|
error[E0425]: cannot find value `unknown_var` in this scope
|
||
|
|
--> src/main.rs:42:5
|
||
|
|
|
|
||
|
|
42 | unknown_var = 42;
|
||
|
|
| ^^^^^^^^^^^ not found in this scope
|
||
|
|
|
||
|
|
error: aborting due to 1 previous error
|
||
|
|
"#;
|
||
|
|
|
||
|
|
let result = optimizer.optimize(cargo_error).expect("optimize failed");
|
||
|
|
|
||
|
|
// Should detect as log
|
||
|
|
assert_eq!(result.content_type, ContentType::Log);
|
||
|
|
|
||
|
|
// Should keep error lines
|
||
|
|
assert!(result.compressed.contains("error[E0425]"));
|
||
|
|
assert!(result.compressed.contains("src/main.rs:42"));
|
||
|
|
|
||
|
|
// Should drop compilation noise
|
||
|
|
assert!(!result.compressed.contains("Compiling myapp"));
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_optimizer_real_world_scenario() {
|
||
|
|
let optimizer = ContextOptimizer::new().expect("failed to create optimizer");
|
||
|
|
|
||
|
|
// Simulate a chunk from a real failure log with mixed content
|
||
|
|
let mixed_content = r#"
|
||
|
|
2026-08-28T09:15:00Z DEBUG: Starting npm install
|
||
|
|
npm WARN deprecated [email protected]: package no longer supported
|
||
|
|
npm notice created a lockfile
|
||
|
|
npm WARN optional SKIPPING OPTIONAL DEPENDENCY
|
||
|
|
2026-08-28T09:15:05Z INFO: dependency resolution
|
||
|
|
npm ERR! 404 Not Found - GET https://registry.npmjs.org/[email protected]
|
||
|
|
npm ERR! 404
|
||
|
|
npm ERR! It is likely you are behind a proxy
|
||
|
|
npm ERR! A complete log: /home/user/.npm/_logs/error.log
|
||
|
|
2026-08-28T09:15:10Z WARN: slow network
|
||
|
|
"#;
|
||
|
|
|
||
|
|
let result = optimizer.optimize(mixed_content).expect("optimize failed");
|
||
|
|
|
||
|
|
// Should detect as log (has timestamps + errors)
|
||
|
|
assert_eq!(result.content_type, ContentType::Log);
|
||
|
|
|
||
|
|
// Should reduce size
|
||
|
|
assert!(result.compressed.len() < mixed_content.len());
|
||
|
|
|
||
|
|
// Should preserve critical information
|
||
|
|
assert!(result.compressed.to_lowercase().contains("npm err!"));
|
||
|
|
assert!(result.compressed.contains("404"));
|
||
|
|
assert!(result.compressed.contains("2026-08-28")); // Timestamps may be kept
|
||
|
|
}
|