diff options
| author | Ophestra <cat@gensokyo.uk> | 2026-08-29 18:58:06 +0900 |
|---|---|---|
| committer | Ophestra <cat@gensokyo.uk> | 2026-08-29 18:58:06 +0900 |
| commit | c2d900ec74e03e9c782cfe7b7ce06ff62cda6601 (patch) | |
| tree | fb13320bfdc62d810aa59769e8809dc2f707919e /pkg/internal | |
| parent | bd4f29909e0750a4660eaf48e3169777a265b0ab (diff) | |
Closes #43.
Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'pkg/internal')
| -rw-r--r-- | pkg/internal/testtool/expected/expected.go | 9 | ||||
| -rw-r--r-- | pkg/internal/testtool/expected/sum_amd64.go | 11 | ||||
| -rw-r--r-- | pkg/internal/testtool/expected/sum_arm64.go | 11 | ||||
| -rw-r--r-- | pkg/internal/testtool/expected/sum_riscv64.go | 11 | ||||
| -rw-r--r-- | pkg/internal/testtool/main.go | 277 |
5 files changed, 319 insertions, 0 deletions
diff --git a/pkg/internal/testtool/expected/expected.go b/pkg/internal/testtool/expected/expected.go new file mode 100644 index 00000000..c0e8e4a2 --- /dev/null +++ b/pkg/internal/testtool/expected/expected.go @@ -0,0 +1,9 @@ +// Package expected contains data shared between test helper and test harness. +package expected + +const ( + // Magic are magic bytes in the binfmt test case. + Magic = "\xca\xfe\xba\xbe\xfd\xfd" + // Full is the full content of the binfmt test case executable. + Full = Magic + ":3" +) diff --git a/pkg/internal/testtool/expected/sum_amd64.go b/pkg/internal/testtool/expected/sum_amd64.go new file mode 100644 index 00000000..354931be --- /dev/null +++ b/pkg/internal/testtool/expected/sum_amd64.go @@ -0,0 +1,11 @@ +package expected + +const ( + Offline = "IKmVhALejtYA3JhN1PCfjKF-Dio1XVcOeMWDHhfSHCbb4iBNhGjFy2UspZveZvb8" + OfflineS = "6ZubjSyCnz4-TKgQZi_BbY-JUwsStYCtD_f-BTDOOotfEbqkm47W20AazHRaLviz" + OvlRoot = "Yox7WpG8B_OqIXWF4HWFZkUfsEl7DGzpFyZM0qtd9T8nQ-7SAkEUurlAe6_DJ6Iu" + Layers = "aAwfxDB-efVo379FNl178jK7HEKU3LEjHbZdaVVjk7GnXGZGEANNsXnB3SCUxM9A" + Net = "IU3GwU2jTBd7HjotvFo2wsDWBQGVGpamwiSKdc2G1EnhM-ZaacxAuK6q0wbTVxra" + Promote = "rOjetGHzT_jPErrBR24IAZKDj8Q9dLLqxFQqloMgjsULss0VXDI--n6LxuMBHvmZ" + Work = "7f9XDeREfvJIjCe0qesND0s0tasExAIcc-OH33-eq9tsrQPUXhJp4KEkpsYH4hCD" +) diff --git a/pkg/internal/testtool/expected/sum_arm64.go b/pkg/internal/testtool/expected/sum_arm64.go new file mode 100644 index 00000000..2e6f7cbf --- /dev/null +++ b/pkg/internal/testtool/expected/sum_arm64.go @@ -0,0 +1,11 @@ +package expected + +const ( + Offline = "MTgCSzwPrzGigp9phvDPRwUTNGLm1KM2EsEtbz-l2cNieqjaGtnzm65CDXlSxXrl" + OfflineS = "p89bQg7_jR4nwaSbpEd08ne1jHOEw7Wlnlyv5FHq7ba1Kml3HSBZwEKRzu0gCqEb" + OvlRoot = "9ifwO6MAaV9kTqRR2O5PJzm8XhfXbr50mFLWyEHQm8OHHcJtAEUgXZzJYoZt9YVV" + Layers = "INuGActFPwJtS7mAR9Bkt7FD4yoHlXHSJ9CaSAQJrpkUBL_k815Cs_jvRfxy5-a7" + Net = "kJvy24uk4ePvHoxSKf4vMOhR4NxLbmyWlA9bTS7d3z3fE9WF1Tvpao9g-QuYU4vm" + Promote = "lYqyYrfjPawIbld5Qz0NbKvd_bmI3nJC1eEnlIQWzsjWE9uA1HuKPAaClnDeyG6L" + Work = "V6k4FqOBMRCmHiqchs5-joVGZ_MhNWZyXm3gdbU0S7S5eMze7G4SwYMTf66ojKQL" +) diff --git a/pkg/internal/testtool/expected/sum_riscv64.go b/pkg/internal/testtool/expected/sum_riscv64.go new file mode 100644 index 00000000..53872c08 --- /dev/null +++ b/pkg/internal/testtool/expected/sum_riscv64.go @@ -0,0 +1,11 @@ +package expected + +const ( + Offline = "LlieSHVDe1lnKvfI8t4oGRg_2hPxwyy1drmaqc-EKCOENuS9C2YHrp2VY5pSyhbg" + OfflineS = "qccjM8oYjUuEYPKFFzAxDFVzMerSUKUZc18NdVQoiPWf-70XOsNK8NaUQqjTgTAD" + OvlRoot = "lpV2bb_KGYFHPiOn-jtGop8K_ew0y1p3BezRp0ebM93_a-T9J-vkqGD5uokda1aN" + Layers = "sM3DJm210CHPGHkAquIbrXhspB81FpVC60ApQrvJGD5El2i7cSONj7LWf7EWqKpT" + Net = "JihQUwsVETRYjb2-yIXLYZ6WVsaFebwl8btSYAsNQ2QapS5MZVaI-dYwrVoySycR" + Promote = "lGqwR4W2OjylSVitMQP1lc6wApOBkbMjsmIqkxQbfEZ3DHEQBbJr84ErW6Xb54zo" + Work = "aZgtyv6aMtoHFkHAaJr6nLaA7N_SHjShgWPyQ5UdzaIqYSiVqvCrZqSokGTCcTii" +) diff --git a/pkg/internal/testtool/main.go b/pkg/internal/testtool/main.go new file mode 100644 index 00000000..edffab7e --- /dev/null +++ b/pkg/internal/testtool/main.go @@ -0,0 +1,277 @@ +//go:build testtool + +package main + +import ( + "encoding/gob" + "log" + "net" + "os" + "path/filepath" + "reflect" + "runtime" + "slices" + "strconv" + "strings" + + "hakurei.app/fhs" + "hakurei.app/vfs" + + "hakurei.app/pkg/internal/testtool/expected" +) + +func main() { + log.SetFlags(0) + log.SetPrefix("testtool: ") + + if os.Getenv("HAKUREI_BINFMT") == "1" { + wantArgs := []string{"/interpreter", "/opt/bin/sample"} + if !slices.Equal(os.Args, wantArgs) { + log.Fatalf("Args: %q, want %q", os.Args, wantArgs) + } + + if err := os.WriteFile("check", []byte("binfmt"), 0400); err != nil { + log.Fatal(err) + } + + return + } + + environ := slices.DeleteFunc(slices.Clone(os.Environ()), func(s string) bool { + for _, t := range []string{ + "CURE_JOBS=" + strconv.Itoa(runtime.NumCPU()), + "CURE_LOAD=" + strconv.Itoa(runtime.NumCPU()+2), + } { + if s == t { + return true + } + } + return false + }) + + var hostNet, layers, promote bool + if len(os.Args) == 2 && os.Args[0] == "testtool" { + switch os.Args[1] { + case "net": + hostNet = true + log.SetPrefix("testtool(net): ") + break + + case "layers": + layers = true + log.SetPrefix("testtool(layers): ") + break + + case "promote": + promote = true + log.SetPrefix("testtool(promote): ") + + default: + log.Fatalf("Args: %q", os.Args) + return + } + } else if wantArgs := []string{"testtool"}; !slices.Equal(os.Args, wantArgs) { + log.Fatalf("Args: %q, want %q", os.Args, wantArgs) + } + + var overlayRoot bool + wantEnv := []string{"HAKUREI_TEST=1"} + if len(environ) == 2 { + overlayRoot = true + if !layers && !promote { + log.SetPrefix("testtool(overlay root): ") + } + wantEnv = []string{"HAKUREI_TEST=1", "HAKUREI_ROOT=1"} + } + if !slices.Equal(wantEnv, environ) { + log.Fatalf("Environ: %q, want %q", environ, wantEnv) + } + + var overlayWork bool + const ( + wantExec = "/opt/bin/testtool" + wantExecWork = "/work/bin/testtool" + ) + var iftPath string + if got, err := os.Executable(); err != nil { + log.Fatalf("Executable: error = %v", err) + } else { + iftPath = filepath.Join(filepath.Dir(filepath.Dir(got)), "ift") + + if got != wantExec { + switch got { + case wantExecWork: + overlayWork = true + log.SetPrefix("testtool(overlay work): ") + + default: + log.Fatalf("Executable: %q, want %q", got, wantExec) + } + } + } + + wantHostname := "cure" + if hostNet { + wantHostname += "-net" + } + + if hostname, err := os.Hostname(); err != nil { + log.Fatalf("Hostname: error = %v", err) + } else if hostname != wantHostname { + log.Fatalf("Hostname: %q, want %q", hostname, wantHostname) + } + + var m *vfs.MountInfo + if f, err := os.Open(fhs.Proc + "self/mountinfo"); err != nil { + log.Fatalf("Open: error = %v", err) + } else { + err = vfs.NewMountInfoDecoder(f).Decode(&m) + closeErr := f.Close() + if err != nil { + log.Fatalf("Decode: error = %v", err) + } + if closeErr != nil { + log.Fatalf("Close: error = %v", err) + } + } + + if ift, err := net.Interfaces(); err != nil { + log.Fatal(err) + } else if !hostNet { + if len(ift) != 1 || ift[0].Name != "lo" { + log.Fatalln("got interfaces", strings.Join(slices.Collect(func(yield func(ifn string) bool) { + for _, ifi := range ift { + if !yield(ifi.Name) { + break + } + } + }), ", ")) + } + } else { + var iftParent []net.Interface + + var r *os.File + if r, err = os.Open(iftPath); err != nil { + log.Fatal(err) + } else { + err = gob.NewDecoder(r).Decode(&iftParent) + closeErr := r.Close() + if err != nil { + log.Fatal(err) + } + if closeErr != nil { + log.Fatal(closeErr) + } + } + + if !reflect.DeepEqual(ift, iftParent) { + log.Fatalf("Interfaces: %#v, want %#v", ift, iftParent) + } + } + + const checksumEmptyDir = "MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU" + ident := expected.Offline + log.Println(m) + next := func() { m = m.Next; log.Println(m) } + + if overlayRoot { + ident = expected.OvlRoot + + if m.Root != "/" || m.Target != "/" || + m.Source != "overlay" || m.FsType != "overlay" { + log.Fatal("unexpected root mount entry") + } + var lowerdir []string + for _, o := range strings.Split(m.FsOptstr, ",") { + const lowerdirKey = "lowerdir+=" + if strings.HasPrefix(o, lowerdirKey) { + lowerdir = append(lowerdir, o[len(lowerdirKey):]) + } + } + if !layers { + if len(lowerdir) != 1 || filepath.Base(lowerdir[0]) != checksumEmptyDir { + log.Fatal("unexpected artifact checksum") + } + } else { + ident = expected.Layers + + if len(lowerdir) != 2 || + filepath.Base(lowerdir[0]) != "MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU" || + filepath.Base(lowerdir[1]) != "nY_CUdiaUM1OL4cPr5TS92FCJ3rCRV7Hm5oVTzAvMXwC03_QnTRfQ5PPs7mOU9fK" { + log.Fatalf("unexpected lowerdirs %s", strings.Join(lowerdir, ", ")) + } + } + } else { + if hostNet { + ident = expected.Net + } + + if m.Root != "/sysroot" || m.Target != "/" { + log.Fatal("unexpected root mount entry") + } + + next() + if filepath.Base(m.Root) != "OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb" { + log.Fatal("unexpected file artifact checksum") + } + + next() + if filepath.Base(m.Root) != checksumEmptyDir { + log.Fatal("unexpected artifact checksum") + } + } + + if promote { + ident = expected.Promote + } + + next() // testtool artifact + + next() + if overlayWork { + ident = expected.Work + if m.Root != "/" || m.Target != "/work" || + m.Source != "overlay" || m.FsType != "overlay" { + log.Fatal("unexpected work mount entry") + } + } else { + if filepath.Base(m.Root) != ident || m.Target != "/work" { + log.Fatal("unexpected work mount entry") + } + } + + next() + if filepath.Base(m.Root) != ident || m.Target != "/tmp" { + log.Fatal("unexpected temp mount entry") + } + + next() + if m.Root != "/" || m.Target != "/proc" || m.Source != "proc" || m.FsType != "proc" { + log.Fatal("unexpected proc mount entry") + } + + next() + if m.Root != "/" || m.Target != "/dev" || m.Source != "devtmpfs" || m.FsType != "tmpfs" { + log.Fatal("unexpected dev mount entry") + } + + for i := 0; i < 9; i++ { // private /dev entries + next() + } + + if m.Next != nil { + log.Println("unexpected extra mount entries") + for m.Next != nil { + next() + } + os.Exit(1) + } + + checkData := []byte{0} + if hostNet { + checkData = []byte("net") + } + if err := os.WriteFile("check", checkData, 0400); err != nil { + log.Fatal(err) + } +} |
