ricecoder-tools 0.1.71

Enhanced tools for RiceCoder: webfetch, patch, todo, and web search
Documentation
//! Property-based tests for webfetch tool
//!
//! Tests the correctness properties of the webfetch tool using property-based testing.

use proptest::prelude::*;
use ricecoder_tools::webfetch::{WebfetchInput, WebfetchOutput, WebfetchTool};

// Property 1: Webfetch content retrieval
// For any valid URL, webfetch returns content or specific error
// Feature: ricecoder-tools-enhanced, Property 1: Webfetch content retrieval
// Validates: Requirements 1.1, 1.2, 1.5, 1.6
proptest! {
    #[test]
    fn prop_webfetch_content_retrieval(url in prop_oneof![
        Just("https://example.com"),
        Just("http://example.com"),
        Just("https://example.com/path"),
        Just("https://example.com:8080/path?query=value"),
    ]) {
        let result = WebfetchTool::validate_url(url);
        // Valid URLs should parse successfully
        prop_assert!(result.is_ok());
    }
}

// Property 2: Webfetch timeout enforcement
// Operations exceeding 10 seconds timeout
// Feature: ricecoder-tools-enhanced, Property 2: Webfetch timeout enforcement
// Validates: Requirements 1.6
proptest! {
    #[test]
    fn prop_webfetch_timeout_enforcement(url in prop_oneof![
        Just("https://example.com"),
        Just("https://httpbin.org/delay/15"),
    ]) {
        let input = WebfetchInput::new(url);
        // Timeout should be set to 10 seconds
        // This is verified by the HTTP client configuration
        prop_assert!(!input.url.is_empty());
    }
}

// Property 3: Webfetch content truncation
// Content >50KB is truncated with indicator
// Feature: ricecoder-tools-enhanced, Property 3: Webfetch content truncation
// Validates: Requirements 1.5
proptest! {
    #[test]
    fn prop_webfetch_content_truncation(
        size in 0usize..100000usize
    ) {
        let content = String::from("x").repeat(size);
        let output = WebfetchOutput::new(content, size);
        
        // The truncation flag should accurately reflect whether content was truncated
        // (i.e., returned_size < original_size)
        if output.original_size > output.returned_size {
            prop_assert!(output.truncated, "Should be marked as truncated when returned_size < original_size");
        } else {
            prop_assert!(!output.truncated, "Should not be marked as truncated when returned_size == original_size");
        }
        
        // Returned size should never exceed original size
        prop_assert!(output.returned_size <= output.original_size);
    }
}

// Test that WebfetchInput can be created with various URLs
proptest! {
    #[test]
    fn test_webfetch_input_creation_property(url in prop_oneof![
        Just("https://example.com"),
        Just("http://example.com"),
        Just("https://example.com/path"),
    ]) {
        let input = WebfetchInput::new(url);
        prop_assert!(!input.url.is_empty());
        prop_assert!(input.max_size.is_none());
    }
}

// Test that WebfetchOutput correctly tracks truncation
proptest! {
    #[test]
    fn test_webfetch_output_truncation_property(size in 0usize..100000usize) {
        let content = String::from("x").repeat(size.min(100000));
        let output = WebfetchOutput::new(content, size);
        
        // Truncation flag should match actual truncation
        if output.original_size > output.returned_size {
            prop_assert!(output.truncated);
        } else {
            prop_assert!(!output.truncated);
        }
    }
}

// Test that URL validation rejects invalid schemes
proptest! {
    #[test]
    fn test_url_validation_scheme_property(url in prop_oneof![
        Just("https://example.com"),
        Just("http://example.com"),
        Just("ftp://example.com"),
        Just("file:///path/to/file"),
    ]) {
        let result = WebfetchTool::validate_url(url);
        
        // Only http and https should be valid
        if url.starts_with("http://") || url.starts_with("https://") {
            prop_assert!(result.is_ok());
        } else {
            prop_assert!(result.is_err());
        }
    }
}

// Test that URL validation rejects localhost
proptest! {
    #[test]
    fn test_url_validation_localhost_property(url in prop_oneof![
        Just("http://localhost"),
        Just("http://localhost:8080"),
        Just("http://127.0.0.1"),
        Just("http://127.0.0.1:8080"),
        Just("http://example.com"),
    ]) {
        let result = WebfetchTool::validate_url(url);
        
        // Localhost and 127.0.0.1 should be rejected
        if url.contains("localhost") || url.contains("127.0.0.1") {
            prop_assert!(result.is_err());
        } else {
            prop_assert!(result.is_ok());
        }
    }
}

// Test that WebfetchInput max_size is properly set
proptest! {
    #[test]
    fn test_webfetch_input_max_size_property(size in 0usize..1000000usize) {
        let input = WebfetchInput::new("https://example.com").with_max_size(size);
        prop_assert!(input.max_size.is_some());
    }
}