All checks were successful
Test / Create distribution (push) Successful in 47s
Test / Sandbox (push) Successful in 2m48s
Test / ShareFS (push) Successful in 4m43s
Test / Sandbox (race detector) (push) Successful in 5m15s
Test / Hpkg (push) Successful in 5m25s
Test / Hakurei (push) Successful in 5m38s
Test / Hakurei (race detector) (push) Successful in 7m28s
Test / Flake checks (push) Successful in 1m44s
This removes all but the /work/ auto overlay behaviour and enables much greater flexibility. This also renames ExecContainerPath to ExecPath so it is easier to type. Signed-off-by: Ophestra <cat@gensokyo.uk>
258 lines
6.8 KiB
Go
258 lines
6.8 KiB
Go
package pkg_test
|
|
|
|
//go:generate env CGO_ENABLED=0 go build -tags testtool -o testdata/testtool ./testdata
|
|
|
|
import (
|
|
_ "embed"
|
|
"errors"
|
|
"log"
|
|
"os"
|
|
"os/exec"
|
|
"testing"
|
|
|
|
"hakurei.app/container/check"
|
|
"hakurei.app/container/stub"
|
|
"hakurei.app/hst"
|
|
"hakurei.app/internal/pkg"
|
|
"hakurei.app/message"
|
|
)
|
|
|
|
// testtoolBin is the container test tool binary made available to the
|
|
// execArtifact for testing its curing environment.
|
|
//
|
|
//go:embed testdata/testtool
|
|
var testtoolBin []byte
|
|
|
|
func TestExec(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
wantChecksumOffline := pkg.MustDecode(
|
|
"GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9",
|
|
)
|
|
|
|
checkWithCache(t, []cacheTestCase{
|
|
{"offline", nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
|
c.SetStrict(true)
|
|
testtool, testtoolDestroy := newTesttool()
|
|
|
|
msg := message.New(log.New(os.Stderr, "container: ", 0))
|
|
msg.SwapVerbose(testing.Verbose())
|
|
|
|
cureMany(t, c, []cureStep{
|
|
{"container", pkg.NewExec(
|
|
t.Context(),
|
|
msg,
|
|
0,
|
|
nil,
|
|
pkg.AbsWork,
|
|
[]string{"HAKUREI_TEST=1"},
|
|
check.MustAbs("/opt/bin/testtool"),
|
|
[]string{"testtool"},
|
|
|
|
pkg.MustPath("/file", false, newStubFile(
|
|
pkg.KindHTTPGet,
|
|
pkg.ID{0xfe, 0},
|
|
nil,
|
|
nil, nil,
|
|
)),
|
|
pkg.MustPath("/.hakurei", false, stubArtifact{
|
|
kind: pkg.KindTar,
|
|
params: []byte("empty directory"),
|
|
cure: func(c *pkg.CureContext) error {
|
|
return os.MkdirAll(c.GetWorkDir().String(), 0700)
|
|
},
|
|
}),
|
|
pkg.MustPath("/opt", false, testtool),
|
|
), ignorePathname, wantChecksumOffline, nil},
|
|
|
|
{"error passthrough", pkg.NewExec(
|
|
t.Context(),
|
|
msg,
|
|
0,
|
|
nil,
|
|
pkg.AbsWork,
|
|
[]string{"HAKUREI_TEST=1"},
|
|
check.MustAbs("/opt/bin/testtool"),
|
|
[]string{"testtool"},
|
|
|
|
pkg.MustPath("/proc/nonexistent", false, stubArtifact{
|
|
kind: pkg.KindTar,
|
|
params: []byte("doomed artifact"),
|
|
cure: func(c *pkg.CureContext) error {
|
|
return stub.UniqueError(0xcafe)
|
|
},
|
|
}),
|
|
), nil, pkg.Checksum{}, errors.Join(stub.UniqueError(0xcafe))},
|
|
|
|
{"invalid paths", pkg.NewExec(
|
|
t.Context(),
|
|
msg,
|
|
0,
|
|
nil,
|
|
pkg.AbsWork,
|
|
[]string{"HAKUREI_TEST=1"},
|
|
check.MustAbs("/opt/bin/testtool"),
|
|
[]string{"testtool"},
|
|
|
|
pkg.ExecPath{},
|
|
), nil, pkg.Checksum{}, os.ErrInvalid},
|
|
})
|
|
|
|
// check init failure passthrough
|
|
var exitError *exec.ExitError
|
|
if _, _, err := c.Cure(pkg.NewExec(
|
|
t.Context(),
|
|
msg,
|
|
0,
|
|
nil,
|
|
pkg.AbsWork,
|
|
nil,
|
|
check.MustAbs("/opt/bin/testtool"),
|
|
[]string{"testtool"},
|
|
)); !errors.As(err, &exitError) ||
|
|
exitError.ExitCode() != hst.ExitFailure {
|
|
t.Fatalf("Cure: error = %v, want init exit status 1", err)
|
|
}
|
|
|
|
testtoolDestroy(t, base, c)
|
|
}, pkg.MustDecode("UiV6kMz7KrTsc_yphiyQzFLqjRanHxUOwrBMtkKuWo4mOO6WgPFAcoUEeSp7eVIW")},
|
|
|
|
{"net", nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
|
c.SetStrict(true)
|
|
testtool, testtoolDestroy := newTesttool()
|
|
|
|
msg := message.New(log.New(os.Stderr, "container: ", 0))
|
|
msg.SwapVerbose(testing.Verbose())
|
|
|
|
wantChecksum := pkg.MustDecode(
|
|
"a1F_i9PVQI4qMcoHgTQkORuyWLkC1GLIxOhDt2JpU1NGAxWc5VJzdlfRK-PYBh3W",
|
|
)
|
|
cureMany(t, c, []cureStep{
|
|
{"container", pkg.NewExec(
|
|
t.Context(),
|
|
msg,
|
|
0,
|
|
&wantChecksum,
|
|
pkg.AbsWork,
|
|
[]string{"HAKUREI_TEST=1"},
|
|
check.MustAbs("/opt/bin/testtool"),
|
|
[]string{"testtool", "net"},
|
|
|
|
pkg.MustPath("/file", false, newStubFile(
|
|
pkg.KindHTTPGet,
|
|
pkg.ID{0xfe, 0},
|
|
nil,
|
|
nil, nil,
|
|
)),
|
|
pkg.MustPath("/.hakurei", false, stubArtifact{
|
|
kind: pkg.KindTar,
|
|
params: []byte("empty directory"),
|
|
cure: func(c *pkg.CureContext) error {
|
|
return os.MkdirAll(c.GetWorkDir().String(), 0700)
|
|
},
|
|
}),
|
|
pkg.MustPath("/opt", false, testtool),
|
|
), ignorePathname, wantChecksum, nil},
|
|
})
|
|
|
|
testtoolDestroy(t, base, c)
|
|
}, pkg.MustDecode("ek4K-0d4iRSArkY2TCs3WK34DbiYeOmhE_4vsJTSu_6roY4ZF3YG6eKRooal-i1o")},
|
|
|
|
{"overlay root", nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
|
c.SetStrict(true)
|
|
testtool, testtoolDestroy := newTesttool()
|
|
|
|
msg := message.New(log.New(os.Stderr, "container: ", 0))
|
|
msg.SwapVerbose(testing.Verbose())
|
|
|
|
cureMany(t, c, []cureStep{
|
|
{"container", pkg.NewExec(
|
|
t.Context(),
|
|
msg,
|
|
0,
|
|
nil,
|
|
pkg.AbsWork,
|
|
[]string{"HAKUREI_TEST=1", "HAKUREI_ROOT=1"},
|
|
check.MustAbs("/opt/bin/testtool"),
|
|
[]string{"testtool"},
|
|
|
|
pkg.MustPath("/", true, stubArtifact{
|
|
kind: pkg.KindTar,
|
|
params: []byte("empty directory"),
|
|
cure: func(c *pkg.CureContext) error {
|
|
return os.MkdirAll(c.GetWorkDir().String(), 0700)
|
|
},
|
|
}),
|
|
pkg.MustPath("/opt", false, testtool),
|
|
), ignorePathname, wantChecksumOffline, nil},
|
|
})
|
|
|
|
testtoolDestroy(t, base, c)
|
|
}, pkg.MustDecode("VIqqpf0ip9jcyw63i6E8lCMGUcLivQBe4Bevt3WusNac-1MSy5bzB647qGUBzl-W")},
|
|
|
|
{"overlay work", nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
|
c.SetStrict(true)
|
|
testtool, testtoolDestroy := newTesttool()
|
|
|
|
msg := message.New(log.New(os.Stderr, "container: ", 0))
|
|
msg.SwapVerbose(testing.Verbose())
|
|
|
|
cureMany(t, c, []cureStep{
|
|
{"container", pkg.NewExec(
|
|
t.Context(),
|
|
msg,
|
|
0,
|
|
nil,
|
|
pkg.AbsWork,
|
|
[]string{"HAKUREI_TEST=1", "HAKUREI_ROOT=1"},
|
|
check.MustAbs("/work/bin/testtool"),
|
|
[]string{"testtool"},
|
|
|
|
pkg.MustPath("/", true, stubArtifact{
|
|
kind: pkg.KindTar,
|
|
params: []byte("empty directory"),
|
|
cure: func(c *pkg.CureContext) error {
|
|
return os.MkdirAll(c.GetWorkDir().String(), 0700)
|
|
},
|
|
}), pkg.MustPath("/work/", false, stubArtifact{
|
|
kind: pkg.KindTar,
|
|
params: []byte("empty directory"),
|
|
cure: func(c *pkg.CureContext) error {
|
|
return os.MkdirAll(c.GetWorkDir().String(), 0700)
|
|
},
|
|
}), pkg.Path(pkg.AbsWork, false /* ignored */, testtool),
|
|
), ignorePathname, wantChecksumOffline, nil},
|
|
})
|
|
|
|
testtoolDestroy(t, base, c)
|
|
}, pkg.MustDecode("RibudsoY1X4_dtshfvL5LYfCPcxVnP0ikOn3yBHzOrt6BpevQiANLJF6Xua76-gM")},
|
|
})
|
|
}
|
|
|
|
// newTesttool returns an [Artifact] that cures into testtoolBin. The returned
|
|
// function must be called at the end of the test but not deferred.
|
|
func newTesttool() (
|
|
testtool pkg.Artifact,
|
|
testtoolDestroy func(t *testing.T, base *check.Absolute, c *pkg.Cache),
|
|
) {
|
|
// testtoolBin is built during go:generate and is not deterministic
|
|
testtool = overrideIdent{pkg.ID{0xfe, 0xff}, stubArtifact{
|
|
kind: pkg.KindTar,
|
|
cure: func(c *pkg.CureContext) error {
|
|
work := c.GetWorkDir()
|
|
if err := os.MkdirAll(
|
|
work.Append("bin").String(),
|
|
0700,
|
|
); err != nil {
|
|
return err
|
|
}
|
|
return os.WriteFile(c.GetWorkDir().Append(
|
|
"bin",
|
|
"testtool",
|
|
).String(), testtoolBin, 0500)
|
|
},
|
|
}}
|
|
testtoolDestroy = newDestroyArtifactFunc(testtool)
|
|
return
|
|
}
|