use super::{SEEDED_MODELS, TEMPLATE_PROVIDERS};
use crate::model_pick::grammar::{GrammarError, MODELS_YAML, roles};
use crate::model_pick::{
Pick, PickError, WORKER_ROLE, WRITE_NOTE, birth_sentence, default_row, plan, scope_sentence,
};
fn pick(model: &str) -> Pick {
Pick {
role: WORKER_ROLE.to_string(),
provider: "codex".to_string(),
model: model.to_string(),
}
}
fn rows() -> Vec<String> {
vec!["codex".to_string(), "google".to_string()]
}
#[test]
fn a_model_unknown_to_models_yaml_plans_both_writes() {
let planned = plan(
SEEDED_MODELS,
TEMPLATE_PROVIDERS,
&rows(),
&pick("gpt-5.6-sol"),
)
.unwrap();
let declared = planned.models_yaml.expect("the id needed declaring");
assert!(declared.contains(" gpt-5.6-sol:\n provider: codex\n"));
assert_eq!(
roles(&planned.providers_yaml)
.into_iter()
.find(|r| r.role == WORKER_ROLE)
.map(|r| r.model),
Some("gpt-5.6-sol".to_string())
);
}
#[test]
fn an_already_declared_model_plans_one_write() {
let planned = plan(
SEEDED_MODELS,
&crate::model_pick::grammar::set_role_model(
TEMPLATE_PROVIDERS,
WORKER_ROLE,
"codex",
"gpt-5.6-sol",
)
.unwrap(),
&rows(),
&pick("gpt-5.4"),
)
.unwrap();
assert_eq!(planned.models_yaml, None);
assert!(planned.providers_yaml.contains(" model: gpt-5.4"));
}
#[test]
fn an_unreadable_models_yaml_refuses_before_the_providers_half() {
let refused = plan(
"models: {}\n",
TEMPLATE_PROVIDERS,
&rows(),
&pick("gpt-5.6-sol"),
);
assert_eq!(
refused,
Err(PickError::Grammar(GrammarError::Inline {
file: MODELS_YAML,
key: "models".into(),
}))
);
assert_eq!(
refused.unwrap_err().to_string(),
GrammarError::Inline {
file: MODELS_YAML,
key: "models".into(),
}
.to_string()
);
}
#[test]
fn an_unreadable_providers_yaml_refuses_the_plan() {
assert!(matches!(
plan(SEEDED_MODELS, "roles: {}\n", &rows(), &pick("gpt-5.6-sol")),
Err(PickError::Grammar(GrammarError::Inline { .. }))
));
}
#[test]
fn a_pick_on_a_row_brazen_lacks_is_refused_before_either_file() {
let live = vec!["openai-chatgpt".to_string()];
let refused = plan(SEEDED_MODELS, TEMPLATE_PROVIDERS, &live, &pick("gpt-5.4"));
assert_eq!(
refused,
Err(PickError::UnknownProvider {
provider: "codex".to_string(),
})
);
let said = refused.unwrap_err().to_string();
assert!(said.contains("no provider row `codex`"), "{said}");
assert!(said.contains("pick a live row here"), "{said}");
}
#[test]
fn a_model_id_the_block_grammar_cannot_hold_is_refused() {
for bad in ["", " ", "gpt 5", "gpt:5", "gpt#5", "a\tb"] {
let mut broken = pick(bad);
broken.model = bad.to_string();
assert_eq!(
plan(SEEDED_MODELS, TEMPLATE_PROVIDERS, &rows(), &broken),
Err(PickError::NotAnId {
model: bad.to_string(),
}),
"{bad:?} must not reach either file"
);
}
let said = PickError::NotAnId {
model: "gpt 5".into(),
}
.to_string();
assert!(said.contains("not a plain model id"), "{said}");
assert!(
plan(
SEEDED_MODELS,
TEMPLATE_PROVIDERS,
&rows(),
&pick("my-local-tag")
)
.is_ok()
);
}
#[test]
fn an_unanswerable_brazen_gates_no_pick() {
assert!(plan(SEEDED_MODELS, TEMPLATE_PROVIDERS, &[], &pick("gpt-5.4")).is_ok());
}
#[test]
fn the_default_row_leaves_a_row_brazen_dropped() {
let live = vec!["openai-chatgpt".to_string(), "google".to_string()];
assert_eq!(default_row("codex", &live), "openai-chatgpt");
assert_eq!(default_row("google", &live), "google");
assert_eq!(default_row("codex", &[]), "codex");
}
#[test]
fn the_scope_sentence_states_branch_workspace_and_the_frozen_conversation() {
let s = scope_sentence("mauve-tapir", "default", "1a2b3c4d");
assert!(s.contains("config/default"));
assert!(s.contains("mauve-tapir workspace"));
assert!(s.contains("NEXT conversation"));
assert!(s.contains("frozen at 1a2b3c4d"));
}
#[test]
fn the_birth_sentence_admits_it_moves_the_workspace_default() {
let s = birth_sentence("mauve-tapir", "default");
assert!(s.contains("mauve-tapir workspace default"));
assert!(s.contains("config/default"));
assert!(s.contains("about to start"));
assert!(!s.contains("frozen"));
}
#[test]
fn the_write_note_names_both_files_in_order() {
let (first, rest) = WRITE_NOTE.split_once("models.yaml").unwrap();
assert!(first.contains("writes"));
assert!(rest.contains("providers.yaml"));
assert!(rest.contains("declared"));
}