diff --git a/AGENTS.md b/AGENTS.md index 30e0077cae..ef56c32680 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -66,6 +66,7 @@ a module map, read/write paths, change-coupling points, and gotchas: - [`src/flow/AGENTS.md`](src/flow/AGENTS.md) - [`src/frontend/AGENTS.md`](src/frontend/AGENTS.md) - [`src/meta-srv/AGENTS.md`](src/meta-srv/AGENTS.md) +- [`tests-integration/AGENTS.md`](tests-integration/AGENTS.md) - [`tests/compatibility/AGENTS.md`](tests/compatibility/AGENTS.md) - [`tests/perf/AGENTS.md`](tests/perf/AGENTS.md) @@ -117,6 +118,10 @@ blast radius requires it. | Query regression harness or DSL | Follow `tests/perf/AGENTS.md` | | Enterprise-gated code | Build/test with `--features enterprise` where applicable and run `make check-enterprise-license` | +For import/export, COPY, or snapshot-storage changes, follow the Windows +portability and validation guidance in +[`tests-integration/AGENTS.md`](tests-integration/AGENTS.md). + ## Before opening a PR 1. If you added a `.rs`, `.py`, or `.ts` file, apply and verify its license diff --git a/tests-integration/AGENTS.md b/tests-integration/AGENTS.md new file mode 100644 index 0000000000..9b83a05497 --- /dev/null +++ b/tests-integration/AGENTS.md @@ -0,0 +1,36 @@ +# tests-integration — Agent & Contributor Guide + +Integration test modules are registered in `tests/main.rs` (`autotests = false`). +Shared instance and storage helpers live in `src/instance.rs` and +`src/test_util.rs`. See [README.md](README.md) for external-service setup. + +## Import/export portability + +Import/export and COPY tests must work on Windows as well as Linux/macOS. +[#9227](https://github.com/GreptimeTeam/greptimedb/issues/9227) records export +tests failing because native Windows paths were compared with `/`-separated +COPY locations. + +- Keep native filesystem paths (`Path`/`PathBuf`), file URIs, and `/`-separated + object-store keys distinct. Compare filesystem paths as paths; for COPY + location assertions, normalize both sides to the defined location format. + Do not compare native `PathBuf::join().display()` strings directly with + `/`-separated export locations. +- Build filesystem fixtures with temporary directories and convert absolute + paths to file URIs with `Url::from_file_path`; do not hard-code `/tmp` or + concatenate `file://` with native paths. Close file handles before rename or + cleanup, including import-state writes. + +## Validation + +Run focused cases from the repository root: + +```bash +cargo nextest run -p tests-integration --test main -E 'test()' +``` + +For import/export changes, run affected tests on Windows. The reference job is +`test-on-windows` in [Nightly CI](../.github/workflows/nightly-ci.yml) +(`cargo nextest run -F dashboard`). Linux/macOS success does not establish +Windows compatibility. If Windows execution is unavailable, explicitly report +that gap and inspect platform-specific paths and file operations. diff --git a/tests-integration/tests/export_logical_tables.rs b/tests-integration/tests/export_logical_tables.rs index 9b4ea97a4a..8d5ea3e42b 100644 --- a/tests-integration/tests/export_logical_tables.rs +++ b/tests-integration/tests/export_logical_tables.rs @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::path::PathBuf; use std::sync::Arc; use common_query::OutputData; @@ -292,15 +293,13 @@ async fn database_export_roundtrip(instance: &Arc) { .path() .join("data") .join(format!("{name}.parquet")) - .to_str() - .unwrap() - .to_string() }) .collect::>(); assert_eq!( summary .output_files .into_iter() + .map(PathBuf::from) .collect::>(), expected ); @@ -697,13 +696,24 @@ async fn database_export_preserves_valid_table_names() { } }) .collect::>(); - assert_eq!( - summary - .output_files - .into_iter() - .collect::>(), - expected - ); + let actual = summary + .output_files + .into_iter() + .collect::>(); + if file_url { + assert_eq!(actual, expected); + } else { + assert_eq!( + actual + .into_iter() + .map(PathBuf::from) + .collect::>(), + expected + .into_iter() + .map(PathBuf::from) + .collect::>() + ); + } } for name in &names { let path = directory.join(format!("{name}.parquet"));