#[cfg(test)]
mod tests {
use std::time::Duration;
#[test]
fn test_response_size_display_formats() {
let sizes = vec![
(512, "512B"),
(1024, "1.0KB"),
(1024 * 512, "512.0KB"),
(1024 * 1024, "1.0MB"),
(1024 * 1024 * 10, "10.0MB"),
];
for (bytes, expected_prefix) in sizes {
let display = if bytes < 1024 {
format!("{}B", bytes)
} else if bytes < 1024 * 1024 {
format!("{:.1}KB", bytes as f64 / 1024.0)
} else {
format!("{:.1}MB", bytes as f64 / (1024.0 * 1024.0))
};
assert!(display.starts_with(expected_prefix),
"Expected {} to start with {}", display, expected_prefix);
}
}
#[test]
fn test_elapsed_time_display() {
let test_cases = vec![
(100, "100ms", true), (500, "500ms", true), (1500, "1.5", true), ];
for (ms, expected_contains, _) in test_cases {
let duration = Duration::from_millis(ms);
let display = if duration.as_millis() < 1000 {
format!("{}ms", duration.as_millis())
} else {
format!("{:.2}s", duration.as_secs_f64())
};
assert!(display.contains(expected_contains),
"Expected {} to contain {}", display, expected_contains);
}
}
#[test]
fn test_url_cursor_bounds() {
let url = "https://example.com/api";
let mut cursor = 10;
if cursor < url.len() {
cursor = (cursor + 1).min(url.len());
}
assert!(cursor <= url.len(), "Cursor {} exceeds URL length {}", cursor, url.len());
}
#[test]
fn test_header_index_bounds() {
let headers: Vec<(String, String)> = vec![];
let index = 0;
let result = headers.get(index);
assert!(result.is_none(), "Empty header list should return None");
let headers = vec![
("Content-Type".to_string(), "application/json".to_string()),
];
assert!(headers.get(0).is_some(), "Valid index should return Some");
assert!(headers.get(999).is_none(), "Out-of-bounds index should return None");
}
#[test]
fn test_collection_access_safety() {
#[derive(Clone)]
struct MockCollection {
name: String,
requests: Vec<String>,
}
let collections = vec![
MockCollection {
name: "Auth".to_string(),
requests: vec!["Login".to_string(), "Logout".to_string()],
},
];
let coll_idx = 0;
let req_idx = 5;
let result = collections
.get(coll_idx)
.and_then(|c| c.requests.get(req_idx));
assert!(result.is_none(), "Out-of-bounds access should return None");
}
#[test]
fn test_response_cache_eviction_logic() {
let max_size = 3;
let mut cache: Vec<(String, u64)> = vec![];
for i in 0..5 {
cache.push((format!("key_{}", i), i as u64));
while cache.len() > max_size {
cache.remove(0);
}
}
assert_eq!(cache.len(), max_size, "Cache size should not exceed max");
assert_eq!(cache[0].0, "key_2", "Should keep most recent items");
assert_eq!(cache[2].0, "key_4", "Should keep most recent items");
}
#[test]
fn test_json_parsing_robustness() {
let invalid_jsons = vec![
"{broken: json}",
"{ incomplete",
"{\"key\": undefined}",
"",
"null",
];
for invalid in invalid_jsons {
let result: Result<serde_json::Value, _> = serde_json::from_str(invalid);
let is_valid_json = result.is_ok() || invalid == "null";
assert!(is_valid_json || result.is_err(),
"Invalid JSON should fail to parse: {}", invalid);
}
}
#[test]
fn test_visual_range_bounds() {
let text = "line1\nline2\nline3";
let lines: Vec<&str> = text.lines().collect();
let total_lines = lines.len();
let cursor_row = 2;
let cursor_col = 5;
assert!(cursor_row < total_lines, "Cursor row must be within bounds");
if let Some(line) = lines.get(cursor_row) {
assert!(cursor_col <= line.len(), "Cursor col must not exceed line length");
}
}
#[test]
fn test_terminal_resize_safety() {
let mut cached_size: Option<(u16, u16)> = None;
let sizes = vec![
(80, 24),
(120, 40),
(40, 20),
(0, 0), (u16::MAX, u16::MAX), ];
for (w, h) in sizes {
cached_size = Some((w, h));
assert!(cached_size.is_some());
}
}
#[test]
fn test_string_line_splitting() {
let test_cases = vec![
("", vec![""]),
("single", vec!["single"]),
("line1\nline2", vec!["line1", "line2"]),
("\n", vec!["", ""]),
("a\n\nb", vec!["a", "", "b"]),
];
for (input, expected) in test_cases {
let lines: Vec<&str> = input.lines().collect();
if input.is_empty() {
assert!(lines.is_empty() || input.is_empty());
} else {
assert!(!lines.is_empty(), "Non-empty input should have lines");
}
}
}
#[test]
fn test_search_match_safety() {
let response_body = "x".repeat(100_000); let query = "target";
let matches: Vec<usize> = response_body
.match_indices(query)
.map(|(pos, _)| pos)
.collect();
assert!(matches.is_empty(), "Query not found returns empty matches");
let response_with_match = "before target after";
let matches: Vec<usize> = response_with_match
.match_indices("target")
.map(|(pos, _)| pos)
.collect();
assert_eq!(matches.len(), 1, "Should find exact match");
}
#[test]
fn test_unicode_width_awareness() {
use unicode_width::UnicodeWidthChar;
let test_chars = vec![
('a', Some(1)), ('é', Some(1)), ('日', Some(2)), ('🚀', Some(2)), ('\0', None), ];
for (ch, expected_width) in test_chars {
let width = UnicodeWidthChar::width(ch);
assert_eq!(width, expected_width,
"Character {:?} should have width {:?}", ch, expected_width);
}
}
#[test]
fn test_circular_chain_detection_logic() {
struct ChainRef {
request_name: String,
depends_on: Vec<String>,
}
let refs = vec![
ChainRef {
request_name: "A".to_string(),
depends_on: vec!["B".to_string()],
},
ChainRef {
request_name: "B".to_string(),
depends_on: vec!["C".to_string()],
},
ChainRef {
request_name: "C".to_string(),
depends_on: vec!["A".to_string()], },
];
fn has_cycle(name: &str, refs: &[ChainRef], visited: &mut Vec<String>) -> bool {
if visited.contains(&name.to_string()) {
return true; }
visited.push(name.to_string());
if let Some(r) = refs.iter().find(|r| r.request_name == name) {
for dep in &r.depends_on {
if has_cycle(dep, refs, visited) {
return true;
}
}
}
visited.pop();
false
}
assert!(has_cycle("A", &refs, &mut vec![]), "Should detect cycle in A→B→C→A");
}
#[test]
fn test_undefined_variable_detection() {
fn find_undefined_vars(text: &str, defined: &[&str]) -> Vec<String> {
let mut undefined = Vec::new();
let mut chars = text.chars().peekable();
while let Some(c) = chars.next() {
if c == '{' && chars.peek() == Some(&'{') {
chars.next(); let mut var_name = String::new();
while let Some(c) = chars.next() {
if c == '}' && chars.peek() == Some(&'}') {
chars.next(); break;
}
var_name.push(c);
}
if !var_name.is_empty() && !defined.contains(&var_name.as_str()) {
undefined.push(var_name);
}
}
}
undefined
}
let text = "Hello {{name}}, your age is {{age}}";
let defined = vec!["name"];
let undefined = find_undefined_vars(text, &defined);
assert!(undefined.contains(&"age".to_string()), "Should find undefined age");
assert!(!undefined.contains(&"name".to_string()), "Should not flag defined name");
}
#[test]
fn test_response_type_inference() {
let test_bodies = vec![
("{\"key\": \"value\"}", true), ("[1, 2, 3]", true), ("not json", false), ("", false), ("{broken", false), ];
for (body, should_be_json) in test_bodies {
let is_json = serde_json::from_str::<serde_json::Value>(body).is_ok();
assert_eq!(is_json, should_be_json,
"Body '{}' JSON inference incorrect", body);
}
}
}