pub const DEFAULT_READ_BUFFER: usize = 8192;
pub const DEFAULT_WRITE_BUFFER: usize = 8192;
pub const DEFAULT_PARSE_BUFFER: usize = 65536;
pub const DEFAULT_INDEX_BUFFER: usize = 1_048_576;
const MIN_READ_BUFFER: usize = 1024; const MAX_READ_BUFFER: usize = 1_048_576; const MIN_WRITE_BUFFER: usize = 1024; const MAX_WRITE_BUFFER: usize = 1_048_576; const MIN_PARSE_BUFFER: usize = 4096; const MAX_PARSE_BUFFER: usize = 10_485_760; const MIN_INDEX_BUFFER: usize = 65536; const MAX_INDEX_BUFFER: usize = 104_857_600;
#[must_use]
pub fn read_buffer_size() -> usize {
let size = std::env::var("SQRY_READ_BUFFER")
.ok()
.and_then(|s| s.parse().ok())
.unwrap_or(DEFAULT_READ_BUFFER);
size.clamp(MIN_READ_BUFFER, MAX_READ_BUFFER)
}
#[must_use]
pub fn write_buffer_size() -> usize {
let size = std::env::var("SQRY_WRITE_BUFFER")
.ok()
.and_then(|s| s.parse().ok())
.unwrap_or(DEFAULT_WRITE_BUFFER);
size.clamp(MIN_WRITE_BUFFER, MAX_WRITE_BUFFER)
}
#[must_use]
pub fn parse_buffer_size() -> usize {
let size = std::env::var("SQRY_PARSE_BUFFER")
.ok()
.and_then(|s| s.parse().ok())
.unwrap_or(DEFAULT_PARSE_BUFFER);
size.clamp(MIN_PARSE_BUFFER, MAX_PARSE_BUFFER)
}
#[must_use]
pub fn index_buffer_size() -> usize {
let size = std::env::var("SQRY_INDEX_BUFFER")
.ok()
.and_then(|s| s.parse().ok())
.unwrap_or(DEFAULT_INDEX_BUFFER);
size.clamp(MIN_INDEX_BUFFER, MAX_INDEX_BUFFER)
}
pub const DEFAULT_MMAP_THRESHOLD: u64 = 10 * 1024 * 1024;
const MIN_MMAP_THRESHOLD: u64 = 1024 * 1024; const MAX_MMAP_THRESHOLD: u64 = 1024 * 1024 * 1024;
pub const DEFAULT_MAX_SOURCE_FILE_SIZE: u64 = 50 * 1024 * 1024;
const MIN_MAX_SOURCE_FILE_SIZE: u64 = 1024 * 1024; const MAX_MAX_SOURCE_FILE_SIZE: u64 = 500 * 1024 * 1024;
pub const DEFAULT_MAX_REPOSITORIES: usize = 1_000;
const MIN_MAX_REPOSITORIES: usize = 10; const MAX_MAX_REPOSITORIES: usize = 10_000;
#[must_use]
pub fn mmap_threshold() -> u64 {
let size = std::env::var("SQRY_MMAP_THRESHOLD")
.ok()
.and_then(|s| s.parse().ok())
.unwrap_or(DEFAULT_MMAP_THRESHOLD);
size.clamp(MIN_MMAP_THRESHOLD, MAX_MMAP_THRESHOLD)
}
#[must_use]
pub fn max_source_file_size() -> u64 {
let size = std::env::var("SQRY_MAX_SOURCE_FILE_SIZE")
.ok()
.and_then(|s| s.parse().ok())
.unwrap_or(DEFAULT_MAX_SOURCE_FILE_SIZE);
size.clamp(MIN_MAX_SOURCE_FILE_SIZE, MAX_MAX_SOURCE_FILE_SIZE)
}
#[must_use]
pub fn max_repositories() -> usize {
let count = std::env::var("SQRY_MAX_REPOSITORIES")
.ok()
.and_then(|s| s.parse().ok())
.unwrap_or(DEFAULT_MAX_REPOSITORIES);
count.clamp(MIN_MAX_REPOSITORIES, MAX_MAX_REPOSITORIES)
}
pub const DEFAULT_WATCH_EVENT_QUEUE: usize = 10_000;
const MIN_WATCH_EVENT_QUEUE: usize = 100; const MAX_WATCH_EVENT_QUEUE: usize = 100_000;
#[must_use]
pub fn watch_event_queue_capacity() -> usize {
let capacity = std::env::var("SQRY_WATCH_EVENT_QUEUE")
.ok()
.and_then(|s| s.parse().ok())
.unwrap_or(DEFAULT_WATCH_EVENT_QUEUE);
capacity.clamp(MIN_WATCH_EVENT_QUEUE, MAX_WATCH_EVENT_QUEUE)
}
pub const DEFAULT_MAX_QUERY_LENGTH: usize = 10 * 1024;
const MIN_MAX_QUERY_LENGTH: usize = 1024; const MAX_MAX_QUERY_LENGTH: usize = 100 * 1024;
#[must_use]
pub fn max_query_length() -> usize {
let length = std::env::var("SQRY_MAX_QUERY_LENGTH")
.ok()
.and_then(|s| s.parse().ok())
.unwrap_or(DEFAULT_MAX_QUERY_LENGTH);
length.clamp(MIN_MAX_QUERY_LENGTH, MAX_MAX_QUERY_LENGTH)
}
pub const DEFAULT_MAX_PREDICATES: usize = 100;
const MIN_MAX_PREDICATES: usize = 10; const MAX_MAX_PREDICATES: usize = 1000;
#[must_use]
pub fn max_predicates() -> usize {
let count = std::env::var("SQRY_MAX_PREDICATES")
.ok()
.and_then(|s| s.parse().ok())
.unwrap_or(DEFAULT_MAX_PREDICATES);
count.clamp(MIN_MAX_PREDICATES, MAX_MAX_PREDICATES)
}
pub const DEFAULT_JSON_MAX_DEPTH: u32 = 64;
const MIN_JSON_MAX_DEPTH: u32 = 8; const MAX_JSON_MAX_DEPTH: u32 = 256;
pub const DEFAULT_JSON_MAX_NODES: u32 = 500_000;
const MIN_JSON_MAX_NODES: u32 = 1_000; const MAX_JSON_MAX_NODES: u32 = 5_000_000;
#[must_use]
pub fn json_max_depth() -> u32 {
let depth = std::env::var("SQRY_JSON_MAX_DEPTH")
.ok()
.and_then(|s| s.parse().ok())
.unwrap_or(DEFAULT_JSON_MAX_DEPTH);
depth.clamp(MIN_JSON_MAX_DEPTH, MAX_JSON_MAX_DEPTH)
}
#[must_use]
pub fn json_max_nodes() -> u32 {
let count = std::env::var("SQRY_JSON_MAX_NODES")
.ok()
.and_then(|s| s.parse().ok())
.unwrap_or(DEFAULT_JSON_MAX_NODES);
count.clamp(MIN_JSON_MAX_NODES, MAX_JSON_MAX_NODES)
}
#[cfg(test)]
mod tests {
use super::*;
use serial_test::serial;
#[test]
#[serial]
fn test_default_read_buffer_size() {
unsafe {
std::env::remove_var("SQRY_READ_BUFFER");
}
assert_eq!(read_buffer_size(), DEFAULT_READ_BUFFER);
}
#[test]
#[serial]
fn test_env_override_read_buffer() {
unsafe {
std::env::set_var("SQRY_READ_BUFFER", "16384");
}
assert_eq!(read_buffer_size(), 16384);
unsafe {
std::env::remove_var("SQRY_READ_BUFFER");
}
}
#[test]
#[serial]
fn test_invalid_env_uses_default() {
unsafe {
std::env::set_var("SQRY_READ_BUFFER", "invalid");
}
assert_eq!(read_buffer_size(), DEFAULT_READ_BUFFER);
unsafe {
std::env::remove_var("SQRY_READ_BUFFER");
}
}
const _: () = assert!(DEFAULT_READ_BUFFER >= 4096, "Read buffer too small");
const _: () = assert!(DEFAULT_READ_BUFFER <= 65536, "Read buffer too large");
const _: () = assert!(DEFAULT_INDEX_BUFFER >= 65536, "Index buffer too small");
#[test]
#[serial]
fn test_write_buffer_size() {
unsafe {
std::env::remove_var("SQRY_WRITE_BUFFER");
}
assert_eq!(write_buffer_size(), DEFAULT_WRITE_BUFFER);
}
#[test]
#[serial]
fn test_parse_buffer_size() {
unsafe {
std::env::remove_var("SQRY_PARSE_BUFFER");
}
assert_eq!(parse_buffer_size(), DEFAULT_PARSE_BUFFER);
}
#[test]
#[serial]
fn test_index_buffer_size() {
unsafe {
std::env::remove_var("SQRY_INDEX_BUFFER");
}
assert_eq!(index_buffer_size(), DEFAULT_INDEX_BUFFER);
}
#[test]
#[serial]
fn test_env_override_write_buffer() {
unsafe {
std::env::set_var("SQRY_WRITE_BUFFER", "32768");
}
assert_eq!(write_buffer_size(), 32768);
unsafe {
std::env::remove_var("SQRY_WRITE_BUFFER");
}
}
#[test]
#[serial]
fn test_env_override_parse_buffer() {
unsafe {
std::env::set_var("SQRY_PARSE_BUFFER", "131072");
}
assert_eq!(parse_buffer_size(), 131_072);
unsafe {
std::env::remove_var("SQRY_PARSE_BUFFER");
}
}
#[test]
#[serial]
fn test_env_override_index_buffer() {
unsafe {
std::env::set_var("SQRY_INDEX_BUFFER", "2097152");
}
assert_eq!(index_buffer_size(), 2_097_152);
unsafe {
std::env::remove_var("SQRY_INDEX_BUFFER");
}
}
#[test]
#[serial]
fn test_parse_buffer_used_in_hash_file() {
use std::io::Write;
use tempfile::NamedTempFile;
let mut temp_file = NamedTempFile::new().unwrap();
let test_data = vec![b'X'; 200_000]; temp_file.write_all(&test_data).unwrap();
temp_file.flush().unwrap();
unsafe {
std::env::set_var("SQRY_PARSE_BUFFER", "32768"); }
assert_eq!(parse_buffer_size(), 32768);
let hash1 = crate::hash::hash_file(temp_file.path()).unwrap();
unsafe {
std::env::set_var("SQRY_PARSE_BUFFER", "16384"); }
assert_eq!(parse_buffer_size(), 16384);
let hash2 = crate::hash::hash_file(temp_file.path()).unwrap();
assert_eq!(hash1, hash2, "Hash should be independent of buffer size");
unsafe {
std::env::remove_var("SQRY_PARSE_BUFFER");
}
}
#[test]
#[serial]
fn test_buffer_clamping() {
unsafe {
std::env::set_var("SQRY_READ_BUFFER", "500"); }
assert_eq!(read_buffer_size(), 1024);
unsafe {
std::env::set_var("SQRY_READ_BUFFER", "5000000"); }
assert_eq!(read_buffer_size(), 1_048_576);
unsafe {
std::env::set_var("SQRY_PARSE_BUFFER", "1000"); }
assert_eq!(parse_buffer_size(), 4096);
unsafe {
std::env::set_var("SQRY_PARSE_BUFFER", "50000000"); }
assert_eq!(parse_buffer_size(), 10_485_760);
unsafe {
std::env::remove_var("SQRY_READ_BUFFER");
std::env::remove_var("SQRY_PARSE_BUFFER");
}
}
#[test]
#[serial]
fn test_parse_buffer_used_in_incremental() {
use std::io::Write;
use tempfile::NamedTempFile;
let mut temp_file = NamedTempFile::new().unwrap();
let test_data = vec![b'Y'; 150_000]; temp_file.write_all(&test_data).unwrap();
temp_file.flush().unwrap();
unsafe {
std::env::set_var("SQRY_PARSE_BUFFER", "65536"); }
assert_eq!(parse_buffer_size(), 65536);
let hash1 = crate::indexing::FileHash::compute(temp_file.path()).unwrap();
unsafe {
std::env::set_var("SQRY_PARSE_BUFFER", "8192"); }
assert_eq!(parse_buffer_size(), 8192);
let hash2 = crate::indexing::FileHash::compute(temp_file.path()).unwrap();
assert_eq!(
hash1.hash, hash2.hash,
"FileHash should be independent of buffer size"
);
unsafe {
std::env::remove_var("SQRY_PARSE_BUFFER");
}
}
#[test]
#[serial]
fn test_default_mmap_threshold() {
unsafe {
std::env::remove_var("SQRY_MMAP_THRESHOLD");
}
assert_eq!(mmap_threshold(), DEFAULT_MMAP_THRESHOLD);
}
#[test]
#[serial]
fn test_env_override_mmap_threshold() {
unsafe {
std::env::set_var("SQRY_MMAP_THRESHOLD", "52428800"); }
assert_eq!(mmap_threshold(), 52_428_800);
unsafe {
std::env::remove_var("SQRY_MMAP_THRESHOLD");
}
}
#[test]
#[serial]
fn test_mmap_threshold_clamping() {
unsafe {
std::env::set_var("SQRY_MMAP_THRESHOLD", "500000"); }
assert_eq!(mmap_threshold(), MIN_MMAP_THRESHOLD);
unsafe {
std::env::set_var("SQRY_MMAP_THRESHOLD", "2147483648"); }
assert_eq!(mmap_threshold(), MAX_MMAP_THRESHOLD);
unsafe {
std::env::remove_var("SQRY_MMAP_THRESHOLD");
}
}
#[test]
#[serial]
fn test_mmap_threshold_malformed() {
unsafe {
std::env::set_var("SQRY_MMAP_THRESHOLD", "not_a_number");
}
assert_eq!(mmap_threshold(), DEFAULT_MMAP_THRESHOLD);
unsafe {
std::env::remove_var("SQRY_MMAP_THRESHOLD");
}
}
#[test]
#[serial]
fn test_default_max_source_file_size() {
unsafe {
std::env::remove_var("SQRY_MAX_SOURCE_FILE_SIZE");
}
assert_eq!(max_source_file_size(), DEFAULT_MAX_SOURCE_FILE_SIZE);
}
#[test]
#[serial]
fn test_env_override_max_source_file_size() {
unsafe {
std::env::set_var("SQRY_MAX_SOURCE_FILE_SIZE", "10485760"); }
assert_eq!(max_source_file_size(), 10_485_760);
unsafe {
std::env::remove_var("SQRY_MAX_SOURCE_FILE_SIZE");
}
}
#[test]
#[serial]
fn test_max_source_file_size_clamping() {
unsafe {
std::env::set_var("SQRY_MAX_SOURCE_FILE_SIZE", "100"); }
assert_eq!(max_source_file_size(), MIN_MAX_SOURCE_FILE_SIZE);
unsafe {
std::env::set_var("SQRY_MAX_SOURCE_FILE_SIZE", "999999999999"); }
assert_eq!(max_source_file_size(), MAX_MAX_SOURCE_FILE_SIZE);
unsafe {
std::env::remove_var("SQRY_MAX_SOURCE_FILE_SIZE");
}
}
#[test]
#[serial]
fn test_max_source_file_size_invalid_env() {
unsafe {
std::env::set_var("SQRY_MAX_SOURCE_FILE_SIZE", "not_a_number");
}
assert_eq!(max_source_file_size(), DEFAULT_MAX_SOURCE_FILE_SIZE);
unsafe {
std::env::remove_var("SQRY_MAX_SOURCE_FILE_SIZE");
}
}
#[test]
#[serial]
fn test_default_max_repositories() {
unsafe {
std::env::remove_var("SQRY_MAX_REPOSITORIES");
}
assert_eq!(max_repositories(), DEFAULT_MAX_REPOSITORIES);
}
#[test]
#[serial]
fn test_env_override_max_repositories() {
unsafe {
std::env::set_var("SQRY_MAX_REPOSITORIES", "500");
}
assert_eq!(max_repositories(), 500);
unsafe {
std::env::remove_var("SQRY_MAX_REPOSITORIES");
}
}
#[test]
#[serial]
fn test_max_repositories_clamping() {
unsafe {
std::env::set_var("SQRY_MAX_REPOSITORIES", "1"); }
assert_eq!(max_repositories(), MIN_MAX_REPOSITORIES);
unsafe {
std::env::set_var("SQRY_MAX_REPOSITORIES", "99999"); }
assert_eq!(max_repositories(), MAX_MAX_REPOSITORIES);
unsafe {
std::env::remove_var("SQRY_MAX_REPOSITORIES");
}
}
#[test]
#[serial]
fn test_max_repositories_invalid_env() {
unsafe {
std::env::set_var("SQRY_MAX_REPOSITORIES", "bad_value");
}
assert_eq!(max_repositories(), DEFAULT_MAX_REPOSITORIES);
unsafe {
std::env::remove_var("SQRY_MAX_REPOSITORIES");
}
}
#[test]
#[serial]
fn test_default_watch_event_queue_capacity() {
unsafe {
std::env::remove_var("SQRY_WATCH_EVENT_QUEUE");
}
assert_eq!(watch_event_queue_capacity(), DEFAULT_WATCH_EVENT_QUEUE);
}
#[test]
#[serial]
fn test_env_override_watch_event_queue() {
unsafe {
std::env::set_var("SQRY_WATCH_EVENT_QUEUE", "5000");
}
assert_eq!(watch_event_queue_capacity(), 5_000);
unsafe {
std::env::remove_var("SQRY_WATCH_EVENT_QUEUE");
}
}
#[test]
#[serial]
fn test_watch_event_queue_clamping() {
unsafe {
std::env::set_var("SQRY_WATCH_EVENT_QUEUE", "10"); }
assert_eq!(watch_event_queue_capacity(), MIN_WATCH_EVENT_QUEUE);
unsafe {
std::env::set_var("SQRY_WATCH_EVENT_QUEUE", "999999"); }
assert_eq!(watch_event_queue_capacity(), MAX_WATCH_EVENT_QUEUE);
unsafe {
std::env::remove_var("SQRY_WATCH_EVENT_QUEUE");
}
}
#[test]
#[serial]
fn test_watch_event_queue_invalid_env() {
unsafe {
std::env::set_var("SQRY_WATCH_EVENT_QUEUE", "nope");
}
assert_eq!(watch_event_queue_capacity(), DEFAULT_WATCH_EVENT_QUEUE);
unsafe {
std::env::remove_var("SQRY_WATCH_EVENT_QUEUE");
}
}
#[test]
#[serial]
fn test_default_max_query_length() {
unsafe {
std::env::remove_var("SQRY_MAX_QUERY_LENGTH");
}
assert_eq!(max_query_length(), DEFAULT_MAX_QUERY_LENGTH);
}
#[test]
#[serial]
fn test_env_override_max_query_length() {
unsafe {
std::env::set_var("SQRY_MAX_QUERY_LENGTH", "20480"); }
assert_eq!(max_query_length(), 20_480);
unsafe {
std::env::remove_var("SQRY_MAX_QUERY_LENGTH");
}
}
#[test]
#[serial]
fn test_max_query_length_clamping() {
unsafe {
std::env::set_var("SQRY_MAX_QUERY_LENGTH", "100"); }
assert_eq!(max_query_length(), MIN_MAX_QUERY_LENGTH);
unsafe {
std::env::set_var("SQRY_MAX_QUERY_LENGTH", "9999999"); }
assert_eq!(max_query_length(), MAX_MAX_QUERY_LENGTH);
unsafe {
std::env::remove_var("SQRY_MAX_QUERY_LENGTH");
}
}
#[test]
#[serial]
fn test_max_query_length_invalid_env() {
unsafe {
std::env::set_var("SQRY_MAX_QUERY_LENGTH", "abc");
}
assert_eq!(max_query_length(), DEFAULT_MAX_QUERY_LENGTH);
unsafe {
std::env::remove_var("SQRY_MAX_QUERY_LENGTH");
}
}
#[test]
#[serial]
fn test_default_max_predicates() {
unsafe {
std::env::remove_var("SQRY_MAX_PREDICATES");
}
assert_eq!(max_predicates(), DEFAULT_MAX_PREDICATES);
}
#[test]
#[serial]
fn test_env_override_max_predicates() {
unsafe {
std::env::set_var("SQRY_MAX_PREDICATES", "200");
}
assert_eq!(max_predicates(), 200);
unsafe {
std::env::remove_var("SQRY_MAX_PREDICATES");
}
}
#[test]
#[serial]
fn test_max_predicates_clamping() {
unsafe {
std::env::set_var("SQRY_MAX_PREDICATES", "1"); }
assert_eq!(max_predicates(), MIN_MAX_PREDICATES);
unsafe {
std::env::set_var("SQRY_MAX_PREDICATES", "99999"); }
assert_eq!(max_predicates(), MAX_MAX_PREDICATES);
unsafe {
std::env::remove_var("SQRY_MAX_PREDICATES");
}
}
#[test]
#[serial]
fn test_max_predicates_invalid_env() {
unsafe {
std::env::set_var("SQRY_MAX_PREDICATES", "??");
}
assert_eq!(max_predicates(), DEFAULT_MAX_PREDICATES);
unsafe {
std::env::remove_var("SQRY_MAX_PREDICATES");
}
}
#[test]
#[serial]
fn test_default_json_max_depth() {
unsafe {
std::env::remove_var("SQRY_JSON_MAX_DEPTH");
}
assert_eq!(json_max_depth(), DEFAULT_JSON_MAX_DEPTH);
}
#[test]
#[serial]
fn test_env_override_json_max_depth() {
unsafe {
std::env::set_var("SQRY_JSON_MAX_DEPTH", "128");
}
assert_eq!(json_max_depth(), 128);
unsafe {
std::env::remove_var("SQRY_JSON_MAX_DEPTH");
}
}
#[test]
#[serial]
fn test_json_max_depth_clamped() {
unsafe {
std::env::set_var("SQRY_JSON_MAX_DEPTH", "1");
}
assert_eq!(json_max_depth(), MIN_JSON_MAX_DEPTH);
unsafe {
std::env::set_var("SQRY_JSON_MAX_DEPTH", "999999");
}
assert_eq!(json_max_depth(), MAX_JSON_MAX_DEPTH);
unsafe {
std::env::remove_var("SQRY_JSON_MAX_DEPTH");
}
}
#[test]
#[serial]
fn test_default_json_max_nodes() {
unsafe {
std::env::remove_var("SQRY_JSON_MAX_NODES");
}
assert_eq!(json_max_nodes(), DEFAULT_JSON_MAX_NODES);
}
#[test]
#[serial]
fn test_env_override_json_max_nodes() {
unsafe {
std::env::set_var("SQRY_JSON_MAX_NODES", "100000");
}
assert_eq!(json_max_nodes(), 100_000);
unsafe {
std::env::remove_var("SQRY_JSON_MAX_NODES");
}
}
#[test]
#[serial]
fn test_json_max_nodes_clamped() {
unsafe {
std::env::set_var("SQRY_JSON_MAX_NODES", "1");
}
assert_eq!(json_max_nodes(), MIN_JSON_MAX_NODES);
unsafe {
std::env::set_var("SQRY_JSON_MAX_NODES", "999999999");
}
assert_eq!(json_max_nodes(), MAX_JSON_MAX_NODES);
unsafe {
std::env::remove_var("SQRY_JSON_MAX_NODES");
}
}
}