forked from rosa/hakurei
This makes package check portable, and removes nonportable behaviour from package pkg, pipewire, and system. All other packages remain nonportable due to their nature. No latency increase was observed due to this change on amd64 and arm64 linux. Signed-off-by: Ophestra <cat@gensokyo.uk>
103 lines
2.1 KiB
Go
103 lines
2.1 KiB
Go
//go:build testtool
|
|
|
|
package sandbox
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"io/fs"
|
|
"path/filepath"
|
|
"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 = filepath.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
|
|
}
|