Files
seaweedfs/test/s3vectors/DESIGN.md
T
Chris Lu 56c081f90e test/s3vectors: data-plane lifecycle integration test (#12242)
* test/s3vectors: data-plane lifecycle integration test

TestVectorDataPlaneLifecycle spawns a real weed-vector against the lance
listener, mirrors the pytest cluster's flags, waits for the gateway to
discover the registered engine, and walks the full lifecycle: create
bucket and index, put/get/list vectors, a filtered query that excludes the
nearer non-matching vector, delete vectors, index, and bucket. The test
skips when no engine binary resolves (VECTOR_BINARY, ./weed-vector, PATH).

* test/s3vectors: fail fast when the engine dies before listening

* test/s3vectors: harden engine launch and tighten lifecycle assertions

* test/s3vectors: wait on the engine's exit once through a broadcast channel
2026-10-30 01:34:02 -07:00

87 lines
4.5 KiB
Markdown

# S3 Vectors integration tests — design
## Goal
Cover the vector-bucket API surface end-to-end against a real `weed` server —
the path no unit or handler-level test exercises: HTTP dispatch on
`X-Amz-Target` / per-path routing, authentication, catalog persistence,
policy enforcement, and (when a vector engine is reachable) the data plane.
## Layout
test/s3vectors/
DESIGN.md this file
s3vectors_integration_test.go environment + test cases
Conventions follow `test/s3tables/sts_integration`: a `TestEnvironment`
brings up `weed server` (master + filer + volume + s3) on testutil-allocated
ports against a temp data dir, the test drives the JSON API over real HTTP,
and `testing.Short()` skips the suite.
## What the test covers
### Tier 1 — no vector engine required (runs everywhere)
These ops resolve through the catalog and the vector policy layer without an
engine RPC, so they work against a plain `weed server`:
- `CreateVectorBucket` / `GetVectorBucket` / `ListVectorBuckets` /
`DeleteVectorBucket` — happy path, `encryptionConfiguration` round-trip
(`sseType` -> stored `sseAlgorithm` -> echoed back as `sseType`), format
filtering (an explicit non-Lance bucket is not a vector bucket).
- `PutVectorBucketPolicy` / `GetVectorBucketPolicy` / `DeleteVectorBucketPolicy`
— the caller's document round-trips verbatim; `s3vectors:` actions are
accepted, foreign-service actions/ARNs rejected; `NotAction`/`NotResource`
rejected.
- Policy **enforcement** through the gateway: a non-owner `PutVectors` /
`GetVectors` is denied without a grant, an `Allow` on
`arn:aws:s3vectors:...:bucket/B/*` grants, a `Deny` vetoes an `Allow` on the
same action, deletion restores owner-only access — the same lifecycle the
package-level conformance test covers, but through signed HTTP requests.
- Validation boundaries: `maxResults` caps, `topK` bounds, `dataType`
rejection, `dimension` range, empty/oversize PutVectors batches (these fail
before the engine is touched, so they work engine-less too).
### Tier 2 — vector engine required (skipped when absent)
`TestVectorDataPlaneLifecycle` spawns a real `weed-vector` against the
environment's lance listener (`-s3.port.lance`), mirroring the cluster the
pytest suite builds in `conftest.py`: `--namespace` points at the lance
HTTP port, `--masters` at `master.http.grpc`, and the storage options carry
the same test credentials the IAM config writes. The binary resolves as
`VECTOR_BINARY` env → `./weed-vector` (the Makefile's output) → PATH; the
test skips when none is found, and `waitForEngineDiscovery` polls a
data-plane op until the gateway routes to the registered engine instead of
503. The test then walks the full lifecycle: `CreateVectorBucket` →
`CreateIndex` → `PutVectors` → `GetVectors` → `ListVectors` → filtered
`QueryVectors` → `DeleteVectors` → `DeleteIndex` → `DeleteVectorBucket`.
## Harness
- `NewTestEnvironment` mirrors `sts_integration`: locate the `weed` binary
(built `weed/weed` first, then PATH), allocate ports with `testutil`
(`MustFreeMiniPorts`, since `weed server` derives each gRPC port as
HTTP+10000), spawn `weed server -dir=<tmp> -master.port -volume.port
-filer -s3.port` against a written `-s3.config` identity file, disable
the unused Iceberg/Lance listeners, wait for the S3 port to serve
`/status`, then run requests. The vectors router rides the S3 port
automatically once the gateway can reach a master — no extra flag.
- Requests are signed SigV4 with the `s3vectors` service name — the gateway
routes vectors traffic on the service name in the credential scope, so an
unsigned or `s3`-signed request never reaches the vectors router. A small
`vectorsClient` helper wraps POST + `X-Amz-Target`/`/op` + signing +
status-code assertions; identities vary per-request for policy tests.
- `Cleanup` kills the process group and removes the temp dir.
- `TestMain`-less design: each test builds its own environment so a hung
server can't take down the suite; `t.Parallel()` is deliberately avoided —
port allocation is cheap but vector-engine bring-up is not.
## Not covered here (by design)
- Auth failure modes (expired creds, bad signatures) — covered by the
`sts_integration` suite and the s3api auth tests; the vectors router shares
the same `iam.AuthenticateRequest` path.
- Lance/segment internals — the package's `listSegmentVectors` unit tests and
the engine's own suite cover them; the integration layer only asserts the
API contract.