mirror of
https://github.com/chrislusf/seaweedfs
synced 2025-08-17 01:22:47 +02:00
* fix listing objects * add more list testing * address comments * fix next marker * fix isTruncated in listing * fix tests * address tests * Update s3api_object_handlers_multipart.go * fixes * store json into bucket content, for tagging and cors * switch bucket metadata from json to proto * fix * Update s3api_bucket_config.go * fix test issue * fix test_bucket_listv2_delimiter_prefix * Update cors.go * skip special characters * passing listing * fix test_bucket_list_delimiter_prefix * ok. fix the xsd generated go code now * fix cors tests * fix test * fix test_bucket_list_unordered and test_bucket_listv2_unordered do not accept the allow-unordered and delimiter parameter combination * fix test_bucket_list_objects_anonymous and test_bucket_listv2_objects_anonymous The tests test_bucket_list_objects_anonymous and test_bucket_listv2_objects_anonymous were failing because they try to set bucket ACL to public-read, but SeaweedFS only supported private ACL. Updated PutBucketAclHandler to use the existing ExtractAcl function which already supports all standard S3 canned ACLs Replaced the hardcoded check for only private ACL with proper ACL parsing that handles public-read, public-read-write, authenticated-read, bucket-owner-read, bucket-owner-full-control, etc. Added unit tests to verify all standard canned ACLs are accepted * fix list unordered The test is expecting the error code to be InvalidArgument instead of InvalidRequest * allow anonymous listing( and head, get) * fix test_bucket_list_maxkeys_invalid Invalid values: max-keys=blah → Returns ErrInvalidMaxKeys (HTTP 400) * updating IsPublicRead when parsing acl * more logs * CORS Test Fix * fix test_bucket_list_return_data * default to private * fix test_bucket_list_delimiter_not_skip_special * default no acl * add debug logging * more logs * use basic http client remove logs also * fixes * debug * Update stats.go * debugging * fix anonymous test expectation anonymous user can read, as configured in s3 json.
169 lines
5.1 KiB
Go
169 lines
5.1 KiB
Go
package basic
|
|
|
|
import (
|
|
"fmt"
|
|
"math/rand"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/aws/aws-sdk-go/aws"
|
|
"github.com/aws/aws-sdk-go/service/s3"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// TestS3ListDelimiterWithDirectoryKeyObjects tests the specific scenario from
|
|
// test_bucket_list_delimiter_not_skip_special where directory key objects
|
|
// should be properly grouped into common prefixes when using delimiters
|
|
func TestS3ListDelimiterWithDirectoryKeyObjects(t *testing.T) {
|
|
bucketName := fmt.Sprintf("test-delimiter-dir-key-%d", rand.Int31())
|
|
|
|
// Create bucket
|
|
_, err := svc.CreateBucket(&s3.CreateBucketInput{
|
|
Bucket: aws.String(bucketName),
|
|
})
|
|
require.NoError(t, err)
|
|
defer cleanupBucket(t, bucketName)
|
|
|
|
// Create objects matching the failing test scenario:
|
|
// ['0/'] + ['0/1000', '0/1001', '0/1002'] + ['1999', '1999#', '1999+', '2000']
|
|
objects := []string{
|
|
"0/", // Directory key object
|
|
"0/1000", // Objects under 0/ prefix
|
|
"0/1001",
|
|
"0/1002",
|
|
"1999", // Objects without delimiter
|
|
"1999#",
|
|
"1999+",
|
|
"2000",
|
|
}
|
|
|
|
// Create all objects
|
|
for _, key := range objects {
|
|
_, err := svc.PutObject(&s3.PutObjectInput{
|
|
Bucket: aws.String(bucketName),
|
|
Key: aws.String(key),
|
|
Body: strings.NewReader(fmt.Sprintf("content for %s", key)),
|
|
})
|
|
require.NoError(t, err, "Failed to create object %s", key)
|
|
}
|
|
|
|
// Test with delimiter='/'
|
|
resp, err := svc.ListObjects(&s3.ListObjectsInput{
|
|
Bucket: aws.String(bucketName),
|
|
Delimiter: aws.String("/"),
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
// Extract keys and prefixes
|
|
var keys []string
|
|
for _, content := range resp.Contents {
|
|
keys = append(keys, *content.Key)
|
|
}
|
|
|
|
var prefixes []string
|
|
for _, prefix := range resp.CommonPrefixes {
|
|
prefixes = append(prefixes, *prefix.Prefix)
|
|
}
|
|
|
|
// Expected results:
|
|
// Keys should be: ['1999', '1999#', '1999+', '2000'] (objects without delimiters)
|
|
// Prefixes should be: ['0/'] (grouping '0/' and all '0/xxxx' objects)
|
|
|
|
expectedKeys := []string{"1999", "1999#", "1999+", "2000"}
|
|
expectedPrefixes := []string{"0/"}
|
|
|
|
t.Logf("Actual keys: %v", keys)
|
|
t.Logf("Actual prefixes: %v", prefixes)
|
|
|
|
assert.ElementsMatch(t, expectedKeys, keys, "Keys should only include objects without delimiters")
|
|
assert.ElementsMatch(t, expectedPrefixes, prefixes, "CommonPrefixes should group directory key object with other objects sharing prefix")
|
|
|
|
// Additional validation
|
|
assert.Equal(t, "/", *resp.Delimiter, "Delimiter should be set correctly")
|
|
assert.Contains(t, prefixes, "0/", "Directory key object '0/' should be grouped into common prefix '0/'")
|
|
assert.NotContains(t, keys, "0/", "Directory key object '0/' should NOT appear as individual key when delimiter is used")
|
|
|
|
// Verify none of the '0/xxxx' objects appear as individual keys
|
|
for _, key := range keys {
|
|
assert.False(t, strings.HasPrefix(key, "0/"), "No object with '0/' prefix should appear as individual key, found: %s", key)
|
|
}
|
|
}
|
|
|
|
// TestS3ListWithoutDelimiter tests that directory key objects appear as individual keys when no delimiter is used
|
|
func TestS3ListWithoutDelimiter(t *testing.T) {
|
|
bucketName := fmt.Sprintf("test-no-delimiter-%d", rand.Int31())
|
|
|
|
// Create bucket
|
|
_, err := svc.CreateBucket(&s3.CreateBucketInput{
|
|
Bucket: aws.String(bucketName),
|
|
})
|
|
require.NoError(t, err)
|
|
defer cleanupBucket(t, bucketName)
|
|
|
|
// Create objects
|
|
objects := []string{"0/", "0/1000", "1999"}
|
|
|
|
for _, key := range objects {
|
|
_, err := svc.PutObject(&s3.PutObjectInput{
|
|
Bucket: aws.String(bucketName),
|
|
Key: aws.String(key),
|
|
Body: strings.NewReader(fmt.Sprintf("content for %s", key)),
|
|
})
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
// Test without delimiter
|
|
resp, err := svc.ListObjects(&s3.ListObjectsInput{
|
|
Bucket: aws.String(bucketName),
|
|
// No delimiter specified
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
// Extract keys
|
|
var keys []string
|
|
for _, content := range resp.Contents {
|
|
keys = append(keys, *content.Key)
|
|
}
|
|
|
|
// When no delimiter is used, all objects should be returned as individual keys
|
|
expectedKeys := []string{"0/", "0/1000", "1999"}
|
|
assert.ElementsMatch(t, expectedKeys, keys, "All objects should be individual keys when no delimiter is used")
|
|
|
|
// No common prefixes should be present
|
|
assert.Empty(t, resp.CommonPrefixes, "No common prefixes should be present when no delimiter is used")
|
|
assert.Contains(t, keys, "0/", "Directory key object '0/' should appear as individual key when no delimiter is used")
|
|
}
|
|
|
|
func cleanupBucket(t *testing.T, bucketName string) {
|
|
// Delete all objects
|
|
resp, err := svc.ListObjects(&s3.ListObjectsInput{
|
|
Bucket: aws.String(bucketName),
|
|
})
|
|
if err != nil {
|
|
t.Logf("Failed to list objects for cleanup: %v", err)
|
|
return
|
|
}
|
|
|
|
for _, obj := range resp.Contents {
|
|
_, err := svc.DeleteObject(&s3.DeleteObjectInput{
|
|
Bucket: aws.String(bucketName),
|
|
Key: obj.Key,
|
|
})
|
|
if err != nil {
|
|
t.Logf("Failed to delete object %s: %v", *obj.Key, err)
|
|
}
|
|
}
|
|
|
|
// Give some time for eventual consistency
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
// Delete bucket
|
|
_, err = svc.DeleteBucket(&s3.DeleteBucketInput{
|
|
Bucket: aws.String(bucketName),
|
|
})
|
|
if err != nil {
|
|
t.Logf("Failed to delete bucket %s: %v", bucketName, err)
|
|
}
|
|
}
|