1// Copyright 2015 Google Inc. All rights reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package android 16 17import ( 18 "errors" 19 "fmt" 20 "reflect" 21 "strings" 22 "testing" 23) 24 25type strsTestCase struct { 26 in []string 27 out string 28 err []error 29} 30 31var commonValidatePathTestCases = []strsTestCase{ 32 { 33 in: []string{""}, 34 out: "", 35 }, 36 { 37 in: []string{"a/b"}, 38 out: "a/b", 39 }, 40 { 41 in: []string{"a/b", "c"}, 42 out: "a/b/c", 43 }, 44 { 45 in: []string{"a/.."}, 46 out: ".", 47 }, 48 { 49 in: []string{"."}, 50 out: ".", 51 }, 52 { 53 in: []string{".."}, 54 out: "", 55 err: []error{errors.New("Path is outside directory: ..")}, 56 }, 57 { 58 in: []string{"../a"}, 59 out: "", 60 err: []error{errors.New("Path is outside directory: ../a")}, 61 }, 62 { 63 in: []string{"b/../../a"}, 64 out: "", 65 err: []error{errors.New("Path is outside directory: ../a")}, 66 }, 67 { 68 in: []string{"/a"}, 69 out: "", 70 err: []error{errors.New("Path is outside directory: /a")}, 71 }, 72 { 73 in: []string{"a", "../b"}, 74 out: "", 75 err: []error{errors.New("Path is outside directory: ../b")}, 76 }, 77 { 78 in: []string{"a", "b/../../c"}, 79 out: "", 80 err: []error{errors.New("Path is outside directory: ../c")}, 81 }, 82 { 83 in: []string{"a", "./.."}, 84 out: "", 85 err: []error{errors.New("Path is outside directory: ..")}, 86 }, 87} 88 89var validateSafePathTestCases = append(commonValidatePathTestCases, []strsTestCase{ 90 { 91 in: []string{"$host/../$a"}, 92 out: "$a", 93 }, 94}...) 95 96var validatePathTestCases = append(commonValidatePathTestCases, []strsTestCase{ 97 { 98 in: []string{"$host/../$a"}, 99 out: "", 100 err: []error{errors.New("Path contains invalid character($): $host/../$a")}, 101 }, 102 { 103 in: []string{"$host/.."}, 104 out: "", 105 err: []error{errors.New("Path contains invalid character($): $host/..")}, 106 }, 107}...) 108 109func TestValidateSafePath(t *testing.T) { 110 for _, testCase := range validateSafePathTestCases { 111 ctx := &configErrorWrapper{} 112 out := validateSafePath(ctx, testCase.in...) 113 check(t, "validateSafePath", p(testCase.in), out, ctx.errors, testCase.out, testCase.err) 114 } 115} 116 117func TestValidatePath(t *testing.T) { 118 for _, testCase := range validatePathTestCases { 119 ctx := &configErrorWrapper{} 120 out := validatePath(ctx, testCase.in...) 121 check(t, "validatePath", p(testCase.in), out, ctx.errors, testCase.out, testCase.err) 122 } 123} 124 125func TestOptionalPath(t *testing.T) { 126 var path OptionalPath 127 checkInvalidOptionalPath(t, path) 128 129 path = OptionalPathForPath(nil) 130 checkInvalidOptionalPath(t, path) 131} 132 133func checkInvalidOptionalPath(t *testing.T, path OptionalPath) { 134 if path.Valid() { 135 t.Errorf("Uninitialized OptionalPath should not be valid") 136 } 137 if path.String() != "" { 138 t.Errorf("Uninitialized OptionalPath String() should return \"\", not %q", path.String()) 139 } 140 defer func() { 141 if r := recover(); r == nil { 142 t.Errorf("Expected a panic when calling Path() on an uninitialized OptionalPath") 143 } 144 }() 145 path.Path() 146} 147 148func check(t *testing.T, testType, testString string, 149 got interface{}, err []error, 150 expected interface{}, expectedErr []error) { 151 152 printedTestCase := false 153 e := func(s string, expected, got interface{}) { 154 if !printedTestCase { 155 t.Errorf("test case %s: %s", testType, testString) 156 printedTestCase = true 157 } 158 t.Errorf("incorrect %s", s) 159 t.Errorf(" expected: %s", p(expected)) 160 t.Errorf(" got: %s", p(got)) 161 } 162 163 if !reflect.DeepEqual(expectedErr, err) { 164 e("errors:", expectedErr, err) 165 } 166 167 if !reflect.DeepEqual(expected, got) { 168 e("output:", expected, got) 169 } 170} 171 172func p(in interface{}) string { 173 if v, ok := in.([]interface{}); ok { 174 s := make([]string, len(v)) 175 for i := range v { 176 s[i] = fmt.Sprintf("%#v", v[i]) 177 } 178 return "[" + strings.Join(s, ", ") + "]" 179 } else { 180 return fmt.Sprintf("%#v", in) 181 } 182} 183