diff options
| author | Ophestra <cat@gensokyo.uk> | 2026-01-06 04:36:01 +0900 |
|---|---|---|
| committer | Ophestra <cat@gensokyo.uk> | 2026-01-06 05:05:34 +0900 |
| commit | 79adf217f4ca94fdfeb8a190fc7dc49fd26254dd (patch) | |
| tree | bc9cfb855369bb6539fb11634fa0d132a6ef6a4e /internal/pkg/exec_test.go | |
| parent | 8efffd72f4c5a0f241075fd13e4d07d71fd7fde8 (diff) | |
internal/pkg: implement exec artifact
This runs a program in a container environment. Artifacts can be made available to the container, they are cured concurrently and mounted in order.
Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'internal/pkg/exec_test.go')
| -rw-r--r-- | internal/pkg/exec_test.go | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/internal/pkg/exec_test.go b/internal/pkg/exec_test.go new file mode 100644 index 00000000..e718b260 --- /dev/null +++ b/internal/pkg/exec_test.go @@ -0,0 +1,138 @@ +package pkg_test + +//go:generate go build -tags testtool -ldflags "-extldflags='-static'" -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() + + checkWithCache(t, []cacheTestCase{ + {"container", nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) { + c.SetStrict(true) + + // this 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) + }, + }} + + msg := message.New(log.New(os.Stderr, "container: ", 0)) + msg.SwapVerbose(testing.Verbose()) + + cureMany(t, c, []cureStep{ + {"container", pkg.NewExec( + t.Context(), + msg, + 0, + check.MustAbs("/work"), + []string{"HAKUREI_TEST=1"}, + check.MustAbs("/opt/bin/testtool"), + []string{"testtool"}, + + pkg.MustPath("/file", newStubFile( + pkg.KindHTTPGet, + pkg.ID{0xfe, 0}, + nil, + nil, nil, + )), + pkg.MustPath("/.hakurei", stubArtifact{ + kind: pkg.KindTar, + params: []byte("empty directory"), + cure: func(c *pkg.CureContext) error { + return os.MkdirAll(c.GetWorkDir().String(), 0700) + }, + }), + pkg.MustPath("/opt", testtool), + ), ignorePathname, pkg.MustDecode( + "GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9", + ), nil}, + + {"error passthrough", pkg.NewExec( + t.Context(), + msg, + 0, + check.MustAbs("/work"), + []string{"HAKUREI_TEST=1"}, + check.MustAbs("/opt/bin/testtool"), + []string{"testtool"}, + + pkg.MustPath("/proc/nonexistent", 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))}, + }) + + // check init failure passthrough + var exitError *exec.ExitError + if _, _, err := c.Cure(pkg.NewExec( + t.Context(), + msg, + 0, + check.MustAbs("/work"), + 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) + } + + // the testtool is not deterministic + if pathname, checksum, err := c.Cure(testtool); err != nil { + t.Fatalf("Cure: error = %v", err) + } else if err = os.Remove(pathname.String()); err != nil { + t.Fatal(err) + } else { + p := base.Append( + "checksum", + pkg.Encode(checksum), + ) + if err = os.Chmod(p.Append("bin").String(), 0700); err != nil { + t.Fatal(err) + } + if err = os.Chmod(p.String(), 0700); err != nil { + t.Fatal(err) + } + if err = os.RemoveAll(p.String()); err != nil { + t.Fatal(err) + } + } + }, pkg.MustDecode("7PoPpWLjFPXIymbuIYLZAzOpCYr-2PN4CZ11jFdO-mDlnZNgFO3JyOtK8HW8Jxvm")}, + }) +} |
