Luigit
repositories / bugabinga.net

bugabinga.net

personal infrastructure for bugabinga!

owned by admin

services/luci/internal/podman/podman_test.go

Raw
package podman

import (
	"bytes"
	"context"
	"os"
	"os/exec"
	"path/filepath"
	"reflect"
	"strings"
	"testing"
	"time"
)

func TestCLIUsesSocketAsContainerHost(t *testing.T) {
	dir := t.TempDir()
	bin := filepath.Join(dir, "podman")
	shell, err := exec.LookPath("sh")
	if err != nil {
		t.Fatal(err)
	}
	if err := os.WriteFile(bin, []byte("#!"+shell+"\nprintf '%s' \"$CONTAINER_HOST\"\n"), 0o755); err != nil {
		t.Fatal(err)
	}
	t.Setenv("PATH", dir+string(os.PathListSeparator)+os.Getenv("PATH"))
	var stdout bytes.Buffer
	if err := (CLI{Socket: "unix:///tmp/podman.sock"}).Run(context.Background(), []string{"version"}, &stdout, &stdout); err != nil {
		t.Fatal(err)
	}
	if stdout.String() != "unix:///tmp/podman.sock" {
		t.Fatalf("CONTAINER_HOST = %q", stdout.String())
	}
}

func TestStepScriptMarksAndTimesSteps(t *testing.T) {
	script := StepScript([]string{"echo first", "echo 'it works'"})
	for _, want := range []string{
		"TOTAL=2",
		"step 'echo first'",
		`step 'echo '\''it works'\'''`,
		"[luci] step %d/%d",
	} {
		if !strings.Contains(script, want) {
			t.Fatalf("script missing %q:\n%s", want, script)
		}
	}
	if strings.Contains(script, "step 'echo 'it works''") {
		t.Fatal("unescaped quote broke script")
	}
}

func TestStepScriptShell(t *testing.T) {
	if testing.Short() {
		t.Skip("shell round trip")
	}
	script := StepScript([]string{"X=set", "test \"$X\" = set", "true"})
	cmd := exec.Command("/bin/sh", "-c", script)
	output, err := cmd.CombinedOutput()
	if err != nil {
		t.Fatalf("err=%v output=%s", err, output)
	}
	if !strings.Contains(string(output), "[luci] step 3/3 done in 0s") {
		t.Fatalf("output=%s", output)
	}

	failing := StepScript([]string{"false"})
	cmd = exec.Command("/bin/sh", "-c", failing)
	output, err = cmd.CombinedOutput()
	if err == nil || !strings.Contains(string(output), "[luci] step 1/1 failed after") {
		t.Fatalf("err=%v output=%s", err, output)
	}
}

func TestBuildArgsUsesBaselineIsolation(t *testing.T) {
	got := BuildArgs(Spec{
		Image:     "docker.io/library/alpine:latest",
		Workspace: "/tmp/work",
		Memory:    "2g",
		CPUs:      "2",
		Env:       map[string]string{"B": "2", "A": "1"},
		Commands:  []string{"echo ok"},
		Timeout:   time.Minute,
	})
	want := []string{
		"run",
		"--rm",
		"--pull=missing",
		"--userns=keep-id",
		"--cap-drop=all",
		"--security-opt=no-new-privileges",
		"--pids-limit=1024",
		"--memory=2g",
		"--cpus=2",
		"--timeout=60",
		"--workdir=/work",
		"--volume", "/tmp/work:/work:Z",
		"--env", "A",
		"--env", "B",
		"--",
		"docker.io/library/alpine:latest",
		"/bin/sh",
		"-c",
		StepScript([]string{"echo ok"}),
	}
	if !reflect.DeepEqual(got, want) {
		t.Fatalf("args = %#v", got)
	}
	if strings.Contains(strings.Join(got, "\x00"), "A=1") || strings.Contains(strings.Join(got, "\x00"), "B=2") {
		t.Fatalf("secret env value leaked into argv: %#v", got)
	}
}

func TestEnvironmentPassesValuesOnlyThroughChildEnvironment(t *testing.T) {
	dir := t.TempDir()
	bin := filepath.Join(dir, "podman")
	shell, err := exec.LookPath("sh")
	if err != nil {
		t.Fatal(err)
	}
	if err := os.WriteFile(bin, []byte("#!"+shell+"\nprintf '%s' \"$TOKEN\"\n"), 0o755); err != nil {
		t.Fatal(err)
	}
	t.Setenv("PATH", dir+string(os.PathListSeparator)+os.Getenv("PATH"))
	spec := Spec{Env: map[string]string{"TOKEN": "secret-value"}}
	args := BuildArgs(spec)
	if strings.Contains(strings.Join(args, "\x00"), "secret-value") {
		t.Fatalf("secret env value leaked into argv: %#v", args)
	}
	var stdout bytes.Buffer
	if err := (CLI{}).RunWithEnv(context.Background(), args, Environment(spec), &stdout, &stdout); err != nil {
		t.Fatal(err)
	}
	if stdout.String() != "secret-value" {
		t.Fatalf("child TOKEN = %q", stdout.String())
	}
}