github.com/minio/minio@v0.0.0-20240328213742-3f72439b8a27/internal/crypto/metadata_test.go (about) 1 // Copyright (c) 2015-2021 MinIO, Inc. 2 // 3 // This file is part of MinIO Object Storage stack 4 // 5 // This program is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Affero General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Affero General Public License for more details. 14 // 15 // You should have received a copy of the GNU Affero General Public License 16 // along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 package crypto 19 20 import ( 21 "bytes" 22 "encoding/base64" 23 "encoding/hex" 24 "testing" 25 26 "github.com/minio/minio/internal/logger" 27 ) 28 29 var isMultipartTests = []struct { 30 Metadata map[string]string 31 Multipart bool 32 }{ 33 {Multipart: true, Metadata: map[string]string{MetaMultipart: ""}}, // 0 34 {Multipart: true, Metadata: map[string]string{"X-Minio-Internal-Encrypted-Multipart": ""}}, // 1 35 {Multipart: true, Metadata: map[string]string{MetaMultipart: "some-value"}}, // 2 36 {Multipart: false, Metadata: map[string]string{"": ""}}, // 3 37 {Multipart: false, Metadata: map[string]string{"X-Minio-Internal-EncryptedMultipart": ""}}, // 4 38 } 39 40 func TestIsMultipart(t *testing.T) { 41 for i, test := range isMultipartTests { 42 if isMultipart := IsMultiPart(test.Metadata); isMultipart != test.Multipart { 43 t.Errorf("Test %d: got '%v' - want '%v'", i, isMultipart, test.Multipart) 44 } 45 } 46 } 47 48 var isEncryptedTests = []struct { 49 Metadata map[string]string 50 Encrypted bool 51 }{ 52 {Encrypted: true, Metadata: map[string]string{MetaMultipart: ""}}, // 0 53 {Encrypted: true, Metadata: map[string]string{MetaIV: ""}}, // 1 54 {Encrypted: true, Metadata: map[string]string{MetaAlgorithm: ""}}, // 2 55 {Encrypted: true, Metadata: map[string]string{MetaSealedKeySSEC: ""}}, // 3 56 {Encrypted: true, Metadata: map[string]string{MetaSealedKeyS3: ""}}, // 4 57 {Encrypted: true, Metadata: map[string]string{MetaKeyID: ""}}, // 5 58 {Encrypted: true, Metadata: map[string]string{MetaDataEncryptionKey: ""}}, // 6 59 {Encrypted: false, Metadata: map[string]string{"": ""}}, // 7 60 {Encrypted: false, Metadata: map[string]string{"X-Minio-Internal-Server-Side-Encryption": ""}}, // 8 61 } 62 63 func TestIsEncrypted(t *testing.T) { 64 for i, test := range isEncryptedTests { 65 if _, isEncrypted := IsEncrypted(test.Metadata); isEncrypted != test.Encrypted { 66 t.Errorf("Test %d: got '%v' - want '%v'", i, isEncrypted, test.Encrypted) 67 } 68 } 69 } 70 71 var s3IsEncryptedTests = []struct { 72 Metadata map[string]string 73 Encrypted bool 74 }{ 75 {Encrypted: false, Metadata: map[string]string{MetaMultipart: ""}}, // 0 76 {Encrypted: false, Metadata: map[string]string{MetaIV: ""}}, // 1 77 {Encrypted: false, Metadata: map[string]string{MetaAlgorithm: ""}}, // 2 78 {Encrypted: false, Metadata: map[string]string{MetaSealedKeySSEC: ""}}, // 3 79 {Encrypted: true, Metadata: map[string]string{MetaSealedKeyS3: ""}}, // 4 80 {Encrypted: false, Metadata: map[string]string{MetaKeyID: ""}}, // 5 81 {Encrypted: false, Metadata: map[string]string{MetaDataEncryptionKey: ""}}, // 6 82 {Encrypted: false, Metadata: map[string]string{"": ""}}, // 7 83 {Encrypted: false, Metadata: map[string]string{"X-Minio-Internal-Server-Side-Encryption": ""}}, // 8 84 } 85 86 func TestS3IsEncrypted(t *testing.T) { 87 for i, test := range s3IsEncryptedTests { 88 if isEncrypted := S3.IsEncrypted(test.Metadata); isEncrypted != test.Encrypted { 89 t.Errorf("Test %d: got '%v' - want '%v'", i, isEncrypted, test.Encrypted) 90 } 91 } 92 } 93 94 var ssecIsEncryptedTests = []struct { 95 Metadata map[string]string 96 Encrypted bool 97 }{ 98 {Encrypted: false, Metadata: map[string]string{MetaMultipart: ""}}, // 0 99 {Encrypted: false, Metadata: map[string]string{MetaIV: ""}}, // 1 100 {Encrypted: false, Metadata: map[string]string{MetaAlgorithm: ""}}, // 2 101 {Encrypted: true, Metadata: map[string]string{MetaSealedKeySSEC: ""}}, // 3 102 {Encrypted: false, Metadata: map[string]string{MetaSealedKeyS3: ""}}, // 4 103 {Encrypted: false, Metadata: map[string]string{MetaKeyID: ""}}, // 5 104 {Encrypted: false, Metadata: map[string]string{MetaDataEncryptionKey: ""}}, // 6 105 {Encrypted: false, Metadata: map[string]string{"": ""}}, // 7 106 {Encrypted: false, Metadata: map[string]string{"X-Minio-Internal-Server-Side-Encryption": ""}}, // 8 107 } 108 109 func TestSSECIsEncrypted(t *testing.T) { 110 for i, test := range ssecIsEncryptedTests { 111 if isEncrypted := SSEC.IsEncrypted(test.Metadata); isEncrypted != test.Encrypted { 112 t.Errorf("Test %d: got '%v' - want '%v'", i, isEncrypted, test.Encrypted) 113 } 114 } 115 } 116 117 var s3ParseMetadataTests = []struct { 118 Metadata map[string]string 119 ExpectedErr error 120 121 DataKey []byte 122 KeyID string 123 SealedKey SealedKey 124 }{ 125 {ExpectedErr: errMissingInternalIV, Metadata: map[string]string{}, DataKey: []byte{}, KeyID: "", SealedKey: SealedKey{}}, // 0 126 { 127 ExpectedErr: errMissingInternalSealAlgorithm, Metadata: map[string]string{MetaIV: ""}, 128 DataKey: []byte{}, KeyID: "", SealedKey: SealedKey{}, 129 }, // 1 130 { 131 ExpectedErr: Errorf("The object metadata is missing the internal sealed key for SSE-S3"), 132 Metadata: map[string]string{MetaIV: "", MetaAlgorithm: ""}, DataKey: []byte{}, KeyID: "", SealedKey: SealedKey{}, 133 }, // 2 134 { 135 ExpectedErr: Errorf("The object metadata is missing the internal KMS key-ID for SSE-S3"), 136 Metadata: map[string]string{MetaIV: "", MetaAlgorithm: "", MetaSealedKeyS3: "", MetaDataEncryptionKey: "IAAF0b=="}, DataKey: []byte{}, KeyID: "", SealedKey: SealedKey{}, 137 }, // 3 138 { 139 ExpectedErr: Errorf("The object metadata is missing the internal sealed KMS data key for SSE-S3"), 140 Metadata: map[string]string{MetaIV: "", MetaAlgorithm: "", MetaSealedKeyS3: "", MetaKeyID: ""}, 141 DataKey: []byte{}, KeyID: "", SealedKey: SealedKey{}, 142 }, // 4 143 { 144 ExpectedErr: errInvalidInternalIV, 145 Metadata: map[string]string{MetaIV: "", MetaAlgorithm: "", MetaSealedKeyS3: "", MetaKeyID: "", MetaDataEncryptionKey: ""}, 146 DataKey: []byte{}, KeyID: "", SealedKey: SealedKey{}, 147 }, // 5 148 { 149 ExpectedErr: errInvalidInternalSealAlgorithm, 150 Metadata: map[string]string{ 151 MetaIV: base64.StdEncoding.EncodeToString(make([]byte, 32)), MetaAlgorithm: "", MetaSealedKeyS3: "", MetaKeyID: "", MetaDataEncryptionKey: "", 152 }, 153 DataKey: []byte{}, KeyID: "", SealedKey: SealedKey{}, 154 }, // 6 155 { 156 ExpectedErr: Errorf("The internal sealed key for SSE-S3 is invalid"), 157 Metadata: map[string]string{ 158 MetaIV: base64.StdEncoding.EncodeToString(make([]byte, 32)), MetaAlgorithm: SealAlgorithm, MetaSealedKeyS3: "", 159 MetaKeyID: "", MetaDataEncryptionKey: "", 160 }, 161 DataKey: []byte{}, KeyID: "", SealedKey: SealedKey{}, 162 }, // 7 163 { 164 ExpectedErr: Errorf("The internal sealed KMS data key for SSE-S3 is invalid"), 165 Metadata: map[string]string{ 166 MetaIV: base64.StdEncoding.EncodeToString(make([]byte, 32)), MetaAlgorithm: SealAlgorithm, 167 MetaSealedKeyS3: base64.StdEncoding.EncodeToString(make([]byte, 64)), MetaKeyID: "key-1", 168 MetaDataEncryptionKey: ".MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ=", // invalid base64 169 }, 170 DataKey: []byte{}, KeyID: "key-1", SealedKey: SealedKey{}, 171 }, // 8 172 { 173 ExpectedErr: nil, 174 Metadata: map[string]string{ 175 MetaIV: base64.StdEncoding.EncodeToString(make([]byte, 32)), MetaAlgorithm: SealAlgorithm, 176 MetaSealedKeyS3: base64.StdEncoding.EncodeToString(make([]byte, 64)), MetaKeyID: "", MetaDataEncryptionKey: "", 177 }, 178 DataKey: []byte{}, KeyID: "", SealedKey: SealedKey{Algorithm: SealAlgorithm}, 179 }, // 9 180 { 181 ExpectedErr: nil, 182 Metadata: map[string]string{ 183 MetaIV: base64.StdEncoding.EncodeToString(append([]byte{1}, make([]byte, 31)...)), MetaAlgorithm: SealAlgorithm, 184 MetaSealedKeyS3: base64.StdEncoding.EncodeToString(append([]byte{1}, make([]byte, 63)...)), MetaKeyID: "key-1", 185 MetaDataEncryptionKey: base64.StdEncoding.EncodeToString(make([]byte, 48)), 186 }, 187 DataKey: make([]byte, 48), KeyID: "key-1", SealedKey: SealedKey{Algorithm: SealAlgorithm, Key: [64]byte{1}, IV: [32]byte{1}}, 188 }, // 10 189 } 190 191 func TestS3ParseMetadata(t *testing.T) { 192 for i, test := range s3ParseMetadataTests { 193 keyID, dataKey, sealedKey, err := S3.ParseMetadata(test.Metadata) 194 if err != nil && test.ExpectedErr == nil { 195 t.Errorf("Test %d: got error '%v' - want error '%v'", i, err, test.ExpectedErr) 196 } 197 if err == nil && test.ExpectedErr != nil { 198 t.Errorf("Test %d: got error '%v' - want error '%v'", i, err, test.ExpectedErr) 199 } 200 if err != nil && test.ExpectedErr != nil { 201 if err.Error() != test.ExpectedErr.Error() { 202 t.Errorf("Test %d: got error '%v' - want error '%v'", i, err, test.ExpectedErr) 203 } 204 } 205 if !bytes.Equal(dataKey, test.DataKey) { 206 t.Errorf("Test %d: got data key '%v' - want data key '%v'", i, dataKey, test.DataKey) 207 } 208 if keyID != test.KeyID { 209 t.Errorf("Test %d: got key-ID '%v' - want key-ID '%v'", i, keyID, test.KeyID) 210 } 211 if sealedKey.Algorithm != test.SealedKey.Algorithm { 212 t.Errorf("Test %d: got sealed key algorithm '%v' - want sealed key algorithm '%v'", i, sealedKey.Algorithm, test.SealedKey.Algorithm) 213 } 214 if !bytes.Equal(sealedKey.Key[:], test.SealedKey.Key[:]) { 215 t.Errorf("Test %d: got sealed key '%v' - want sealed key '%v'", i, sealedKey.Key, test.SealedKey.Key) 216 } 217 if !bytes.Equal(sealedKey.IV[:], test.SealedKey.IV[:]) { 218 t.Errorf("Test %d: got sealed key IV '%v' - want sealed key IV '%v'", i, sealedKey.IV, test.SealedKey.IV) 219 } 220 } 221 } 222 223 var ssecParseMetadataTests = []struct { 224 Metadata map[string]string 225 ExpectedErr error 226 227 SealedKey SealedKey 228 }{ 229 {ExpectedErr: errMissingInternalIV, Metadata: map[string]string{}, SealedKey: SealedKey{}}, // 0 230 {ExpectedErr: errMissingInternalSealAlgorithm, Metadata: map[string]string{MetaIV: ""}, SealedKey: SealedKey{}}, // 1 231 { 232 ExpectedErr: Errorf("The object metadata is missing the internal sealed key for SSE-C"), 233 Metadata: map[string]string{MetaIV: "", MetaAlgorithm: ""}, SealedKey: SealedKey{}, 234 }, // 2 235 { 236 ExpectedErr: errInvalidInternalIV, 237 Metadata: map[string]string{MetaIV: "", MetaAlgorithm: "", MetaSealedKeySSEC: ""}, SealedKey: SealedKey{}, 238 }, // 3 239 { 240 ExpectedErr: errInvalidInternalSealAlgorithm, 241 Metadata: map[string]string{ 242 MetaIV: base64.StdEncoding.EncodeToString(make([]byte, 32)), MetaAlgorithm: "", MetaSealedKeySSEC: "", 243 }, 244 SealedKey: SealedKey{}, 245 }, // 4 246 { 247 ExpectedErr: Errorf("The internal sealed key for SSE-C is invalid"), 248 Metadata: map[string]string{ 249 MetaIV: base64.StdEncoding.EncodeToString(make([]byte, 32)), MetaAlgorithm: SealAlgorithm, MetaSealedKeySSEC: "", 250 }, 251 SealedKey: SealedKey{}, 252 }, // 5 253 { 254 ExpectedErr: nil, 255 Metadata: map[string]string{ 256 MetaIV: base64.StdEncoding.EncodeToString(make([]byte, 32)), MetaAlgorithm: SealAlgorithm, 257 MetaSealedKeySSEC: base64.StdEncoding.EncodeToString(make([]byte, 64)), 258 }, 259 SealedKey: SealedKey{Algorithm: SealAlgorithm}, 260 }, // 6 261 { 262 ExpectedErr: nil, 263 Metadata: map[string]string{ 264 MetaIV: base64.StdEncoding.EncodeToString(append([]byte{1}, make([]byte, 31)...)), MetaAlgorithm: InsecureSealAlgorithm, 265 MetaSealedKeySSEC: base64.StdEncoding.EncodeToString(append([]byte{1}, make([]byte, 63)...)), 266 }, 267 SealedKey: SealedKey{Algorithm: InsecureSealAlgorithm, Key: [64]byte{1}, IV: [32]byte{1}}, 268 }, // 7 269 } 270 271 func TestCreateMultipartMetadata(t *testing.T) { 272 metadata := CreateMultipartMetadata(nil) 273 if v, ok := metadata[MetaMultipart]; !ok || v != "" { 274 t.Errorf("Metadata is missing the correct value for '%s': got '%s' - want '%s'", MetaMultipart, v, "") 275 } 276 } 277 278 func TestSSECParseMetadata(t *testing.T) { 279 for i, test := range ssecParseMetadataTests { 280 sealedKey, err := SSEC.ParseMetadata(test.Metadata) 281 if err != nil && test.ExpectedErr == nil { 282 t.Errorf("Test %d: got error '%v' - want error '%v'", i, err, test.ExpectedErr) 283 } 284 if err == nil && test.ExpectedErr != nil { 285 t.Errorf("Test %d: got error '%v' - want error '%v'", i, err, test.ExpectedErr) 286 } 287 if err != nil && test.ExpectedErr != nil { 288 if err.Error() != test.ExpectedErr.Error() { 289 t.Errorf("Test %d: got error '%v' - want error '%v'", i, err, test.ExpectedErr) 290 } 291 } 292 if sealedKey.Algorithm != test.SealedKey.Algorithm { 293 t.Errorf("Test %d: got sealed key algorithm '%v' - want sealed key algorithm '%v'", i, sealedKey.Algorithm, test.SealedKey.Algorithm) 294 } 295 if !bytes.Equal(sealedKey.Key[:], test.SealedKey.Key[:]) { 296 t.Errorf("Test %d: got sealed key '%v' - want sealed key '%v'", i, sealedKey.Key, test.SealedKey.Key) 297 } 298 if !bytes.Equal(sealedKey.IV[:], test.SealedKey.IV[:]) { 299 t.Errorf("Test %d: got sealed key IV '%v' - want sealed key IV '%v'", i, sealedKey.IV, test.SealedKey.IV) 300 } 301 } 302 } 303 304 var s3CreateMetadataTests = []struct { 305 KeyID string 306 SealedDataKey []byte 307 SealedKey SealedKey 308 }{ 309 {KeyID: "", SealedDataKey: nil, SealedKey: SealedKey{Algorithm: SealAlgorithm}}, 310 {KeyID: "my-minio-key", SealedDataKey: make([]byte, 48), SealedKey: SealedKey{Algorithm: SealAlgorithm}}, 311 {KeyID: "cafebabe", SealedDataKey: make([]byte, 48), SealedKey: SealedKey{Algorithm: SealAlgorithm}}, 312 {KeyID: "deadbeef", SealedDataKey: make([]byte, 32), SealedKey: SealedKey{IV: [32]byte{0xf7}, Key: [64]byte{0xea}, Algorithm: SealAlgorithm}}, 313 } 314 315 func TestS3CreateMetadata(t *testing.T) { 316 defer func(l bool) { logger.DisableErrorLog = l }(logger.DisableErrorLog) 317 logger.DisableErrorLog = true 318 for i, test := range s3CreateMetadataTests { 319 metadata := S3.CreateMetadata(nil, test.KeyID, test.SealedDataKey, test.SealedKey) 320 keyID, kmsKey, sealedKey, err := S3.ParseMetadata(metadata) 321 if err != nil { 322 t.Errorf("Test %d: failed to parse metadata: %v", i, err) 323 continue 324 } 325 if keyID != test.KeyID { 326 t.Errorf("Test %d: Key-ID mismatch: got '%s' - want '%s'", i, keyID, test.KeyID) 327 } 328 if !bytes.Equal(kmsKey, test.SealedDataKey) { 329 t.Errorf("Test %d: sealed KMS data mismatch: got '%v' - want '%v'", i, kmsKey, test.SealedDataKey) 330 } 331 if sealedKey.Algorithm != test.SealedKey.Algorithm { 332 t.Errorf("Test %d: seal algorithm mismatch: got '%s' - want '%s'", i, sealedKey.Algorithm, test.SealedKey.Algorithm) 333 } 334 if !bytes.Equal(sealedKey.IV[:], test.SealedKey.IV[:]) { 335 t.Errorf("Test %d: IV mismatch: got '%v' - want '%v'", i, sealedKey.IV, test.SealedKey.IV) 336 } 337 if !bytes.Equal(sealedKey.Key[:], test.SealedKey.Key[:]) { 338 t.Errorf("Test %d: sealed key mismatch: got '%v' - want '%v'", i, sealedKey.Key, test.SealedKey.Key) 339 } 340 } 341 342 defer func() { 343 if err := recover(); err == nil || err != logger.ErrCritical { 344 t.Errorf("Expected '%s' panic for invalid seal algorithm but got '%s'", logger.ErrCritical, err) 345 } 346 }() 347 _ = S3.CreateMetadata(nil, "", []byte{}, SealedKey{Algorithm: InsecureSealAlgorithm}) 348 } 349 350 var ssecCreateMetadataTests = []struct { 351 KeyID string 352 SealedDataKey []byte 353 SealedKey SealedKey 354 }{ 355 {KeyID: "", SealedDataKey: make([]byte, 48), SealedKey: SealedKey{Algorithm: SealAlgorithm}}, 356 {KeyID: "cafebabe", SealedDataKey: make([]byte, 48), SealedKey: SealedKey{Algorithm: SealAlgorithm}}, 357 {KeyID: "deadbeef", SealedDataKey: make([]byte, 32), SealedKey: SealedKey{IV: [32]byte{0xf7}, Key: [64]byte{0xea}, Algorithm: SealAlgorithm}}, 358 } 359 360 func TestSSECCreateMetadata(t *testing.T) { 361 defer func(l bool) { logger.DisableErrorLog = l }(logger.DisableErrorLog) 362 logger.DisableErrorLog = true 363 for i, test := range ssecCreateMetadataTests { 364 metadata := SSEC.CreateMetadata(nil, test.SealedKey) 365 sealedKey, err := SSEC.ParseMetadata(metadata) 366 if err != nil { 367 t.Errorf("Test %d: failed to parse metadata: %v", i, err) 368 continue 369 } 370 if sealedKey.Algorithm != test.SealedKey.Algorithm { 371 t.Errorf("Test %d: seal algorithm mismatch: got '%s' - want '%s'", i, sealedKey.Algorithm, test.SealedKey.Algorithm) 372 } 373 if !bytes.Equal(sealedKey.IV[:], test.SealedKey.IV[:]) { 374 t.Errorf("Test %d: IV mismatch: got '%v' - want '%v'", i, sealedKey.IV, test.SealedKey.IV) 375 } 376 if !bytes.Equal(sealedKey.Key[:], test.SealedKey.Key[:]) { 377 t.Errorf("Test %d: sealed key mismatch: got '%v' - want '%v'", i, sealedKey.Key, test.SealedKey.Key) 378 } 379 } 380 381 defer func() { 382 if err := recover(); err == nil || err != logger.ErrCritical { 383 t.Errorf("Expected '%s' panic for invalid seal algorithm but got '%s'", logger.ErrCritical, err) 384 } 385 }() 386 _ = SSEC.CreateMetadata(nil, SealedKey{Algorithm: InsecureSealAlgorithm}) 387 } 388 389 var isETagSealedTests = []struct { 390 ETag string 391 IsSealed bool 392 }{ 393 {ETag: "", IsSealed: false}, // 0 394 {ETag: "90682b8e8cc7609c4671e1d64c73fc30", IsSealed: false}, // 1 395 {ETag: "f201040c9dc593e39ea004dc1323699bcd", IsSealed: true}, // 2 not valid ciphertext but looks like sealed ETag 396 {ETag: "20000f00fba2ee2ae4845f725964eeb9e092edfabc7ab9f9239e8344341f769a51ce99b4801b0699b92b16a72fa94972", IsSealed: true}, // 3 397 } 398 399 func TestIsETagSealed(t *testing.T) { 400 for i, test := range isETagSealedTests { 401 etag, err := hex.DecodeString(test.ETag) 402 if err != nil { 403 t.Errorf("Test %d: failed to decode etag: %s", i, err) 404 } 405 if sealed := IsETagSealed(etag); sealed != test.IsSealed { 406 t.Errorf("Test %d: got %v - want %v", i, sealed, test.IsSealed) 407 } 408 } 409 } 410 411 var removeInternalEntriesTests = []struct { 412 Metadata, Expected map[string]string 413 }{ 414 { // 0 415 Metadata: map[string]string{ 416 MetaMultipart: "", 417 MetaIV: "", 418 MetaAlgorithm: "", 419 MetaSealedKeySSEC: "", 420 MetaSealedKeyS3: "", 421 MetaKeyID: "", 422 MetaDataEncryptionKey: "", 423 }, 424 Expected: map[string]string{}, 425 }, 426 { // 1 427 Metadata: map[string]string{ 428 MetaMultipart: "", 429 MetaIV: "", 430 "X-Amz-Meta-A": "X", 431 "X-Minio-Internal-B": "Y", 432 }, 433 Expected: map[string]string{ 434 "X-Amz-Meta-A": "X", 435 "X-Minio-Internal-B": "Y", 436 }, 437 }, 438 } 439 440 func TestRemoveInternalEntries(t *testing.T) { 441 isEqual := func(x, y map[string]string) bool { 442 if len(x) != len(y) { 443 return false 444 } 445 for k, v := range x { 446 if u, ok := y[k]; !ok || v != u { 447 return false 448 } 449 } 450 return true 451 } 452 453 for i, test := range removeInternalEntriesTests { 454 RemoveInternalEntries(test.Metadata) 455 if !isEqual(test.Metadata, test.Expected) { 456 t.Errorf("Test %d: got %v - want %v", i, test.Metadata, test.Expected) 457 } 458 } 459 }