Merge pull request #2475 from dualfroz/fix/mp-lister-truncated

fix: compute IsTruncated from the absolute index in ListMultipartUploads
This commit is contained in:
Ben McClelland
2026-10-08 12:00:13 -07:00
committed by GitHub
3 changed files with 58 additions and 1 deletions
+2 -1
View File
@@ -113,7 +113,8 @@ func (l *MultipartUploadLister) Run() (*ListMultipartUploadsPage, error) {
return emitted == l.MaxUploads
}
for i, up := range l.Uploads[startIndex:] {
for i := startIndex; i < len(l.Uploads); i++ {
up := l.Uploads[i]
if l.Delimiter != "" {
// delimiter check
suffix := strings.TrimPrefix(up.Key, l.Prefix)
+54
View File
@@ -537,6 +537,60 @@ func ListMultipartUploads_delimiter_truncated(s *S3Conf) error {
})
}
func ListMultipartUploads_upload_id_marker_truncated(s *S3Conf) error {
testName := "ListMultipartUploads_upload_id_marker_truncated"
return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {
uploads := make([]types.MultipartUpload, 0, 3)
for _, key := range []string{"bar", "baz", "foo"} {
out, err := createMp(s3client, bucket, key)
if err != nil {
return err
}
uploads = append(uploads, types.MultipartUpload{
Key: out.Key,
UploadId: out.UploadId,
StorageClass: types.StorageClassStandard,
})
}
// the listing starts after the first upload, so a page of 1
// leaves one upload behind and a page of 2 reaches the end
for _, test := range []struct {
maxUploads int32
expected []types.MultipartUpload
truncated bool
}{
{1, uploads[1:2], true},
{2, uploads[1:], false},
} {
ctx, cancel := context.WithTimeout(context.Background(), shortTimeout)
out, err := s3client.ListMultipartUploads(ctx, &s3.ListMultipartUploadsInput{
Bucket: &bucket,
KeyMarker: uploads[0].Key,
UploadIdMarker: uploads[0].UploadId,
MaxUploads: &test.maxUploads,
})
cancel()
if err != nil {
return err
}
if !compareMultipartUploads(test.expected, out.Uploads) {
return fmt.Errorf("expected the mp list to be %v, instead got %v", test.expected, out.Uploads)
}
if out.IsTruncated == nil {
return fmt.Errorf("unexpected nil is-truncated")
}
if *out.IsTruncated != test.truncated {
return fmt.Errorf("expected is-truncated to be %v with max-uploads %v, instead got %v",
test.truncated, test.maxUploads, *out.IsTruncated)
}
}
return nil
})
}
func ListMultipartUploads_prefix(s *S3Conf) error {
testName := "ListMultipartUploads_prefix"
return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {
+2
View File
@@ -558,6 +558,7 @@ func TestListMultipartUploads(ts *TestState) {
ts.Run(ListMultipartUploads_keyMarker_not_from_list)
ts.Run(ListMultipartUploads_upload_id_marker_with_key_marker)
ts.Run(ListMultipartUploads_delimiter_truncated)
ts.Run(ListMultipartUploads_upload_id_marker_truncated)
ts.Run(ListMultipartUploads_prefix)
ts.Run(ListMultipartUploads_both_delimiter_and_prefix)
ts.Run(ListMultipartUploads_delimiter_no_matches)
@@ -3331,6 +3332,7 @@ func GetIntTests() IntTests {
"ListMultipartUploads_keyMarker_not_from_list": ListMultipartUploads_keyMarker_not_from_list,
"ListMultipartUploads_upload_id_marker_with_key_marker": ListMultipartUploads_upload_id_marker_with_key_marker,
"ListMultipartUploads_delimiter_truncated": ListMultipartUploads_delimiter_truncated,
"ListMultipartUploads_upload_id_marker_truncated": ListMultipartUploads_upload_id_marker_truncated,
"ListMultipartUploads_prefix": ListMultipartUploads_prefix,
"ListMultipartUploads_both_delimiter_and_prefix": ListMultipartUploads_both_delimiter_and_prefix,
"ListMultipartUploads_with_upload_id": ListMultipartUploads_with_upload_id,