storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/cmd/handler-utils_test.go (about) 1 /* 2 * MinIO Cloud Storage, (C) 2015, 2016, 2017 MinIO, Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package cmd 18 19 import ( 20 "bytes" 21 "context" 22 "encoding/xml" 23 "io/ioutil" 24 "net/http" 25 "net/textproto" 26 "os" 27 "reflect" 28 "strings" 29 "testing" 30 31 "storj.io/minio/cmd/config" 32 ) 33 34 // Tests validate bucket LocationConstraint. 35 func TestIsValidLocationContraint(t *testing.T) { 36 obj, fsDir, err := prepareFS() 37 if err != nil { 38 t.Fatal(err) 39 } 40 defer os.RemoveAll(fsDir) 41 if err = newTestConfig(globalMinioDefaultRegion, obj); err != nil { 42 t.Fatal(err) 43 } 44 45 // Corrupted XML 46 malformedReq := &http.Request{ 47 Body: ioutil.NopCloser(bytes.NewReader([]byte("<>"))), 48 ContentLength: int64(len("<>")), 49 } 50 51 // Not an XML 52 badRequest := &http.Request{ 53 Body: ioutil.NopCloser(bytes.NewReader([]byte("garbage"))), 54 ContentLength: int64(len("garbage")), 55 } 56 57 // generates the input request with XML bucket configuration set to the request body. 58 createExpectedRequest := func(req *http.Request, location string) *http.Request { 59 createBucketConfig := createBucketLocationConfiguration{} 60 createBucketConfig.Location = location 61 createBucketConfigBytes, _ := xml.Marshal(createBucketConfig) 62 createBucketConfigBuffer := bytes.NewReader(createBucketConfigBytes) 63 req.Body = ioutil.NopCloser(createBucketConfigBuffer) 64 req.ContentLength = int64(createBucketConfigBuffer.Len()) 65 return req 66 } 67 68 testCases := []struct { 69 request *http.Request 70 serverConfigRegion string 71 expectedCode APIErrorCode 72 }{ 73 // Test case - 1. 74 {createExpectedRequest(&http.Request{}, "eu-central-1"), globalMinioDefaultRegion, ErrNone}, 75 // Test case - 2. 76 // In case of empty request body ErrNone is returned. 77 {createExpectedRequest(&http.Request{}, ""), globalMinioDefaultRegion, ErrNone}, 78 // Test case - 3 79 // In case of garbage request body ErrMalformedXML is returned. 80 {badRequest, globalMinioDefaultRegion, ErrMalformedXML}, 81 // Test case - 4 82 // In case of invalid XML request body ErrMalformedXML is returned. 83 {malformedReq, globalMinioDefaultRegion, ErrMalformedXML}, 84 } 85 86 for i, testCase := range testCases { 87 config.SetRegion(globalServerConfig, testCase.serverConfigRegion) 88 _, actualCode := parseLocationConstraint(testCase.request) 89 if testCase.expectedCode != actualCode { 90 t.Errorf("Test %d: Expected the APIErrCode to be %d, but instead found %d", i+1, testCase.expectedCode, actualCode) 91 } 92 } 93 } 94 95 // Test validate form field size. 96 func TestValidateFormFieldSize(t *testing.T) { 97 testCases := []struct { 98 header http.Header 99 err error 100 }{ 101 // Empty header returns error as nil, 102 { 103 header: nil, 104 err: nil, 105 }, 106 // Valid header returns error as nil. 107 { 108 header: http.Header{ 109 "Content-Type": []string{"image/png"}, 110 }, 111 err: nil, 112 }, 113 // Invalid header value > maxFormFieldSize+1 114 { 115 header: http.Header{ 116 "Garbage": []string{strings.Repeat("a", int(maxFormFieldSize)+1)}, 117 }, 118 err: errSizeUnexpected, 119 }, 120 } 121 122 // Run validate form field size check under all test cases. 123 for i, testCase := range testCases { 124 err := validateFormFieldSize(context.Background(), testCase.header) 125 if err != nil { 126 if err.Error() != testCase.err.Error() { 127 t.Errorf("Test %d: Expected error %s, got %s", i+1, testCase.err, err) 128 } 129 } 130 } 131 } 132 133 // Tests validate metadata extraction from http headers. 134 func TestExtractMetadataHeaders(t *testing.T) { 135 testCases := []struct { 136 header http.Header 137 metadata map[string]string 138 shouldFail bool 139 }{ 140 // Validate if there a known 'content-type'. 141 { 142 header: http.Header{ 143 "Content-Type": []string{"image/png"}, 144 }, 145 metadata: map[string]string{ 146 "content-type": "image/png", 147 }, 148 shouldFail: false, 149 }, 150 // Validate if there are no keys to extract. 151 { 152 header: http.Header{ 153 "Test-1": []string{"123"}, 154 }, 155 metadata: map[string]string{}, 156 shouldFail: false, 157 }, 158 // Validate that there are all headers extracted 159 { 160 header: http.Header{ 161 "X-Amz-Meta-Appid": []string{"amz-meta"}, 162 "X-Minio-Meta-Appid": []string{"minio-meta"}, 163 }, 164 metadata: map[string]string{ 165 "X-Amz-Meta-Appid": "amz-meta", 166 "X-Minio-Meta-Appid": "minio-meta", 167 }, 168 shouldFail: false, 169 }, 170 // Fail if header key is not in canonicalized form 171 { 172 header: http.Header{ 173 "x-amz-meta-appid": []string{"amz-meta"}, 174 }, 175 metadata: map[string]string{ 176 "x-amz-meta-appid": "amz-meta", 177 }, 178 shouldFail: false, 179 }, 180 // Support multiple values 181 { 182 header: http.Header{ 183 "x-amz-meta-key": []string{"amz-meta1", "amz-meta2"}, 184 }, 185 metadata: map[string]string{ 186 "x-amz-meta-key": "amz-meta1,amz-meta2", 187 }, 188 shouldFail: false, 189 }, 190 // Empty header input returns empty metadata. 191 { 192 header: nil, 193 metadata: nil, 194 shouldFail: true, 195 }, 196 } 197 198 // Validate if the extracting headers. 199 for i, testCase := range testCases { 200 metadata := make(map[string]string) 201 err := extractMetadataFromMime(context.Background(), textproto.MIMEHeader(testCase.header), metadata) 202 if err != nil && !testCase.shouldFail { 203 t.Fatalf("Test %d failed to extract metadata: %v", i+1, err) 204 } 205 if err == nil && testCase.shouldFail { 206 t.Fatalf("Test %d should fail, but it passed", i+1) 207 } 208 if err == nil && !reflect.DeepEqual(metadata, testCase.metadata) { 209 t.Fatalf("Test %d failed: Expected \"%#v\", got \"%#v\"", i+1, testCase.metadata, metadata) 210 } 211 } 212 } 213 214 // Test getResource() 215 func TestGetResource(t *testing.T) { 216 testCases := []struct { 217 p string 218 host string 219 domains []string 220 expectedResource string 221 }{ 222 {"/a/b/c", "test.mydomain.com", []string{"mydomain.com"}, "/test/a/b/c"}, 223 {"/a/b/c", "test.mydomain.com", []string{"notmydomain.com"}, "/a/b/c"}, 224 {"/a/b/c", "test.mydomain.com", nil, "/a/b/c"}, 225 } 226 for i, test := range testCases { 227 gotResource, err := getResource(test.p, test.host, test.domains) 228 if err != nil { 229 t.Fatal(err) 230 } 231 if gotResource != test.expectedResource { 232 t.Fatalf("test %d: expected %s got %s", i+1, test.expectedResource, gotResource) 233 } 234 } 235 }