* test(s3): force-drop collection after deleteBucket across tagging/versioning/cors/copying Each test creates a unique bucket (= new SeaweedFS collection) and the master's warm-create issues a 7-volume grow batch. The S3 DeleteBucket-driven collection sweep snapshots the layout once, but in-flight `volume_grow` requests keep registering volumes after the snapshot, leaking 1-3 volumes per bucket. On a single `weed mini` data node with the auto-derived volume cap, those leaks pile up fast and every subsequent PutObject 500s with "Not enough data nodes found". Mirror the retention-suite fix (commitsac3a756d,363d5caa) into the four other suites that share the same shape: defer a master-side /col/delete after each bucket teardown, and sweep stale prefix-matching buckets before every new createBucket. Each suite gets its own MASTER_ENDPOINT default plus the allTestBucketPrefixes / cleanupAllTestBuckets / cleanupLeftoverTestBuckets / forceDeleteCollection helpers. Skipped: iam (separate framework + v1 SDK; already passes -master.volumeSizeLimitMB=100), sse (different cleanup signature; docker-compose already passes -volumeSizeLimitMB=50), policy (its TestCluster already uses -master.volumeSizeLimitMB=32 and tears the whole cluster down). Suites under 5 tests cannot exhaust the cap and were left untouched. * test(s3): default master endpoint to 127.0.0.1 to avoid IPv6 resolution Mirror the explicit IPv4 default already used by test/s3/copying. On hosts where `localhost` resolves to ::1 first the master HTTP listener (bound on 0.0.0.0) is unreachable, so the new force-delete-collection helper would silently skip cleanup. Pin the default to 127.0.0.1 in tagging/cors/versioning; the MASTER_ENDPOINT env var still wins when set. * test(s3): skip buckets newer than this process in leftover-bucket sweep cleanupAllTestBuckets/cleanupTestBuckets used to delete every bucket whose name matched the suite's prefix. With shared S3/master endpoints, a second concurrent `go test` run could have its live buckets torn down mid-test by the first run's sweep. Capture testRunStart at package init (with a 1-minute backdate for clock skew) and skip any bucket whose CreationDate is newer than that. Stale buckets from panicked or interrupted prior runs (the original target of the sweep) still get collected because they were created before this process started. * test(s3-copying): sweep stale prefix buckets from createBucket, not just from a few callers The s3-copying suite already had cleanupTestBuckets that walks every bucket and drops the test-copying-* prefix matches, but only four tests in the file invoke it; the rest go straight to createBucket. So a panicked or interrupted prior run could leak buckets that survive into the next run and exhaust the data node's volume slots before any of the prefix-sweeping tests get a chance to run. Hoist the sweep into createBucket so every test that creates a bucket starts on a clean slate. The per-process CreationDate filter from the prior commit keeps this safe under concurrent runs. * test(s3): scope leftover-bucket sweep to this run via runID marker The CreationDate filter only protected against runs that started later than this process. A different `go test` against the same S3/master endpoints that started *earlier* and is still active has buckets older than testRunStart, so the sweep would still tear them down mid-test. Replace the time window with a per-process runID baked into bucket names: every bucket this run creates gets `r{runID}-` after the suite's BucketPrefix, and the sweep only matches that owned subset. Concurrent runs each carry their own runID and never see each other's buckets. Trade-off: buckets left behind by a crashed prior run carry a different runID and won't be cleaned up by this sweep. That recovery path now belongs to `make clean` / data-dir wipe, which is what CI already does between jobs. Fixed-name versioning buckets (e.g. test-versioning-directories) bypass getNewBucketName and so also bypass this sweep — they are short-lived and handled by their own deferred deleteBucket. * test(s3): drop cleanupLeftoverTestBuckets wrapper, call cleanupAllTestBuckets directly cleanupLeftoverTestBuckets was a one-line forwarder kept only as a semantic name at the createBucket call site. Inline the call and update the doc comments to point at the actual implementation. tagging/cors/versioning all had the wrapper; copying never did.
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
- Go 1.19+: Required for AWS SDK v2 and modern Go features
- SeaweedFS Binary: Built from source (
../../../weed/weed) - Free Ports: 8333 (S3), 8888 (Filer), 8080 (Volume), 9333 (Master)
- Dependencies: Uses the main repository's go.mod with existing AWS SDK v2 and testify dependencies
Quick Start
1. Build SeaweedFS
cd ../../../
make
2. Run Tests
# 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 filesmake test-multipart- Run multipart copying tests onlymake test-conditional- Run conditional copying tests only
Server Management
make start-seaweedfs- Start SeaweedFS server for testingmake stop-seaweedfs- Stop SeaweedFS servermake manual-start- Start server for manual testingmake manual-stop- Stop server and clean up
Debugging
make debug-logs- Show recent log entries from all servicesmake debug-status- Show process and port statusmake check-binary- Verify SeaweedFS binary exists
Performance Testing
make benchmark- Run performance benchmarksmake stress- Run stress tests with multiple iterationsmake 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:
{
"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:
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:
- Basic S3 Operations: Standard
PutObject,GetObject,ListBuckets,ListObjectsAPIs - Bucket Management: Bucket creation, deletion, and listing
- Object Storage: Binary and text data storage with metadata
- Large Object Handling: Efficient storage and retrieval of large files
- Basic S3 Copy Operations: Standard
CopyObjectAPI - Multipart Copy Operations:
UploadPartCopyAPI with range support - Conditional Operations: ETag-based conditional copying
- Metadata Handling: Proper metadata preservation and replacement
- ACL Handling: Access control list management during copy
- Error Handling: Proper error responses for invalid operations
Troubleshooting
Common Issues
-
Port Already in Use
make stop-seaweedfs make clean -
SeaweedFS Binary Not Found
cd ../../../ make -
Test Timeouts
export TEST_TIMEOUT=30m make test -
Permission Denied
sudo make clean
Debug Information
# 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:
- Follow the existing naming convention (
TestXxxYyy) - Use the helper functions for common operations
- Add cleanup with
defer deleteBucket(t, client, bucketName) - Include error checking with
require.NoError(t, err) - Use assertions with
assert.Equal(t, expected, actual) - 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:
# 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.