s3storage_test.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. package storage
  2. import (
  3. "bytes"
  4. "errors"
  5. "io"
  6. "reflect"
  7. "testing"
  8. "github.com/minio/minio-go/v7"
  9. )
  10. // TestS3Storage_protocol tests the protocol() method returns correct values based on insecure flag
  11. func TestS3Storage_protocol(t *testing.T) {
  12. tests := []struct {
  13. name string
  14. insecure bool
  15. want string
  16. }{
  17. {
  18. name: "secure connection returns HTTPS",
  19. insecure: false,
  20. want: "HTTPS",
  21. },
  22. {
  23. name: "insecure connection returns HTTP",
  24. insecure: true,
  25. want: "HTTP",
  26. },
  27. }
  28. for _, tt := range tests {
  29. t.Run(tt.name, func(t *testing.T) {
  30. s3 := &S3Storage{
  31. insecure: tt.insecure,
  32. }
  33. got := s3.protocol()
  34. if got != tt.want {
  35. t.Errorf("S3Storage.protocol() = %v, want %v", got, tt.want)
  36. }
  37. })
  38. }
  39. }
  40. func TestSetGetObjectRange(t *testing.T) {
  41. tests := []struct {
  42. name string
  43. off int64
  44. length int64
  45. expectErr bool
  46. }{
  47. {
  48. name: "full object range",
  49. off: 0,
  50. length: -1,
  51. expectErr: false,
  52. },
  53. {
  54. name: "offset to EOF range",
  55. off: 100,
  56. length: -1,
  57. expectErr: false,
  58. },
  59. {
  60. name: "bounded range",
  61. off: 128,
  62. length: 4096,
  63. expectErr: false,
  64. },
  65. {
  66. name: "negative offset rejected",
  67. off: -1,
  68. length: -1,
  69. expectErr: true,
  70. },
  71. {
  72. name: "zero length rejected",
  73. off: 0,
  74. length: 0,
  75. expectErr: true,
  76. },
  77. {
  78. name: "invalid negative length rejected",
  79. off: 0,
  80. length: -2,
  81. expectErr: true,
  82. },
  83. }
  84. for _, tt := range tests {
  85. t.Run(tt.name, func(t *testing.T) {
  86. opts := &minio.GetObjectOptions{}
  87. err := setGetObjectRange(opts, tt.off, tt.length)
  88. if tt.expectErr && err == nil {
  89. t.Fatalf("expected error, got nil")
  90. }
  91. if !tt.expectErr && err != nil {
  92. t.Fatalf("unexpected error: %v", err)
  93. }
  94. })
  95. }
  96. }
  97. func TestS3ChunkReader_ReadUsesRanges(t *testing.T) {
  98. data := []byte("abcdefghijklmnopqrstuvwxyz")
  99. var calls [][2]int64
  100. reader := newS3ChunkReader(int64(len(data)), 8, func(off, length int64) ([]byte, error) {
  101. calls = append(calls, [2]int64{off, length})
  102. end := off + length
  103. if end > int64(len(data)) {
  104. end = int64(len(data))
  105. }
  106. return data[off:end], nil
  107. })
  108. defer reader.Close()
  109. got, err := io.ReadAll(reader)
  110. if err != nil {
  111. t.Fatalf("reading chunked reader failed: %v", err)
  112. }
  113. if !bytes.Equal(got, data) {
  114. t.Fatalf("data mismatch: got=%q want=%q", string(got), string(data))
  115. }
  116. wantCalls := [][2]int64{
  117. {0, 8},
  118. {8, 8},
  119. {16, 8},
  120. {24, 2},
  121. }
  122. if !reflect.DeepEqual(calls, wantCalls) {
  123. t.Fatalf("range calls mismatch: got=%v want=%v", calls, wantCalls)
  124. }
  125. }
  126. func TestS3ChunkReader_Close(t *testing.T) {
  127. reader := newS3ChunkReader(10, 4, func(off, length int64) ([]byte, error) {
  128. return []byte("xxxx"), nil
  129. })
  130. if err := reader.Close(); err != nil {
  131. t.Fatalf("close failed: %v", err)
  132. }
  133. p := make([]byte, 4)
  134. _, err := reader.Read(p)
  135. if err == nil {
  136. t.Fatal("expected read error after close")
  137. }
  138. }
  139. func TestS3ChunkReader_PropagatesFetchError(t *testing.T) {
  140. reader := newS3ChunkReader(10, 4, func(off, length int64) ([]byte, error) {
  141. return nil, errors.New("fetch failed")
  142. })
  143. defer reader.Close()
  144. p := make([]byte, 4)
  145. _, err := reader.Read(p)
  146. if err == nil || err.Error() != "fetch failed" {
  147. t.Fatalf("expected fetch error, got: %v", err)
  148. }
  149. }