aboutsummaryrefslogtreecommitdiffhomepage
path: root/test/internal/sandbox/fs.go
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2025-11-12 23:03:22 +0900
committerOphestra <cat@gensokyo.uk>2025-11-12 23:03:22 +0900
commitb5630f6883c874d458d9ae3c666cfb7ae5e3121d (patch)
treee2c488165211b1f68b9eaef8469d92a81ba37f43 /test/internal/sandbox/fs.go
parent17ffdb2dcf3bb5c8edf277a017cecd8e71a2e26b (diff)
test: move package sandbox internal
This should never be used outside vm tests. Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'test/internal/sandbox/fs.go')
-rw-r--r--test/internal/sandbox/fs.go102
1 files changed, 102 insertions, 0 deletions
diff --git a/test/internal/sandbox/fs.go b/test/internal/sandbox/fs.go
new file mode 100644
index 00000000..36d6c6d3
--- /dev/null
+++ b/test/internal/sandbox/fs.go
@@ -0,0 +1,102 @@
+//go:build testtool
+
+package sandbox
+
+import (
+ "errors"
+ "fmt"
+ "io/fs"
+ "path"
+ "strings"
+)
+
+var (
+ ErrFSBadLength = errors.New("bad dir length")
+ ErrFSBadData = errors.New("data differs")
+ ErrFSBadMode = errors.New("mode differs")
+ ErrFSInvalidEnt = errors.New("invalid entry condition")
+)
+
+type FS struct {
+ Mode fs.FileMode `json:"mode"`
+ Dir map[string]*FS `json:"dir"`
+ Data *string `json:"data"`
+}
+
+func printDir(prefix string, dir []fs.DirEntry) {
+ names := make([]string, len(dir))
+ for i, ent := range dir {
+ name := ent.Name()
+ if ent.IsDir() {
+ name += "/"
+ }
+ names[i] = fmt.Sprintf("%q", name)
+ }
+ printf("[FAIL] d %s: %s", prefix, strings.Join(names, " "))
+}
+
+func (s *FS) Compare(prefix string, e fs.FS) error {
+ if s.Data != nil {
+ if s.Dir != nil {
+ panic("invalid state")
+ }
+ panic("invalid compare call")
+ }
+
+ if s.Dir == nil {
+ printf("[ OK ] s %s", prefix)
+ return nil
+ }
+
+ var dir []fs.DirEntry
+ if d, err := fs.ReadDir(e, prefix); err != nil {
+ return err
+ } else if len(d) != len(s.Dir) {
+ printDir(prefix, d)
+ return ErrFSBadLength
+ } else {
+ dir = d
+ }
+
+ for _, got := range dir {
+ name := got.Name()
+
+ if want, ok := s.Dir[name]; !ok {
+ printDir(prefix, dir)
+ return fs.ErrNotExist
+ } else if want.Dir != nil && !got.IsDir() {
+ printDir(prefix, dir)
+ return ErrFSInvalidEnt
+ } else {
+ name = path.Join(prefix, name)
+
+ if fi, err := got.Info(); err != nil {
+ return err
+ } else if fi.Mode() != want.Mode {
+ printf("[FAIL] m %s: %x, want %x",
+ name, uint32(fi.Mode()), uint32(want.Mode))
+ return ErrFSBadMode
+ }
+
+ if want.Data != nil {
+ if want.Dir != nil {
+ panic("invalid state")
+ }
+ if v, err := fs.ReadFile(e, name); err != nil {
+ return err
+ } else if string(v) != *want.Data {
+ printf("[FAIL] f %s", name)
+ printf("got: %s", v)
+ printf("want: %s", *want.Data)
+ return ErrFSBadData
+ }
+ printf("[ OK ] f %s", name)
+ } else if err := want.Compare(name, e); err != nil {
+ return err
+ }
+ }
+ }
+ printf("[ OK ] d %s", prefix)
+
+ return nil
+}