github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/fs/path_test.go (about) 1 // Copyright 2018 The gVisor Authors. 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 15 package fs 16 17 import ( 18 "testing" 19 ) 20 21 // TestSplitLast tests variants of path splitting. 22 func TestSplitLast(t *testing.T) { 23 cases := []struct { 24 path string 25 dir string 26 file string 27 }{ 28 {path: "/", dir: "/", file: "."}, 29 {path: "/.", dir: "/", file: "."}, 30 {path: "/./", dir: "/", file: "."}, 31 {path: "/./.", dir: "/.", file: "."}, 32 {path: "/././", dir: "/.", file: "."}, 33 {path: "/./..", dir: "/.", file: ".."}, 34 {path: "/./../", dir: "/.", file: ".."}, 35 {path: "/..", dir: "/", file: ".."}, 36 {path: "/../", dir: "/", file: ".."}, 37 {path: "/../.", dir: "/..", file: "."}, 38 {path: "/.././", dir: "/..", file: "."}, 39 {path: "/../..", dir: "/..", file: ".."}, 40 {path: "/../../", dir: "/..", file: ".."}, 41 42 {path: "", dir: ".", file: "."}, 43 {path: ".", dir: ".", file: "."}, 44 {path: "./", dir: ".", file: "."}, 45 {path: "./.", dir: ".", file: "."}, 46 {path: "././", dir: ".", file: "."}, 47 {path: "./..", dir: ".", file: ".."}, 48 {path: "./../", dir: ".", file: ".."}, 49 {path: "..", dir: ".", file: ".."}, 50 {path: "../", dir: ".", file: ".."}, 51 {path: "../.", dir: "..", file: "."}, 52 {path: ".././", dir: "..", file: "."}, 53 {path: "../..", dir: "..", file: ".."}, 54 {path: "../../", dir: "..", file: ".."}, 55 56 {path: "/foo", dir: "/", file: "foo"}, 57 {path: "/foo/", dir: "/", file: "foo"}, 58 {path: "/foo/.", dir: "/foo", file: "."}, 59 {path: "/foo/./", dir: "/foo", file: "."}, 60 {path: "/foo/./.", dir: "/foo/.", file: "."}, 61 {path: "/foo/./..", dir: "/foo/.", file: ".."}, 62 {path: "/foo/..", dir: "/foo", file: ".."}, 63 {path: "/foo/../", dir: "/foo", file: ".."}, 64 {path: "/foo/../.", dir: "/foo/..", file: "."}, 65 {path: "/foo/../..", dir: "/foo/..", file: ".."}, 66 67 {path: "/foo/bar", dir: "/foo", file: "bar"}, 68 {path: "/foo/bar/", dir: "/foo", file: "bar"}, 69 {path: "/foo/bar/.", dir: "/foo/bar", file: "."}, 70 {path: "/foo/bar/./", dir: "/foo/bar", file: "."}, 71 {path: "/foo/bar/./.", dir: "/foo/bar/.", file: "."}, 72 {path: "/foo/bar/./..", dir: "/foo/bar/.", file: ".."}, 73 {path: "/foo/bar/..", dir: "/foo/bar", file: ".."}, 74 {path: "/foo/bar/../", dir: "/foo/bar", file: ".."}, 75 {path: "/foo/bar/../.", dir: "/foo/bar/..", file: "."}, 76 {path: "/foo/bar/../..", dir: "/foo/bar/..", file: ".."}, 77 78 {path: "foo", dir: ".", file: "foo"}, 79 {path: "foo", dir: ".", file: "foo"}, 80 {path: "foo/", dir: ".", file: "foo"}, 81 {path: "foo/.", dir: "foo", file: "."}, 82 {path: "foo/./", dir: "foo", file: "."}, 83 {path: "foo/./.", dir: "foo/.", file: "."}, 84 {path: "foo/./..", dir: "foo/.", file: ".."}, 85 {path: "foo/..", dir: "foo", file: ".."}, 86 {path: "foo/../", dir: "foo", file: ".."}, 87 {path: "foo/../.", dir: "foo/..", file: "."}, 88 {path: "foo/../..", dir: "foo/..", file: ".."}, 89 {path: "foo/", dir: ".", file: "foo"}, 90 {path: "foo/.", dir: "foo", file: "."}, 91 92 {path: "foo/bar", dir: "foo", file: "bar"}, 93 {path: "foo/bar/", dir: "foo", file: "bar"}, 94 {path: "foo/bar/.", dir: "foo/bar", file: "."}, 95 {path: "foo/bar/./", dir: "foo/bar", file: "."}, 96 {path: "foo/bar/./.", dir: "foo/bar/.", file: "."}, 97 {path: "foo/bar/./..", dir: "foo/bar/.", file: ".."}, 98 {path: "foo/bar/..", dir: "foo/bar", file: ".."}, 99 {path: "foo/bar/../", dir: "foo/bar", file: ".."}, 100 {path: "foo/bar/../.", dir: "foo/bar/..", file: "."}, 101 {path: "foo/bar/../..", dir: "foo/bar/..", file: ".."}, 102 {path: "foo/bar/", dir: "foo", file: "bar"}, 103 {path: "foo/bar/.", dir: "foo/bar", file: "."}, 104 } 105 106 for _, c := range cases { 107 dir, file := SplitLast(c.path) 108 if dir != c.dir || file != c.file { 109 t.Errorf("SplitLast(%q) got (%q, %q), expected (%q, %q)", c.path, dir, file, c.dir, c.file) 110 } 111 } 112 } 113 114 // TestSplitFirst tests variants of path splitting. 115 func TestSplitFirst(t *testing.T) { 116 cases := []struct { 117 path string 118 first string 119 remainder string 120 }{ 121 {path: "/", first: "/", remainder: ""}, 122 {path: "/.", first: "/", remainder: "."}, 123 {path: "///.", first: "/", remainder: "//."}, 124 {path: "/.///", first: "/", remainder: "."}, 125 {path: "/./.", first: "/", remainder: "./."}, 126 {path: "/././", first: "/", remainder: "./."}, 127 {path: "/./..", first: "/", remainder: "./.."}, 128 {path: "/./../", first: "/", remainder: "./.."}, 129 {path: "/..", first: "/", remainder: ".."}, 130 {path: "/../", first: "/", remainder: ".."}, 131 {path: "/../.", first: "/", remainder: "../."}, 132 {path: "/.././", first: "/", remainder: "../."}, 133 {path: "/../..", first: "/", remainder: "../.."}, 134 {path: "/../../", first: "/", remainder: "../.."}, 135 136 {path: "", first: ".", remainder: ""}, 137 {path: ".", first: ".", remainder: ""}, 138 {path: "./", first: ".", remainder: ""}, 139 {path: ".///", first: ".", remainder: ""}, 140 {path: "./.", first: ".", remainder: "."}, 141 {path: "././", first: ".", remainder: "."}, 142 {path: "./..", first: ".", remainder: ".."}, 143 {path: "./../", first: ".", remainder: ".."}, 144 {path: "..", first: "..", remainder: ""}, 145 {path: "../", first: "..", remainder: ""}, 146 {path: "../.", first: "..", remainder: "."}, 147 {path: ".././", first: "..", remainder: "."}, 148 {path: "../..", first: "..", remainder: ".."}, 149 {path: "../../", first: "..", remainder: ".."}, 150 151 {path: "/foo", first: "/", remainder: "foo"}, 152 {path: "/foo/", first: "/", remainder: "foo"}, 153 {path: "/foo///", first: "/", remainder: "foo"}, 154 {path: "/foo/.", first: "/", remainder: "foo/."}, 155 {path: "/foo/./", first: "/", remainder: "foo/."}, 156 {path: "/foo/./.", first: "/", remainder: "foo/./."}, 157 {path: "/foo/./..", first: "/", remainder: "foo/./.."}, 158 {path: "/foo/..", first: "/", remainder: "foo/.."}, 159 {path: "/foo/../", first: "/", remainder: "foo/.."}, 160 {path: "/foo/../.", first: "/", remainder: "foo/../."}, 161 {path: "/foo/../..", first: "/", remainder: "foo/../.."}, 162 163 {path: "/foo/bar", first: "/", remainder: "foo/bar"}, 164 {path: "///foo/bar", first: "/", remainder: "//foo/bar"}, 165 {path: "/foo///bar", first: "/", remainder: "foo///bar"}, 166 {path: "/foo/bar/.", first: "/", remainder: "foo/bar/."}, 167 {path: "/foo/bar/./", first: "/", remainder: "foo/bar/."}, 168 {path: "/foo/bar/./.", first: "/", remainder: "foo/bar/./."}, 169 {path: "/foo/bar/./..", first: "/", remainder: "foo/bar/./.."}, 170 {path: "/foo/bar/..", first: "/", remainder: "foo/bar/.."}, 171 {path: "/foo/bar/../", first: "/", remainder: "foo/bar/.."}, 172 {path: "/foo/bar/../.", first: "/", remainder: "foo/bar/../."}, 173 {path: "/foo/bar/../..", first: "/", remainder: "foo/bar/../.."}, 174 175 {path: "foo", first: "foo", remainder: ""}, 176 {path: "foo", first: "foo", remainder: ""}, 177 {path: "foo/", first: "foo", remainder: ""}, 178 {path: "foo///", first: "foo", remainder: ""}, 179 {path: "foo/.", first: "foo", remainder: "."}, 180 {path: "foo/./", first: "foo", remainder: "."}, 181 {path: "foo/./.", first: "foo", remainder: "./."}, 182 {path: "foo/./..", first: "foo", remainder: "./.."}, 183 {path: "foo/..", first: "foo", remainder: ".."}, 184 {path: "foo/../", first: "foo", remainder: ".."}, 185 {path: "foo/../.", first: "foo", remainder: "../."}, 186 {path: "foo/../..", first: "foo", remainder: "../.."}, 187 {path: "foo/", first: "foo", remainder: ""}, 188 {path: "foo/.", first: "foo", remainder: "."}, 189 190 {path: "foo/bar", first: "foo", remainder: "bar"}, 191 {path: "foo///bar", first: "foo", remainder: "bar"}, 192 {path: "foo/bar/", first: "foo", remainder: "bar"}, 193 {path: "foo/bar/.", first: "foo", remainder: "bar/."}, 194 {path: "foo/bar/./", first: "foo", remainder: "bar/."}, 195 {path: "foo/bar/./.", first: "foo", remainder: "bar/./."}, 196 {path: "foo/bar/./..", first: "foo", remainder: "bar/./.."}, 197 {path: "foo/bar/..", first: "foo", remainder: "bar/.."}, 198 {path: "foo/bar/../", first: "foo", remainder: "bar/.."}, 199 {path: "foo/bar/../.", first: "foo", remainder: "bar/../."}, 200 {path: "foo/bar/../..", first: "foo", remainder: "bar/../.."}, 201 {path: "foo/bar/", first: "foo", remainder: "bar"}, 202 {path: "foo/bar/.", first: "foo", remainder: "bar/."}, 203 } 204 205 for _, c := range cases { 206 first, remainder := SplitFirst(c.path) 207 if first != c.first || remainder != c.remainder { 208 t.Errorf("SplitFirst(%q) got (%q, %q), expected (%q, %q)", c.path, first, remainder, c.first, c.remainder) 209 } 210 } 211 } 212 213 // TestIsSubpath tests the IsSubpath method. 214 func TestIsSubpath(t *testing.T) { 215 tcs := []struct { 216 // Two absolute paths. 217 pathA string 218 pathB string 219 220 // Whether pathA is a subpath of pathB. 221 wantIsSubpath bool 222 223 // Relative path from pathA to pathB. Only checked if 224 // wantIsSubpath is true. 225 wantRelpath string 226 }{ 227 { 228 pathA: "/foo/bar/baz", 229 pathB: "/foo", 230 wantIsSubpath: true, 231 wantRelpath: "bar/baz", 232 }, 233 { 234 pathA: "/foo", 235 pathB: "/foo/bar/baz", 236 wantIsSubpath: false, 237 }, 238 { 239 pathA: "/foo", 240 pathB: "/foo", 241 wantIsSubpath: false, 242 }, 243 { 244 pathA: "/foobar", 245 pathB: "/foo", 246 wantIsSubpath: false, 247 }, 248 { 249 pathA: "/foo", 250 pathB: "/foobar", 251 wantIsSubpath: false, 252 }, 253 { 254 pathA: "/foo", 255 pathB: "/foobar", 256 wantIsSubpath: false, 257 }, 258 { 259 pathA: "/", 260 pathB: "/foo", 261 wantIsSubpath: false, 262 }, 263 { 264 pathA: "/foo", 265 pathB: "/", 266 wantIsSubpath: true, 267 wantRelpath: "foo", 268 }, 269 { 270 pathA: "/foo/bar/../bar", 271 pathB: "/foo", 272 wantIsSubpath: true, 273 wantRelpath: "bar", 274 }, 275 { 276 pathA: "/foo/bar", 277 pathB: "/foo/../foo", 278 wantIsSubpath: true, 279 wantRelpath: "bar", 280 }, 281 } 282 283 for _, tc := range tcs { 284 gotRelpath, gotIsSubpath := IsSubpath(tc.pathA, tc.pathB) 285 if gotRelpath != tc.wantRelpath || gotIsSubpath != tc.wantIsSubpath { 286 t.Errorf("IsSubpath(%q, %q) got %q %t, want %q %t", tc.pathA, tc.pathB, gotRelpath, gotIsSubpath, tc.wantRelpath, tc.wantIsSubpath) 287 } 288 } 289 }