nixbuild/exec_test.go
Ophestra 8d502f1574
context: expose more internals
This makes overriding the Nix method easier.
2025-09-13 18:32:12 +09:00

134 lines
3.7 KiB
Go

package nix_test
import (
"context"
"errors"
"os"
"os/exec"
"reflect"
"slices"
"syscall"
"testing"
"unsafe"
"gensokyo.uk/nix"
)
func TestContext(t *testing.T) {
ctx := nix.New(t.Context(), &nix.BinaryCache{
Compression: "none",
ParallelCompression: false,
Bucket: "example",
Endpoint: "s3.example.org",
Region: "us-east-1",
Scheme: "http",
CredentialsPath: "/dev/null",
KeyPath: nonexistent,
}, []string{
nix.FlagOption, nix.OptionBuildUseSubstitutes, nix.ValueFalse,
nix.FlagOption, nix.OptionSubstituters, "",
nix.FlagOption, nix.OptionTrustedSubstituters, "",
nix.FlagOption, nix.OptionTrustedPublicKeys, "",
}, nil, nil)
extraVal := reflect.ValueOf(ctx).Elem().FieldByName("extra")
wantExtra := reflect.NewAt(extraVal.Type(), unsafe.Pointer(extraVal.UnsafeAddr())).Elem().Interface().([]string)
t.Run("extra", func(t *testing.T) {
got := ctx.Extra()
if !slices.Equal(got, wantExtra) {
t.Errorf("Extra: %#v, want %#v", got, wantExtra)
}
got[0] = "\x00"
if slices.Equal(got, wantExtra) {
t.Errorf("Extra did not return a copy")
}
})
t.Run("store env", func(t *testing.T) {
t.Run("nil", func(t *testing.T) {
want := nix.New(t.Context(), nil, nil, nil, nil).StoreEnv()
if want != nil {
t.Errorf("StoreEnv: %#v", want)
}
})
want := []string{"AWS_SHARED_CREDENTIALS_FILE=/dev/null"}
got := ctx.StoreEnv()
if !slices.Equal(got, want) {
t.Errorf("StoreEnv: %#v, want %#v", got, want)
}
})
}
func TestNixWriteStdin(t *testing.T) {
t.Run("store", func(t *testing.T) {
ctx := nix.New(t.Context(), &nix.BinaryCache{
Compression: "none",
ParallelCompression: false,
Bucket: "example",
Endpoint: "s3.example.org",
Region: "us-east-1",
Scheme: "http",
CredentialsPath: "/dev/null",
KeyPath: nonexistent,
}, nil, nil, nil)
cmd := ctx.Nix(t.Context(), nix.FlagVersion).(nix.ExecCmd)
wantArgs := []string{
nix.Nix,
nix.FlagStore,
"s3://example?compression=none&parallel-compression=false&region=us-east-1&scheme=http&endpoint=s3.example.org&secret-key=/proc/nonexistent",
nix.FlagVersion}
if !slices.Equal(cmd.Args, wantArgs) {
t.Errorf("Args = %#v, want %#v", cmd.Args, wantArgs)
}
wantEnv := []string{nix.EnvAwsSharedCredentialsFile + "=/dev/null"}
if !slices.Equal(cmd.Env, wantEnv) {
t.Errorf("Env = %#v, want %#v", cmd.Env, wantEnv)
}
})
t.Run("already set", func(t *testing.T) {
ctx := nix.New(t.Context(), nil, nil, os.Stdout, os.Stderr)
cmd := nix.ExecCmd{Cmd: exec.CommandContext(t.Context(), nonexistent)}
cmd.Stdin(os.Stdin)
if _, err := ctx.WriteStdin(cmd, nil, nil); err == nil {
t.Fatal("WriteStdinCommand unexpectedly succeeded")
}
})
t.Run("f returns error", func(t *testing.T) {
stubNixCommand(t)
ctx := newStubContext(t.Context(), nil, os.Stdout, os.Stderr)
cmd := ctx.Nix(t.Context(), "true")
if _, err := ctx.WriteStdin(
cmd,
slices.Values(make([]string, 0)),
func() error { return syscall.ENOSYS },
); !errors.Is(err, syscall.ENOSYS) {
t.Fatalf("WriteStdinCommand: error = %v, want %v", err, syscall.ENOSYS)
}
})
t.Run("exit before cancel", func(t *testing.T) {
stubNixCommand(t)
ctx := newStubContext(t.Context(), nil, os.Stdout, os.Stderr)
c, cancel := context.WithCancel(t.Context())
defer cancel()
cmd := ctx.Nix(c, "true").(nix.ExecCmd)
if err := cmd.Start(); err != nil {
t.Fatalf("Start: error = %v", err)
}
// Cancel is skipped after exec.Cmd.Wait completes
if _, err := cmd.Process.Wait(); err != nil {
t.Fatalf("Wait: error = %v", err)
}
cancel()
if cmd.Err != nil {
t.Fatalf("Err = %v", cmd.Err)
}
})
}