feat: Add tests for symlink behaviour of chmod

This commit is contained in:
Felicitas Pojtinger
2022-01-22 18:26:02 +01:00
parent 48d0cd56db
commit 5f069ab85a
2 changed files with 471 additions and 30 deletions

View File

@@ -880,10 +880,40 @@ func (f *STFS) Chmod(name string, mode os.FileMode) error {
)
if err != nil {
if err == sql.ErrNoRows {
return os.ErrNotExist
}
hdr, err = inventory.Stat(
f.metadata,
return err
name,
true,
f.onHeader,
)
if err != nil {
if err == sql.ErrNoRows {
return os.ErrNotExist
} else {
return err
}
} else {
hdr, err = inventory.Stat(
f.metadata,
hdr.Linkname,
false,
f.onHeader,
)
if err != nil {
if err == sql.ErrNoRows {
return os.ErrNotExist
} else {
return err
}
}
}
} else {
return err
}
}
hdr.Mode = int64(mode)

View File

@@ -3300,8 +3300,8 @@ var chmodTests = []struct {
name string
args chmodArgs
wantErr bool
prepare func(afero.Fs) error
check func(f os.FileInfo) error
prepare func(symFs) error
check func(f os.FileInfo, l os.FileInfo) error
withCache bool
withOsFs bool
}{
@@ -3309,8 +3309,8 @@ var chmodTests = []struct {
"Can chmod / to 0666",
chmodArgs{"/", 0666},
false,
func(f afero.Fs) error { return nil },
func(f os.FileInfo) error {
func(f symFs) error { return nil },
func(f os.FileInfo, l os.FileInfo) error {
if dir, _ := path.Split(f.Name()); !(dir == "/" || dir == "") {
return fmt.Errorf("invalid dir part of path %v, should be ''", dir)
@@ -3332,14 +3332,14 @@ var chmodTests = []struct {
"Can chmod /test.txt to 0666 if it exists",
chmodArgs{"/test.txt", 0666},
false,
func(f afero.Fs) error {
func(f symFs) error {
if _, err := f.Create("/test.txt"); err != nil {
return err
}
return nil
},
func(f os.FileInfo) error {
func(f os.FileInfo, l os.FileInfo) error {
want := "test.txt"
got := f.Name()
@@ -3363,14 +3363,14 @@ var chmodTests = []struct {
"Can chmod /test.txt to 0777 if it exists",
chmodArgs{"/test.txt", 0777},
false,
func(f afero.Fs) error {
func(f symFs) error {
if _, err := f.Create("/test.txt"); err != nil {
return err
}
return nil
},
func(f os.FileInfo) error {
func(f os.FileInfo, l os.FileInfo) error {
want := "test.txt"
got := f.Name()
@@ -3394,8 +3394,8 @@ var chmodTests = []struct {
"Can not chmod /test.txt without creating it",
chmodArgs{"/test.txt", 0666},
true,
func(f afero.Fs) error { return nil },
func(f os.FileInfo) error { return nil },
func(f symFs) error { return nil },
func(f os.FileInfo, l os.FileInfo) error { return nil },
true,
true,
},
@@ -3403,8 +3403,8 @@ var chmodTests = []struct {
"Can not chmod /mydir/test.txt without creating it",
chmodArgs{"/mydir/test.txt", 0666},
true,
func(f afero.Fs) error { return nil },
func(f os.FileInfo) error { return nil },
func(f symFs) error { return nil },
func(f os.FileInfo, l os.FileInfo) error { return nil },
true,
true,
},
@@ -3412,7 +3412,7 @@ var chmodTests = []struct {
"Can chmod /mydir/test.txt to 0666 after creating it",
chmodArgs{"/mydir/test.txt", 0666},
false,
func(f afero.Fs) error {
func(f symFs) error {
if err := f.Mkdir("/mydir", os.ModePerm); err != nil {
return err
}
@@ -3423,7 +3423,7 @@ var chmodTests = []struct {
return nil
},
func(f os.FileInfo) error {
func(f os.FileInfo, l os.FileInfo) error {
want := "test.txt"
got := f.Name()
@@ -3443,6 +3443,408 @@ var chmodTests = []struct {
true,
true,
},
{
"Can chmod /mydir/test.txt to 0774 after creating it",
chmodArgs{"/mydir/test.txt", 0774},
false,
func(f symFs) error {
if err := f.Mkdir("/mydir", os.ModePerm); err != nil {
return err
}
if _, err := f.Create("/mydir/test.txt"); err != nil {
return err
}
return nil
},
func(f os.FileInfo, l os.FileInfo) error {
want := "test.txt"
got := f.Name()
if want != got {
return fmt.Errorf("invalid name, got %v, want %v", got, want)
}
wantPerm := fs.FileMode(0774)
gotPerm := f.Mode().Perm()
if wantPerm != gotPerm {
return fmt.Errorf("invalid perm, got %v, want %v", gotPerm, wantPerm)
}
return nil
},
true,
true,
},
{
"Can chmod symlink to root to 0777 after creating it",
chmodArgs{"/existingsymlink", 0777},
false,
func(f symFs) error {
if err := f.SymlinkIfPossible("/", "/existingsymlink"); err != nil {
return nil
}
return nil
},
func(f os.FileInfo, l os.FileInfo) error {
if dir, _ := path.Split(f.Name()); !(dir == "/" || dir == "") {
return fmt.Errorf("invalid dir part of path %v, should be ''", dir)
}
wantSourcePerm := fs.FileMode(0777)
gotSourcePerm := f.Mode().Perm()
if wantSourcePerm != gotSourcePerm {
return fmt.Errorf("invalid source perm, got %v, want %v", gotSourcePerm, wantSourcePerm)
}
wantTargetPerm := fs.FileMode(0777)
gotTargetPerm := f.Mode().Perm()
if wantTargetPerm != gotTargetPerm {
return fmt.Errorf("invalid target perm, got %v, want %v", gotTargetPerm, wantTargetPerm)
}
return nil
},
false, // FIXME: With cache enabled, directories can't be `chmod`ed
true,
},
{
"Can chmod symlink to root to 0774 after creating it",
chmodArgs{"/existingsymlink", 0774},
false,
func(f symFs) error {
if err := f.SymlinkIfPossible("/", "/existingsymlink"); err != nil {
return nil
}
return nil
},
func(f os.FileInfo, l os.FileInfo) error {
if dir, _ := path.Split(f.Name()); !(dir == "/" || dir == "") {
return fmt.Errorf("invalid dir part of path %v, should be ''", dir)
}
wantSourcePerm := fs.FileMode(0774)
gotSourcePerm := f.Mode().Perm()
if wantSourcePerm != gotSourcePerm {
return fmt.Errorf("invalid source perm, got %v, want %v", gotSourcePerm, wantSourcePerm)
}
wantTargetPerm := fs.FileMode(0774)
gotTargetPerm := f.Mode().Perm()
if wantTargetPerm != gotTargetPerm {
return fmt.Errorf("invalid target perm, got %v, want %v", gotTargetPerm, wantTargetPerm)
}
return nil
},
false, // FIXME: With cache enabled, directories can't be `chmod`ed
true,
},
{
"Can not chmod broken symlink to /test.txt to 0777 after creating it",
chmodArgs{"/brokensymlink", 0777},
true,
func(f symFs) error {
if err := f.SymlinkIfPossible("/test.txt", "/brokensymlink"); err != nil {
return nil
}
return nil
},
func(f os.FileInfo, l os.FileInfo) error { return nil },
false, // FIXME: With cache enabled, directories can't be `chmod`ed
true,
},
{
"Can not chmod broken symlink to /mydir to 0777 after creating it",
chmodArgs{"/brokensymlink", 0777},
true,
func(f symFs) error {
if err := f.SymlinkIfPossible("/mydir", "/brokensymlink"); err != nil {
return nil
}
return nil
},
func(f os.FileInfo, l os.FileInfo) error { return nil },
false, // FIXME: With cache enabled, directories can't be `chmod`ed
true,
},
{
"Can chmod symlink to /test.txt to 0777 after creating it",
chmodArgs{"/existingsymlink", 0777},
false,
func(f symFs) error {
file, err := f.Create("/test.txt")
if err != nil {
return err
}
if err := file.Close(); err != nil {
return err
}
if err := f.SymlinkIfPossible("/test.txt", "/existingsymlink"); err != nil {
return nil
}
return nil
},
func(f os.FileInfo, l os.FileInfo) error {
wantSource := "existingsymlink"
gotSource := f.Name()
if wantSource != gotSource {
return fmt.Errorf("invalid source name, got %v, want %v", gotSource, wantSource)
}
wantTarget := "existingsymlink"
gotTarget := f.Name()
if wantTarget != gotTarget {
return fmt.Errorf("invalid target name, got %v, want %v", gotTarget, wantTarget)
}
wantSourcePerm := fs.FileMode(0777)
gotSourcePerm := f.Mode().Perm()
if wantSourcePerm != gotSourcePerm {
return fmt.Errorf("invalid source perm, got %v, want %v", gotSourcePerm, wantSourcePerm)
}
wantTargetPerm := fs.FileMode(0777)
gotTargetPerm := f.Mode().Perm()
if wantTargetPerm != gotTargetPerm {
return fmt.Errorf("invalid target perm, got %v, want %v", gotTargetPerm, wantTargetPerm)
}
return nil
},
true,
true,
},
{
"Can chmod symlink to /test.txt to 0666 after creating it",
chmodArgs{"/existingsymlink", 0666},
false,
func(f symFs) error {
file, err := f.Create("/test.txt")
if err != nil {
return err
}
if err := file.Close(); err != nil {
return err
}
if err := f.SymlinkIfPossible("/test.txt", "/existingsymlink"); err != nil {
return nil
}
return nil
},
func(f os.FileInfo, l os.FileInfo) error {
wantSource := "existingsymlink"
gotSource := f.Name()
if wantSource != gotSource {
return fmt.Errorf("invalid source name, got %v, want %v", gotSource, wantSource)
}
wantTarget := "existingsymlink"
gotTarget := f.Name()
if wantTarget != gotTarget {
return fmt.Errorf("invalid target name, got %v, want %v", gotTarget, wantTarget)
}
wantSourcePerm := fs.FileMode(0666)
gotSourcePerm := f.Mode().Perm()
if wantSourcePerm != gotSourcePerm {
return fmt.Errorf("invalid source perm, got %v, want %v", gotSourcePerm, wantSourcePerm)
}
wantTargetPerm := fs.FileMode(0666)
gotTargetPerm := f.Mode().Perm()
if wantTargetPerm != gotTargetPerm {
return fmt.Errorf("invalid target perm, got %v, want %v", gotTargetPerm, wantTargetPerm)
}
return nil
},
true,
true,
},
{
"Can chmod symlink to /test.txt to 0774 after creating it",
chmodArgs{"/existingsymlink", 0774},
false,
func(f symFs) error {
file, err := f.Create("/test.txt")
if err != nil {
return err
}
if err := file.Close(); err != nil {
return err
}
if err := f.SymlinkIfPossible("/test.txt", "/existingsymlink"); err != nil {
return nil
}
return nil
},
func(f os.FileInfo, l os.FileInfo) error {
wantSource := "existingsymlink"
gotSource := f.Name()
if wantSource != gotSource {
return fmt.Errorf("invalid source name, got %v, want %v", gotSource, wantSource)
}
wantTarget := "existingsymlink"
gotTarget := f.Name()
if wantTarget != gotTarget {
return fmt.Errorf("invalid target name, got %v, want %v", gotTarget, wantTarget)
}
wantSourcePerm := fs.FileMode(0774)
gotSourcePerm := f.Mode().Perm()
if wantSourcePerm != gotSourcePerm {
return fmt.Errorf("invalid source perm, got %v, want %v", gotSourcePerm, wantSourcePerm)
}
wantTargetPerm := fs.FileMode(0774)
gotTargetPerm := f.Mode().Perm()
if wantTargetPerm != gotTargetPerm {
return fmt.Errorf("invalid target perm, got %v, want %v", gotTargetPerm, wantTargetPerm)
}
return nil
},
true,
true,
},
{
"Can chmod symlink to empty directory /mydir to 0774 after creating it",
chmodArgs{"/existingsymlink", 0774},
false,
func(f symFs) error {
if err := f.Mkdir("/mydir", os.ModePerm); err != nil {
return err
}
if err := f.SymlinkIfPossible("/mydir", "/existingsymlink"); err != nil {
return nil
}
return nil
},
func(f os.FileInfo, l os.FileInfo) error {
wantSource := "existingsymlink"
gotSource := f.Name()
if wantSource != gotSource {
return fmt.Errorf("invalid source name, got %v, want %v", gotSource, wantSource)
}
wantTarget := "existingsymlink"
gotTarget := f.Name()
if wantTarget != gotTarget {
return fmt.Errorf("invalid target name, got %v, want %v", gotTarget, wantTarget)
}
wantSourcePerm := fs.FileMode(0774)
gotSourcePerm := f.Mode().Perm()
if wantSourcePerm != gotSourcePerm {
return fmt.Errorf("invalid source perm, got %v, want %v", gotSourcePerm, wantSourcePerm)
}
wantTargetPerm := fs.FileMode(0774)
gotTargetPerm := f.Mode().Perm()
if wantTargetPerm != gotTargetPerm {
return fmt.Errorf("invalid target perm, got %v, want %v", gotTargetPerm, wantTargetPerm)
}
return nil
},
true,
true,
},
{
"Can chmod symlink to non-empty directory /mydir to 0774 after creating it",
chmodArgs{"/existingsymlink", 0774},
false,
func(f symFs) error {
if err := f.Mkdir("/mydir", os.ModePerm); err != nil {
return err
}
if err := f.Mkdir("/mydir/subdir", os.ModePerm); err != nil {
return err
}
if _, err := f.Create("/mydir/subdir/test.txt"); err != nil {
return err
}
if err := f.SymlinkIfPossible("/mydir", "/existingsymlink"); err != nil {
return nil
}
return nil
},
func(f os.FileInfo, l os.FileInfo) error {
wantSource := "existingsymlink"
gotSource := f.Name()
if wantSource != gotSource {
return fmt.Errorf("invalid source name, got %v, want %v", gotSource, wantSource)
}
wantTarget := "existingsymlink"
gotTarget := f.Name()
if wantTarget != gotTarget {
return fmt.Errorf("invalid target name, got %v, want %v", gotTarget, wantTarget)
}
wantSourcePerm := fs.FileMode(0774)
gotSourcePerm := f.Mode().Perm()
if wantSourcePerm != gotSourcePerm {
return fmt.Errorf("invalid source perm, got %v, want %v", gotSourcePerm, wantSourcePerm)
}
wantTargetPerm := fs.FileMode(0774)
gotTargetPerm := f.Mode().Perm()
if wantTargetPerm != gotTargetPerm {
return fmt.Errorf("invalid target perm, got %v, want %v", gotTargetPerm, wantTargetPerm)
}
return nil
},
true,
true,
},
}
func TestSTFS_Chmod(t *testing.T) {
@@ -3450,29 +3852,38 @@ func TestSTFS_Chmod(t *testing.T) {
tt := tt
runTestForAllFss(t, tt.name, true, tt.withCache, tt.withOsFs, func(t *testing.T, fs fsConfig) {
if err := tt.prepare(fs.fs); err != nil {
t.Errorf("%v prepare() error = %v", fs.fs.Name(), err)
symFs, ok := fs.fs.(symFs)
if !ok {
return
}
if err := tt.prepare(symFs); err != nil {
t.Errorf("%v prepare() error = %v", symFs.Name(), err)
return
}
if err := fs.fs.Chmod(tt.args.name, tt.args.mode); (err != nil) != tt.wantErr {
t.Errorf("%v.Chmod() error = %v, wantErr %v", fs.fs.Name(), err, tt.wantErr)
return
}
got, err := fs.fs.Stat(tt.args.name)
err := symFs.Chmod(tt.args.name, tt.args.mode)
if (err != nil) != tt.wantErr {
t.Errorf("%v.Stat() error = %v, wantErr %v", fs.fs.Name(), err, tt.wantErr)
t.Errorf("%v.Chmod() error = %v, wantErr %v", symFs.Name(), err, tt.wantErr)
return
}
if err := tt.check(got); err != nil {
t.Errorf("%v check() error = %v", fs.fs.Name(), err)
if err == nil {
gotStat, errStat := symFs.Stat(tt.args.name)
gotLstat, _, errLstat := symFs.LstatIfPossible(tt.args.name)
if (errStat != nil && errLstat != nil) != tt.wantErr {
t.Errorf("%v.Stat() error = %v, %v.LstatIfPossible() error = %v, wantErr %v", symFs.Name(), errStat, symFs.Name(), errLstat, tt.wantErr)
return
return
}
if err := tt.check(gotStat, gotLstat); err != nil {
t.Errorf("%v check() error = %v", symFs.Name(), err)
return
}
}
})
}