mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
Make AGENTS.md discovery FS-aware (#15826)
## Summary - make AGENTS.md discovery and loading fully FS-aware and remove the non-FS discover helper - migrate remote-aware codex-core tests to use TestEnv workspace setup instead of syncing a local workspace copy - add AGENTS.md corner-case coverage, including directory fallbacks and remote-aware integration coverage ## Testing - cargo test -p codex-core project_doc -- --nocapture - cargo test -p codex-core hierarchical_agents -- --nocapture - cargo test -p codex-core agents_md -- --nocapture - cargo test -p codex-tui status -- --nocapture - cargo test -p codex-tui-app-server status -- --nocapture - just fix - just fmt - just bazel-lock-update - just bazel-lock-check - just argument-comment-lint - remote Linux executor tests in progress via scripts/test-remote-env.sh
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
use std::future::Future;
|
||||
use std::mem::swap;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
@@ -34,12 +35,12 @@ use codex_protocol::protocol::SessionConfiguredEvent;
|
||||
use codex_protocol::protocol::SessionSource;
|
||||
use codex_protocol::user_input::UserInput;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
use futures::future::BoxFuture;
|
||||
use serde_json::Value;
|
||||
use tempfile::TempDir;
|
||||
use wiremock::MockServer;
|
||||
|
||||
use crate::PathBufExt;
|
||||
use crate::PathExt;
|
||||
use crate::RemoteEnvConfig;
|
||||
use crate::TempDirExt;
|
||||
use crate::get_remote_test_env;
|
||||
@@ -55,6 +56,8 @@ use wiremock::matchers::path_regex;
|
||||
|
||||
type ConfigMutator = dyn FnOnce(&mut Config) + Send;
|
||||
type PreBuildHook = dyn FnOnce(&Path) + Send + 'static;
|
||||
type WorkspaceSetup = dyn FnOnce(AbsolutePathBuf, Arc<dyn ExecutorFileSystem>) -> BoxFuture<'static, Result<()>>
|
||||
+ Send;
|
||||
const TEST_MODEL_WITH_EXPERIMENTAL_TOOLS: &str = "test-gpt-5.1-codex";
|
||||
const REMOTE_EXEC_SERVER_START_TIMEOUT: Duration = Duration::from_secs(5);
|
||||
const REMOTE_EXEC_SERVER_POLL_INTERVAL: Duration = Duration::from_millis(25);
|
||||
@@ -97,24 +100,28 @@ impl RemoteExecServerProcess {
|
||||
#[derive(Debug)]
|
||||
pub struct TestEnv {
|
||||
environment: codex_exec_server::Environment,
|
||||
cwd: PathBuf,
|
||||
_local_cwd_temp_dir: Option<TempDir>,
|
||||
cwd: AbsolutePathBuf,
|
||||
local_cwd_temp_dir: Option<Arc<TempDir>>,
|
||||
_remote_exec_server_process: Option<RemoteExecServerProcess>,
|
||||
}
|
||||
|
||||
impl TestEnv {
|
||||
pub async fn local() -> Result<Self> {
|
||||
let local_cwd_temp_dir = TempDir::new()?;
|
||||
let cwd = local_cwd_temp_dir.path().to_path_buf();
|
||||
let local_cwd_temp_dir = Arc::new(TempDir::new()?);
|
||||
let cwd = local_cwd_temp_dir.abs();
|
||||
let environment = codex_exec_server::Environment::create(/*exec_server_url*/ None).await?;
|
||||
Ok(Self {
|
||||
environment,
|
||||
cwd,
|
||||
_local_cwd_temp_dir: Some(local_cwd_temp_dir),
|
||||
local_cwd_temp_dir: Some(local_cwd_temp_dir),
|
||||
_remote_exec_server_process: None,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn cwd(&self) -> &AbsolutePathBuf {
|
||||
&self.cwd
|
||||
}
|
||||
|
||||
pub fn environment(&self) -> &codex_exec_server::Environment {
|
||||
&self.environment
|
||||
}
|
||||
@@ -122,6 +129,10 @@ impl TestEnv {
|
||||
pub fn exec_server_url(&self) -> Option<&str> {
|
||||
self.environment.exec_server_url()
|
||||
}
|
||||
|
||||
fn local_cwd_temp_dir(&self) -> Option<Arc<TempDir>> {
|
||||
self.local_cwd_temp_dir.clone()
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn test_env() -> Result<TestEnv> {
|
||||
@@ -134,16 +145,13 @@ pub async fn test_env() -> Result<TestEnv> {
|
||||
let cwd = remote_aware_cwd_path();
|
||||
environment
|
||||
.get_filesystem()
|
||||
.create_directory(
|
||||
&absolute_path(&cwd)?,
|
||||
CreateDirectoryOptions { recursive: true },
|
||||
)
|
||||
.create_directory(&cwd, CreateDirectoryOptions { recursive: true })
|
||||
.await?;
|
||||
remote_process.process.register_cleanup_path(&cwd);
|
||||
remote_process.process.register_cleanup_path(cwd.as_path());
|
||||
Ok(TestEnv {
|
||||
environment,
|
||||
cwd,
|
||||
_local_cwd_temp_dir: None,
|
||||
local_cwd_temp_dir: None,
|
||||
_remote_exec_server_process: Some(remote_process.process),
|
||||
})
|
||||
}
|
||||
@@ -201,11 +209,12 @@ echo $!"
|
||||
})
|
||||
}
|
||||
|
||||
fn remote_aware_cwd_path() -> PathBuf {
|
||||
fn remote_aware_cwd_path() -> AbsolutePathBuf {
|
||||
PathBuf::from(format!(
|
||||
"/tmp/codex-core-test-cwd-{}",
|
||||
remote_exec_server_instance_id()
|
||||
))
|
||||
.abs()
|
||||
}
|
||||
|
||||
fn wait_for_remote_listen_url(container_name: &str, stdout_path: &str) -> Result<String> {
|
||||
@@ -299,10 +308,6 @@ fn docker_command_capture_stdout<const N: usize>(args: [&str; N]) -> Result<Stri
|
||||
String::from_utf8(output.stdout).context("docker stdout must be utf-8")
|
||||
}
|
||||
|
||||
fn absolute_path(path: &Path) -> Result<AbsolutePathBuf> {
|
||||
Ok(path.abs())
|
||||
}
|
||||
|
||||
/// A collection of different ways the model can output an apply_patch call
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum ApplyPatchModelOutput {
|
||||
@@ -326,6 +331,7 @@ pub struct TestCodexBuilder {
|
||||
config_mutators: Vec<Box<ConfigMutator>>,
|
||||
auth: CodexAuth,
|
||||
pre_build_hooks: Vec<Box<PreBuildHook>>,
|
||||
workspace_setups: Vec<Box<WorkspaceSetup>>,
|
||||
home: Option<Arc<TempDir>>,
|
||||
user_shell_override: Option<Shell>,
|
||||
}
|
||||
@@ -359,6 +365,16 @@ impl TestCodexBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_workspace_setup<F, Fut>(mut self, setup: F) -> Self
|
||||
where
|
||||
F: FnOnce(AbsolutePathBuf, Arc<dyn ExecutorFileSystem>) -> Fut + Send + 'static,
|
||||
Fut: Future<Output = Result<()>> + Send + 'static,
|
||||
{
|
||||
self.workspace_setups
|
||||
.push(Box::new(move |cwd, fs| Box::pin(setup(cwd, fs))));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_home(mut self, home: Arc<TempDir>) -> Self {
|
||||
self.home = Some(home);
|
||||
self
|
||||
@@ -382,25 +398,24 @@ impl TestCodexBuilder {
|
||||
Some(home) => home,
|
||||
None => Arc::new(TempDir::new()?),
|
||||
};
|
||||
Box::pin(self.build_with_home(server, home, /*resume_from*/ None)).await
|
||||
let base_url = format!("{}/v1", server.uri());
|
||||
let test_env = TestEnv::local().await?;
|
||||
Box::pin(self.build_with_home_and_base_url(base_url, home, /*resume_from*/ None, test_env))
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn build_remote_aware(
|
||||
&mut self,
|
||||
server: &wiremock::MockServer,
|
||||
) -> anyhow::Result<TestCodex> {
|
||||
let test_env = test_env().await?;
|
||||
let home = match self.home.clone() {
|
||||
Some(home) => home,
|
||||
None => Arc::new(TempDir::new()?),
|
||||
};
|
||||
let base_url = format!("{}/v1", server.uri());
|
||||
let cwd = test_env.cwd.to_path_buf();
|
||||
self.config_mutators.push(Box::new(move |config| {
|
||||
config.cwd = cwd.abs();
|
||||
}));
|
||||
let (config, cwd) = self.prepare_config(base_url, &home).await?;
|
||||
Box::pin(self.build_from_config(config, cwd, home, /*resume_from*/ None, test_env)).await
|
||||
let test_env = test_env().await?;
|
||||
Box::pin(self.build_with_home_and_base_url(base_url, home, /*resume_from*/ None, test_env))
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn build_with_streaming_server(
|
||||
@@ -412,10 +427,12 @@ impl TestCodexBuilder {
|
||||
Some(home) => home,
|
||||
None => Arc::new(TempDir::new()?),
|
||||
};
|
||||
let test_env = TestEnv::local().await?;
|
||||
Box::pin(self.build_with_home_and_base_url(
|
||||
format!("{base_url}/v1"),
|
||||
home,
|
||||
/*resume_from*/ None,
|
||||
test_env,
|
||||
))
|
||||
.await
|
||||
}
|
||||
@@ -435,7 +452,9 @@ impl TestCodexBuilder {
|
||||
config.model_provider.supports_websockets = true;
|
||||
config.experimental_realtime_ws_model = Some("realtime-test-model".to_string());
|
||||
}));
|
||||
Box::pin(self.build_with_home_and_base_url(base_url, home, /*resume_from*/ None)).await
|
||||
let test_env = TestEnv::local().await?;
|
||||
Box::pin(self.build_with_home_and_base_url(base_url, home, /*resume_from*/ None, test_env))
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn resume(
|
||||
@@ -443,19 +462,10 @@ impl TestCodexBuilder {
|
||||
server: &wiremock::MockServer,
|
||||
home: Arc<TempDir>,
|
||||
rollout_path: PathBuf,
|
||||
) -> anyhow::Result<TestCodex> {
|
||||
Box::pin(self.build_with_home(server, home, Some(rollout_path))).await
|
||||
}
|
||||
|
||||
async fn build_with_home(
|
||||
&mut self,
|
||||
server: &wiremock::MockServer,
|
||||
home: Arc<TempDir>,
|
||||
resume_from: Option<PathBuf>,
|
||||
) -> anyhow::Result<TestCodex> {
|
||||
let base_url = format!("{}/v1", server.uri());
|
||||
let (config, cwd) = self.prepare_config(base_url, &home).await?;
|
||||
Box::pin(self.build_from_config(config, cwd, home, resume_from, TestEnv::local().await?))
|
||||
let test_env = TestEnv::local().await?;
|
||||
Box::pin(self.build_with_home_and_base_url(base_url, home, Some(rollout_path), test_env))
|
||||
.await
|
||||
}
|
||||
|
||||
@@ -464,10 +474,30 @@ impl TestCodexBuilder {
|
||||
base_url: String,
|
||||
home: Arc<TempDir>,
|
||||
resume_from: Option<PathBuf>,
|
||||
test_env: TestEnv,
|
||||
) -> anyhow::Result<TestCodex> {
|
||||
let (config, cwd) = self.prepare_config(base_url, &home).await?;
|
||||
Box::pin(self.build_from_config(config, cwd, home, resume_from, TestEnv::local().await?))
|
||||
.await
|
||||
let (config, fallback_cwd) = self
|
||||
.prepare_config(base_url, &home, test_env.cwd().clone())
|
||||
.await?;
|
||||
let environment_manager = Arc::new(codex_exec_server::EnvironmentManager::new(
|
||||
test_env.exec_server_url().map(str::to_owned),
|
||||
));
|
||||
let file_system = test_env.environment().get_filesystem();
|
||||
let mut workspace_setups = vec![];
|
||||
swap(&mut self.workspace_setups, &mut workspace_setups);
|
||||
for setup in workspace_setups {
|
||||
setup(config.cwd.clone(), Arc::clone(&file_system)).await?;
|
||||
}
|
||||
let cwd = test_env.local_cwd_temp_dir().unwrap_or(fallback_cwd);
|
||||
Box::pin(self.build_from_config(
|
||||
config,
|
||||
cwd,
|
||||
home,
|
||||
resume_from,
|
||||
test_env,
|
||||
environment_manager,
|
||||
))
|
||||
.await
|
||||
}
|
||||
|
||||
async fn build_from_config(
|
||||
@@ -477,11 +507,9 @@ impl TestCodexBuilder {
|
||||
home: Arc<TempDir>,
|
||||
resume_from: Option<PathBuf>,
|
||||
test_env: TestEnv,
|
||||
environment_manager: Arc<codex_exec_server::EnvironmentManager>,
|
||||
) -> anyhow::Result<TestCodex> {
|
||||
let auth = self.auth.clone();
|
||||
let environment_manager = Arc::new(codex_exec_server::EnvironmentManager::new(
|
||||
test_env.exec_server_url().map(str::to_owned),
|
||||
));
|
||||
let thread_manager = if config.model_catalog.is_some() {
|
||||
ThreadManager::new(
|
||||
&config,
|
||||
@@ -553,6 +581,7 @@ impl TestCodexBuilder {
|
||||
&mut self,
|
||||
base_url: String,
|
||||
home: &TempDir,
|
||||
cwd_override: AbsolutePathBuf,
|
||||
) -> anyhow::Result<(Config, Arc<TempDir>)> {
|
||||
let model_provider = ModelProviderInfo {
|
||||
base_url: Some(base_url),
|
||||
@@ -563,7 +592,7 @@ impl TestCodexBuilder {
|
||||
};
|
||||
let cwd = Arc::new(TempDir::new()?);
|
||||
let mut config = load_default_config_for_test(home).await;
|
||||
config.cwd = cwd.abs();
|
||||
config.cwd = cwd_override;
|
||||
config.model_provider = model_provider;
|
||||
for hook in self.pre_build_hooks.drain(..) {
|
||||
hook(home.path());
|
||||
@@ -897,6 +926,7 @@ pub fn test_codex() -> TestCodexBuilder {
|
||||
config_mutators: vec![],
|
||||
auth: CodexAuth::from_api_key("dummy"),
|
||||
pre_build_hooks: vec![],
|
||||
workspace_setups: vec![],
|
||||
home: None,
|
||||
user_shell_override: None,
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ impl TestCodexExecBuilder {
|
||||
);
|
||||
cmd.current_dir(self.cwd.path())
|
||||
.env("CODEX_HOME", self.home.path())
|
||||
.env("CODEX_SQLITE_HOME", self.home.path())
|
||||
.env(CODEX_API_KEY_ENV_VAR, "dummy");
|
||||
cmd
|
||||
}
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
use anyhow::Result;
|
||||
use codex_exec_server::CreateDirectoryOptions;
|
||||
use core_test_support::responses::ev_completed;
|
||||
use core_test_support::responses::ev_response_created;
|
||||
use core_test_support::responses::mount_sse_once;
|
||||
use core_test_support::responses::sse;
|
||||
use core_test_support::responses::start_mock_server;
|
||||
use core_test_support::test_codex::TestCodexBuilder;
|
||||
use core_test_support::test_codex::test_codex;
|
||||
|
||||
async fn agents_instructions(mut builder: TestCodexBuilder) -> Result<String> {
|
||||
let server = start_mock_server().await;
|
||||
let resp_mock = mount_sse_once(
|
||||
&server,
|
||||
sse(vec![ev_response_created("resp1"), ev_completed("resp1")]),
|
||||
)
|
||||
.await;
|
||||
|
||||
let test = builder.build_remote_aware(&server).await?;
|
||||
test.submit_turn("hello").await?;
|
||||
|
||||
let request = resp_mock.single_request();
|
||||
request
|
||||
.message_input_texts("user")
|
||||
.into_iter()
|
||||
.find(|text| text.starts_with("# AGENTS.md instructions for "))
|
||||
.ok_or_else(|| anyhow::anyhow!("instructions message not found"))
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn agents_override_is_preferred_over_agents_md() -> Result<()> {
|
||||
let instructions =
|
||||
agents_instructions(test_codex().with_workspace_setup(|cwd, fs| async move {
|
||||
let agents_md = cwd.join("AGENTS.md").expect("absolute AGENTS.md path");
|
||||
let override_md = cwd
|
||||
.join("AGENTS.override.md")
|
||||
.expect("absolute AGENTS.override.md path");
|
||||
fs.write_file(&agents_md, b"base doc".to_vec()).await?;
|
||||
fs.write_file(&override_md, b"override doc".to_vec())
|
||||
.await?;
|
||||
Ok::<(), anyhow::Error>(())
|
||||
}))
|
||||
.await?;
|
||||
|
||||
assert!(
|
||||
instructions.contains("override doc"),
|
||||
"expected AGENTS.override.md contents: {instructions}"
|
||||
);
|
||||
assert!(
|
||||
!instructions.contains("base doc"),
|
||||
"expected AGENTS.md to be ignored when override exists: {instructions}"
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn configured_fallback_is_used_when_agents_candidate_is_directory() -> Result<()> {
|
||||
let instructions = agents_instructions(
|
||||
test_codex()
|
||||
.with_config(|config| {
|
||||
config.project_doc_fallback_filenames = vec!["WORKFLOW.md".to_string()];
|
||||
})
|
||||
.with_workspace_setup(|cwd, fs| async move {
|
||||
let agents_dir = cwd.join("AGENTS.md").expect("absolute AGENTS.md path");
|
||||
let fallback = cwd.join("WORKFLOW.md").expect("absolute WORKFLOW.md path");
|
||||
fs.create_directory(&agents_dir, CreateDirectoryOptions { recursive: true })
|
||||
.await?;
|
||||
fs.write_file(&fallback, b"fallback doc".to_vec()).await?;
|
||||
Ok::<(), anyhow::Error>(())
|
||||
}),
|
||||
)
|
||||
.await?;
|
||||
|
||||
assert!(
|
||||
instructions.contains("fallback doc"),
|
||||
"expected fallback doc contents: {instructions}"
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn agents_docs_are_concatenated_from_project_root_to_cwd() -> Result<()> {
|
||||
let instructions = agents_instructions(
|
||||
test_codex()
|
||||
.with_config(|config| {
|
||||
config.cwd = config
|
||||
.cwd
|
||||
.join("nested/workspace")
|
||||
.expect("absolute nested workspace path");
|
||||
})
|
||||
.with_workspace_setup(|cwd, fs| async move {
|
||||
let nested = cwd.clone();
|
||||
let root = nested
|
||||
.parent()
|
||||
.and_then(|parent| parent.parent())
|
||||
.expect("nested workspace should have a project root ancestor");
|
||||
let root_agents = root
|
||||
.join("AGENTS.md")
|
||||
.expect("absolute root AGENTS.md path");
|
||||
let git_marker = root.join(".git").expect("absolute .git path");
|
||||
let nested_agents = nested
|
||||
.join("AGENTS.md")
|
||||
.expect("absolute nested AGENTS.md path");
|
||||
|
||||
fs.create_directory(&nested, CreateDirectoryOptions { recursive: true })
|
||||
.await?;
|
||||
fs.write_file(&root_agents, b"root doc".to_vec()).await?;
|
||||
fs.write_file(&git_marker, b"gitdir: /tmp/mock-git-dir\n".to_vec())
|
||||
.await?;
|
||||
fs.write_file(&nested_agents, b"child doc".to_vec()).await?;
|
||||
Ok::<(), anyhow::Error>(())
|
||||
}),
|
||||
)
|
||||
.await?;
|
||||
|
||||
let root_pos = instructions
|
||||
.find("root doc")
|
||||
.expect("expected root doc in AGENTS instructions");
|
||||
let child_pos = instructions
|
||||
.find("child doc")
|
||||
.expect("expected child doc in AGENTS instructions");
|
||||
assert!(
|
||||
root_pos < child_pos,
|
||||
"expected root doc before child doc: {instructions}"
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -18,21 +18,22 @@ async fn hierarchical_agents_appends_to_project_doc_in_user_instructions() {
|
||||
)
|
||||
.await;
|
||||
|
||||
let mut builder = test_codex().with_config(|config| {
|
||||
config
|
||||
.features
|
||||
.enable(Feature::ChildAgentsMd)
|
||||
.expect("test config should allow feature update");
|
||||
std::fs::write(
|
||||
let mut builder = test_codex()
|
||||
.with_config(|config| {
|
||||
config
|
||||
.cwd
|
||||
.join("AGENTS.md")
|
||||
.expect("absolute AGENTS.md path"),
|
||||
"be nice",
|
||||
)
|
||||
.expect("write AGENTS.md");
|
||||
});
|
||||
let test = builder.build(&server).await.expect("build test codex");
|
||||
.features
|
||||
.enable(Feature::ChildAgentsMd)
|
||||
.expect("test config should allow feature update");
|
||||
})
|
||||
.with_workspace_setup(|cwd, fs| async move {
|
||||
let agents_md = cwd.join("AGENTS.md").expect("absolute AGENTS.md path");
|
||||
fs.write_file(&agents_md, b"be nice".to_vec()).await?;
|
||||
Ok::<(), anyhow::Error>(())
|
||||
});
|
||||
let test = builder
|
||||
.build_remote_aware(&server)
|
||||
.await
|
||||
.expect("build test codex");
|
||||
|
||||
test.submit_turn("hello").await.expect("submit turn");
|
||||
|
||||
@@ -73,7 +74,10 @@ async fn hierarchical_agents_emits_when_no_project_doc() {
|
||||
.enable(Feature::ChildAgentsMd)
|
||||
.expect("test config should allow feature update");
|
||||
});
|
||||
let test = builder.build(&server).await.expect("build test codex");
|
||||
let test = builder
|
||||
.build_remote_aware(&server)
|
||||
.await
|
||||
.expect("build test codex");
|
||||
|
||||
test.submit_turn("hello").await.expect("submit turn");
|
||||
|
||||
|
||||
@@ -74,6 +74,7 @@ pub static CODEX_ALIASES_TEMP_DIR: Option<TestCodexAliasesGuard> = {
|
||||
mod abort_tasks;
|
||||
mod agent_jobs;
|
||||
mod agent_websocket;
|
||||
mod agents_md;
|
||||
mod apply_patch_cli;
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
mod approvals;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use anyhow::Result;
|
||||
use codex_exec_server::RemoveOptions;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
use core_test_support::PathBufExt;
|
||||
use core_test_support::get_remote_test_env;
|
||||
use core_test_support::test_codex::test_env;
|
||||
use pretty_assertions::assert_eq;
|
||||
@@ -17,8 +17,7 @@ async fn remote_test_env_can_connect_and_use_filesystem() -> Result<()> {
|
||||
let test_env = test_env().await?;
|
||||
let file_system = test_env.environment().get_filesystem();
|
||||
|
||||
let file_path = remote_test_file_path();
|
||||
let file_path_abs = absolute_path(file_path.clone())?;
|
||||
let file_path_abs = remote_test_file_path().abs();
|
||||
let payload = b"remote-test-env-ok".to_vec();
|
||||
|
||||
file_system
|
||||
@@ -39,12 +38,6 @@ async fn remote_test_env_can_connect_and_use_filesystem() -> Result<()> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn absolute_path(path: PathBuf) -> Result<AbsolutePathBuf> {
|
||||
AbsolutePathBuf::try_from(path.clone())
|
||||
.map_err(|err| anyhow::anyhow!("invalid absolute path {}: {err}", path.display()))
|
||||
}
|
||||
|
||||
fn remote_test_file_path() -> PathBuf {
|
||||
let nanos = match SystemTime::now().duration_since(UNIX_EPOCH) {
|
||||
Ok(duration) => duration.as_nanos(),
|
||||
|
||||
Reference in New Issue
Block a user