diff options
Diffstat (limited to 'test/s3/sse/s3_range_headers_test.go')
| -rw-r--r-- | test/s3/sse/s3_range_headers_test.go | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/test/s3/sse/s3_range_headers_test.go b/test/s3/sse/s3_range_headers_test.go new file mode 100644 index 000000000..e54004eb7 --- /dev/null +++ b/test/s3/sse/s3_range_headers_test.go @@ -0,0 +1,104 @@ +package sse_test + +import ( + "bytes" + "context" + "fmt" + "io" + "testing" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/s3" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// TestPlainObjectRangeAndHeadHeaders ensures non-SSE objects advertise correct +// Content-Length and Content-Range information for both HEAD and ranged GETs. +func TestPlainObjectRangeAndHeadHeaders(t *testing.T) { + ctx := context.Background() + + client, err := createS3Client(ctx, defaultConfig) + require.NoError(t, err, "failed to create S3 client") + + bucketName, err := createTestBucket(ctx, client, defaultConfig.BucketPrefix+"range-plain-") + require.NoError(t, err, "failed to create test bucket") + defer cleanupTestBucket(ctx, client, bucketName) + + // SeaweedFS S3 auto-chunks uploads at 8MiB (see chunkSize in putToFiler). + // Using 16MiB ensures at least two chunks without stressing CI resources. + const chunkSize = 8 * 1024 * 1024 + const objectSize = 2 * chunkSize + objectKey := "plain-range-validation" + testData := generateTestData(objectSize) + + _, err = client.PutObject(ctx, &s3.PutObjectInput{ + Bucket: aws.String(bucketName), + Key: aws.String(objectKey), + Body: bytes.NewReader(testData), + }) + require.NoError(t, err, "failed to upload test object") + + t.Run("HeadObject reports accurate Content-Length", func(t *testing.T) { + resp, err := client.HeadObject(ctx, &s3.HeadObjectInput{ + Bucket: aws.String(bucketName), + Key: aws.String(objectKey), + }) + require.NoError(t, err, "HeadObject request failed") + assert.Equal(t, int64(objectSize), resp.ContentLength, "Content-Length mismatch on HEAD") + assert.Equal(t, "bytes", aws.ToString(resp.AcceptRanges), "Accept-Ranges should advertise bytes") + }) + + t.Run("Range request across chunk boundary", func(t *testing.T) { + // Test range that spans an 8MiB chunk boundary (chunkSize - 1KB to chunkSize + 3KB) + rangeStart := int64(chunkSize - 1024) + rangeEnd := rangeStart + 4096 - 1 + rangeHeader := fmt.Sprintf("bytes=%d-%d", rangeStart, rangeEnd) + + resp, err := client.GetObject(ctx, &s3.GetObjectInput{ + Bucket: aws.String(bucketName), + Key: aws.String(objectKey), + Range: aws.String(rangeHeader), + }) + require.NoError(t, err, "GetObject range request failed") + defer resp.Body.Close() + + expectedLen := rangeEnd - rangeStart + 1 + assert.Equal(t, expectedLen, resp.ContentLength, "Content-Length must match requested range size") + assert.Equal(t, + fmt.Sprintf("bytes %d-%d/%d", rangeStart, rangeEnd, objectSize), + aws.ToString(resp.ContentRange), + "Content-Range header mismatch") + + body, err := io.ReadAll(resp.Body) + require.NoError(t, err, "failed to read range response body") + assert.Equal(t, int(expectedLen), len(body), "actual bytes read mismatch") + assert.Equal(t, testData[rangeStart:rangeEnd+1], body, "range payload mismatch") + }) + + t.Run("Suffix range request", func(t *testing.T) { + const suffixSize = 2048 + resp, err := client.GetObject(ctx, &s3.GetObjectInput{ + Bucket: aws.String(bucketName), + Key: aws.String(objectKey), + Range: aws.String(fmt.Sprintf("bytes=-%d", suffixSize)), + }) + require.NoError(t, err, "GetObject suffix range request failed") + defer resp.Body.Close() + + expectedStart := int64(objectSize - suffixSize) + expectedEnd := int64(objectSize - 1) + expectedLen := expectedEnd - expectedStart + 1 + + assert.Equal(t, expectedLen, resp.ContentLength, "suffix Content-Length mismatch") + assert.Equal(t, + fmt.Sprintf("bytes %d-%d/%d", expectedStart, expectedEnd, objectSize), + aws.ToString(resp.ContentRange), + "suffix Content-Range mismatch") + + body, err := io.ReadAll(resp.Body) + require.NoError(t, err, "failed to read suffix range response body") + assert.Equal(t, int(expectedLen), len(body), "suffix range byte count mismatch") + assert.Equal(t, testData[expectedStart:expectedEnd+1], body, "suffix range payload mismatch") + }) +} |
