// Copyright 2015 Google Inc. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package common import ( "errors" "fmt" "reflect" "strings" "testing" ) type strsTestCase struct { in []string out string err []error } var commonValidatePathTestCases = []strsTestCase{ { in: []string{""}, out: "", }, { in: []string{"a/b"}, out: "a/b", }, { in: []string{"a/b", "c"}, out: "a/b/c", }, { in: []string{"a/.."}, out: ".", }, { in: []string{"."}, out: ".", }, { in: []string{".."}, out: "", err: []error{errors.New("Path is outside directory: ..")}, }, { in: []string{"../a"}, out: "", err: []error{errors.New("Path is outside directory: ../a")}, }, { in: []string{"b/../../a"}, out: "", err: []error{errors.New("Path is outside directory: ../a")}, }, { in: []string{"/a"}, out: "", err: []error{errors.New("Path is outside directory: /a")}, }, { in: []string{"a", "../b"}, out: "", err: []error{errors.New("Path is outside directory: ../b")}, }, { in: []string{"a", "b/../../c"}, out: "", err: []error{errors.New("Path is outside directory: ../c")}, }, { in: []string{"a", "./.."}, out: "", err: []error{errors.New("Path is outside directory: ..")}, }, } var validateSafePathTestCases = append(commonValidatePathTestCases, []strsTestCase{ { in: []string{"$host/../$a"}, out: "$a", }, }...) var validatePathTestCases = append(commonValidatePathTestCases, []strsTestCase{ { in: []string{"$host/../$a"}, out: "", err: []error{errors.New("Path contains invalid character($): $host/../$a")}, }, { in: []string{"$host/.."}, out: "", err: []error{errors.New("Path contains invalid character($): $host/..")}, }, }...) func TestValidateSafePath(t *testing.T) { for _, testCase := range validateSafePathTestCases { ctx := &configErrorWrapper{} out := validateSafePath(ctx, testCase.in...) check(t, "validateSafePath", p(testCase.in), out, ctx.errors, testCase.out, testCase.err) } } func TestValidatePath(t *testing.T) { for _, testCase := range validatePathTestCases { ctx := &configErrorWrapper{} out := validatePath(ctx, testCase.in...) check(t, "validatePath", p(testCase.in), out, ctx.errors, testCase.out, testCase.err) } } func TestOptionalPath(t *testing.T) { var path OptionalPath checkInvalidOptionalPath(t, path) path = OptionalPathForPath(nil) checkInvalidOptionalPath(t, path) } func checkInvalidOptionalPath(t *testing.T, path OptionalPath) { if path.Valid() { t.Errorf("Uninitialized OptionalPath should not be valid") } if path.String() != "" { t.Errorf("Uninitialized OptionalPath String() should return \"\", not %q", path.String()) } defer func() { if r := recover(); r == nil { t.Errorf("Expected a panic when calling Path() on an uninitialized OptionalPath") } }() path.Path() } func check(t *testing.T, testType, testString string, got interface{}, err []error, expected interface{}, expectedErr []error) { printedTestCase := false e := func(s string, expected, got interface{}) { if !printedTestCase { t.Errorf("test case %s: %s", testType, testString) printedTestCase = true } t.Errorf("incorrect %s", s) t.Errorf(" expected: %s", p(expected)) t.Errorf(" got: %s", p(got)) } if !reflect.DeepEqual(expectedErr, err) { e("errors:", expectedErr, err) } if !reflect.DeepEqual(expected, got) { e("output:", expected, got) } } func p(in interface{}) string { if v, ok := in.([]interface{}); ok { s := make([]string, len(v)) for i := range v { s[i] = fmt.Sprintf("%#v", v[i]) } return "[" + strings.Join(s, ", ") + "]" } else { return fmt.Sprintf("%#v", in) } }