use crate::harness::Weight;
use exeora_cli::protocol::ToolName;
use serde_json::{Value, json};
use std::{fs, path::Path};
pub const PACKAGES: usize = 12;
pub const MODULES: usize = 4;
pub const UNITS: usize = 25;
const HAYSTACK_LINES: usize = 120_000;
pub const MISS_PATTERN: &str = "absent_beacon_[0-9]{4}_symbol";
pub const ALTERNATION_PATTERN: &str = "(?:zeta|omega|kappa|sigma)_[0-9]{3}_beacon";
const LONG_LINE_PATTERN: &str = "runtime_beacon_marker";
const BLOB_PATTERN: &str = "blob_adjacent_marker";
const EDIT_ANCHOR_OLD: &str = "pub const UNIQUE_EDIT_ANCHOR: u64 = 424242;";
pub const EDIT_ANCHOR_NEW: &str = "pub const UNIQUE_EDIT_ANCHOR: u64 = 848484;";
#[cfg(unix)]
const STDOUT_COMMAND: &str = "cat streams/stdout-700k.txt";
#[cfg(windows)]
const STDOUT_COMMAND: &str = "type streams\\stdout-700k.txt";
pub struct HardCase {
pub name: &'static str,
pub weight: Weight,
pub tool: ToolName,
pub arguments: Value,
pub reset: bool,
}
fn case(name: &'static str, weight: Weight, tool: ToolName, arguments: Value) -> HardCase {
HardCase {
name,
weight,
tool,
arguments,
reset: false,
}
}
pub fn hard_cases() -> Vec<HardCase> {
vec![
case(
"read_file_8mb",
Weight::Medium,
ToolName::ReadFile,
json!({"path":"big/haystack.rs"}),
),
case(
"read_file_tail_slice",
Weight::Light,
ToolName::ReadFile,
json!({"path":"big/haystack.rs", "offset":HAYSTACK_LINES - 1_000, "limit":100}),
),
case(
"list_files_corpus_1k",
Weight::Medium,
ToolName::ListFiles,
json!({"path":"corpus", "recursive":true}),
),
case(
"list_files_glob_corpus",
Weight::Medium,
ToolName::ListFiles,
json!({"path":"corpus", "recursive":true, "glob":"**/unit-0*.rs"}),
),
case(
"grep_full_scan_miss",
Weight::XHeavy,
ToolName::Grep,
json!({"pattern":MISS_PATTERN, "path":"corpus", "maxResults":200}),
),
case(
"grep_regex_alternation",
Weight::XHeavy,
ToolName::Grep,
json!({"pattern":ALTERNATION_PATTERN, "path":"corpus", "caseInsensitive":true, "maxResults":200}),
),
case(
"grep_long_lines",
Weight::Heavy,
ToolName::Grep,
json!({"pattern":LONG_LINE_PATTERN, "path":"minified", "maxResults":200}),
),
case(
"grep_binary_corpus",
Weight::Heavy,
ToolName::Grep,
json!({"pattern":BLOB_PATTERN, "path":"blobs", "maxResults":200}),
),
HardCase {
reset: true,
..case(
"edit_file_2mb",
Weight::Heavy,
ToolName::EditFile,
json!({"path":"big/editable.rs", "oldString":EDIT_ANCHOR_OLD, "newString":EDIT_ANCHOR_NEW}),
)
},
case(
"write_file_8mb",
Weight::Medium,
ToolName::WriteFile,
json!({"path":"big/written.txt", "content":"x".repeat(8 * 1024 * 1024)}),
),
case(
"run_command_700kb_stdout",
Weight::Heavy,
ToolName::RunCommand,
json!({"command":STDOUT_COMMAND}),
),
]
}
pub fn reset_case(root: &Path) {
fs::copy(
root.join("big/editable-pristine.rs"),
root.join("big/editable.rs"),
)
.expect("restore editable fixture");
}
pub fn unit_path(index: usize) -> String {
format!(
"corpus/pkg-{:02}/mod-{}/unit-{:02}.rs",
index % PACKAGES,
(index >> 2) % MODULES,
index % UNITS
)
}
pub fn package_path(index: usize) -> String {
format!("corpus/pkg-{:02}", index % PACKAGES)
}