#![allow(unused_imports)]
use std::net::{IpAddr, SocketAddr};
use std::time::Instant;
use three_word_networking::ThreeWordAdaptiveEncoder;
mod test_config;
use test_config::*;
#[test]
fn test_complete_ipv4_workflow() {
init_test_env();
let generator = AddressGenerator::new();
for addr in generator.ipv4_addresses() {
let encoded = encode_ip_address(addr).expect("Encoding failed");
let decoded = decode_words(&encoded).expect("Decoding failed");
assert_encoding_roundtrip(addr, &encoded, &decoded);
}
}
#[test]
fn test_complete_ipv6_workflow() {
init_test_env();
let generator = AddressGenerator::new();
for addr in generator.ipv6_addresses() {
let encoded = encode_ip_address(addr).expect("Encoding failed");
let decoded = decode_words(&encoded).expect("Decoding failed");
assert_encoding_roundtrip(addr, &encoded, &decoded);
}
}
#[test]
fn test_socket_address_workflow() {
init_test_env();
let test_cases = vec![
"127.0.0.1:8080",
"192.168.1.1:443",
"[::1]:8080",
"[2001:db8::1]:443",
];
for addr in test_cases {
let encoded = encode_socket_address(addr).expect("Encoding failed");
let decoded = decode_socket_address(&encoded).expect("Decoding failed");
assert_encoding_roundtrip(addr, &encoded, &decoded);
}
}
#[test]
fn test_ip_address_workflow() {
init_test_env();
let generator = AddressGenerator::new();
for addr in generator.ipv4_with_ports() {
let encoder = ThreeWordAdaptiveEncoder::new().unwrap();
if let Ok(encoded) = encoder.encode(addr) {
let decoded = encoder.decode(&encoded).expect("Decoding failed");
assert_eq!(addr, &decoded, "Roundtrip failed for {}", addr);
}
}
for addr in generator.ipv6_with_ports() {
let encoder = ThreeWordAdaptiveEncoder::new().unwrap();
if let Ok(encoded) = encoder.encode(addr) {
let decoded = encoder.decode(&encoded).expect("Decoding failed");
assert_eq!(addr, &decoded, "Roundtrip failed for {}", addr);
}
}
}
#[test]
fn test_invalid_input_handling() {
init_test_env();
let invalid_inputs = vec![
"invalid.ip.address",
"999.999.999.999",
"::gg",
"not-an-ip",
"",
"127.0.0.1:99999",
];
for input in invalid_inputs {
match encode_ip_address(input) {
Ok(_) => panic!("Expected error for invalid input: {}", input),
Err(_) => {} }
}
}
#[test]
fn test_word_validation() {
init_test_env();
let valid_words = vec!["apple orange banana", "one two three", "first second third"];
for words in valid_words {
let result = validate_word_format(words);
assert!(
result.is_ok(),
"Valid words should pass validation: {}",
words
);
}
let invalid_words = vec![
"one two", "one two three four", "one two three", "", ];
for words in invalid_words {
let result = validate_word_format(words);
assert!(
result.is_err(),
"Invalid words should fail validation: {}",
words
);
}
}
#[test]
fn test_encoding_performance() {
init_test_env();
let test_ip = "192.168.1.1";
test_performance!(
"IPv4 encoding",
{
let _ = encode_ip_address(test_ip).expect("Encoding failed");
},
100000
); }
#[test]
fn test_decoding_performance() {
init_test_env();
let test_ip = "192.168.1.1";
let encoded = encode_ip_address(test_ip).expect("Encoding failed");
test_performance!(
"IPv4 decoding",
{
let _ = decode_words(&encoded).expect("Decoding failed");
},
50000
); }
#[test]
fn test_batch_processing_performance() {
init_test_env();
let generator = AddressGenerator::new();
let addresses: Vec<_> = generator
.ipv4_addresses()
.iter()
.chain(generator.ipv6_addresses().iter())
.collect();
let start = Instant::now();
for addr in &addresses {
let encoded = encode_ip_address(addr).expect("Encoding failed");
let _decoded = decode_words(&encoded).expect("Decoding failed");
}
let duration = start.elapsed();
let ops_per_sec = (addresses.len() as f64 * 2.0) / duration.as_secs_f64();
assert!(
ops_per_sec >= 100.0,
"Batch processing too slow: {:.2} ops/sec",
ops_per_sec
);
}
#[test]
fn test_memory_efficiency() {
init_test_env();
let generator = AddressGenerator::new();
for _ in 0..1000 {
for addr in generator.ipv4_addresses() {
let encoded = encode_ip_address(addr).expect("Encoding failed");
let _decoded = decode_words(&encoded).expect("Decoding failed");
}
}
assert!(true);
}
#[test]
fn test_concurrent_encoding() {
init_test_env();
use std::sync::Arc;
use std::thread;
let generator = Arc::new(AddressGenerator::new());
let mut handles = vec![];
for _ in 0..10 {
let generator_clone = Arc::clone(&generator);
let handle = thread::spawn(move || {
for addr in generator_clone.ipv4_addresses() {
let encoded = encode_ip_address(addr).expect("Encoding failed");
let decoded = decode_words(&encoded).expect("Decoding failed");
assert_encoding_roundtrip(addr, &encoded, &decoded);
}
});
handles.push(handle);
}
for handle in handles {
handle.join().expect("Thread failed");
}
}
#[test]
fn test_real_world_patterns() {
init_test_env();
let real_world_addresses = real_world_data();
for addr in real_world_addresses {
let encoded = encode_ip_address(&addr).expect("Encoding failed");
let decoded = decode_words(&encoded).expect("Decoding failed");
assert_encoding_roundtrip(&addr, &encoded, &decoded);
}
}
#[test]
fn test_edge_cases() {
init_test_env();
let edge_cases = edge_case_data();
for addr in edge_cases {
let encoded = encode_ip_address(&addr).expect("Encoding failed");
let decoded = decode_words(&encoded).expect("Decoding failed");
assert_encoding_roundtrip(&addr, &encoded, &decoded);
}
}
#[test]
fn test_compression_efficiency() {
init_test_env();
let test_cases = vec![
("127.0.0.1", 48), ("192.168.1.1", 48),
("::1", 96), ("2001:db8::1", 96),
];
for (addr, expected_max_bytes) in test_cases {
let encoded = encode_ip_address(addr).expect("Encoding failed");
let byte_count = encoded.len();
assert!(
byte_count <= expected_max_bytes,
"Encoding too long for {}: {} bytes > {} bytes",
addr,
byte_count,
expected_max_bytes
);
}
}
#[test]
fn test_deterministic_encoding() {
init_test_env();
let test_ip = "192.168.1.1";
let encodings: Vec<_> = (0..10)
.map(|_| encode_ip_address(test_ip).expect("Encoding failed"))
.collect();
let first = &encodings[0];
for encoding in &encodings[1..] {
assert_eq!(first, encoding, "Encoding should be deterministic");
}
}
#[test]
fn test_word_quality() {
init_test_env();
let test_ip = "192.168.1.1";
let encoded = encode_ip_address(test_ip).expect("Encoding failed");
let words: Vec<&str> = encoded.split(' ').collect();
for word in words {
assert!(word.len() >= 2, "Word too short: {}", word);
assert!(
word.chars().all(|c| c.is_ascii_lowercase()),
"Word contains invalid characters: {}",
word
);
}
}
#[test]
fn test_error_recovery() {
init_test_env();
let malformed_words = vec![
"one.two", "one.two.three.four", "zzzzz999.xxxxx888.qqqqq777", ".two.three", "one..three", ];
for words in malformed_words {
match decode_words(words) {
Ok(_) => panic!("Expected error for malformed words: {}", words),
Err(e) => {
let error_msg = format!("{}", e);
assert!(!error_msg.is_empty(), "Error message should not be empty");
assert!(error_msg.len() > 10, "Error message should be descriptive");
}
}
}
}
#[test]
fn test_cli_integration() {
init_test_env();
use std::process::Command;
let test_ip = "192.168.1.1";
let output = Command::new("cargo")
.args(&["run", "--bin", "3wn", "--", test_ip])
.output()
.expect("Failed to execute CLI");
assert!(output.status.success(), "CLI encoding failed");
let encoded = String::from_utf8(output.stdout)
.expect("Invalid UTF-8 output")
.trim()
.to_string();
let output = Command::new("cargo")
.args(&["run", "--bin", "3wn", "--", &encoded])
.output()
.expect("Failed to execute CLI");
assert!(output.status.success(), "CLI decoding failed");
let decoded = String::from_utf8(output.stdout)
.expect("Invalid UTF-8 output")
.trim()
.to_string();
let expected = if !test_ip.contains(':') {
format!("{}:80", test_ip)
} else {
test_ip.to_string()
};
assert_eq!(expected, decoded, "CLI roundtrip failed");
}
fn encode_ip_address(addr: &str) -> Result<String, Box<dyn std::error::Error>> {
let encoder = ThreeWordAdaptiveEncoder::new()?;
encoder.encode(addr).map_err(|e| e.into())
}
fn decode_words(words: &str) -> Result<String, Box<dyn std::error::Error>> {
let encoder = ThreeWordAdaptiveEncoder::new()?;
encoder.decode(words).map_err(|e| e.into())
}
fn encode_socket_address(addr: &str) -> Result<String, Box<dyn std::error::Error>> {
let encoder = ThreeWordAdaptiveEncoder::new()?;
encoder.encode(addr).map_err(|e| e.into())
}
fn decode_socket_address(words: &str) -> Result<String, Box<dyn std::error::Error>> {
let encoder = ThreeWordAdaptiveEncoder::new()?;
encoder.decode(words).map_err(|e| e.into())
}
fn validate_word_format(words: &str) -> Result<(), Box<dyn std::error::Error>> {
let parts: Vec<&str> = words.split(' ').collect();
if parts.len() != 3 {
return Err(Box::new(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
"Must have exactly 3 words",
)));
}
for part in parts {
if part.is_empty() {
return Err(Box::new(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
"Words cannot be empty",
)));
}
if !part.chars().all(|c| c.is_ascii_lowercase()) {
return Err(Box::new(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
"Words can only contain lowercase letters and hyphens",
)));
}
}
Ok(())
}