github.com/meulengracht/snapd@v0.0.0-20210719210640-8bde69bcc84e/osutil/stat_test.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2014-2015 Canonical Ltd 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 3 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package osutil_test 21 22 import ( 23 "fmt" 24 "io/ioutil" 25 "os" 26 "path/filepath" 27 "strings" 28 "syscall" 29 30 . "gopkg.in/check.v1" 31 32 "github.com/snapcore/snapd/osutil" 33 ) 34 35 type StatTestSuite struct{} 36 37 var _ = Suite(&StatTestSuite{}) 38 39 func (ts *StatTestSuite) TestFileDoesNotExist(c *C) { 40 c.Assert(osutil.FileExists("/i-do-not-exist"), Equals, false) 41 } 42 43 func (ts *StatTestSuite) TestFileExistsSimple(c *C) { 44 fname := filepath.Join(c.MkDir(), "foo") 45 err := ioutil.WriteFile(fname, []byte(fname), 0644) 46 c.Assert(err, IsNil) 47 48 c.Assert(osutil.FileExists(fname), Equals, true) 49 } 50 51 func (ts *StatTestSuite) TestFileExistsExistsOddPermissions(c *C) { 52 fname := filepath.Join(c.MkDir(), "foo") 53 err := ioutil.WriteFile(fname, []byte(fname), 0100) 54 c.Assert(err, IsNil) 55 56 c.Assert(osutil.FileExists(fname), Equals, true) 57 } 58 59 func (ts *StatTestSuite) TestIsDirectoryDoesNotExist(c *C) { 60 c.Assert(osutil.IsDirectory("/i-do-not-exist"), Equals, false) 61 } 62 63 func (ts *StatTestSuite) TestIsDirectorySimple(c *C) { 64 dname := filepath.Join(c.MkDir(), "bar") 65 err := os.Mkdir(dname, 0700) 66 c.Assert(err, IsNil) 67 68 c.Assert(osutil.IsDirectory(dname), Equals, true) 69 } 70 71 func (ts *StatTestSuite) TestIsSymlink(c *C) { 72 sname := filepath.Join(c.MkDir(), "symlink") 73 err := os.Symlink("/", sname) 74 c.Assert(err, IsNil) 75 76 c.Assert(osutil.IsSymlink(sname), Equals, true) 77 } 78 79 func (ts *StatTestSuite) TestIsSymlinkNoSymlink(c *C) { 80 c.Assert(osutil.IsSymlink(c.MkDir()), Equals, false) 81 } 82 83 func (ts *StatTestSuite) TestExecutableExists(c *C) { 84 oldPath := os.Getenv("PATH") 85 defer os.Setenv("PATH", oldPath) 86 d := c.MkDir() 87 os.Setenv("PATH", d) 88 c.Check(osutil.ExecutableExists("xyzzy"), Equals, false) 89 90 fname := filepath.Join(d, "xyzzy") 91 c.Assert(ioutil.WriteFile(fname, []byte{}, 0644), IsNil) 92 c.Check(osutil.ExecutableExists("xyzzy"), Equals, false) 93 94 c.Assert(os.Chmod(fname, 0755), IsNil) 95 c.Check(osutil.ExecutableExists("xyzzy"), Equals, true) 96 } 97 98 func (ts *StatTestSuite) TestLookPathDefaultGivesCorrectPath(c *C) { 99 r := osutil.MockLookPath(func(name string) (string, error) { return "/bin/true", nil }) 100 defer r() 101 c.Assert(osutil.LookPathDefault("true", "/bin/foo"), Equals, "/bin/true") 102 } 103 104 func (ts *StatTestSuite) TestLookPathDefaultReturnsDefaultWhenNotFound(c *C) { 105 r := osutil.MockLookPath(func(name string) (string, error) { return "", fmt.Errorf("Not found") }) 106 defer r() 107 c.Assert(osutil.LookPathDefault("bar", "/bin/bla"), Equals, "/bin/bla") 108 } 109 110 func makeTestPath(c *C, path string, mode os.FileMode) string { 111 return makeTestPathInDir(c, c.MkDir(), path, mode) 112 } 113 114 func makeTestPathInDir(c *C, dir, path string, mode os.FileMode) string { 115 mkdir := strings.HasSuffix(path, "/") 116 path = filepath.Join(dir, path) 117 118 if mkdir { 119 // request for directory 120 c.Assert(os.MkdirAll(path, mode), IsNil) 121 } else { 122 // request for a file 123 c.Assert(os.MkdirAll(filepath.Dir(path), 0755), IsNil) 124 c.Assert(ioutil.WriteFile(path, nil, mode), IsNil) 125 } 126 127 return path 128 } 129 130 func (ts *StatTestSuite) TestIsWritableDir(c *C) { 131 for _, t := range []struct { 132 path string 133 mode os.FileMode 134 isWritable bool 135 }{ 136 {"dir/", 0755, true}, 137 {"dir/", 0555, false}, 138 {"dir/", 0750, true}, 139 {"dir/", 0550, false}, 140 {"dir/", 0700, true}, 141 {"dir/", 0500, false}, 142 143 {"file", 0644, true}, 144 {"file", 0444, false}, 145 {"file", 0640, true}, 146 {"file", 0440, false}, 147 {"file", 0600, true}, 148 {"file", 0400, false}, 149 } { 150 writable := osutil.IsWritable(makeTestPath(c, t.path, t.mode)) 151 c.Check(writable, Equals, t.isWritable, Commentf("incorrect result for %q (%s), got %v, expected %v", t.path, t.mode, writable, t.isWritable)) 152 } 153 } 154 155 func (ts *StatTestSuite) TestIsDirNotExist(c *C) { 156 for _, e := range []error{ 157 os.ErrNotExist, 158 syscall.ENOENT, 159 syscall.ENOTDIR, 160 &os.PathError{Err: syscall.ENOENT}, 161 &os.PathError{Err: syscall.ENOTDIR}, 162 &os.LinkError{Err: syscall.ENOENT}, 163 &os.LinkError{Err: syscall.ENOTDIR}, 164 &os.SyscallError{Err: syscall.ENOENT}, 165 &os.SyscallError{Err: syscall.ENOTDIR}, 166 } { 167 c.Check(osutil.IsDirNotExist(e), Equals, true, Commentf("%#v (%v)", e, e)) 168 } 169 170 for _, e := range []error{ 171 nil, 172 fmt.Errorf("hello"), 173 } { 174 c.Check(osutil.IsDirNotExist(e), Equals, false) 175 } 176 } 177 178 func (ts *StatTestSuite) TestDirExists(c *C) { 179 for _, t := range []struct { 180 make string 181 path string 182 exists bool 183 isDir bool 184 }{ 185 {"", "foo", false, false}, 186 {"", "foo/bar", false, false}, 187 {"foo", "foo/bar", false, false}, 188 {"foo", "foo", true, false}, 189 {"foo/", "foo", true, true}, 190 } { 191 base := c.MkDir() 192 comm := Commentf("path:%q make:%q", t.path, t.make) 193 if t.make != "" { 194 makeTestPathInDir(c, base, t.make, 0755) 195 } 196 exists, isDir, err := osutil.DirExists(filepath.Join(base, t.path)) 197 c.Check(exists, Equals, t.exists, comm) 198 c.Check(isDir, Equals, t.isDir, comm) 199 c.Check(err, IsNil, comm) 200 } 201 202 p := makeTestPath(c, "foo/bar", 0) 203 c.Assert(os.Chmod(filepath.Dir(p), 0), IsNil) 204 defer os.Chmod(filepath.Dir(p), 0755) 205 exists, isDir, err := osutil.DirExists(p) 206 c.Check(exists, Equals, false) 207 c.Check(isDir, Equals, false) 208 c.Check(err, NotNil) 209 } 210 211 func (ts *StatTestSuite) TestIsExecutable(c *C) { 212 c.Check(osutil.IsExecutable("non-existent"), Equals, false) 213 c.Check(osutil.IsExecutable("."), Equals, false) 214 dir := c.MkDir() 215 c.Check(osutil.IsExecutable(dir), Equals, false) 216 217 for _, tc := range []struct { 218 mode os.FileMode 219 is bool 220 }{ 221 {0644, false}, 222 {0444, false}, 223 {0444, false}, 224 {0000, false}, 225 {0100, true}, 226 {0010, true}, 227 {0001, true}, 228 {0755, true}, 229 } { 230 c.Logf("tc: %v %v", tc.mode, tc.is) 231 p := filepath.Join(dir, "foo") 232 err := os.Remove(p) 233 c.Check(err == nil || os.IsNotExist(err), Equals, true) 234 235 err = ioutil.WriteFile(p, []byte(""), tc.mode) 236 c.Assert(err, IsNil) 237 c.Check(osutil.IsExecutable(p), Equals, tc.is) 238 } 239 } 240 241 func (ts *StatTestSuite) TestRegularFileExists(c *C) { 242 tt := []struct { 243 make bool 244 makeNonRegular bool 245 path string 246 expExists bool 247 expIsReg bool 248 expErr string 249 comment string 250 }{ 251 { 252 make: true, 253 path: "foo", 254 expExists: true, 255 expIsReg: true, 256 comment: "file is regular", 257 }, 258 { 259 make: true, 260 makeNonRegular: true, 261 path: "bar", 262 expExists: true, 263 comment: "file is symlink", 264 }, 265 { 266 path: "not-exists", 267 expExists: false, 268 expErr: ".*no such file or directory", 269 comment: "file doesn't exist", 270 }, 271 } 272 273 for _, t := range tt { 274 fullpath := filepath.Join(c.MkDir(), t.path) 275 comment := Commentf(t.comment) 276 277 if t.make { 278 if t.makeNonRegular { 279 // make it a symlink 280 err := os.Symlink("foo", fullpath) 281 c.Assert(err, IsNil, comment) 282 } else { 283 // make it a normal file 284 err := ioutil.WriteFile(fullpath, nil, 0644) 285 c.Assert(err, IsNil, comment) 286 } 287 } 288 289 exists, isReg, err := osutil.RegularFileExists(fullpath) 290 if t.expErr != "" { 291 c.Assert(err, ErrorMatches, t.expErr, comment) 292 continue 293 } 294 c.Assert(exists, Equals, t.expExists, comment) 295 c.Assert(isReg, Equals, t.expIsReg, comment) 296 } 297 }