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")}, }) }