Files
RenewCMS/test/update_helper_nofollow_linux_test.go

125 lines
3.8 KiB
Go

//go:build linux
package test
import (
infraUpdate "RenewCMS/internal/infrastructure/update"
"os"
"path/filepath"
"testing"
)
func TestNoFollowFilesystemOnLinux(t *testing.T) {
files := infraUpdate.NewNoFollowFilesystem()
directory := t.TempDir()
outside := filepath.Join(t.TempDir(), "outside.txt")
if err := os.WriteFile(outside, []byte("sentinel"), 0o644); err != nil {
t.Fatal(err)
}
link := filepath.Join(directory, "link")
if err := os.Symlink(outside, link); err != nil {
t.Fatal(err)
}
t.Run("lstat reports a symlink without following it", func(t *testing.T) {
info, err := files.Lstat(link)
if err != nil || !info.IsSymlink || info.IsRegular {
t.Errorf("info = %+v, err = %v", info, err)
}
})
t.Run("it never reads, copies, writes or chmods through a symlink", func(t *testing.T) {
if _, err := files.ReadFile(link); err == nil {
t.Error("read followed the link")
}
if err := files.Copy(link, filepath.Join(directory, "copy"), 0o600); err == nil {
t.Error("copy followed the link")
}
if err := files.CreateExclusive(link, []byte("x"), 0o600); err == nil {
t.Error("create followed the link")
}
if err := files.Chmod(link, 0o777); err == nil {
t.Error("chmod followed the link")
}
if content, _ := os.ReadFile(outside); string(content) != "sentinel" {
t.Errorf("the target changed: %q", content)
}
if info, _ := os.Stat(outside); info.Mode().Perm() != 0o644 {
t.Errorf("the target mode changed: %v", info.Mode())
}
})
t.Run("create-exclusive refuses an existing file and sets the mode", func(t *testing.T) {
path := filepath.Join(directory, "exclusive")
if err := files.CreateExclusive(path, []byte("one"), 0o640); err != nil {
t.Fatal(err)
}
if err := files.CreateExclusive(path, []byte("two"), 0o640); err == nil {
t.Error("the second create must fail")
}
if info, _ := os.Stat(path); info.Mode().Perm() != 0o640 {
t.Errorf("mode = %v", info.Mode())
}
})
t.Run("copy, rename, chmod and remove work on regular files", func(t *testing.T) {
source := filepath.Join(directory, "source")
_ = os.WriteFile(source, []byte("payload"), 0o600)
copied := filepath.Join(directory, "copied")
if err := files.Copy(source, copied, 0o755); err != nil {
t.Fatal(err)
}
renamed := filepath.Join(directory, "renamed")
if err := files.Rename(copied, renamed); err != nil {
t.Fatal(err)
}
if err := files.Chmod(renamed, 0o700); err != nil {
t.Fatal(err)
}
content, _ := files.ReadFile(renamed)
info, _ := os.Stat(renamed)
if string(content) != "payload" || info.Mode().Perm() != 0o700 {
t.Errorf("content = %q, mode = %v", content, info.Mode())
}
if err := files.Remove(renamed); err != nil {
t.Error(err)
}
})
t.Run("remove-all unlinks links and never descends into them", func(t *testing.T) {
tree := filepath.Join(directory, "tree")
_ = os.MkdirAll(filepath.Join(tree, "nested"), 0o755)
_ = os.WriteFile(filepath.Join(tree, "nested", "file"), []byte("x"), 0o644)
escape := t.TempDir()
_ = os.WriteFile(filepath.Join(escape, "keep"), []byte("keep"), 0o644)
_ = os.Symlink(escape, filepath.Join(tree, "escape"))
if err := files.RemoveAll(tree); err != nil {
t.Fatal(err)
}
if _, err := os.Stat(tree); err == nil {
t.Error("the tree must be gone")
}
if content, _ := os.ReadFile(filepath.Join(escape, "keep")); string(content) != "keep" {
t.Error("the link target must be intact")
}
if err := files.RemoveAll(tree); err != nil {
t.Errorf("removing a missing path = %v", err)
}
})
t.Run("the temp directory is private", func(t *testing.T) {
temp, err := files.MakePrivateTempDir()
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(temp)
info, _ := os.Stat(temp)
if !info.IsDir() || info.Mode().Perm() != 0o700 {
t.Errorf("mode = %v", info.Mode())
}
})
}