mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
chore: migrate from Config::load_from_base_config_with_overrides to ConfigBuilder (#8276)
https://github.com/openai/codex/pull/8235 introduced `ConfigBuilder` and this PR updates all call non-test call sites to use it instead of `Config::load_from_base_config_with_overrides()`. This is important because `load_from_base_config_with_overrides()` uses an empty `ConfigRequirements`, which is a reasonable default for testing so the tests are not influenced by the settings on the host. This method is now guarded by `#[cfg(test)]` so it cannot be used by business logic. Because `ConfigBuilder::build()` is `async`, many of the test methods had to be migrated to be `async`, as well. On the bright side, this made it possible to eliminate a bunch of `block_on_future()` stuff.
This commit is contained in:
committed by
GitHub
Unverified
parent
2d9826098e
commit
3d4ced3ff5
+12
-14
@@ -636,8 +636,7 @@ mod tests {
|
||||
use crate::auth::storage::FileAuthStorage;
|
||||
use crate::auth::storage::get_auth_file;
|
||||
use crate::config::Config;
|
||||
use crate::config::ConfigOverrides;
|
||||
use crate::config::ConfigToml;
|
||||
use crate::config::ConfigBuilder;
|
||||
use crate::token_data::IdTokenInfo;
|
||||
use crate::token_data::KnownPlan as InternalKnownPlan;
|
||||
use crate::token_data::PlanType as InternalPlanType;
|
||||
@@ -862,17 +861,16 @@ mod tests {
|
||||
Ok(fake_jwt)
|
||||
}
|
||||
|
||||
fn build_config(
|
||||
async fn build_config(
|
||||
codex_home: &Path,
|
||||
forced_login_method: Option<ForcedLoginMethod>,
|
||||
forced_chatgpt_workspace_id: Option<String>,
|
||||
) -> Config {
|
||||
let mut config = Config::load_from_base_config_with_overrides(
|
||||
ConfigToml::default(),
|
||||
ConfigOverrides::default(),
|
||||
codex_home.to_path_buf(),
|
||||
)
|
||||
.expect("config should load");
|
||||
let mut config = ConfigBuilder::default()
|
||||
.codex_home(codex_home.to_path_buf())
|
||||
.build()
|
||||
.await
|
||||
.expect("config should load");
|
||||
config.forced_login_method = forced_login_method;
|
||||
config.forced_chatgpt_workspace_id = forced_chatgpt_workspace_id;
|
||||
config
|
||||
@@ -915,7 +913,7 @@ mod tests {
|
||||
login_with_api_key(codex_home.path(), "sk-test", AuthCredentialsStoreMode::File)
|
||||
.expect("seed api key");
|
||||
|
||||
let config = build_config(codex_home.path(), Some(ForcedLoginMethod::Chatgpt), None);
|
||||
let config = build_config(codex_home.path(), Some(ForcedLoginMethod::Chatgpt), None).await;
|
||||
|
||||
let err = super::enforce_login_restrictions(&config)
|
||||
.await
|
||||
@@ -941,7 +939,7 @@ mod tests {
|
||||
)
|
||||
.expect("failed to write auth file");
|
||||
|
||||
let config = build_config(codex_home.path(), None, Some("org_mine".to_string()));
|
||||
let config = build_config(codex_home.path(), None, Some("org_mine".to_string())).await;
|
||||
|
||||
let err = super::enforce_login_restrictions(&config)
|
||||
.await
|
||||
@@ -967,7 +965,7 @@ mod tests {
|
||||
)
|
||||
.expect("failed to write auth file");
|
||||
|
||||
let config = build_config(codex_home.path(), None, Some("org_mine".to_string()));
|
||||
let config = build_config(codex_home.path(), None, Some("org_mine".to_string())).await;
|
||||
|
||||
super::enforce_login_restrictions(&config)
|
||||
.await
|
||||
@@ -985,7 +983,7 @@ mod tests {
|
||||
login_with_api_key(codex_home.path(), "sk-test", AuthCredentialsStoreMode::File)
|
||||
.expect("seed api key");
|
||||
|
||||
let config = build_config(codex_home.path(), None, Some("org_mine".to_string()));
|
||||
let config = build_config(codex_home.path(), None, Some("org_mine".to_string())).await;
|
||||
|
||||
super::enforce_login_restrictions(&config)
|
||||
.await
|
||||
@@ -1002,7 +1000,7 @@ mod tests {
|
||||
let _guard = EnvVarGuard::set(CODEX_API_KEY_ENV_VAR, "sk-env");
|
||||
let codex_home = tempdir().unwrap();
|
||||
|
||||
let config = build_config(codex_home.path(), Some(ForcedLoginMethod::Chatgpt), None);
|
||||
let config = build_config(codex_home.path(), Some(ForcedLoginMethod::Chatgpt), None).await;
|
||||
|
||||
let err = super::enforce_login_restrictions(&config)
|
||||
.await
|
||||
|
||||
+48
-62
@@ -2750,8 +2750,7 @@ pub(crate) use tests::make_session_and_context_with_rx;
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::CodexAuth;
|
||||
use crate::config::ConfigOverrides;
|
||||
use crate::config::ConfigToml;
|
||||
use crate::config::ConfigBuilder;
|
||||
use crate::exec::ExecToolCallOutput;
|
||||
use crate::function_tool::FunctionCallError;
|
||||
use crate::shell::default_user_shell;
|
||||
@@ -2778,6 +2777,7 @@ mod tests {
|
||||
use codex_app_server_protocol::AuthMode;
|
||||
use codex_protocol::models::ContentItem;
|
||||
use codex_protocol::models::ResponseItem;
|
||||
use std::path::Path;
|
||||
use std::time::Duration;
|
||||
use tokio::time::sleep;
|
||||
|
||||
@@ -2790,9 +2790,9 @@ mod tests {
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration as StdDuration;
|
||||
|
||||
#[test]
|
||||
fn reconstruct_history_matches_live_compactions() {
|
||||
let (session, turn_context) = make_session_and_context();
|
||||
#[tokio::test]
|
||||
async fn reconstruct_history_matches_live_compactions() {
|
||||
let (session, turn_context) = make_session_and_context().await;
|
||||
let (rollout_items, expected) = sample_rollout(&session, &turn_context);
|
||||
|
||||
let reconstructed = session.reconstruct_history_from_rollout(&turn_context, &rollout_items);
|
||||
@@ -2800,47 +2800,40 @@ mod tests {
|
||||
assert_eq!(expected, reconstructed);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn record_initial_history_reconstructs_resumed_transcript() {
|
||||
let (session, turn_context) = make_session_and_context();
|
||||
#[tokio::test]
|
||||
async fn record_initial_history_reconstructs_resumed_transcript() {
|
||||
let (session, turn_context) = make_session_and_context().await;
|
||||
let (rollout_items, expected) = sample_rollout(&session, &turn_context);
|
||||
|
||||
tokio_test::block_on(session.record_initial_history(InitialHistory::Resumed(
|
||||
ResumedHistory {
|
||||
session
|
||||
.record_initial_history(InitialHistory::Resumed(ResumedHistory {
|
||||
conversation_id: ConversationId::default(),
|
||||
history: rollout_items,
|
||||
rollout_path: PathBuf::from("/tmp/resume.jsonl"),
|
||||
},
|
||||
)));
|
||||
}))
|
||||
.await;
|
||||
|
||||
let actual = tokio_test::block_on(async {
|
||||
session.state.lock().await.clone_history().get_history()
|
||||
});
|
||||
let actual = session.state.lock().await.clone_history().get_history();
|
||||
assert_eq!(expected, actual);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn record_initial_history_reconstructs_forked_transcript() {
|
||||
let (session, turn_context) = make_session_and_context();
|
||||
#[tokio::test]
|
||||
async fn record_initial_history_reconstructs_forked_transcript() {
|
||||
let (session, turn_context) = make_session_and_context().await;
|
||||
let (rollout_items, expected) = sample_rollout(&session, &turn_context);
|
||||
|
||||
tokio_test::block_on(session.record_initial_history(InitialHistory::Forked(rollout_items)));
|
||||
session
|
||||
.record_initial_history(InitialHistory::Forked(rollout_items))
|
||||
.await;
|
||||
|
||||
let actual = tokio_test::block_on(async {
|
||||
session.state.lock().await.clone_history().get_history()
|
||||
});
|
||||
let actual = session.state.lock().await.clone_history().get_history();
|
||||
assert_eq!(expected, actual);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_rate_limits_retains_previous_credits() {
|
||||
#[tokio::test]
|
||||
async fn set_rate_limits_retains_previous_credits() {
|
||||
let codex_home = tempfile::tempdir().expect("create temp dir");
|
||||
let config = Config::load_from_base_config_with_overrides(
|
||||
ConfigToml::default(),
|
||||
ConfigOverrides::default(),
|
||||
codex_home.path().to_path_buf(),
|
||||
)
|
||||
.expect("load default test config");
|
||||
let config = build_test_config(codex_home.path()).await;
|
||||
let config = Arc::new(config);
|
||||
let model = ModelsManager::get_model_offline(config.model.as_deref());
|
||||
let session_configuration = SessionConfiguration {
|
||||
@@ -2904,15 +2897,10 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_rate_limits_updates_plan_type_when_present() {
|
||||
#[tokio::test]
|
||||
async fn set_rate_limits_updates_plan_type_when_present() {
|
||||
let codex_home = tempfile::tempdir().expect("create temp dir");
|
||||
let config = Config::load_from_base_config_with_overrides(
|
||||
ConfigToml::default(),
|
||||
ConfigOverrides::default(),
|
||||
codex_home.path().to_path_buf(),
|
||||
)
|
||||
.expect("load default test config");
|
||||
let config = build_test_config(codex_home.path()).await;
|
||||
let config = Arc::new(config);
|
||||
let model = ModelsManager::get_model_offline(config.model.as_deref());
|
||||
let session_configuration = SessionConfiguration {
|
||||
@@ -3002,8 +2990,8 @@ mod tests {
|
||||
assert_eq!(expected, got);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn includes_timed_out_message() {
|
||||
#[tokio::test]
|
||||
async fn includes_timed_out_message() {
|
||||
let exec = ExecToolCallOutput {
|
||||
exit_code: 0,
|
||||
stdout: StreamOutput::new(String::new()),
|
||||
@@ -3012,7 +3000,7 @@ mod tests {
|
||||
duration: StdDuration::from_secs(1),
|
||||
timed_out: true,
|
||||
};
|
||||
let (_, turn_context) = make_session_and_context();
|
||||
let (_, turn_context) = make_session_and_context().await;
|
||||
|
||||
let out = format_exec_output_str(&exec, turn_context.truncation_policy);
|
||||
|
||||
@@ -3085,6 +3073,14 @@ mod tests {
|
||||
})
|
||||
}
|
||||
|
||||
async fn build_test_config(codex_home: &Path) -> Config {
|
||||
ConfigBuilder::default()
|
||||
.codex_home(codex_home.to_path_buf())
|
||||
.build()
|
||||
.await
|
||||
.expect("load default test config")
|
||||
}
|
||||
|
||||
fn otel_manager(
|
||||
conversation_id: ConversationId,
|
||||
config: &Config,
|
||||
@@ -3104,15 +3100,10 @@ mod tests {
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn make_session_and_context() -> (Session, TurnContext) {
|
||||
pub(crate) async fn make_session_and_context() -> (Session, TurnContext) {
|
||||
let (tx_event, _rx_event) = async_channel::unbounded();
|
||||
let codex_home = tempfile::tempdir().expect("create temp dir");
|
||||
let config = Config::load_from_base_config_with_overrides(
|
||||
ConfigToml::default(),
|
||||
ConfigOverrides::default(),
|
||||
codex_home.path().to_path_buf(),
|
||||
)
|
||||
.expect("load default test config");
|
||||
let config = build_test_config(codex_home.path()).await;
|
||||
let config = Arc::new(config);
|
||||
let conversation_id = ConversationId::default();
|
||||
let auth_manager =
|
||||
@@ -3191,19 +3182,14 @@ mod tests {
|
||||
|
||||
// Like make_session_and_context, but returns Arc<Session> and the event receiver
|
||||
// so tests can assert on emitted events.
|
||||
pub(crate) fn make_session_and_context_with_rx() -> (
|
||||
pub(crate) async fn make_session_and_context_with_rx() -> (
|
||||
Arc<Session>,
|
||||
Arc<TurnContext>,
|
||||
async_channel::Receiver<Event>,
|
||||
) {
|
||||
let (tx_event, rx_event) = async_channel::unbounded();
|
||||
let codex_home = tempfile::tempdir().expect("create temp dir");
|
||||
let config = Config::load_from_base_config_with_overrides(
|
||||
ConfigToml::default(),
|
||||
ConfigOverrides::default(),
|
||||
codex_home.path().to_path_buf(),
|
||||
)
|
||||
.expect("load default test config");
|
||||
let config = build_test_config(codex_home.path()).await;
|
||||
let config = Arc::new(config);
|
||||
let conversation_id = ConversationId::default();
|
||||
let auth_manager =
|
||||
@@ -3282,7 +3268,7 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn record_model_warning_appends_user_message() {
|
||||
let (mut session, turn_context) = make_session_and_context();
|
||||
let (mut session, turn_context) = make_session_and_context().await;
|
||||
let mut features = Features::with_defaults();
|
||||
features.enable(Feature::ModelWarnings);
|
||||
session.features = features;
|
||||
@@ -3341,7 +3327,7 @@ mod tests {
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
#[test_log::test]
|
||||
async fn abort_regular_task_emits_turn_aborted_only() {
|
||||
let (sess, tc, rx) = make_session_and_context_with_rx();
|
||||
let (sess, tc, rx) = make_session_and_context_with_rx().await;
|
||||
let input = vec![UserInput::Text {
|
||||
text: "hello".to_string(),
|
||||
}];
|
||||
@@ -3370,7 +3356,7 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn abort_gracefuly_emits_turn_aborted_only() {
|
||||
let (sess, tc, rx) = make_session_and_context_with_rx();
|
||||
let (sess, tc, rx) = make_session_and_context_with_rx().await;
|
||||
let input = vec![UserInput::Text {
|
||||
text: "hello".to_string(),
|
||||
}];
|
||||
@@ -3396,7 +3382,7 @@ mod tests {
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn abort_review_task_emits_exited_then_aborted_and_records_history() {
|
||||
let (sess, tc, rx) = make_session_and_context_with_rx();
|
||||
let (sess, tc, rx) = make_session_and_context_with_rx().await;
|
||||
let input = vec![UserInput::Text {
|
||||
text: "start review".to_string(),
|
||||
}];
|
||||
@@ -3444,7 +3430,7 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn fatal_tool_error_stops_turn_and_reports_error() {
|
||||
let (session, turn_context, _rx) = make_session_and_context_with_rx();
|
||||
let (session, turn_context, _rx) = make_session_and_context_with_rx().await;
|
||||
let tools = {
|
||||
session
|
||||
.services
|
||||
@@ -3607,7 +3593,7 @@ mod tests {
|
||||
use crate::turn_diff_tracker::TurnDiffTracker;
|
||||
use std::collections::HashMap;
|
||||
|
||||
let (session, mut turn_context_raw) = make_session_and_context();
|
||||
let (session, mut turn_context_raw) = make_session_and_context().await;
|
||||
// Ensure policy is NOT OnRequest so the early rejection path triggers
|
||||
turn_context_raw.approval_policy = AskForApproval::OnFailure;
|
||||
let session = Arc::new(session);
|
||||
@@ -3738,7 +3724,7 @@ mod tests {
|
||||
use crate::sandboxing::SandboxPermissions;
|
||||
use crate::turn_diff_tracker::TurnDiffTracker;
|
||||
|
||||
let (session, mut turn_context_raw) = make_session_and_context();
|
||||
let (session, mut turn_context_raw) = make_session_and_context().await;
|
||||
turn_context_raw.approval_policy = AskForApproval::OnFailure;
|
||||
let session = Arc::new(session);
|
||||
let turn_context = Arc::new(turn_context_raw);
|
||||
|
||||
@@ -366,7 +366,7 @@ mod tests {
|
||||
rx_event: rx_events,
|
||||
});
|
||||
|
||||
let (session, ctx, _rx_evt) = crate::codex::make_session_and_context_with_rx();
|
||||
let (session, ctx, _rx_evt) = crate::codex::make_session_and_context_with_rx().await;
|
||||
|
||||
let (tx_out, rx_out) = bounded(1);
|
||||
tx_out
|
||||
|
||||
@@ -694,7 +694,6 @@ mod tests {
|
||||
use codex_protocol::openai_models::ReasoningEffort;
|
||||
use pretty_assertions::assert_eq;
|
||||
use tempfile::tempdir;
|
||||
use tokio::runtime::Builder;
|
||||
use toml::Value as TomlValue;
|
||||
|
||||
#[test]
|
||||
@@ -1455,22 +1454,16 @@ model_reasoning_effort = "high"
|
||||
assert_eq!(contents, initial_expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn blocking_set_asynchronous_helpers_available() {
|
||||
let rt = Builder::new_current_thread()
|
||||
.enable_all()
|
||||
.build()
|
||||
.expect("runtime");
|
||||
#[tokio::test]
|
||||
async fn blocking_set_asynchronous_helpers_available() {
|
||||
let tmp = tempdir().expect("tmpdir");
|
||||
let codex_home = tmp.path().to_path_buf();
|
||||
|
||||
rt.block_on(async {
|
||||
ConfigEditsBuilder::new(&codex_home)
|
||||
.set_hide_full_access_warning(true)
|
||||
.apply()
|
||||
.await
|
||||
.expect("persist");
|
||||
});
|
||||
ConfigEditsBuilder::new(&codex_home)
|
||||
.set_hide_full_access_warning(true)
|
||||
.apply()
|
||||
.await
|
||||
.expect("persist");
|
||||
|
||||
let raw = std::fs::read_to_string(codex_home.join(CONFIG_TOML_FILE)).expect("read config");
|
||||
let notice = toml::from_str::<TomlValue>(&raw)
|
||||
|
||||
@@ -992,14 +992,13 @@ pub fn resolve_oss_provider(
|
||||
}
|
||||
|
||||
impl Config {
|
||||
/// Meant to be used exclusively for tests. For new tests, prefer using
|
||||
/// [ConfigBuilder::build()], if possible, so ultimately we can make this
|
||||
/// method private to this file.
|
||||
pub fn load_from_base_config_with_overrides(
|
||||
#[cfg(test)]
|
||||
fn load_from_base_config_with_overrides(
|
||||
cfg: ConfigToml,
|
||||
overrides: ConfigOverrides,
|
||||
codex_home: PathBuf,
|
||||
) -> std::io::Result<Self> {
|
||||
// Note this ignores requirements.toml enforcement for tests.
|
||||
let requirements = ConfigRequirements::default();
|
||||
Self::load_config_with_requirements(cfg, overrides, codex_home, requirements)
|
||||
}
|
||||
|
||||
@@ -379,9 +379,9 @@ mod tests {
|
||||
assert_matches!(truncated2, InitialHistory::New);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ignores_session_prefix_messages_when_truncating() {
|
||||
let (session, turn_context) = make_session_and_context();
|
||||
#[tokio::test]
|
||||
async fn ignores_session_prefix_messages_when_truncating() {
|
||||
let (session, turn_context) = make_session_and_context().await;
|
||||
let mut items = session.build_initial_context(&turn_context);
|
||||
items.push(user_msg("feature request"));
|
||||
items.push(assistant_msg("ack"));
|
||||
|
||||
@@ -401,9 +401,7 @@ fn history_log_id(_metadata: &std::fs::Metadata) -> Option<u64> {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::config::Config;
|
||||
use crate::config::ConfigOverrides;
|
||||
use crate::config::ConfigToml;
|
||||
use crate::config::ConfigBuilder;
|
||||
use codex_protocol::ConversationId;
|
||||
use pretty_assertions::assert_eq;
|
||||
use std::fs::File;
|
||||
@@ -493,12 +491,11 @@ mod tests {
|
||||
async fn append_entry_trims_history_when_beyond_max_bytes() {
|
||||
let codex_home = TempDir::new().expect("create temp dir");
|
||||
|
||||
let mut config = Config::load_from_base_config_with_overrides(
|
||||
ConfigToml::default(),
|
||||
ConfigOverrides::default(),
|
||||
codex_home.path().to_path_buf(),
|
||||
)
|
||||
.expect("load config");
|
||||
let mut config = ConfigBuilder::default()
|
||||
.codex_home(codex_home.path().to_path_buf())
|
||||
.build()
|
||||
.await
|
||||
.expect("load config");
|
||||
|
||||
let conversation_id = ConversationId::new();
|
||||
|
||||
@@ -541,12 +538,11 @@ mod tests {
|
||||
async fn append_entry_trims_history_to_soft_cap() {
|
||||
let codex_home = TempDir::new().expect("create temp dir");
|
||||
|
||||
let mut config = Config::load_from_base_config_with_overrides(
|
||||
ConfigToml::default(),
|
||||
ConfigOverrides::default(),
|
||||
codex_home.path().to_path_buf(),
|
||||
)
|
||||
.expect("load config");
|
||||
let mut config = ConfigBuilder::default()
|
||||
.codex_home(codex_home.path().to_path_buf())
|
||||
.build()
|
||||
.await
|
||||
.expect("load config");
|
||||
|
||||
let conversation_id = ConversationId::new();
|
||||
|
||||
|
||||
@@ -314,9 +314,7 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::CodexAuth;
|
||||
use crate::auth::AuthCredentialsStoreMode;
|
||||
use crate::config::Config;
|
||||
use crate::config::ConfigOverrides;
|
||||
use crate::config::ConfigToml;
|
||||
use crate::config::ConfigBuilder;
|
||||
use crate::features::Feature;
|
||||
use crate::model_provider_info::WireApi;
|
||||
use codex_protocol::openai_models::ModelsResponse;
|
||||
@@ -397,12 +395,11 @@ mod tests {
|
||||
.await;
|
||||
|
||||
let codex_home = tempdir().expect("temp dir");
|
||||
let mut config = Config::load_from_base_config_with_overrides(
|
||||
ConfigToml::default(),
|
||||
ConfigOverrides::default(),
|
||||
codex_home.path().to_path_buf(),
|
||||
)
|
||||
.expect("load default test config");
|
||||
let mut config = ConfigBuilder::default()
|
||||
.codex_home(codex_home.path().to_path_buf())
|
||||
.build()
|
||||
.await
|
||||
.expect("load default test config");
|
||||
config.features.enable(Feature::RemoteModels);
|
||||
let auth_manager =
|
||||
AuthManager::from_auth_for_testing(CodexAuth::create_dummy_chatgpt_auth_for_testing());
|
||||
@@ -455,12 +452,11 @@ mod tests {
|
||||
.await;
|
||||
|
||||
let codex_home = tempdir().expect("temp dir");
|
||||
let mut config = Config::load_from_base_config_with_overrides(
|
||||
ConfigToml::default(),
|
||||
ConfigOverrides::default(),
|
||||
codex_home.path().to_path_buf(),
|
||||
)
|
||||
.expect("load default test config");
|
||||
let mut config = ConfigBuilder::default()
|
||||
.codex_home(codex_home.path().to_path_buf())
|
||||
.build()
|
||||
.await
|
||||
.expect("load default test config");
|
||||
config.features.enable(Feature::RemoteModels);
|
||||
let auth_manager = Arc::new(AuthManager::new(
|
||||
codex_home.path().to_path_buf(),
|
||||
@@ -511,12 +507,11 @@ mod tests {
|
||||
.await;
|
||||
|
||||
let codex_home = tempdir().expect("temp dir");
|
||||
let mut config = Config::load_from_base_config_with_overrides(
|
||||
ConfigToml::default(),
|
||||
ConfigOverrides::default(),
|
||||
codex_home.path().to_path_buf(),
|
||||
)
|
||||
.expect("load default test config");
|
||||
let mut config = ConfigBuilder::default()
|
||||
.codex_home(codex_home.path().to_path_buf())
|
||||
.build()
|
||||
.await
|
||||
.expect("load default test config");
|
||||
config.features.enable(Feature::RemoteModels);
|
||||
let auth_manager = Arc::new(AuthManager::new(
|
||||
codex_home.path().to_path_buf(),
|
||||
@@ -587,12 +582,11 @@ mod tests {
|
||||
.await;
|
||||
|
||||
let codex_home = tempdir().expect("temp dir");
|
||||
let mut config = Config::load_from_base_config_with_overrides(
|
||||
ConfigToml::default(),
|
||||
ConfigOverrides::default(),
|
||||
codex_home.path().to_path_buf(),
|
||||
)
|
||||
.expect("load default test config");
|
||||
let mut config = ConfigBuilder::default()
|
||||
.codex_home(codex_home.path().to_path_buf())
|
||||
.build()
|
||||
.await
|
||||
.expect("load default test config");
|
||||
config.features.enable(Feature::RemoteModels);
|
||||
let auth_manager =
|
||||
AuthManager::from_auth_for_testing(CodexAuth::create_dummy_chatgpt_auth_for_testing());
|
||||
|
||||
@@ -232,8 +232,7 @@ fn merge_project_docs_with_skills(
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::config::ConfigOverrides;
|
||||
use crate::config::ConfigToml;
|
||||
use crate::config::ConfigBuilder;
|
||||
use crate::skills::load_skills;
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
@@ -244,14 +243,13 @@ mod tests {
|
||||
/// optionally specify a custom `instructions` string – when `None` the
|
||||
/// value is cleared to mimic a scenario where no system instructions have
|
||||
/// been configured.
|
||||
fn make_config(root: &TempDir, limit: usize, instructions: Option<&str>) -> Config {
|
||||
async fn make_config(root: &TempDir, limit: usize, instructions: Option<&str>) -> Config {
|
||||
let codex_home = TempDir::new().unwrap();
|
||||
let mut config = Config::load_from_base_config_with_overrides(
|
||||
ConfigToml::default(),
|
||||
ConfigOverrides::default(),
|
||||
codex_home.path().to_path_buf(),
|
||||
)
|
||||
.expect("defaults for test should always succeed");
|
||||
let mut config = ConfigBuilder::default()
|
||||
.codex_home(codex_home.path().to_path_buf())
|
||||
.build()
|
||||
.await
|
||||
.expect("defaults for test should always succeed");
|
||||
|
||||
config.cwd = root.path().to_path_buf();
|
||||
config.project_doc_max_bytes = limit;
|
||||
@@ -260,13 +258,13 @@ mod tests {
|
||||
config
|
||||
}
|
||||
|
||||
fn make_config_with_fallback(
|
||||
async fn make_config_with_fallback(
|
||||
root: &TempDir,
|
||||
limit: usize,
|
||||
instructions: Option<&str>,
|
||||
fallbacks: &[&str],
|
||||
) -> Config {
|
||||
let mut config = make_config(root, limit, instructions);
|
||||
let mut config = make_config(root, limit, instructions).await;
|
||||
config.project_doc_fallback_filenames = fallbacks
|
||||
.iter()
|
||||
.map(std::string::ToString::to_string)
|
||||
@@ -279,7 +277,7 @@ mod tests {
|
||||
async fn no_doc_file_returns_none() {
|
||||
let tmp = tempfile::tempdir().expect("tempdir");
|
||||
|
||||
let res = get_user_instructions(&make_config(&tmp, 4096, None), None).await;
|
||||
let res = get_user_instructions(&make_config(&tmp, 4096, None).await, None).await;
|
||||
assert!(
|
||||
res.is_none(),
|
||||
"Expected None when AGENTS.md is absent and no system instructions provided"
|
||||
@@ -293,7 +291,7 @@ mod tests {
|
||||
let tmp = tempfile::tempdir().expect("tempdir");
|
||||
fs::write(tmp.path().join("AGENTS.md"), "hello world").unwrap();
|
||||
|
||||
let res = get_user_instructions(&make_config(&tmp, 4096, None), None)
|
||||
let res = get_user_instructions(&make_config(&tmp, 4096, None).await, None)
|
||||
.await
|
||||
.expect("doc expected");
|
||||
|
||||
@@ -312,7 +310,7 @@ mod tests {
|
||||
let huge = "A".repeat(LIMIT * 2); // 2 KiB
|
||||
fs::write(tmp.path().join("AGENTS.md"), &huge).unwrap();
|
||||
|
||||
let res = get_user_instructions(&make_config(&tmp, LIMIT, None), None)
|
||||
let res = get_user_instructions(&make_config(&tmp, LIMIT, None).await, None)
|
||||
.await
|
||||
.expect("doc expected");
|
||||
|
||||
@@ -341,7 +339,7 @@ mod tests {
|
||||
std::fs::create_dir_all(&nested).unwrap();
|
||||
|
||||
// Build config pointing at the nested dir.
|
||||
let mut cfg = make_config(&repo, 4096, None);
|
||||
let mut cfg = make_config(&repo, 4096, None).await;
|
||||
cfg.cwd = nested;
|
||||
|
||||
let res = get_user_instructions(&cfg, None)
|
||||
@@ -356,7 +354,7 @@ mod tests {
|
||||
let tmp = tempfile::tempdir().expect("tempdir");
|
||||
fs::write(tmp.path().join("AGENTS.md"), "something").unwrap();
|
||||
|
||||
let res = get_user_instructions(&make_config(&tmp, 0, None), None).await;
|
||||
let res = get_user_instructions(&make_config(&tmp, 0, None).await, None).await;
|
||||
assert!(
|
||||
res.is_none(),
|
||||
"With limit 0 the function should return None"
|
||||
@@ -372,7 +370,7 @@ mod tests {
|
||||
|
||||
const INSTRUCTIONS: &str = "base instructions";
|
||||
|
||||
let res = get_user_instructions(&make_config(&tmp, 4096, Some(INSTRUCTIONS)), None)
|
||||
let res = get_user_instructions(&make_config(&tmp, 4096, Some(INSTRUCTIONS)).await, None)
|
||||
.await
|
||||
.expect("should produce a combined instruction string");
|
||||
|
||||
@@ -389,7 +387,8 @@ mod tests {
|
||||
|
||||
const INSTRUCTIONS: &str = "some instructions";
|
||||
|
||||
let res = get_user_instructions(&make_config(&tmp, 4096, Some(INSTRUCTIONS)), None).await;
|
||||
let res =
|
||||
get_user_instructions(&make_config(&tmp, 4096, Some(INSTRUCTIONS)).await, None).await;
|
||||
|
||||
assert_eq!(res, Some(INSTRUCTIONS.to_string()));
|
||||
}
|
||||
@@ -415,7 +414,7 @@ mod tests {
|
||||
std::fs::create_dir_all(&nested).unwrap();
|
||||
fs::write(nested.join("AGENTS.md"), "crate doc").unwrap();
|
||||
|
||||
let mut cfg = make_config(&repo, 4096, None);
|
||||
let mut cfg = make_config(&repo, 4096, None).await;
|
||||
cfg.cwd = nested;
|
||||
|
||||
let res = get_user_instructions(&cfg, None)
|
||||
@@ -431,7 +430,7 @@ mod tests {
|
||||
fs::write(tmp.path().join(DEFAULT_PROJECT_DOC_FILENAME), "versioned").unwrap();
|
||||
fs::write(tmp.path().join(LOCAL_PROJECT_DOC_FILENAME), "local").unwrap();
|
||||
|
||||
let cfg = make_config(&tmp, 4096, None);
|
||||
let cfg = make_config(&tmp, 4096, None).await;
|
||||
|
||||
let res = get_user_instructions(&cfg, None)
|
||||
.await
|
||||
@@ -453,7 +452,7 @@ mod tests {
|
||||
let tmp = tempfile::tempdir().expect("tempdir");
|
||||
fs::write(tmp.path().join("EXAMPLE.md"), "example instructions").unwrap();
|
||||
|
||||
let cfg = make_config_with_fallback(&tmp, 4096, None, &["EXAMPLE.md"]);
|
||||
let cfg = make_config_with_fallback(&tmp, 4096, None, &["EXAMPLE.md"]).await;
|
||||
|
||||
let res = get_user_instructions(&cfg, None)
|
||||
.await
|
||||
@@ -469,7 +468,7 @@ mod tests {
|
||||
fs::write(tmp.path().join("AGENTS.md"), "primary").unwrap();
|
||||
fs::write(tmp.path().join("EXAMPLE.md"), "secondary").unwrap();
|
||||
|
||||
let cfg = make_config_with_fallback(&tmp, 4096, None, &["EXAMPLE.md", ".example.md"]);
|
||||
let cfg = make_config_with_fallback(&tmp, 4096, None, &["EXAMPLE.md", ".example.md"]).await;
|
||||
|
||||
let res = get_user_instructions(&cfg, None)
|
||||
.await
|
||||
@@ -493,7 +492,7 @@ mod tests {
|
||||
let tmp = tempfile::tempdir().expect("tempdir");
|
||||
fs::write(tmp.path().join("AGENTS.md"), "base doc").unwrap();
|
||||
|
||||
let cfg = make_config(&tmp, 4096, None);
|
||||
let cfg = make_config(&tmp, 4096, None).await;
|
||||
create_skill(
|
||||
cfg.codex_home.clone(),
|
||||
"pdf-processing",
|
||||
@@ -524,7 +523,7 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn skills_render_without_project_doc() {
|
||||
let tmp = tempfile::tempdir().expect("tempdir");
|
||||
let cfg = make_config(&tmp, 4096, None);
|
||||
let cfg = make_config(&tmp, 4096, None).await;
|
||||
create_skill(cfg.codex_home.clone(), "linting", "run clippy");
|
||||
|
||||
let skills = load_skills(&cfg);
|
||||
|
||||
@@ -302,21 +302,19 @@ fn extract_frontmatter(contents: &str) -> Option<String> {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::config::ConfigOverrides;
|
||||
use crate::config::ConfigToml;
|
||||
use crate::config::ConfigBuilder;
|
||||
use codex_protocol::protocol::SkillScope;
|
||||
use pretty_assertions::assert_eq;
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
use tempfile::TempDir;
|
||||
|
||||
fn make_config(codex_home: &TempDir) -> Config {
|
||||
let mut config = Config::load_from_base_config_with_overrides(
|
||||
ConfigToml::default(),
|
||||
ConfigOverrides::default(),
|
||||
codex_home.path().to_path_buf(),
|
||||
)
|
||||
.expect("defaults for test should always succeed");
|
||||
async fn make_config(codex_home: &TempDir) -> Config {
|
||||
let mut config = ConfigBuilder::default()
|
||||
.codex_home(codex_home.path().to_path_buf())
|
||||
.build()
|
||||
.await
|
||||
.expect("defaults for test should always succeed");
|
||||
|
||||
config.cwd = codex_home.path().to_path_buf();
|
||||
config
|
||||
@@ -352,11 +350,11 @@ mod tests {
|
||||
path
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn loads_valid_skill() {
|
||||
#[tokio::test]
|
||||
async fn loads_valid_skill() {
|
||||
let codex_home = tempfile::tempdir().expect("tempdir");
|
||||
write_skill(&codex_home, "demo", "demo-skill", "does things\ncarefully");
|
||||
let cfg = make_config(&codex_home);
|
||||
let cfg = make_config(&codex_home).await;
|
||||
|
||||
let outcome = load_skills(&cfg);
|
||||
assert!(
|
||||
@@ -376,15 +374,15 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn loads_short_description_from_metadata() {
|
||||
#[tokio::test]
|
||||
async fn loads_short_description_from_metadata() {
|
||||
let codex_home = tempfile::tempdir().expect("tempdir");
|
||||
let skill_dir = codex_home.path().join("skills/demo");
|
||||
fs::create_dir_all(&skill_dir).unwrap();
|
||||
let contents = "---\nname: demo-skill\ndescription: long description\nmetadata:\n short-description: short summary\n---\n\n# Body\n";
|
||||
fs::write(skill_dir.join(SKILLS_FILENAME), contents).unwrap();
|
||||
|
||||
let cfg = make_config(&codex_home);
|
||||
let cfg = make_config(&codex_home).await;
|
||||
let outcome = load_skills(&cfg);
|
||||
assert!(
|
||||
outcome.errors.is_empty(),
|
||||
@@ -398,8 +396,8 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn enforces_short_description_length_limits() {
|
||||
#[tokio::test]
|
||||
async fn enforces_short_description_length_limits() {
|
||||
let codex_home = tempfile::tempdir().expect("tempdir");
|
||||
let skill_dir = codex_home.path().join("skills/demo");
|
||||
fs::create_dir_all(&skill_dir).unwrap();
|
||||
@@ -409,7 +407,7 @@ mod tests {
|
||||
);
|
||||
fs::write(skill_dir.join(SKILLS_FILENAME), contents).unwrap();
|
||||
|
||||
let cfg = make_config(&codex_home);
|
||||
let cfg = make_config(&codex_home).await;
|
||||
let outcome = load_skills(&cfg);
|
||||
assert_eq!(outcome.skills.len(), 0);
|
||||
assert_eq!(outcome.errors.len(), 1);
|
||||
@@ -422,8 +420,8 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn skips_hidden_and_invalid() {
|
||||
#[tokio::test]
|
||||
async fn skips_hidden_and_invalid() {
|
||||
let codex_home = tempfile::tempdir().expect("tempdir");
|
||||
let hidden_dir = codex_home.path().join("skills/.hidden");
|
||||
fs::create_dir_all(&hidden_dir).unwrap();
|
||||
@@ -438,7 +436,7 @@ mod tests {
|
||||
fs::create_dir_all(&invalid_dir).unwrap();
|
||||
fs::write(invalid_dir.join(SKILLS_FILENAME), "---\nname: bad").unwrap();
|
||||
|
||||
let cfg = make_config(&codex_home);
|
||||
let cfg = make_config(&codex_home).await;
|
||||
let outcome = load_skills(&cfg);
|
||||
assert_eq!(outcome.skills.len(), 0);
|
||||
assert_eq!(outcome.errors.len(), 1);
|
||||
@@ -450,12 +448,12 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn enforces_length_limits() {
|
||||
#[tokio::test]
|
||||
async fn enforces_length_limits() {
|
||||
let codex_home = tempfile::tempdir().expect("tempdir");
|
||||
let max_desc = "\u{1F4A1}".repeat(MAX_DESCRIPTION_LEN);
|
||||
write_skill(&codex_home, "max-len", "max-len", &max_desc);
|
||||
let cfg = make_config(&codex_home);
|
||||
let cfg = make_config(&codex_home).await;
|
||||
|
||||
let outcome = load_skills(&cfg);
|
||||
assert!(
|
||||
@@ -476,8 +474,8 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn loads_skills_from_repo_root() {
|
||||
#[tokio::test]
|
||||
async fn loads_skills_from_repo_root() {
|
||||
let codex_home = tempfile::tempdir().expect("tempdir");
|
||||
let repo_dir = tempfile::tempdir().expect("tempdir");
|
||||
|
||||
@@ -493,7 +491,7 @@ mod tests {
|
||||
.join(REPO_ROOT_CONFIG_DIR_NAME)
|
||||
.join(SKILLS_DIR_NAME);
|
||||
write_skill_at(&skills_root, "repo", "repo-skill", "from repo");
|
||||
let mut cfg = make_config(&codex_home);
|
||||
let mut cfg = make_config(&codex_home).await;
|
||||
cfg.cwd = repo_dir.path().to_path_buf();
|
||||
let repo_root = normalize_path(&skills_root).unwrap_or_else(|_| skills_root.clone());
|
||||
|
||||
@@ -509,8 +507,8 @@ mod tests {
|
||||
assert!(skill.path.starts_with(&repo_root));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn loads_skills_from_nearest_codex_dir_under_repo_root() {
|
||||
#[tokio::test]
|
||||
async fn loads_skills_from_nearest_codex_dir_under_repo_root() {
|
||||
let codex_home = tempfile::tempdir().expect("tempdir");
|
||||
let repo_dir = tempfile::tempdir().expect("tempdir");
|
||||
|
||||
@@ -544,7 +542,7 @@ mod tests {
|
||||
"from nested",
|
||||
);
|
||||
|
||||
let mut cfg = make_config(&codex_home);
|
||||
let mut cfg = make_config(&codex_home).await;
|
||||
cfg.cwd = nested_dir;
|
||||
|
||||
let outcome = load_skills(&cfg);
|
||||
@@ -557,8 +555,8 @@ mod tests {
|
||||
assert_eq!(outcome.skills[0].name, "nested-skill");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn loads_skills_from_codex_dir_when_not_git_repo() {
|
||||
#[tokio::test]
|
||||
async fn loads_skills_from_codex_dir_when_not_git_repo() {
|
||||
let codex_home = tempfile::tempdir().expect("tempdir");
|
||||
let work_dir = tempfile::tempdir().expect("tempdir");
|
||||
|
||||
@@ -572,7 +570,7 @@ mod tests {
|
||||
"from cwd",
|
||||
);
|
||||
|
||||
let mut cfg = make_config(&codex_home);
|
||||
let mut cfg = make_config(&codex_home).await;
|
||||
cfg.cwd = work_dir.path().to_path_buf();
|
||||
|
||||
let outcome = load_skills(&cfg);
|
||||
@@ -586,8 +584,8 @@ mod tests {
|
||||
assert_eq!(outcome.skills[0].scope, SkillScope::Repo);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deduplicates_by_name_preferring_repo_over_user() {
|
||||
#[tokio::test]
|
||||
async fn deduplicates_by_name_preferring_repo_over_user() {
|
||||
let codex_home = tempfile::tempdir().expect("tempdir");
|
||||
let repo_dir = tempfile::tempdir().expect("tempdir");
|
||||
|
||||
@@ -609,7 +607,7 @@ mod tests {
|
||||
"from repo",
|
||||
);
|
||||
|
||||
let mut cfg = make_config(&codex_home);
|
||||
let mut cfg = make_config(&codex_home).await;
|
||||
cfg.cwd = repo_dir.path().to_path_buf();
|
||||
|
||||
let outcome = load_skills(&cfg);
|
||||
@@ -623,14 +621,14 @@ mod tests {
|
||||
assert_eq!(outcome.skills[0].scope, SkillScope::Repo);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn loads_system_skills_with_lowest_priority() {
|
||||
#[tokio::test]
|
||||
async fn loads_system_skills_with_lowest_priority() {
|
||||
let codex_home = tempfile::tempdir().expect("tempdir");
|
||||
|
||||
write_system_skill(&codex_home, "system", "dupe-skill", "from system");
|
||||
write_skill(&codex_home, "user", "dupe-skill", "from user");
|
||||
|
||||
let cfg = make_config(&codex_home);
|
||||
let cfg = make_config(&codex_home).await;
|
||||
let outcome = load_skills(&cfg);
|
||||
assert!(
|
||||
outcome.errors.is_empty(),
|
||||
@@ -642,8 +640,8 @@ mod tests {
|
||||
assert_eq!(outcome.skills[0].scope, SkillScope::User);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn repo_skills_search_does_not_escape_repo_root() {
|
||||
#[tokio::test]
|
||||
async fn repo_skills_search_does_not_escape_repo_root() {
|
||||
let codex_home = tempfile::tempdir().expect("tempdir");
|
||||
let outer_dir = tempfile::tempdir().expect("tempdir");
|
||||
let repo_dir = outer_dir.path().join("repo");
|
||||
@@ -666,7 +664,7 @@ mod tests {
|
||||
.expect("git init");
|
||||
assert!(status.success(), "git init failed");
|
||||
|
||||
let mut cfg = make_config(&codex_home);
|
||||
let mut cfg = make_config(&codex_home).await;
|
||||
cfg.cwd = repo_dir;
|
||||
|
||||
let outcome = load_skills(&cfg);
|
||||
@@ -678,8 +676,8 @@ mod tests {
|
||||
assert_eq!(outcome.skills.len(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn loads_skills_when_cwd_is_file_in_repo() {
|
||||
#[tokio::test]
|
||||
async fn loads_skills_when_cwd_is_file_in_repo() {
|
||||
let codex_home = tempfile::tempdir().expect("tempdir");
|
||||
let repo_dir = tempfile::tempdir().expect("tempdir");
|
||||
|
||||
@@ -702,7 +700,7 @@ mod tests {
|
||||
let file_path = repo_dir.path().join("some-file.txt");
|
||||
fs::write(&file_path, "contents").unwrap();
|
||||
|
||||
let mut cfg = make_config(&codex_home);
|
||||
let mut cfg = make_config(&codex_home).await;
|
||||
cfg.cwd = file_path;
|
||||
|
||||
let outcome = load_skills(&cfg);
|
||||
@@ -716,8 +714,8 @@ mod tests {
|
||||
assert_eq!(outcome.skills[0].scope, SkillScope::Repo);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn non_git_repo_skills_search_does_not_walk_parents() {
|
||||
#[tokio::test]
|
||||
async fn non_git_repo_skills_search_does_not_walk_parents() {
|
||||
let codex_home = tempfile::tempdir().expect("tempdir");
|
||||
let outer_dir = tempfile::tempdir().expect("tempdir");
|
||||
let nested_dir = outer_dir.path().join("nested/inner");
|
||||
@@ -733,7 +731,7 @@ mod tests {
|
||||
"from outer",
|
||||
);
|
||||
|
||||
let mut cfg = make_config(&codex_home);
|
||||
let mut cfg = make_config(&codex_home).await;
|
||||
cfg.cwd = nested_dir;
|
||||
|
||||
let outcome = load_skills(&cfg);
|
||||
@@ -745,14 +743,14 @@ mod tests {
|
||||
assert_eq!(outcome.skills.len(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn loads_skills_from_system_cache_when_present() {
|
||||
#[tokio::test]
|
||||
async fn loads_skills_from_system_cache_when_present() {
|
||||
let codex_home = tempfile::tempdir().expect("tempdir");
|
||||
let work_dir = tempfile::tempdir().expect("tempdir");
|
||||
|
||||
write_system_skill(&codex_home, "system", "system-skill", "from system");
|
||||
|
||||
let mut cfg = make_config(&codex_home);
|
||||
let mut cfg = make_config(&codex_home).await;
|
||||
cfg.cwd = work_dir.path().to_path_buf();
|
||||
|
||||
let outcome = load_skills(&cfg);
|
||||
@@ -766,15 +764,15 @@ mod tests {
|
||||
assert_eq!(outcome.skills[0].scope, SkillScope::System);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deduplicates_by_name_preferring_user_over_system() {
|
||||
#[tokio::test]
|
||||
async fn deduplicates_by_name_preferring_user_over_system() {
|
||||
let codex_home = tempfile::tempdir().expect("tempdir");
|
||||
let work_dir = tempfile::tempdir().expect("tempdir");
|
||||
|
||||
write_skill(&codex_home, "user", "dupe-skill", "from user");
|
||||
write_system_skill(&codex_home, "system", "dupe-skill", "from system");
|
||||
|
||||
let mut cfg = make_config(&codex_home);
|
||||
let mut cfg = make_config(&codex_home).await;
|
||||
cfg.cwd = work_dir.path().to_path_buf();
|
||||
|
||||
let outcome = load_skills(&cfg);
|
||||
@@ -788,8 +786,8 @@ mod tests {
|
||||
assert_eq!(outcome.skills[0].scope, SkillScope::User);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deduplicates_by_name_preferring_repo_over_system() {
|
||||
#[tokio::test]
|
||||
async fn deduplicates_by_name_preferring_repo_over_system() {
|
||||
let codex_home = tempfile::tempdir().expect("tempdir");
|
||||
let repo_dir = tempfile::tempdir().expect("tempdir");
|
||||
|
||||
@@ -811,7 +809,7 @@ mod tests {
|
||||
);
|
||||
write_system_skill(&codex_home, "system", "dupe-skill", "from system");
|
||||
|
||||
let mut cfg = make_config(&codex_home);
|
||||
let mut cfg = make_config(&codex_home).await;
|
||||
cfg.cwd = repo_dir.path().to_path_buf();
|
||||
|
||||
let outcome = load_skills(&cfg);
|
||||
|
||||
@@ -358,9 +358,9 @@ mod tests {
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn shell_command_handler_to_exec_params_uses_session_shell_and_turn_context() {
|
||||
let (session, turn_context) = make_session_and_context();
|
||||
#[tokio::test]
|
||||
async fn shell_command_handler_to_exec_params_uses_session_shell_and_turn_context() {
|
||||
let (session, turn_context) = make_session_and_context().await;
|
||||
|
||||
let command = "echo hello".to_string();
|
||||
let workdir = Some("subdir".to_string());
|
||||
|
||||
@@ -187,8 +187,8 @@ mod tests {
|
||||
|
||||
use super::session::OutputBufferState;
|
||||
|
||||
fn test_session_and_turn() -> (Arc<Session>, Arc<TurnContext>) {
|
||||
let (session, mut turn) = make_session_and_context();
|
||||
async fn test_session_and_turn() -> (Arc<Session>, Arc<TurnContext>) {
|
||||
let (session, mut turn) = make_session_and_context().await;
|
||||
turn.approval_policy = AskForApproval::Never;
|
||||
turn.sandbox_policy = SandboxPolicy::DangerFullAccess;
|
||||
(Arc::new(session), Arc::new(turn))
|
||||
@@ -266,7 +266,7 @@ mod tests {
|
||||
async fn unified_exec_persists_across_requests() -> anyhow::Result<()> {
|
||||
skip_if_sandbox!(Ok(()));
|
||||
|
||||
let (session, turn) = test_session_and_turn();
|
||||
let (session, turn) = test_session_and_turn().await;
|
||||
|
||||
let open_shell = exec_command(&session, &turn, "bash -i", 2_500).await?;
|
||||
let process_id = open_shell
|
||||
@@ -302,7 +302,7 @@ mod tests {
|
||||
async fn multi_unified_exec_sessions() -> anyhow::Result<()> {
|
||||
skip_if_sandbox!(Ok(()));
|
||||
|
||||
let (session, turn) = test_session_and_turn();
|
||||
let (session, turn) = test_session_and_turn().await;
|
||||
|
||||
let shell_a = exec_command(&session, &turn, "bash -i", 2_500).await?;
|
||||
let session_a = shell_a
|
||||
@@ -354,7 +354,7 @@ mod tests {
|
||||
async fn unified_exec_timeouts() -> anyhow::Result<()> {
|
||||
skip_if_sandbox!(Ok(()));
|
||||
|
||||
let (session, turn) = test_session_and_turn();
|
||||
let (session, turn) = test_session_and_turn().await;
|
||||
|
||||
let open_shell = exec_command(&session, &turn, "bash -i", 2_500).await?;
|
||||
let process_id = open_shell
|
||||
@@ -398,7 +398,7 @@ mod tests {
|
||||
#[tokio::test]
|
||||
#[ignore] // Ignored while we have a better way to test this.
|
||||
async fn requests_with_large_timeout_are_capped() -> anyhow::Result<()> {
|
||||
let (session, turn) = test_session_and_turn();
|
||||
let (session, turn) = test_session_and_turn().await;
|
||||
|
||||
let result = exec_command(&session, &turn, "echo codex", 120_000).await?;
|
||||
|
||||
@@ -411,7 +411,7 @@ mod tests {
|
||||
#[tokio::test]
|
||||
#[ignore] // Ignored while we have a better way to test this.
|
||||
async fn completed_commands_do_not_persist_sessions() -> anyhow::Result<()> {
|
||||
let (session, turn) = test_session_and_turn();
|
||||
let (session, turn) = test_session_and_turn().await;
|
||||
let result = exec_command(&session, &turn, "echo codex", 2_500).await?;
|
||||
|
||||
assert!(
|
||||
@@ -438,7 +438,7 @@ mod tests {
|
||||
async fn reusing_completed_session_returns_unknown_session() -> anyhow::Result<()> {
|
||||
skip_if_sandbox!(Ok(()));
|
||||
|
||||
let (session, turn) = test_session_and_turn();
|
||||
let (session, turn) = test_session_and_turn().await;
|
||||
|
||||
let open_shell = exec_command(&session, &turn, "bash -i", 2_500).await?;
|
||||
let process_id = open_shell
|
||||
|
||||
@@ -80,8 +80,8 @@ mod tests {
|
||||
assert!(!is_user_shell_command_text("echo hi"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn formats_basic_record() {
|
||||
#[tokio::test]
|
||||
async fn formats_basic_record() {
|
||||
let exec_output = ExecToolCallOutput {
|
||||
exit_code: 0,
|
||||
stdout: StreamOutput::new("hi".to_string()),
|
||||
@@ -90,7 +90,7 @@ mod tests {
|
||||
duration: Duration::from_secs(1),
|
||||
timed_out: false,
|
||||
};
|
||||
let (_, turn_context) = make_session_and_context();
|
||||
let (_, turn_context) = make_session_and_context().await;
|
||||
let item = user_shell_command_record_item("echo hi", &exec_output, &turn_context);
|
||||
let ResponseItem::Message { content, .. } = item else {
|
||||
panic!("expected message");
|
||||
@@ -104,8 +104,8 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn uses_aggregated_output_over_streams() {
|
||||
#[tokio::test]
|
||||
async fn uses_aggregated_output_over_streams() {
|
||||
let exec_output = ExecToolCallOutput {
|
||||
exit_code: 42,
|
||||
stdout: StreamOutput::new("stdout-only".to_string()),
|
||||
@@ -114,7 +114,7 @@ mod tests {
|
||||
duration: Duration::from_millis(120),
|
||||
timed_out: false,
|
||||
};
|
||||
let (_, turn_context) = make_session_and_context();
|
||||
let (_, turn_context) = make_session_and_context().await;
|
||||
let record = format_user_shell_command_record("false", &exec_output, &turn_context);
|
||||
assert_eq!(
|
||||
record,
|
||||
|
||||
Reference in New Issue
Block a user