vflight 0.9.2

Share files over the Veilid distributed network with content-addressable storage
Documentation
use std::fs;
use std::path::PathBuf;
use tempfile::TempDir;

// Test module for chunker
#[cfg(test)]
mod chunker_tests {
    use super::*;

    #[test]
    fn test_chunk_file_small_file() {
        let temp_dir = TempDir::new().unwrap();
        let test_file = temp_dir.path().join("test.txt");
        let test_data = b"Hello, World!";
        fs::write(&test_file, test_data).unwrap();

        // This would require exposing the chunker module
        // For now, we're setting up the test structure
        assert!(test_file.exists());
    }

    #[test]
    fn test_chunk_file_empty_file() {
        let temp_dir = TempDir::new().unwrap();
        let test_file = temp_dir.path().join("empty.txt");
        fs::write(&test_file, b"").unwrap();

        assert!(test_file.exists());
        assert_eq!(fs::metadata(&test_file).unwrap().len(), 0);
    }

    #[test]
    fn test_chunk_file_large_file() {
        let temp_dir = TempDir::new().unwrap();
        let test_file = temp_dir.path().join("large.bin");
        let large_data = vec![0u8; 1_000_000]; // 1 MB
        fs::write(&test_file, &large_data).unwrap();

        assert!(test_file.exists());
        assert_eq!(fs::metadata(&test_file).unwrap().len(), 1_000_000);
    }

    #[test]
    fn test_chunk_file_nonexistent_file() {
        let nonexistent = PathBuf::from("/tmp/nonexistent_file_xyz.txt");
        assert!(!nonexistent.exists());
    }
}

// Test module for protocol
#[cfg(test)]
mod protocol_tests {

    #[test]
    fn test_chunk_size_constant() {
        // CHUNK_SIZE should be a reasonable value for network transmission
        const EXPECTED_CHUNK_SIZE: usize = 30_000;
        assert_eq!(EXPECTED_CHUNK_SIZE, 30_000);
    }

    #[test]
    fn test_file_metadata_structure() {
        // Test that FileMetadata has the required fields
        // This validates the protocol structure
        let metadata_fields = ["name", "size", "total_chunks", "chunk_hashes", "route_blob"];
        assert_eq!(metadata_fields.len(), 5);
    }
}

// Test module for node initialization
#[cfg(test)]
mod node_tests {

    #[test]
    fn test_namespace_creation() {
        let namespace = "test_instance_1";
        assert!(!namespace.is_empty());
        assert!(namespace.chars().all(|c| c.is_alphanumeric() || c == '_'));
    }

    #[test]
    fn test_multiple_namespaces() {
        let namespaces = vec!["seeder", "fetcher", "relay"];
        assert_eq!(namespaces.len(), 3);
        for ns in namespaces {
            assert!(!ns.is_empty());
        }
    }
}

// Test module for file operations
#[cfg(test)]
mod file_tests {
    use super::*;

    #[test]
    fn test_file_creation_and_deletion() {
        let temp_dir = TempDir::new().unwrap();
        let test_file = temp_dir.path().join("test.txt");
        let test_content = b"Test content";

        fs::write(&test_file, test_content).unwrap();
        assert!(test_file.exists());

        let read_content = fs::read(&test_file).unwrap();
        assert_eq!(read_content, test_content);
    }

    #[test]
    fn test_file_metadata_retrieval() {
        let temp_dir = TempDir::new().unwrap();
        let test_file = temp_dir.path().join("metadata_test.txt");
        let test_data = b"Test data for metadata";
        fs::write(&test_file, test_data).unwrap();

        let metadata = fs::metadata(&test_file).unwrap();
        assert_eq!(metadata.len(), test_data.len() as u64);
        assert!(metadata.is_file());
    }

    #[test]
    fn test_directory_operations() {
        let temp_dir = TempDir::new().unwrap();
        let output_dir = temp_dir.path().join("output");
        fs::create_dir(&output_dir).unwrap();

        assert!(output_dir.exists());
        assert!(output_dir.is_dir());
    }

    #[test]
    fn test_file_not_found_handling() {
        let nonexistent = PathBuf::from("/tmp/definitely_not_existing_12345.txt");
        let result = fs::read(&nonexistent);
        assert!(result.is_err());
    }
}

// Test module for hash verification
#[cfg(test)]
mod hash_tests {

    #[test]
    fn test_blake3_hash_consistency() {
        let data = b"consistent data";
        let hash1 = blake3::hash(data).to_hex().to_string();
        let hash2 = blake3::hash(data).to_hex().to_string();

        assert_eq!(hash1, hash2);
    }

    #[test]
    fn test_blake3_hash_differs_for_different_data() {
        let data1 = b"data one";
        let data2 = b"data two";
        let hash1 = blake3::hash(data1).to_hex().to_string();
        let hash2 = blake3::hash(data2).to_hex().to_string();

        assert_ne!(hash1, hash2);
    }

    #[test]
    fn test_hash_length() {
        let data = b"test";
        let hash = blake3::hash(data).to_hex().to_string();
        // blake3 produces 64-character hex string (256 bits / 4 bits per hex char)
        assert_eq!(hash.len(), 64);
    }
}

// Test module for CLI argument parsing
#[cfg(test)]
mod cli_tests {
    use super::*;

    #[test]
    fn test_path_validation() {
        let valid_path = PathBuf::from("./test.txt");
        assert!(valid_path.to_str().is_some());
    }

    #[test]
    fn test_dht_key_format() {
        let dht_key = "abcdef0123456789";
        assert!(!dht_key.is_empty());
        // DHT keys should be hex strings
        assert!(dht_key.chars().all(|c| c.is_ascii_hexdigit()));
    }

    #[test]
    fn test_output_directory_default() {
        let default_output = PathBuf::from(".");
        assert_eq!(default_output.to_str().unwrap(), ".");
    }
}

// Integration test setup (requires async runtime)
#[cfg(test)]
mod integration_setup_tests {
    use super::*;

    #[test]
    fn test_temp_directory_setup() {
        let temp_dir = TempDir::new().unwrap();
        let path = temp_dir.path();

        assert!(path.exists());
        assert!(path.is_dir());

        // Create test files
        let test_file1 = path.join("file1.txt");
        let test_file2 = path.join("file2.txt");

        fs::write(&test_file1, b"content1").unwrap();
        fs::write(&test_file2, b"content2").unwrap();

        let entries: Vec<_> = fs::read_dir(path).unwrap().filter_map(|e| e.ok()).collect();
        assert_eq!(entries.len(), 2);
    }

    #[test]
    fn test_byte_data_handling() {
        let original_data = vec![0u8, 1, 2, 3, 4, 5, 255, 254, 253];
        let temp_dir = TempDir::new().unwrap();
        let test_file = temp_dir.path().join("binary.dat");

        fs::write(&test_file, &original_data).unwrap();
        let read_data = fs::read(&test_file).unwrap();

        assert_eq!(original_data, read_data);
    }
}