blob: 9d69473a018150c559ec4a09efa51346e5122716 [file] [log] [blame]
Dan Willemsen34cc69e2015-09-23 15:26:20 -07001// 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
Colin Cross635c3b02016-05-18 15:37:25 -070015package android
Dan Willemsen34cc69e2015-09-23 15:26:20 -070016
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 },
Dan Willemsen80a7c2a2015-12-21 14:57:11 -080072 {
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 },
Dan Willemsen34cc69e2015-09-23 15:26:20 -070087}
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}