pub const DATABASE_FILENAME: &str = "main.sqlite";
pub const DATABASE_DIR: &str = "Things Database.thingsdatabase";
pub const THINGS_CONTAINER: &str = "JLMPQHK8H4.com.culturedcode.Things3";
pub const DEFAULT_QUERY_LIMIT: usize = 100;
pub const MAX_QUERY_LIMIT: usize = 1000;
pub const DEFAULT_MCP_PORT: u16 = 3000;
pub const DATE_FORMATS: &[&str] = &["%Y-%m-%d", "%m/%d/%Y", "%d/%m/%Y"];
pub const DATETIME_FORMATS: &[&str] = &[
"%Y-%m-%d %H:%M:%S",
"%Y-%m-%dT%H:%M:%S",
"%Y-%m-%d %H:%M:%S UTC",
];
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_database_filename() {
assert_eq!(DATABASE_FILENAME, "main.sqlite");
}
#[test]
fn test_database_dir() {
assert_eq!(DATABASE_DIR, "Things Database.thingsdatabase");
}
#[test]
fn test_things_container() {
assert_eq!(THINGS_CONTAINER, "JLMPQHK8H4.com.culturedcode.Things3");
}
#[test]
fn test_default_query_limit() {
assert_eq!(DEFAULT_QUERY_LIMIT, 100);
}
#[test]
fn test_max_query_limit() {
assert_eq!(MAX_QUERY_LIMIT, 1000);
}
#[test]
fn test_default_mcp_port() {
assert_eq!(DEFAULT_MCP_PORT, 3000);
}
#[test]
fn test_date_formats() {
assert_eq!(DATE_FORMATS.len(), 3);
assert!(DATE_FORMATS.contains(&"%Y-%m-%d"));
assert!(DATE_FORMATS.contains(&"%m/%d/%Y"));
assert!(DATE_FORMATS.contains(&"%d/%m/%Y"));
}
#[test]
fn test_datetime_formats() {
assert_eq!(DATETIME_FORMATS.len(), 3);
assert!(DATETIME_FORMATS.contains(&"%Y-%m-%d %H:%M:%S"));
assert!(DATETIME_FORMATS.contains(&"%Y-%m-%dT%H:%M:%S"));
assert!(DATETIME_FORMATS.contains(&"%Y-%m-%d %H:%M:%S UTC"));
}
#[test]
fn test_constants_are_public() {
let _ = DATABASE_FILENAME;
let _ = DATABASE_DIR;
let _ = THINGS_CONTAINER;
let _ = DEFAULT_QUERY_LIMIT;
let _ = MAX_QUERY_LIMIT;
let _ = DEFAULT_MCP_PORT;
let _ = DATE_FORMATS;
let _ = DATETIME_FORMATS;
}
#[test]
fn test_constants_types_and_values() {
assert!(DATABASE_FILENAME.ends_with(".sqlite"));
assert!(DATABASE_DIR.contains("Things"));
assert!(THINGS_CONTAINER.contains(".com."));
for format in DATE_FORMATS {
assert!(format.contains('%'));
assert!(format.contains('Y')); }
for format in DATETIME_FORMATS {
assert!(format.contains('%'));
assert!(format.contains('Y')); assert!(format.contains('H') || format.contains('M') || format.contains('S'));
}
}
#[test]
fn test_constants_immutability_and_static_nature() {
let db_filename_ref: &'static str = DATABASE_FILENAME;
let db_dir_ref: &'static str = DATABASE_DIR;
let container_ref: &'static str = THINGS_CONTAINER;
assert_eq!(db_filename_ref, "main.sqlite");
assert_eq!(db_dir_ref, "Things Database.thingsdatabase");
assert_eq!(container_ref, "JLMPQHK8H4.com.culturedcode.Things3");
let default_limit: usize = DEFAULT_QUERY_LIMIT;
let max_limit: usize = MAX_QUERY_LIMIT;
let port: u16 = DEFAULT_MCP_PORT;
assert_eq!(default_limit, 100);
assert_eq!(max_limit, 1000);
assert_eq!(port, 3000);
let date_formats_ref: &'static [&'static str] = DATE_FORMATS;
let datetime_formats_ref: &'static [&'static str] = DATETIME_FORMATS;
assert_eq!(date_formats_ref.len(), 3);
assert_eq!(datetime_formats_ref.len(), 3);
}
#[test]
fn test_constants_usage_scenarios() {
let db_path = format!("/{DATABASE_DIR}/{DATABASE_FILENAME}");
assert!(db_path.contains("Things Database.thingsdatabase"));
assert!(db_path.contains("main.sqlite"));
let container_path = format!("/Library/Group Containers/{THINGS_CONTAINER}");
assert!(container_path.contains("JLMPQHK8H4.com.culturedcode.Things3"));
let clamped_limit = std::cmp::min(500, MAX_QUERY_LIMIT);
assert_eq!(clamped_limit, 500);
let server_url = format!("http://localhost:{DEFAULT_MCP_PORT}");
assert_eq!(server_url, "http://localhost:3000");
assert!(DATE_FORMATS.contains(&"%Y-%m-%d"));
assert!(DATETIME_FORMATS.iter().any(|&f| f.contains("UTC")));
}
#[test]
fn test_constants_comprehensive_coverage() {
for (i, format) in DATE_FORMATS.iter().enumerate() {
assert!(format.contains('%'), "Date format {i} should contain %");
assert!(format.contains('Y'), "Date format {i} should contain Y");
assert!(!format.is_empty(), "Date format {i} should not be empty");
}
for (i, format) in DATETIME_FORMATS.iter().enumerate() {
assert!(format.contains('%'), "DateTime format {i} should contain %");
assert!(format.contains('Y'), "DateTime format {i} should contain Y");
assert!(
!format.is_empty(),
"DateTime format {i} should not be empty"
);
}
let db_filename_upper = DATABASE_FILENAME.to_uppercase();
assert!(db_filename_upper.contains("SQLITE"));
let db_dir_lower = DATABASE_DIR.to_lowercase();
assert!(db_dir_lower.contains("things"));
let container_parts: Vec<&str> = THINGS_CONTAINER.split('.').collect();
assert!(container_parts.len() >= 3);
let total_limit = DEFAULT_QUERY_LIMIT + MAX_QUERY_LIMIT;
assert!(total_limit > DEFAULT_QUERY_LIMIT);
assert!(total_limit > MAX_QUERY_LIMIT);
let port_range = u32::from(DEFAULT_MCP_PORT) + 1000;
assert!(port_range > u32::from(DEFAULT_MCP_PORT));
let date_format_count = DATE_FORMATS.len();
let datetime_format_count = DATETIME_FORMATS.len();
assert!(date_format_count > 0);
assert!(datetime_format_count > 0);
let first_date_format = DATE_FORMATS.first().unwrap();
let last_date_format = DATE_FORMATS.last().unwrap();
assert!(!first_date_format.is_empty());
assert!(!last_date_format.is_empty());
let first_datetime_format = DATETIME_FORMATS.first().unwrap();
let last_datetime_format = DATETIME_FORMATS.last().unwrap();
assert!(!first_datetime_format.is_empty());
assert!(!last_datetime_format.is_empty());
}
#[test]
fn test_constants_edge_cases_and_boundaries() {
assert!(!DATABASE_FILENAME.trim().is_empty());
assert!(!DATABASE_DIR.trim().is_empty());
assert!(!THINGS_CONTAINER.trim().is_empty());
let default_limit = DEFAULT_QUERY_LIMIT;
let max_limit = MAX_QUERY_LIMIT;
assert!(default_limit > 0);
assert!(default_limit <= max_limit);
assert!(max_limit > default_limit);
let port_value = DEFAULT_MCP_PORT;
assert!(port_value > 1024); assert!(port_value < 65535);
for format in DATE_FORMATS {
let percent_count = format.chars().filter(|&c| c == '%').count();
assert!(
percent_count > 0,
"Format should have at least one % specifier: {format}"
);
}
for format in DATETIME_FORMATS {
let percent_count = format.chars().filter(|&c| c == '%').count();
assert!(
percent_count > 0,
"Format should have at least one % specifier: {format}"
);
}
assert!(DATABASE_FILENAME.ends_with(".sqlite"));
assert!(DATABASE_DIR.contains("Database"));
assert!(THINGS_CONTAINER.contains("com.culturedcode"));
let _as_bytes = DATABASE_FILENAME.as_bytes();
let _as_chars: Vec<char> = DATABASE_DIR.chars().collect();
let _as_string = THINGS_CONTAINER.to_string();
let mut date_format_iter = DATE_FORMATS.iter();
assert!(date_format_iter.next().is_some());
let mut datetime_format_iter = DATETIME_FORMATS.iter();
assert!(datetime_format_iter.next().is_some());
}
#[test]
fn test_constants_comprehensive_string_operations() {
assert_eq!(DATABASE_FILENAME.len(), 11); assert!(DATABASE_FILENAME.starts_with("main"));
assert!(DATABASE_FILENAME.ends_with(".sqlite"));
assert!(DATABASE_FILENAME.contains('.'));
assert!(DATABASE_FILENAME.is_ascii());
let filename_bytes = DATABASE_FILENAME.as_bytes();
assert_eq!(filename_bytes[0], b'm');
assert_eq!(filename_bytes[filename_bytes.len() - 1], b'e');
assert!(DATABASE_DIR.len() > 10);
assert!(DATABASE_DIR.starts_with("Things"));
assert!(DATABASE_DIR.ends_with(".thingsdatabase"));
assert!(DATABASE_DIR.contains("Database"));
assert!(DATABASE_DIR.contains(' '));
assert!(DATABASE_DIR.is_ascii());
assert!(THINGS_CONTAINER.len() > 20);
assert!(THINGS_CONTAINER.starts_with("JLMPQHK8H4"));
assert!(THINGS_CONTAINER.ends_with("Things3"));
assert!(THINGS_CONTAINER.contains(".com."));
assert!(THINGS_CONTAINER.contains("culturedcode"));
assert!(THINGS_CONTAINER.is_ascii());
let upper_filename = DATABASE_FILENAME.to_uppercase();
assert_eq!(upper_filename, "MAIN.SQLITE");
let lower_dir = DATABASE_DIR.to_lowercase();
assert!(lower_dir.contains("things"));
assert!(lower_dir.contains("database"));
let container_parts: Vec<&str> = THINGS_CONTAINER.split('.').collect();
assert!(container_parts.len() >= 4);
assert_eq!(container_parts[0], "JLMPQHK8H4");
assert_eq!(container_parts[1], "com");
assert_eq!(container_parts[2], "culturedcode");
assert_eq!(container_parts[3], "Things3");
let modified_filename = DATABASE_FILENAME.replace("main", "test");
assert_eq!(modified_filename, "test.sqlite");
let modified_dir = DATABASE_DIR.replace("Things", "Test");
assert!(modified_dir.contains("Test Database"));
}
#[test]
fn test_constants_array_comprehensive_operations() {
assert_eq!(DATE_FORMATS.len(), 3);
assert_eq!(DATE_FORMATS[0], "%Y-%m-%d");
assert_eq!(DATE_FORMATS[1], "%m/%d/%Y");
assert_eq!(DATE_FORMATS[2], "%d/%m/%Y");
assert!(DATE_FORMATS.contains(&"%Y-%m-%d"));
assert!(DATE_FORMATS.contains(&"%m/%d/%Y"));
assert!(DATE_FORMATS.contains(&"%d/%m/%Y"));
assert!(!DATE_FORMATS.contains(&"%Y/%m/%d"));
assert_eq!(DATE_FORMATS.first(), Some(&"%Y-%m-%d"));
assert_eq!(DATE_FORMATS.last(), Some(&"%d/%m/%Y"));
let mut count = 0;
for format in DATE_FORMATS {
assert!(format.contains('%'));
assert!(format.contains('Y'));
count += 1;
}
assert_eq!(count, 3);
assert_eq!(DATETIME_FORMATS.len(), 3);
assert_eq!(DATETIME_FORMATS[0], "%Y-%m-%d %H:%M:%S");
assert_eq!(DATETIME_FORMATS[1], "%Y-%m-%dT%H:%M:%S");
assert_eq!(DATETIME_FORMATS[2], "%Y-%m-%d %H:%M:%S UTC");
assert!(DATETIME_FORMATS.contains(&"%Y-%m-%d %H:%M:%S"));
assert!(DATETIME_FORMATS.contains(&"%Y-%m-%dT%H:%M:%S"));
assert!(DATETIME_FORMATS.contains(&"%Y-%m-%d %H:%M:%S UTC"));
assert!(!DATETIME_FORMATS.contains(&"%Y/%m/%d %H:%M:%S"));
assert_eq!(DATETIME_FORMATS.first(), Some(&"%Y-%m-%d %H:%M:%S"));
assert_eq!(DATETIME_FORMATS.last(), Some(&"%Y-%m-%d %H:%M:%S UTC"));
let mut datetime_count = 0;
for format in DATETIME_FORMATS {
assert!(format.contains('%'));
assert!(format.contains('Y'));
assert!(format.contains('H') || format.contains('M') || format.contains('S'));
datetime_count += 1;
}
assert_eq!(datetime_count, 3);
let date_slice = &DATE_FORMATS[0..2];
assert_eq!(date_slice.len(), 2);
assert_eq!(date_slice[0], "%Y-%m-%d");
assert_eq!(date_slice[1], "%m/%d/%Y");
let datetime_slice = &DATETIME_FORMATS[1..];
assert_eq!(datetime_slice.len(), 2);
assert_eq!(datetime_slice[0], "%Y-%m-%dT%H:%M:%S");
assert_eq!(datetime_slice[1], "%Y-%m-%d %H:%M:%S UTC");
}
#[test]
fn test_constants_numeric_comprehensive_operations() {
assert_eq!(DEFAULT_QUERY_LIMIT, 100);
let doubled_default = DEFAULT_QUERY_LIMIT * 2;
assert_eq!(doubled_default, 200);
let halved_default = DEFAULT_QUERY_LIMIT / 2;
assert_eq!(halved_default, 50);
let sum_limits = DEFAULT_QUERY_LIMIT + MAX_QUERY_LIMIT;
assert_eq!(sum_limits, 1100);
assert_eq!(MAX_QUERY_LIMIT, 1000);
let default_limit = DEFAULT_QUERY_LIMIT;
let max_limit = MAX_QUERY_LIMIT;
assert!(default_limit < max_limit);
assert!(max_limit > default_limit);
assert!(default_limit != max_limit);
assert_eq!(max_limit / default_limit, 10);
assert_eq!(DEFAULT_MCP_PORT, 3000);
let port_plus_one = DEFAULT_MCP_PORT + 1;
assert_eq!(port_plus_one, 3001);
let port_range = DEFAULT_MCP_PORT..DEFAULT_MCP_PORT + 10;
assert!(port_range.contains(&3005));
assert!(!port_range.contains(&3010));
let port_as_u32 = u32::from(DEFAULT_MCP_PORT);
assert_eq!(port_as_u32, 3000);
let port_as_i32_value = i32::from(DEFAULT_MCP_PORT);
assert_eq!(port_as_i32_value, 3000);
let default_limit: usize = DEFAULT_QUERY_LIMIT;
let max_limit: usize = MAX_QUERY_LIMIT;
let port_value: u16 = DEFAULT_MCP_PORT;
assert_eq!(default_limit, 100);
assert_eq!(max_limit, 1000);
assert_eq!(port_value, 3000);
}
}