// Copyright (c) 2015-2022 MinIO, Inc. // // This file is part of MinIO Object Storage stack // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . package versioning import ( "encoding/xml" "strings" "testing" ) func TestParseConfig(t *testing.T) { testcases := []struct { input string err error excludedPrefixes []string excludeFolders bool }{ { input: ` Enabled `, err: nil, }, { input: ` Enabled path/to/my/workload/_staging/ path/to/my/workload/_temporary/ `, err: nil, excludedPrefixes: []string{"path/to/my/workload/_staging/", "path/to/my/workload/_temporary/"}, }, { input: ` Suspended path/to/my/workload/_staging `, err: errExcludedPrefixNotSupported, }, { input: ` Enabled path/to/my/workload/_staging/ab/ path/to/my/workload/_staging/cd/ path/to/my/workload/_staging/ef/ path/to/my/workload/_staging/gh/ path/to/my/workload/_staging/ij/ path/to/my/workload/_staging/kl/ path/to/my/workload/_staging/mn/ path/to/my/workload/_staging/op/ path/to/my/workload/_staging/qr/ path/to/my/workload/_staging/st/ path/to/my/workload/_staging/uv/ `, err: errTooManyExcludedPrefixes, }, { input: ` Enabled true path/to/my/workload/_staging/ path/to/my/workload/_temporary/ `, err: nil, excludedPrefixes: []string{"path/to/my/workload/_staging/", "path/to/my/workload/_temporary/"}, excludeFolders: true, }, { input: ` Enabled path/to/my/workload/_staging `, err: errInvalidPrefixPattern, }, } for i, tc := range testcases { var v *Versioning var err error v, err = ParseConfig(strings.NewReader(tc.input)) if tc.err != err { t.Fatalf("Test %d: expected %v but got %v", i+1, tc.err, err) } if err != nil { if tc.err == nil { t.Fatalf("Test %d: failed due to %v", i+1, err) } } else { if err := v.Validate(); tc.err != err { t.Fatalf("Test %d: validation failed due to %v", i+1, err) } if len(tc.excludedPrefixes) > 0 { var mismatch bool if len(v.ExcludedPrefixes) != len(tc.excludedPrefixes) { t.Fatalf("Test %d: Expected length of excluded prefixes %d but got %d", i+1, len(tc.excludedPrefixes), len(v.ExcludedPrefixes)) } var i int var eprefix string for i, eprefix = range tc.excludedPrefixes { if eprefix != v.ExcludedPrefixes[i].Prefix { mismatch = true break } } if mismatch { t.Fatalf("Test %d: Expected excluded prefix %s but got %s", i+1, tc.excludedPrefixes[i], v.ExcludedPrefixes[i].Prefix) } } if tc.excludeFolders != v.ExcludeFolders { t.Fatalf("Test %d: Expected ExcludeFoldersr=%v but got %v", i+1, tc.excludeFolders, v.ExcludeFolders) } } } } func TestMarshalXML(t *testing.T) { // Validates if Versioning with no excluded prefixes omits // ExcludedPrefixes tags v := Versioning{ Status: Enabled, } buf, err := xml.Marshal(v) if err != nil { t.Fatalf("Failed to marshal %v: %v", v, err) } str := string(buf) if strings.Contains(str, "ExcludedPrefixes") { t.Fatalf("XML shouldn't contain ExcludedPrefixes tag - %s", str) } } func TestVersioningZero(t *testing.T) { var v Versioning if v.Enabled() { t.Fatalf("Expected to be disabled but got enabled") } if v.Suspended() { t.Fatalf("Expected to be disabled but got suspended") } } func TestExcludeFolders(t *testing.T) { v := Versioning{ Status: Enabled, ExcludeFolders: true, } testPrefixes := []string{"jobs/output/_temporary/", "jobs/output/", "jobs/"} for i, prefix := range testPrefixes { if v.PrefixEnabled(prefix) || !v.PrefixSuspended(prefix) { t.Fatalf("Test %d: Expected versioning to be excluded for %s", i+1, prefix) } } // Test applicability for regular objects if prefix := "prefix-1/obj-1"; !v.PrefixEnabled(prefix) || v.PrefixSuspended(prefix) { t.Fatalf("Expected versioning to be enabled for %s", prefix) } // Test when ExcludeFolders is disabled v.ExcludeFolders = false for i, prefix := range testPrefixes { if !v.PrefixEnabled(prefix) || v.PrefixSuspended(prefix) { t.Fatalf("Test %d: Expected versioning to be enabled for %s", i+1, prefix) } } } func TestExcludedPrefixesMatch(t *testing.T) { v := Versioning{ Status: Enabled, ExcludedPrefixes: []ExcludedPrefix{{"*/_temporary/"}}, } if err := v.Validate(); err != nil { t.Fatalf("Invalid test versioning config %v: %v", v, err) } tests := []struct { prefix string excluded bool }{ { prefix: "app1-jobs/output/_temporary/attempt1/data.csv", excluded: true, }, { prefix: "app1-jobs/output/final/attempt1/data.csv", excluded: false, }, } for i, test := range tests { if v.PrefixSuspended(test.prefix) != test.excluded { if test.excluded { t.Fatalf("Test %d: Expected prefix %s to be excluded from versioning", i+1, test.prefix) } else { t.Fatalf("Test %d: Expected prefix %s to have versioning enabled", i+1, test.prefix) } } } }