snapshot of https://github.com/seaweedfs/seaweedfs.git (master, 2026-09-16; blobs > 131072B omitted)
Some checks failed
go: build dev binaries / cleanup (push) Successful in 4s
Codespell / Check for spelling errors (push) Failing after 3s
docker: build dev containers / build-rust-binaries (amd64, x86_64-unknown-linux-musl) (push) Failing after 3s
docker: build dev containers / build-dev-containers (push) Has been skipped
docker: build dev containers / build-rust-binaries (arm64, true, aarch64-unknown-linux-musl) (push) Failing after 3s
End to End / FUSE Mount (push) Failing after 2s
EC Integration Tests / EC Integration Tests (push) Failing after 30s
FUSE DLM Integration Tests / FUSE DLM Integration Tests (push) Failing after 3s
FUSE Volume Server Failover Tests / FUSE Volume Server Failover (push) Failing after 3s
FUSE Integration Tests / FUSE Integration Testing (push) Failing after 2s
FUSE P2P Peer Chunk Sharing Integration Tests / FUSE P2P Peer Chunk Sharing (push) Failing after 3s
go: build binary / Go Vet (push) Failing after 2s
go: build binary / Go Vet 32-bit (push) Failing after 3s
go: build binary / Build (push) Failing after 4s
go: build binary / Build cross-platform (freebsd/amd64) (push) Failing after 3s
go: build binary / Build cross-platform (windows/amd64) (push) Failing after 3s
go: build binary / Build cross-platform (darwin/arm64) (push) Failing after 3s
go: build binary / Build cross-platform (windows/arm64) (push) Failing after 3s
go: build binary / Test (push) Failing after 2s
go: build binary / Test 32-bit (push) Failing after 3s
helm: lint and test charts / lint-test (push) Failing after 3s
Java Client Integration Tests / Java Integration Tests (11) (push) Failing after 3s
Java Client Integration Tests / Java Integration Tests (17) (push) Failing after 3s
go: build dev binaries / build_dev_linux_windows (amd64, linux) (push) Failing after 2s
go: build dev binaries / build_dev_linux_windows (amd64, windows) (push) Failing after 3s
go: build dev binaries / build_dev_darwin (amd64, darwin) (push) Has been skipped
go: build dev binaries / build_dev_darwin (arm64, darwin) (push) Has been skipped
Java Client Unit Tests / Java Unit Tests (11) (push) Failing after 3s
Java Client Unit Tests / Java Unit Tests (17) (push) Failing after 2s
Java Client Unit Tests / Java Unit Tests (21) (push) Failing after 3s
Java Client Unit Tests / Java Unit Tests (8) (push) Failing after 3s
Kafka Quick Test (Load Test with Schema Registry) / Kafka Client Load Test (Quick) (push) Failing after 3s
Kafka Gateway Tests / Kafka Unit Tests (unit-tests-1) (push) Failing after 11s
Kafka Gateway Tests / Kafka Integration Tests (Critical) (integration-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka End-to-End Tests (with SMQ) (e2e-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka Consumer Group Tests (Highly Isolated) (consumer-group-1) (push) Failing after 2s
Kafka Gateway Tests / Kafka Client Compatibility (with SMQ) (client-compat-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka SMQ Integration Tests (Full Stack) (smq-integration-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka Protocol Tests (Isolated) (protocol-1) (push) Failing after 3s
KMS Tests / KMS Provider Integration Tests (push) Failing after 2s
KMS Tests / S3 KMS End-to-End Tests (push) Failing after 3s
Master Cold Start Tests / Master Cold Start Tests (push) Failing after 4s
Metadata Subscribe Integration Tests / Metadata Subscribe Integration Tests (push) Failing after 3s
Multi-Master Tests / Multi-Master Failover Tests (push) Failing after 3s
Performance / CPU and Heap Profile (push) Failing after 2s
Performance / S3 Read/Write Benchmark (rust volume) (push) Failing after 3s
pjdfstest POSIX Compliance / pjdfstest (push) Failing after 2s
Plugin Worker Integration Tests / Plugin Worker: erasure_coding (push) Failing after 3s
Plugin Worker Integration Tests / Plugin Worker: vacuum (push) Failing after 3s
Rust Volume Server Tests / Rust Integration Tests (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 1) (push) Failing after 2s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 1) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 2) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 2) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 3) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Distributed Tests (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Performance Tests (push) Failing after 3s
Performance / Throughput Benchmark (go volume) (push) Failing after 3s
Performance / Throughput Benchmark (rust volume) (push) Failing after 2s
Performance / S3 Read/Write Benchmark (go volume) (push) Failing after 3s
Plugin Worker Integration Tests / Plugin Worker: volume_balance (push) Failing after 3s
PostgreSQL Gateway Tests / PostgreSQL Basic Tests (push) Failing after 3s
Rust Volume Server Tests / Rust Unit Tests (push) Failing after 2s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 3) (push) Failing after 3s
Rust Plugin Worker Tests / Rust Plugin Worker Build and Unit Tests (push) Failing after 3s
rust: build dev volume server binaries / cleanup (push) Successful in 3s
S3 ETag and ACL Tests / S3 ETag + ACL Integration Tests (push) Failing after 3s
S3 IAM Integration Tests / IAM Unit Tests (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (advanced) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (basic) (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Integration Tests (group) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (policy-enforcement) (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Integration Tests (sts) (push) Failing after 4s
S3 Keycloak Integration Tests / S3 Keycloak Integration Tests (push) Failing after 3s
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.11) (push) Failing after 3s
S3 PyArrow Parquet Tests / Go Unit Tests (Implicit Directory) (push) Has been cancelled
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.12) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-darwin (darwin-amd64, x86_64-apple-darwin) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-darwin (darwin-arm64, aarch64-apple-darwin) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-linux (linux-amd64, x86_64-unknown-linux-gnu) (push) Has been cancelled
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.9) (push) Has been cancelled
S3 Proxy Signature Tests / S3 Proxy Signature Verification Tests (push) Has been cancelled
S3 SDK V2 Route Disambiguation Tests / S3 SDK V2 Routing Tests (push) Has been cancelled
S3 SSE Tests / S3 SSE Integration Tests (quick) (push) Has been cancelled
S3 SSE Tests / S3 SSE Compatibility Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Metadata Persistence Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Copy Operations Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Multipart Upload Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Performance Test (push) Has been cancelled
S3 SSE Tests / S3 Volume Encryption Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Integration Tests (comprehensive) (push) Has been cancelled
Spark Integration Tests / Spark Integration Tests (push) Failing after 2s
Telemetry Integration Tests / telemetry-integration-test (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 1) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 1) (push) Failing after 3s
Ceph S3 tests / Basic S3 tests (KV store) (push) Has been cancelled
Ceph S3 tests / S3 Versioning & Object Lock tests (push) Has been cancelled
S3 Policy Integration Tests / S3 Policy Unit Tests (push) Failing after 3s
Ceph S3 tests / S3 CORS tests (push) Has been cancelled
Ceph S3 tests / SeaweedFS Custom S3 Copy tests (push) Has been cancelled
Ceph S3 tests / Basic S3 tests (SQL store) (push) Has been cancelled
test s3 over https using aws-cli / awscli-tests (push) Has been cancelled
TLS Rotation Integration Tests / TLS Rotation Integration Tests (push) Has been cancelled
Vacuum Integration Tests / Vacuum Integration Tests (push) Has been cancelled
S3 Policy Integration Tests / S3 Policy Variables Integration Tests (push) Failing after 3s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (advanced-policy) (push) Failing after 3s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (basic-policy) (push) Failing after 2s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (contextual-policy) (push) Failing after 4s
S3 Policy Integration Tests / Trusted Proxy Detection Tests (push) Failing after 2s
S3 Policy Integration Tests / S3 Policy Shell Integration Tests (push) Failing after 3s
Samba on FUSE Integration / samba-integration (push) Failing after 2s
SFTP Integration Tests / SFTP Integration Testing (push) Failing after 3s
terraform: validate and test modules / fmt, validate, plan-level tests (push) Failing after 3s
terraform: validate and test modules / local cluster smoke test (real weed) (push) Failing after 2s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 3) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 2) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 2) (push) Failing after 2s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 3) (push) Failing after 5s
mount: windows conformance / WinFsp conformance (push) Has been cancelled
mount: windows / Mount on Windows (push) Has been cancelled
Some checks failed
go: build dev binaries / cleanup (push) Successful in 4s
Codespell / Check for spelling errors (push) Failing after 3s
docker: build dev containers / build-rust-binaries (amd64, x86_64-unknown-linux-musl) (push) Failing after 3s
docker: build dev containers / build-dev-containers (push) Has been skipped
docker: build dev containers / build-rust-binaries (arm64, true, aarch64-unknown-linux-musl) (push) Failing after 3s
End to End / FUSE Mount (push) Failing after 2s
EC Integration Tests / EC Integration Tests (push) Failing after 30s
FUSE DLM Integration Tests / FUSE DLM Integration Tests (push) Failing after 3s
FUSE Volume Server Failover Tests / FUSE Volume Server Failover (push) Failing after 3s
FUSE Integration Tests / FUSE Integration Testing (push) Failing after 2s
FUSE P2P Peer Chunk Sharing Integration Tests / FUSE P2P Peer Chunk Sharing (push) Failing after 3s
go: build binary / Go Vet (push) Failing after 2s
go: build binary / Go Vet 32-bit (push) Failing after 3s
go: build binary / Build (push) Failing after 4s
go: build binary / Build cross-platform (freebsd/amd64) (push) Failing after 3s
go: build binary / Build cross-platform (windows/amd64) (push) Failing after 3s
go: build binary / Build cross-platform (darwin/arm64) (push) Failing after 3s
go: build binary / Build cross-platform (windows/arm64) (push) Failing after 3s
go: build binary / Test (push) Failing after 2s
go: build binary / Test 32-bit (push) Failing after 3s
helm: lint and test charts / lint-test (push) Failing after 3s
Java Client Integration Tests / Java Integration Tests (11) (push) Failing after 3s
Java Client Integration Tests / Java Integration Tests (17) (push) Failing after 3s
go: build dev binaries / build_dev_linux_windows (amd64, linux) (push) Failing after 2s
go: build dev binaries / build_dev_linux_windows (amd64, windows) (push) Failing after 3s
go: build dev binaries / build_dev_darwin (amd64, darwin) (push) Has been skipped
go: build dev binaries / build_dev_darwin (arm64, darwin) (push) Has been skipped
Java Client Unit Tests / Java Unit Tests (11) (push) Failing after 3s
Java Client Unit Tests / Java Unit Tests (17) (push) Failing after 2s
Java Client Unit Tests / Java Unit Tests (21) (push) Failing after 3s
Java Client Unit Tests / Java Unit Tests (8) (push) Failing after 3s
Kafka Quick Test (Load Test with Schema Registry) / Kafka Client Load Test (Quick) (push) Failing after 3s
Kafka Gateway Tests / Kafka Unit Tests (unit-tests-1) (push) Failing after 11s
Kafka Gateway Tests / Kafka Integration Tests (Critical) (integration-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka End-to-End Tests (with SMQ) (e2e-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka Consumer Group Tests (Highly Isolated) (consumer-group-1) (push) Failing after 2s
Kafka Gateway Tests / Kafka Client Compatibility (with SMQ) (client-compat-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka SMQ Integration Tests (Full Stack) (smq-integration-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka Protocol Tests (Isolated) (protocol-1) (push) Failing after 3s
KMS Tests / KMS Provider Integration Tests (push) Failing after 2s
KMS Tests / S3 KMS End-to-End Tests (push) Failing after 3s
Master Cold Start Tests / Master Cold Start Tests (push) Failing after 4s
Metadata Subscribe Integration Tests / Metadata Subscribe Integration Tests (push) Failing after 3s
Multi-Master Tests / Multi-Master Failover Tests (push) Failing after 3s
Performance / CPU and Heap Profile (push) Failing after 2s
Performance / S3 Read/Write Benchmark (rust volume) (push) Failing after 3s
pjdfstest POSIX Compliance / pjdfstest (push) Failing after 2s
Plugin Worker Integration Tests / Plugin Worker: erasure_coding (push) Failing after 3s
Plugin Worker Integration Tests / Plugin Worker: vacuum (push) Failing after 3s
Rust Volume Server Tests / Rust Integration Tests (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 1) (push) Failing after 2s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 1) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 2) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 2) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 3) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Distributed Tests (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Performance Tests (push) Failing after 3s
Performance / Throughput Benchmark (go volume) (push) Failing after 3s
Performance / Throughput Benchmark (rust volume) (push) Failing after 2s
Performance / S3 Read/Write Benchmark (go volume) (push) Failing after 3s
Plugin Worker Integration Tests / Plugin Worker: volume_balance (push) Failing after 3s
PostgreSQL Gateway Tests / PostgreSQL Basic Tests (push) Failing after 3s
Rust Volume Server Tests / Rust Unit Tests (push) Failing after 2s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 3) (push) Failing after 3s
Rust Plugin Worker Tests / Rust Plugin Worker Build and Unit Tests (push) Failing after 3s
rust: build dev volume server binaries / cleanup (push) Successful in 3s
S3 ETag and ACL Tests / S3 ETag + ACL Integration Tests (push) Failing after 3s
S3 IAM Integration Tests / IAM Unit Tests (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (advanced) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (basic) (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Integration Tests (group) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (policy-enforcement) (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Integration Tests (sts) (push) Failing after 4s
S3 Keycloak Integration Tests / S3 Keycloak Integration Tests (push) Failing after 3s
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.11) (push) Failing after 3s
S3 PyArrow Parquet Tests / Go Unit Tests (Implicit Directory) (push) Has been cancelled
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.12) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-darwin (darwin-amd64, x86_64-apple-darwin) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-darwin (darwin-arm64, aarch64-apple-darwin) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-linux (linux-amd64, x86_64-unknown-linux-gnu) (push) Has been cancelled
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.9) (push) Has been cancelled
S3 Proxy Signature Tests / S3 Proxy Signature Verification Tests (push) Has been cancelled
S3 SDK V2 Route Disambiguation Tests / S3 SDK V2 Routing Tests (push) Has been cancelled
S3 SSE Tests / S3 SSE Integration Tests (quick) (push) Has been cancelled
S3 SSE Tests / S3 SSE Compatibility Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Metadata Persistence Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Copy Operations Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Multipart Upload Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Performance Test (push) Has been cancelled
S3 SSE Tests / S3 Volume Encryption Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Integration Tests (comprehensive) (push) Has been cancelled
Spark Integration Tests / Spark Integration Tests (push) Failing after 2s
Telemetry Integration Tests / telemetry-integration-test (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 1) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 1) (push) Failing after 3s
Ceph S3 tests / Basic S3 tests (KV store) (push) Has been cancelled
Ceph S3 tests / S3 Versioning & Object Lock tests (push) Has been cancelled
S3 Policy Integration Tests / S3 Policy Unit Tests (push) Failing after 3s
Ceph S3 tests / S3 CORS tests (push) Has been cancelled
Ceph S3 tests / SeaweedFS Custom S3 Copy tests (push) Has been cancelled
Ceph S3 tests / Basic S3 tests (SQL store) (push) Has been cancelled
test s3 over https using aws-cli / awscli-tests (push) Has been cancelled
TLS Rotation Integration Tests / TLS Rotation Integration Tests (push) Has been cancelled
Vacuum Integration Tests / Vacuum Integration Tests (push) Has been cancelled
S3 Policy Integration Tests / S3 Policy Variables Integration Tests (push) Failing after 3s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (advanced-policy) (push) Failing after 3s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (basic-policy) (push) Failing after 2s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (contextual-policy) (push) Failing after 4s
S3 Policy Integration Tests / Trusted Proxy Detection Tests (push) Failing after 2s
S3 Policy Integration Tests / S3 Policy Shell Integration Tests (push) Failing after 3s
Samba on FUSE Integration / samba-integration (push) Failing after 2s
SFTP Integration Tests / SFTP Integration Testing (push) Failing after 3s
terraform: validate and test modules / fmt, validate, plan-level tests (push) Failing after 3s
terraform: validate and test modules / local cluster smoke test (real weed) (push) Failing after 2s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 3) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 2) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 2) (push) Failing after 2s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 3) (push) Failing after 5s
mount: windows conformance / WinFsp conformance (push) Has been cancelled
mount: windows / Mount on Windows (push) Has been cancelled
This commit is contained in:
217
test/s3/copying/Makefile
Normal file
217
test/s3/copying/Makefile
Normal file
@@ -0,0 +1,217 @@
|
||||
# Makefile for S3 Copying Tests
|
||||
# This Makefile provides targets for running comprehensive S3 copying tests
|
||||
|
||||
# Default values
|
||||
SEAWEEDFS_BINARY ?= weed
|
||||
S3_PORT ?= 8333
|
||||
FILER_PORT ?= 8888
|
||||
VOLUME_PORT ?= 8080
|
||||
MASTER_PORT ?= 9333
|
||||
TEST_TIMEOUT ?= 10m
|
||||
BUCKET_PREFIX ?= test-copying-
|
||||
ACCESS_KEY ?= some_access_key1
|
||||
SECRET_KEY ?= some_secret_key1
|
||||
VOLUME_MAX_SIZE_MB ?= 50
|
||||
|
||||
# Let the tests force-drop collections at the master they actually run against
|
||||
export MASTER_ENDPOINT ?= http://127.0.0.1:$(MASTER_PORT)
|
||||
|
||||
# Test directory
|
||||
TEST_DIR := $(shell pwd)
|
||||
SEAWEEDFS_ROOT := $(shell cd ../../../ && pwd)
|
||||
|
||||
# Colors for output
|
||||
RED := \033[0;31m
|
||||
GREEN := \033[0;32m
|
||||
YELLOW := \033[1;33m
|
||||
NC := \033[0m # No Color
|
||||
|
||||
.PHONY: all test clean start-seaweedfs stop-seaweedfs check-binary help
|
||||
|
||||
all: test-basic
|
||||
|
||||
help:
|
||||
@echo "SeaweedFS S3 Copying Tests"
|
||||
@echo ""
|
||||
@echo "Available targets:"
|
||||
@echo " test-basic - Run basic S3 put/get tests first"
|
||||
@echo " test - Run all S3 copying tests"
|
||||
@echo " test-quick - Run quick tests only"
|
||||
@echo " test-full - Run full test suite including large files"
|
||||
@echo " start-seaweedfs - Start SeaweedFS server for testing"
|
||||
@echo " stop-seaweedfs - Stop SeaweedFS server"
|
||||
@echo " clean - Clean up test artifacts"
|
||||
@echo " check-binary - Check if SeaweedFS binary exists"
|
||||
@echo ""
|
||||
@echo "Configuration:"
|
||||
@echo " SEAWEEDFS_BINARY=$(SEAWEEDFS_BINARY)"
|
||||
@echo " S3_PORT=$(S3_PORT)"
|
||||
@echo " FILER_PORT=$(FILER_PORT)"
|
||||
@echo " VOLUME_PORT=$(VOLUME_PORT)"
|
||||
@echo " MASTER_PORT=$(MASTER_PORT)"
|
||||
@echo " TEST_TIMEOUT=$(TEST_TIMEOUT)"
|
||||
@echo " VOLUME_MAX_SIZE_MB=$(VOLUME_MAX_SIZE_MB)"
|
||||
|
||||
check-binary:
|
||||
@if ! command -v $(SEAWEEDFS_BINARY) > /dev/null 2>&1; then \
|
||||
echo "$(RED)Error: SeaweedFS binary '$(SEAWEEDFS_BINARY)' not found in PATH$(NC)"; \
|
||||
echo "Please build SeaweedFS first by running 'make' in the root directory"; \
|
||||
exit 1; \
|
||||
fi
|
||||
@echo "$(GREEN)SeaweedFS binary found: $$(which $(SEAWEEDFS_BINARY))$(NC)"
|
||||
|
||||
start-seaweedfs: check-binary
|
||||
@echo "$(YELLOW)Starting SeaweedFS server...$(NC)"
|
||||
@pkill -f "weed master" || true
|
||||
@pkill -f "weed volume" || true
|
||||
@pkill -f "weed filer" || true
|
||||
@pkill -f "weed s3" || true
|
||||
@pkill -f "weed mini" || true
|
||||
@sleep 2
|
||||
@mkdir -p /tmp/seaweedfs-test-copying
|
||||
@echo "Starting weed mini with dir=/tmp/seaweedfs-test-copying"
|
||||
@AWS_ACCESS_KEY_ID=$(ACCESS_KEY) AWS_SECRET_ACCESS_KEY=$(SECRET_KEY) nohup $(SEAWEEDFS_BINARY) mini \
|
||||
-dir=/tmp/seaweedfs-test-copying \
|
||||
-s3.port=$(S3_PORT) \
|
||||
-ip=127.0.0.1 \
|
||||
> /tmp/seaweedfs-mini.log 2>&1 & echo $$! > /tmp/weed-mini.pid
|
||||
@echo "$(YELLOW)Waiting for S3 service to be ready...$(NC)"
|
||||
@for i in $$(seq 1 30); do \
|
||||
if curl -s -f http://127.0.0.1:$(S3_PORT) > /dev/null 2>&1; then \
|
||||
echo "$(GREEN)S3 service is ready$(NC)"; \
|
||||
break; \
|
||||
fi; \
|
||||
echo "Waiting for S3 service... ($$i/30)"; \
|
||||
sleep 1; \
|
||||
done
|
||||
@sleep 2
|
||||
@echo "$(GREEN)SeaweedFS server started successfully$(NC)"
|
||||
@echo "Mini Log: /tmp/seaweedfs-mini.log"
|
||||
@echo "S3: http://localhost:$(S3_PORT)"
|
||||
|
||||
stop-seaweedfs:
|
||||
@echo "$(YELLOW)Stopping SeaweedFS server...$(NC)"
|
||||
@pkill -f "weed master" || true
|
||||
@pkill -f "weed volume" || true
|
||||
@pkill -f "weed filer" || true
|
||||
@pkill -f "weed s3" || true
|
||||
@pkill -f "weed mini" || true
|
||||
@sleep 2
|
||||
@rm -f /tmp/weed-mini.pid
|
||||
@echo "$(GREEN)SeaweedFS server stopped$(NC)"
|
||||
|
||||
clean:
|
||||
@echo "$(YELLOW)Cleaning up test artifacts...$(NC)"
|
||||
@rm -rf /tmp/seaweedfs-test-copying-*
|
||||
@rm -f /tmp/seaweedfs-*.log
|
||||
@rm -f /tmp/seaweedfs-s3.json
|
||||
@rm -f /tmp/weed-mini.pid
|
||||
@echo "$(GREEN)Cleanup completed$(NC)"
|
||||
|
||||
test-basic: check-binary
|
||||
@echo "$(YELLOW)Running basic S3 put/get tests...$(NC)"
|
||||
@$(MAKE) start-seaweedfs
|
||||
@sleep 5
|
||||
@echo "$(GREEN)Starting basic tests...$(NC)"
|
||||
@cd $(SEAWEEDFS_ROOT) && go test -v -timeout=$(TEST_TIMEOUT) -run "TestBasic" ./test/s3/copying || (echo "$(RED)Basic tests failed$(NC)" && $(MAKE) stop-seaweedfs && exit 1)
|
||||
@$(MAKE) stop-seaweedfs
|
||||
@echo "$(GREEN)Basic tests completed successfully!$(NC)"
|
||||
|
||||
test: test-basic
|
||||
@echo "$(YELLOW)Running S3 copying tests...$(NC)"
|
||||
@$(MAKE) start-seaweedfs
|
||||
@sleep 5
|
||||
@echo "$(GREEN)Starting tests...$(NC)"
|
||||
@cd $(SEAWEEDFS_ROOT) && go test -v -timeout=$(TEST_TIMEOUT) -run "Test.*" ./test/s3/copying || (echo "$(RED)Tests failed$(NC)" && $(MAKE) stop-seaweedfs && exit 1)
|
||||
@$(MAKE) stop-seaweedfs
|
||||
@echo "$(GREEN)All tests completed successfully!$(NC)"
|
||||
|
||||
test-quick: check-binary
|
||||
@echo "$(YELLOW)Running quick S3 copying tests...$(NC)"
|
||||
@$(MAKE) start-seaweedfs
|
||||
@sleep 5
|
||||
@echo "$(GREEN)Starting quick tests...$(NC)"
|
||||
@cd $(SEAWEEDFS_ROOT) && go test -v -timeout=$(TEST_TIMEOUT) -run "TestObjectCopy|TestCopyObjectIf" ./test/s3/copying || (echo "$(RED)Tests failed$(NC)" && $(MAKE) stop-seaweedfs && exit 1)
|
||||
@$(MAKE) stop-seaweedfs
|
||||
@echo "$(GREEN)Quick tests completed successfully!$(NC)"
|
||||
|
||||
test-full: check-binary
|
||||
@echo "$(YELLOW)Running full S3 copying test suite...$(NC)"
|
||||
@$(MAKE) start-seaweedfs
|
||||
@sleep 5
|
||||
@echo "$(GREEN)Starting full test suite...$(NC)"
|
||||
@cd $(SEAWEEDFS_ROOT) && go test -v -timeout=30m -run "Test.*" ./test/s3/copying || (echo "$(RED)Tests failed$(NC)" && $(MAKE) stop-seaweedfs && exit 1)
|
||||
@$(MAKE) stop-seaweedfs
|
||||
@echo "$(GREEN)Full test suite completed successfully!$(NC)"
|
||||
|
||||
test-multipart: check-binary
|
||||
@echo "$(YELLOW)Running multipart copying tests...$(NC)"
|
||||
@$(MAKE) start-seaweedfs
|
||||
@sleep 5
|
||||
@echo "$(GREEN)Starting multipart tests...$(NC)"
|
||||
@cd $(SEAWEEDFS_ROOT) && go test -v -timeout=$(TEST_TIMEOUT) -run "TestMultipart" ./test/s3/copying || (echo "$(RED)Tests failed$(NC)" && $(MAKE) stop-seaweedfs && exit 1)
|
||||
@$(MAKE) stop-seaweedfs
|
||||
@echo "$(GREEN)Multipart tests completed successfully!$(NC)"
|
||||
|
||||
test-conditional: check-binary
|
||||
@echo "$(YELLOW)Running conditional copying tests...$(NC)"
|
||||
@$(MAKE) start-seaweedfs
|
||||
@sleep 5
|
||||
@echo "$(GREEN)Starting conditional tests...$(NC)"
|
||||
@cd $(SEAWEEDFS_ROOT) && go test -v -timeout=$(TEST_TIMEOUT) -run "TestCopyObjectIf" ./test/s3/copying || (echo "$(RED)Tests failed$(NC)" && $(MAKE) stop-seaweedfs && exit 1)
|
||||
@$(MAKE) stop-seaweedfs
|
||||
@echo "$(GREEN)Conditional tests completed successfully!$(NC)"
|
||||
|
||||
# Debug targets
|
||||
debug-logs:
|
||||
@echo "$(YELLOW)=== Master Log ===$(NC)"
|
||||
@tail -n 50 /tmp/seaweedfs-master.log || echo "No master log found"
|
||||
@echo "$(YELLOW)=== Volume Log ===$(NC)"
|
||||
@tail -n 50 /tmp/seaweedfs-volume.log || echo "No volume log found"
|
||||
@echo "$(YELLOW)=== Filer Log ===$(NC)"
|
||||
@tail -n 50 /tmp/seaweedfs-filer.log || echo "No filer log found"
|
||||
@echo "$(YELLOW)=== S3 Log ===$(NC)"
|
||||
@tail -n 50 /tmp/seaweedfs-s3.log || echo "No S3 log found"
|
||||
|
||||
debug-status:
|
||||
@echo "$(YELLOW)=== Process Status ===$(NC)"
|
||||
@ps aux | grep -E "(weed|seaweedfs)" | grep -v grep || echo "No SeaweedFS processes found"
|
||||
@echo "$(YELLOW)=== Port Status ===$(NC)"
|
||||
@netstat -an | grep -E "($(MASTER_PORT)|$(VOLUME_PORT)|$(FILER_PORT)|$(S3_PORT))" || echo "No ports in use"
|
||||
|
||||
# Manual test targets for development
|
||||
manual-start: start-seaweedfs
|
||||
@echo "$(GREEN)SeaweedFS is now running for manual testing$(NC)"
|
||||
@echo "Run 'make manual-stop' when finished"
|
||||
|
||||
manual-stop: stop-seaweedfs clean
|
||||
|
||||
# CI/CD targets
|
||||
ci-test: test-quick
|
||||
|
||||
# Benchmark targets
|
||||
benchmark: check-binary
|
||||
@echo "$(YELLOW)Running S3 copying benchmarks...$(NC)"
|
||||
@$(MAKE) start-seaweedfs
|
||||
@sleep 5
|
||||
@cd $(SEAWEEDFS_ROOT) && go test -v -timeout=30m -bench=. -run=Benchmark ./test/s3/copying || (echo "$(RED)Benchmarks failed$(NC)" && $(MAKE) stop-seaweedfs && exit 1)
|
||||
@$(MAKE) stop-seaweedfs
|
||||
@echo "$(GREEN)Benchmarks completed!$(NC)"
|
||||
|
||||
# Stress test
|
||||
stress: check-binary
|
||||
@echo "$(YELLOW)Running S3 copying stress tests...$(NC)"
|
||||
@$(MAKE) start-seaweedfs
|
||||
@sleep 5
|
||||
@cd $(SEAWEEDFS_ROOT) && go test -v -timeout=60m -run="TestMultipartCopyMultipleSizes" -count=10 ./test/s3/copying || (echo "$(RED)Stress tests failed$(NC)" && $(MAKE) stop-seaweedfs && exit 1)
|
||||
@$(MAKE) stop-seaweedfs
|
||||
@echo "$(GREEN)Stress tests completed!$(NC)"
|
||||
|
||||
# Performance test with larger files
|
||||
perf: check-binary
|
||||
@echo "$(YELLOW)Running S3 copying performance tests...$(NC)"
|
||||
@$(MAKE) start-seaweedfs
|
||||
@sleep 5
|
||||
@cd $(SEAWEEDFS_ROOT) && go test -v -timeout=60m -run="TestMultipartCopyMultipleSizes" ./test/s3/copying || (echo "$(RED)Performance tests failed$(NC)" && $(MAKE) stop-seaweedfs && exit 1)
|
||||
@$(MAKE) stop-seaweedfs
|
||||
@echo "$(GREEN)Performance tests completed!$(NC)"
|
||||
325
test/s3/copying/README.md
Normal file
325
test/s3/copying/README.md
Normal file
@@ -0,0 +1,325 @@
|
||||
# SeaweedFS S3 Copying Tests
|
||||
|
||||
This directory contains comprehensive Go tests for SeaweedFS S3 copying functionality, converted from the failing Python tests in the s3-tests repository.
|
||||
|
||||
## Overview
|
||||
|
||||
These tests verify that SeaweedFS correctly implements S3 operations, starting with basic put/get operations and progressing to advanced copy operations, including:
|
||||
- **Basic S3 Operations**: Put/Get operations, bucket management, and metadata handling
|
||||
- **Basic object copying**: within the same bucket
|
||||
- **Cross-bucket copying**: across different buckets
|
||||
- **Multipart copy operations**: for large files
|
||||
- **Conditional copy operations**: ETag-based conditional copying
|
||||
- **Metadata handling**: during copy operations
|
||||
- **ACL handling**: during copy operations
|
||||
|
||||
## Test Coverage
|
||||
|
||||
### Basic S3 Operations (Run First)
|
||||
- **TestBasicPutGet**: Tests fundamental S3 put/get operations with various object types
|
||||
- **TestBasicBucketOperations**: Tests bucket creation, listing, and deletion
|
||||
- **TestBasicLargeObject**: Tests handling of larger objects (up to 10MB)
|
||||
|
||||
### Basic Copy Operations
|
||||
- **TestObjectCopySameBucket**: Tests copying objects within the same bucket
|
||||
- **TestObjectCopyDiffBucket**: Tests copying objects to different buckets
|
||||
- **TestObjectCopyCannedAcl**: Tests copying with ACL settings
|
||||
- **TestObjectCopyRetainingMetadata**: Tests metadata preservation during copy
|
||||
|
||||
### Multipart Copy Operations
|
||||
- **TestMultipartCopySmall**: Tests multipart copying of small files
|
||||
- **TestMultipartCopyWithoutRange**: Tests multipart copying without range specification
|
||||
- **TestMultipartCopySpecialNames**: Tests multipart copying with special character names
|
||||
- **TestMultipartCopyMultipleSizes**: Tests multipart copying with various file sizes
|
||||
|
||||
### Conditional Copy Operations
|
||||
- **TestCopyObjectIfMatchGood**: Tests copying with matching ETag condition
|
||||
- **TestCopyObjectIfMatchFailed**: Tests copying with non-matching ETag condition (should fail)
|
||||
- **TestCopyObjectIfNoneMatchFailed**: Tests copying with non-matching ETag condition (should succeed)
|
||||
- **TestCopyObjectIfNoneMatchGood**: Tests copying with matching ETag condition (should fail)
|
||||
|
||||
## Requirements
|
||||
|
||||
1. **Go 1.19+**: Required for AWS SDK v2 and modern Go features
|
||||
2. **SeaweedFS Binary**: Built from source (`../../../weed/weed`)
|
||||
3. **Free Ports**: 8333 (S3), 8888 (Filer), 8080 (Volume), 9333 (Master)
|
||||
4. **Dependencies**: Uses the main repository's go.mod with existing AWS SDK v2 and testify dependencies
|
||||
|
||||
## Quick Start
|
||||
|
||||
### 1. Build SeaweedFS
|
||||
```bash
|
||||
cd ../../../
|
||||
make
|
||||
```
|
||||
|
||||
### 2. Run Tests
|
||||
```bash
|
||||
# Run basic S3 operations first (recommended)
|
||||
make test-basic
|
||||
|
||||
# Run all tests (starts with basic, then copy tests)
|
||||
make test
|
||||
|
||||
# Run quick tests only
|
||||
make test-quick
|
||||
|
||||
# Run multipart tests only
|
||||
make test-multipart
|
||||
|
||||
# Run conditional tests only
|
||||
make test-conditional
|
||||
```
|
||||
|
||||
## Available Make Targets
|
||||
|
||||
### Basic Test Execution
|
||||
- `make test-basic` - Run basic S3 put/get operations (recommended first)
|
||||
- `make test` - Run all S3 tests (starts with basic, then copying)
|
||||
- `make test-quick` - Run quick tests only (basic copying)
|
||||
- `make test-full` - Run full test suite including large files
|
||||
- `make test-multipart` - Run multipart copying tests only
|
||||
- `make test-conditional` - Run conditional copying tests only
|
||||
|
||||
### Server Management
|
||||
- `make start-seaweedfs` - Start SeaweedFS server for testing
|
||||
- `make stop-seaweedfs` - Stop SeaweedFS server
|
||||
- `make manual-start` - Start server for manual testing
|
||||
- `make manual-stop` - Stop server and clean up
|
||||
|
||||
### Debugging
|
||||
- `make debug-logs` - Show recent log entries from all services
|
||||
- `make debug-status` - Show process and port status
|
||||
- `make check-binary` - Verify SeaweedFS binary exists
|
||||
|
||||
### Performance Testing
|
||||
- `make benchmark` - Run performance benchmarks
|
||||
- `make stress` - Run stress tests with multiple iterations
|
||||
- `make perf` - Run performance tests with large files
|
||||
|
||||
### Cleanup
|
||||
- `make clean` - Clean up test artifacts and temporary files
|
||||
|
||||
## Configuration
|
||||
|
||||
The tests use the following default configuration:
|
||||
|
||||
```json
|
||||
{
|
||||
"endpoint": "http://localhost:8333",
|
||||
"access_key": "some_access_key1",
|
||||
"secret_key": "some_secret_key1",
|
||||
"region": "us-east-1",
|
||||
"bucket_prefix": "test-copying-",
|
||||
"use_ssl": false,
|
||||
"skip_verify_ssl": true
|
||||
}
|
||||
```
|
||||
|
||||
You can modify these values in `test_config.json` or by setting environment variables:
|
||||
|
||||
```bash
|
||||
export SEAWEEDFS_BINARY=/path/to/weed
|
||||
export S3_PORT=8333
|
||||
export FILER_PORT=8888
|
||||
export VOLUME_PORT=8080
|
||||
export MASTER_PORT=9333
|
||||
export TEST_TIMEOUT=10m
|
||||
export VOLUME_MAX_SIZE_MB=50
|
||||
```
|
||||
|
||||
**Note**: The volume size limit is set to 50MB to ensure proper testing of volume boundaries and multipart operations.
|
||||
|
||||
## Test Details
|
||||
|
||||
### TestBasicPutGet
|
||||
- Tests fundamental S3 put/get operations with various object types:
|
||||
- Simple text objects
|
||||
- Empty objects
|
||||
- Binary objects (1KB random data)
|
||||
- Objects with metadata and content-type
|
||||
- Verifies ETag consistency between put and get operations
|
||||
- Tests metadata preservation
|
||||
|
||||
### TestBasicBucketOperations
|
||||
- Tests bucket creation and existence verification
|
||||
- Tests object listing in buckets
|
||||
- Tests object creation and listing with directory-like prefixes
|
||||
- Tests bucket deletion and cleanup
|
||||
- Verifies proper error handling for operations on non-existent buckets
|
||||
|
||||
### TestBasicLargeObject
|
||||
- Tests handling of progressively larger objects:
|
||||
- 1KB, 10KB, 100KB, 1MB, 5MB, 10MB
|
||||
- Verifies data integrity for large objects
|
||||
- Tests memory handling and streaming for large files
|
||||
- Ensures proper handling up to the 50MB volume limit
|
||||
|
||||
### TestObjectCopySameBucket
|
||||
- Creates a bucket with a source object
|
||||
- Copies the object to a different key within the same bucket
|
||||
- Verifies the copied object has the same content
|
||||
|
||||
### TestObjectCopyDiffBucket
|
||||
- Creates source and destination buckets
|
||||
- Copies an object from source to destination bucket
|
||||
- Verifies the copied object has the same content
|
||||
|
||||
### TestObjectCopyCannedAcl
|
||||
- Tests copying with ACL settings (`public-read`)
|
||||
- Tests metadata replacement during copy with ACL
|
||||
- Verifies both basic copying and metadata handling
|
||||
|
||||
### TestObjectCopyRetainingMetadata
|
||||
- Tests with different file sizes (3 bytes, 1MB)
|
||||
- Verifies metadata and content-type preservation
|
||||
- Checks that all metadata is correctly copied
|
||||
|
||||
### TestMultipartCopySmall
|
||||
- Tests multipart copy with 1-byte files
|
||||
- Uses range-based copying (`bytes=0-0`)
|
||||
- Verifies multipart upload completion
|
||||
|
||||
### TestMultipartCopyWithoutRange
|
||||
- Tests multipart copy without specifying range
|
||||
- Should copy entire source object
|
||||
- Verifies correct content length and data
|
||||
|
||||
### TestMultipartCopySpecialNames
|
||||
- Tests with special character names: `" "`, `"_"`, `"__"`, `"?versionId"`
|
||||
- Verifies proper URL encoding and handling
|
||||
- Each special name is tested in isolation
|
||||
|
||||
### TestMultipartCopyMultipleSizes
|
||||
- Tests with various copy sizes:
|
||||
- 5MB (single part)
|
||||
- 5MB + 100KB (multi-part)
|
||||
- 5MB + 600KB (multi-part)
|
||||
- 10MB + 100KB (multi-part)
|
||||
- 10MB + 600KB (multi-part)
|
||||
- 10MB (exact multi-part boundary)
|
||||
- Uses 5MB part size for all copies
|
||||
- Verifies data integrity across all sizes
|
||||
|
||||
### TestCopyObjectIfMatchGood
|
||||
- Tests conditional copy with matching ETag
|
||||
- Should succeed when ETag matches
|
||||
- Verifies successful copy operation
|
||||
|
||||
### TestCopyObjectIfMatchFailed
|
||||
- Tests conditional copy with non-matching ETag
|
||||
- Should fail with precondition error
|
||||
- Verifies proper error handling
|
||||
|
||||
### TestCopyObjectIfNoneMatchFailed
|
||||
- Tests conditional copy with non-matching ETag for IfNoneMatch
|
||||
- Should succeed when ETag doesn't match
|
||||
- Verifies successful copy operation
|
||||
|
||||
### TestCopyObjectIfNoneMatchGood
|
||||
- Tests conditional copy with matching ETag for IfNoneMatch
|
||||
- Should fail with precondition error
|
||||
- Verifies proper error handling
|
||||
|
||||
## Expected Behavior
|
||||
|
||||
These tests verify that SeaweedFS correctly implements:
|
||||
|
||||
1. **Basic S3 Operations**: Standard `PutObject`, `GetObject`, `ListBuckets`, `ListObjects` APIs
|
||||
2. **Bucket Management**: Bucket creation, deletion, and listing
|
||||
3. **Object Storage**: Binary and text data storage with metadata
|
||||
4. **Large Object Handling**: Efficient storage and retrieval of large files
|
||||
5. **Basic S3 Copy Operations**: Standard `CopyObject` API
|
||||
6. **Multipart Copy Operations**: `UploadPartCopy` API with range support
|
||||
7. **Conditional Operations**: ETag-based conditional copying
|
||||
8. **Metadata Handling**: Proper metadata preservation and replacement
|
||||
9. **ACL Handling**: Access control list management during copy
|
||||
10. **Error Handling**: Proper error responses for invalid operations
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
1. **Port Already in Use**
|
||||
```bash
|
||||
make stop-seaweedfs
|
||||
make clean
|
||||
```
|
||||
|
||||
2. **SeaweedFS Binary Not Found**
|
||||
```bash
|
||||
cd ../../../
|
||||
make
|
||||
```
|
||||
|
||||
3. **Test Timeouts**
|
||||
```bash
|
||||
export TEST_TIMEOUT=30m
|
||||
make test
|
||||
```
|
||||
|
||||
4. **Permission Denied**
|
||||
```bash
|
||||
sudo make clean
|
||||
```
|
||||
|
||||
### Debug Information
|
||||
|
||||
```bash
|
||||
# Check server status
|
||||
make debug-status
|
||||
|
||||
# View recent logs
|
||||
make debug-logs
|
||||
|
||||
# Manual server start for investigation
|
||||
make manual-start
|
||||
# ... perform manual testing ...
|
||||
make manual-stop
|
||||
```
|
||||
|
||||
### Log Locations
|
||||
|
||||
When running tests, logs are stored in:
|
||||
- Master: `/tmp/seaweedfs-master.log`
|
||||
- Volume: `/tmp/seaweedfs-volume.log`
|
||||
- Filer: `/tmp/seaweedfs-filer.log`
|
||||
- S3: `/tmp/seaweedfs-s3.log`
|
||||
|
||||
## Contributing
|
||||
|
||||
When adding new tests:
|
||||
|
||||
1. Follow the existing naming convention (`TestXxxYyy`)
|
||||
2. Use the helper functions for common operations
|
||||
3. Add cleanup with `defer deleteBucket(t, client, bucketName)`
|
||||
4. Include error checking with `require.NoError(t, err)`
|
||||
5. Use assertions with `assert.Equal(t, expected, actual)`
|
||||
6. Add the test to the appropriate Make target
|
||||
|
||||
## Performance Notes
|
||||
|
||||
- **TestMultipartCopyMultipleSizes** is the most resource-intensive test
|
||||
- Large file tests may take several minutes to complete
|
||||
- Memory usage scales with file sizes being tested
|
||||
- Network latency affects multipart copy performance
|
||||
|
||||
## Integration with CI/CD
|
||||
|
||||
For automated testing:
|
||||
|
||||
```bash
|
||||
# Basic validation (recommended first)
|
||||
make test-basic
|
||||
|
||||
# Quick validation
|
||||
make ci-test
|
||||
|
||||
# Full validation
|
||||
make test-full
|
||||
|
||||
# Performance validation
|
||||
make perf
|
||||
```
|
||||
|
||||
The tests are designed to be self-contained and can run in containerized environments.
|
||||
1081
test/s3/copying/s3_copying_test.go
Normal file
1081
test/s3/copying/s3_copying_test.go
Normal file
File diff suppressed because it is too large
Load Diff
333
test/s3/copying/s3_rename_test.go
Normal file
333
test/s3/copying/s3_rename_test.go
Normal file
@@ -0,0 +1,333 @@
|
||||
package copying_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3/types"
|
||||
smithyhttp "github.com/aws/smithy-go/transport/http"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// createRenameSource builds the x-amz-rename-source value the way the AWS CLI,
|
||||
// Java and Rust examples do: the bare source key, URL encoded.
|
||||
func createRenameSource(key string) string {
|
||||
return url.PathEscape(key)
|
||||
}
|
||||
|
||||
// createQualifiedRenameSource builds the alternate bucket/key form the second
|
||||
// AWS CLI example and the boto3 conditional example use.
|
||||
func createQualifiedRenameSource(bucketName, key string) string {
|
||||
return fmt.Sprintf("%s/%s", bucketName, url.PathEscape(key))
|
||||
}
|
||||
|
||||
func renameObject(t *testing.T, client *s3.Client, bucketName, srcKey, dstKey string) {
|
||||
t.Helper()
|
||||
_, err := client.RenameObject(context.TODO(), &s3.RenameObjectInput{
|
||||
Bucket: aws.String(bucketName),
|
||||
Key: aws.String(dstKey),
|
||||
RenameSource: aws.String(createRenameSource(srcKey)),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
// requireRenameStatus asserts err carries the given HTTP status code.
|
||||
func requireRenameStatus(t *testing.T, err error, status int) {
|
||||
t.Helper()
|
||||
require.Error(t, err)
|
||||
var respErr *smithyhttp.ResponseError
|
||||
require.True(t, errors.As(err, &respErr), "expected an HTTP response error, got %v", err)
|
||||
assert.Equal(t, status, respErr.HTTPStatusCode(), "unexpected error: %v", err)
|
||||
}
|
||||
|
||||
func objectExists(t *testing.T, client *s3.Client, bucketName, key string) bool {
|
||||
t.Helper()
|
||||
_, err := client.HeadObject(context.TODO(), &s3.HeadObjectInput{
|
||||
Bucket: aws.String(bucketName),
|
||||
Key: aws.String(key),
|
||||
})
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// TestRenameObject renames an object and checks the bytes, metadata and ETag
|
||||
// arrive under the new key while the old key disappears.
|
||||
func TestRenameObject(t *testing.T) {
|
||||
client := getS3Client(t)
|
||||
bucketName := getNewBucketName()
|
||||
createBucket(t, client, bucketName)
|
||||
defer deleteBucket(t, client, bucketName)
|
||||
|
||||
content := "rename me"
|
||||
put := putObjectWithMetadata(t, client, bucketName, "source.txt", content,
|
||||
map[string]string{"origin": "source"}, "text/plain")
|
||||
|
||||
renameObject(t, client, bucketName, "source.txt", "renamed/target.txt")
|
||||
|
||||
assert.False(t, objectExists(t, client, bucketName, "source.txt"), "source should be gone")
|
||||
|
||||
resp := getObject(t, client, bucketName, "renamed/target.txt")
|
||||
assert.Equal(t, content, getObjectBody(t, resp))
|
||||
assert.Equal(t, "text/plain", aws.ToString(resp.ContentType))
|
||||
assert.Equal(t, "source", resp.Metadata["origin"])
|
||||
assert.Equal(t, aws.ToString(put.ETag), aws.ToString(resp.ETag), "ETag must survive the rename")
|
||||
}
|
||||
|
||||
// TestRenameObjectOverwritesDestination: without a conditional header a rename
|
||||
// replaces whatever the destination key held.
|
||||
func TestRenameObjectOverwritesDestination(t *testing.T) {
|
||||
client := getS3Client(t)
|
||||
bucketName := getNewBucketName()
|
||||
createBucket(t, client, bucketName)
|
||||
defer deleteBucket(t, client, bucketName)
|
||||
|
||||
putObject(t, client, bucketName, "source.txt", "new content")
|
||||
putObject(t, client, bucketName, "target.txt", "old content")
|
||||
|
||||
renameObject(t, client, bucketName, "source.txt", "target.txt")
|
||||
|
||||
resp := getObject(t, client, bucketName, "target.txt")
|
||||
assert.Equal(t, "new content", getObjectBody(t, resp))
|
||||
}
|
||||
|
||||
// TestRenameObjectIfNoneMatch: If-None-Match: * protects an existing destination.
|
||||
func TestRenameObjectIfNoneMatch(t *testing.T) {
|
||||
client := getS3Client(t)
|
||||
bucketName := getNewBucketName()
|
||||
createBucket(t, client, bucketName)
|
||||
defer deleteBucket(t, client, bucketName)
|
||||
|
||||
putObject(t, client, bucketName, "source.txt", "new content")
|
||||
putObject(t, client, bucketName, "target.txt", "old content")
|
||||
|
||||
_, err := client.RenameObject(context.TODO(), &s3.RenameObjectInput{
|
||||
Bucket: aws.String(bucketName),
|
||||
Key: aws.String("target.txt"),
|
||||
RenameSource: aws.String(createRenameSource("source.txt")),
|
||||
DestinationIfNoneMatch: aws.String("*"),
|
||||
})
|
||||
requireRenameStatus(t, err, 412)
|
||||
|
||||
resp := getObject(t, client, bucketName, "target.txt")
|
||||
assert.Equal(t, "old content", getObjectBody(t, resp))
|
||||
assert.True(t, objectExists(t, client, bucketName, "source.txt"), "a failed rename must leave the source alone")
|
||||
|
||||
// The same rename onto a free key succeeds.
|
||||
_, err = client.RenameObject(context.TODO(), &s3.RenameObjectInput{
|
||||
Bucket: aws.String(bucketName),
|
||||
Key: aws.String("free.txt"),
|
||||
RenameSource: aws.String(createRenameSource("source.txt")),
|
||||
DestinationIfNoneMatch: aws.String("*"),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
// TestRenameObjectSourceIfMatch gates the rename on the source's ETag.
|
||||
func TestRenameObjectSourceIfMatch(t *testing.T) {
|
||||
client := getS3Client(t)
|
||||
bucketName := getNewBucketName()
|
||||
createBucket(t, client, bucketName)
|
||||
defer deleteBucket(t, client, bucketName)
|
||||
|
||||
put := putObject(t, client, bucketName, "source.txt", "content")
|
||||
|
||||
_, err := client.RenameObject(context.TODO(), &s3.RenameObjectInput{
|
||||
Bucket: aws.String(bucketName),
|
||||
Key: aws.String("target.txt"),
|
||||
RenameSource: aws.String(createRenameSource("source.txt")),
|
||||
SourceIfMatch: aws.String("\"00000000000000000000000000000000\""),
|
||||
})
|
||||
requireRenameStatus(t, err, 412)
|
||||
assert.True(t, objectExists(t, client, bucketName, "source.txt"))
|
||||
|
||||
_, err = client.RenameObject(context.TODO(), &s3.RenameObjectInput{
|
||||
Bucket: aws.String(bucketName),
|
||||
Key: aws.String("target.txt"),
|
||||
RenameSource: aws.String(createRenameSource("source.txt")),
|
||||
SourceIfMatch: put.ETag,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.False(t, objectExists(t, client, bucketName, "source.txt"))
|
||||
assert.True(t, objectExists(t, client, bucketName, "target.txt"))
|
||||
}
|
||||
|
||||
// TestRenameObjectOntoDirectory: S3 keys are flat, so a key that other keys are
|
||||
// nested under is still a key of its own. The rename writes it without disturbing
|
||||
// them - it does not replace the directory, it stores the object on it.
|
||||
func TestRenameObjectOntoDirectory(t *testing.T) {
|
||||
client := getS3Client(t)
|
||||
bucketName := getNewBucketName()
|
||||
createBucket(t, client, bucketName)
|
||||
defer deleteBucket(t, client, bucketName)
|
||||
|
||||
putObject(t, client, bucketName, "source.txt", "content")
|
||||
putObject(t, client, bucketName, "target/child.txt", "child")
|
||||
|
||||
_, err := client.RenameObject(context.TODO(), &s3.RenameObjectInput{
|
||||
Bucket: aws.String(bucketName),
|
||||
Key: aws.String("target"),
|
||||
RenameSource: aws.String(createRenameSource("source.txt")),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.False(t, objectExists(t, client, bucketName, "source.txt"))
|
||||
assert.Equal(t, "content", getObjectBody(t, getObject(t, client, bucketName, "target")))
|
||||
assert.Equal(t, "child", getObjectBody(t, getObject(t, client, bucketName, "target/child.txt")))
|
||||
}
|
||||
|
||||
// TestRenameObjectDirectorySource: a directory can be named without a trailing
|
||||
// slash, and renaming one would move a whole subtree. It is not an object, so it
|
||||
// is a missing key.
|
||||
func TestRenameObjectDirectorySource(t *testing.T) {
|
||||
client := getS3Client(t)
|
||||
bucketName := getNewBucketName()
|
||||
createBucket(t, client, bucketName)
|
||||
defer deleteBucket(t, client, bucketName)
|
||||
|
||||
putObject(t, client, bucketName, "source/child.txt", "child")
|
||||
|
||||
for _, src := range []string{"source", "source/"} {
|
||||
_, err := client.RenameObject(context.TODO(), &s3.RenameObjectInput{
|
||||
Bucket: aws.String(bucketName),
|
||||
Key: aws.String("target.txt"),
|
||||
RenameSource: aws.String(createRenameSource(src)),
|
||||
})
|
||||
requireRenameStatus(t, err, 404)
|
||||
}
|
||||
assert.True(t, objectExists(t, client, bucketName, "source/child.txt"))
|
||||
assert.False(t, objectExists(t, client, bucketName, "target.txt"))
|
||||
}
|
||||
|
||||
// TestRenameObjectMissingSource reports a missing source as NoSuchKey.
|
||||
func TestRenameObjectMissingSource(t *testing.T) {
|
||||
client := getS3Client(t)
|
||||
bucketName := getNewBucketName()
|
||||
createBucket(t, client, bucketName)
|
||||
defer deleteBucket(t, client, bucketName)
|
||||
|
||||
_, err := client.RenameObject(context.TODO(), &s3.RenameObjectInput{
|
||||
Bucket: aws.String(bucketName),
|
||||
Key: aws.String("target.txt"),
|
||||
RenameSource: aws.String(createRenameSource("absent.txt")),
|
||||
})
|
||||
requireRenameStatus(t, err, 404)
|
||||
}
|
||||
|
||||
// TestRenameObjectQualifiedSource: the bucket/key form AWS's second CLI example
|
||||
// and the boto3 conditional example use resolves to the same object as the bare
|
||||
// key.
|
||||
func TestRenameObjectQualifiedSource(t *testing.T) {
|
||||
client := getS3Client(t)
|
||||
bucketName := getNewBucketName()
|
||||
createBucket(t, client, bucketName)
|
||||
defer deleteBucket(t, client, bucketName)
|
||||
|
||||
putObject(t, client, bucketName, "dir/source.txt", "content")
|
||||
|
||||
_, err := client.RenameObject(context.TODO(), &s3.RenameObjectInput{
|
||||
Bucket: aws.String(bucketName),
|
||||
Key: aws.String("target.txt"),
|
||||
RenameSource: aws.String(createQualifiedRenameSource(bucketName, "dir/source.txt")),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.False(t, objectExists(t, client, bucketName, "dir/source.txt"))
|
||||
assert.Equal(t, "content", getObjectBody(t, getObject(t, client, bucketName, "target.txt")))
|
||||
}
|
||||
|
||||
// TestRenameObjectSourceShadowingTheBucketName: a key whose own first segment is
|
||||
// the bucket name is a real key, and must win over reading the same value as a
|
||||
// bucket-qualified source.
|
||||
func TestRenameObjectSourceShadowingTheBucketName(t *testing.T) {
|
||||
client := getS3Client(t)
|
||||
bucketName := getNewBucketName()
|
||||
createBucket(t, client, bucketName)
|
||||
defer deleteBucket(t, client, bucketName)
|
||||
|
||||
shadowed := bucketName + "/source.txt"
|
||||
putObject(t, client, bucketName, shadowed, "shadowed")
|
||||
putObject(t, client, bucketName, "source.txt", "bare")
|
||||
|
||||
_, err := client.RenameObject(context.TODO(), &s3.RenameObjectInput{
|
||||
Bucket: aws.String(bucketName),
|
||||
Key: aws.String("target.txt"),
|
||||
RenameSource: aws.String(createQualifiedRenameSource(bucketName, "source.txt")),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "shadowed", getObjectBody(t, getObject(t, client, bucketName, "target.txt")))
|
||||
assert.False(t, objectExists(t, client, bucketName, shadowed))
|
||||
assert.True(t, objectExists(t, client, bucketName, "source.txt"), "the bare key must be left alone")
|
||||
}
|
||||
|
||||
// TestRenameObjectSourceShadowedByADirectory: the literal reading of the source
|
||||
// names a directory here, and the bucket-qualified reading names a live object.
|
||||
// Naming a directory is an error about that directory — falling through to the
|
||||
// other reading would rename a different object than the one asked for.
|
||||
func TestRenameObjectSourceShadowedByADirectory(t *testing.T) {
|
||||
client := getS3Client(t)
|
||||
bucketName := getNewBucketName()
|
||||
createBucket(t, client, bucketName)
|
||||
defer deleteBucket(t, client, bucketName)
|
||||
|
||||
putObject(t, client, bucketName, bucketName+"/source.txt/child.txt", "child")
|
||||
putObject(t, client, bucketName, "source.txt", "bare")
|
||||
|
||||
_, err := client.RenameObject(context.TODO(), &s3.RenameObjectInput{
|
||||
Bucket: aws.String(bucketName),
|
||||
Key: aws.String("target.txt"),
|
||||
RenameSource: aws.String(createQualifiedRenameSource(bucketName, "source.txt")),
|
||||
})
|
||||
requireRenameStatus(t, err, 404)
|
||||
assert.True(t, objectExists(t, client, bucketName, "source.txt"), "the bare key must be left alone")
|
||||
assert.False(t, objectExists(t, client, bucketName, "target.txt"))
|
||||
}
|
||||
|
||||
// TestRenameObjectCrossBucket: RenameObject moves within one bucket, so another
|
||||
// bucket's name in the source is just part of a key this bucket does not hold.
|
||||
func TestRenameObjectCrossBucket(t *testing.T) {
|
||||
client := getS3Client(t)
|
||||
srcBucket := getNewBucketName()
|
||||
createBucket(t, client, srcBucket)
|
||||
defer deleteBucket(t, client, srcBucket)
|
||||
dstBucket := getNewBucketName()
|
||||
createBucket(t, client, dstBucket)
|
||||
defer deleteBucket(t, client, dstBucket)
|
||||
|
||||
putObject(t, client, srcBucket, "source.txt", "content")
|
||||
|
||||
_, err := client.RenameObject(context.TODO(), &s3.RenameObjectInput{
|
||||
Bucket: aws.String(dstBucket),
|
||||
Key: aws.String("target.txt"),
|
||||
RenameSource: aws.String(createQualifiedRenameSource(srcBucket, "source.txt")),
|
||||
})
|
||||
requireRenameStatus(t, err, 404)
|
||||
assert.True(t, objectExists(t, client, srcBucket, "source.txt"))
|
||||
}
|
||||
|
||||
// TestRenameObjectVersionedBucket: versioned buckets are not supported yet, and
|
||||
// must say so rather than silently dropping versions.
|
||||
func TestRenameObjectVersionedBucket(t *testing.T) {
|
||||
client := getS3Client(t)
|
||||
bucketName := getNewBucketName()
|
||||
createBucket(t, client, bucketName)
|
||||
defer deleteBucket(t, client, bucketName)
|
||||
|
||||
_, err := client.PutBucketVersioning(context.TODO(), &s3.PutBucketVersioningInput{
|
||||
Bucket: aws.String(bucketName),
|
||||
VersioningConfiguration: &types.VersioningConfiguration{Status: types.BucketVersioningStatusEnabled},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
putObject(t, client, bucketName, "source.txt", "content")
|
||||
|
||||
_, err = client.RenameObject(context.TODO(), &s3.RenameObjectInput{
|
||||
Bucket: aws.String(bucketName),
|
||||
Key: aws.String("target.txt"),
|
||||
RenameSource: aws.String(createRenameSource("source.txt")),
|
||||
})
|
||||
requireRenameStatus(t, err, 501)
|
||||
assert.True(t, objectExists(t, client, bucketName, "source.txt"))
|
||||
}
|
||||
9
test/s3/copying/test_config.json
Normal file
9
test/s3/copying/test_config.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"endpoint": "http://localhost:8333",
|
||||
"access_key": "some_access_key1",
|
||||
"secret_key": "some_secret_key1",
|
||||
"region": "us-east-1",
|
||||
"bucket_prefix": "test-copying-",
|
||||
"use_ssl": false,
|
||||
"skip_verify_ssl": true
|
||||
}
|
||||
Reference in New Issue
Block a user