blob: ab94dbe90f8da0b826afc3294375199946da4095 [file] [log] [blame]
// Package docker is for running Dockerfiles.
package docker
import (
"context"
"path/filepath"
"strings"
"testing"
"time"
"github.com/stretchr/testify/require"
"go.skia.org/infra/go/exec"
"go.skia.org/infra/go/testutils"
"go.skia.org/infra/go/testutils/unittest"
"go.skia.org/infra/task_driver/go/td"
)
func TestBuild(t *testing.T) {
unittest.MediumTest(t)
// Strip our PATH so we find our version of `docker` which is in the
// testdata directory. Then add `/bin` to the PATH since we are running a
// Bash shell.
testDataDir := testutils.TestDataDir(t)
dockerCmd = filepath.Join(testDataDir, "docker_mock")
type args struct {
tag string
}
tests := []struct {
name string
args args
subSteps int
timeout time.Duration
expected td.StepResult
expectedSteps []td.StepReport
wantErr bool
buildArgs map[string]string
}{
{
name: "success",
args: args{
tag: "success",
},
timeout: time.Minute,
expected: td.StepResultSuccess,
expectedSteps: []td.StepReport{
{
StepProperties: &td.StepProperties{
Name: "Step 1/7 : FROM debian:testing-slim",
},
Result: td.StepResultSuccess,
},
{
StepProperties: &td.StepProperties{
Name: "Step 2/7 : RUN apt-get update && apt-get upgrade -y && apt-get install -y git python curl",
},
Result: td.StepResultSuccess,
},
{
StepProperties: &td.StepProperties{
Name: "Step 3/7 : RUN mkdir -p --mode=0777 /workspace/__cache && groupadd -g 2000 skia && useradd -u 2000 -g 2000 --home /workspace/__cache skia",
},
Result: td.StepResultSuccess,
},
{
StepProperties: &td.StepProperties{
Name: "Step 4/7 : ENV VPYTHON_VIRTUALENV_ROOT /workspace/__cache",
},
Result: td.StepResultSuccess,
},
{
StepProperties: &td.StepProperties{
Name: "Step 5/7 : ENV CIPD_CACHE_DIR /workspace/__cache",
},
Result: td.StepResultSuccess,
},
{
StepProperties: &td.StepProperties{
Name: "Step 6/7 : USER skia",
},
Result: td.StepResultSuccess,
},
{
StepProperties: &td.StepProperties{
Name: "Step 7/7 : RUN printenv && cd /tmp && git clone 'https://chromium.googlesource.com/chromium/tools/depot_tools.git' && mkdir -p /tmp/skia && cd /tmp/skia && export PATH=$PATH:/tmp/depot_tools && touch noop.py && vpython noop.py && ls -al /tmp/depot_tools && /tmp/depot_tools/fetch skia && ls -al /workspace/__cache && printenv",
},
Result: td.StepResultSuccess,
},
},
wantErr: false,
buildArgs: map[string]string{"arg1": "value1"},
},
{
name: "failure",
args: args{
tag: "failure",
},
timeout: time.Minute,
expected: td.StepResultFailure,
expectedSteps: []td.StepReport{
{
StepProperties: &td.StepProperties{
Name: "Step 1/7 : FROM debian:testing-slim",
},
Result: td.StepResultSuccess,
},
{
StepProperties: &td.StepProperties{
Name: "Step 2/7 : RUN apt-get update && apt-get upgrade -y && apt-get install -y git python curl",
},
Result: td.StepResultSuccess,
},
{
StepProperties: &td.StepProperties{
Name: "Step 3/7 : RUN mkdir -p --mode=0777 /workspace/__cache && groupadd -g 2000 skia && useradd -u 2000 -g 2000 --home /workspace/__cache skia",
},
Result: td.StepResultSuccess,
},
{
StepProperties: &td.StepProperties{
Name: "Step 4/7 : ENV VPYTHON_VIRTUALENV_ROOT /workspace/__cache",
},
Result: td.StepResultSuccess,
},
{
StepProperties: &td.StepProperties{
Name: "Step 5/7 : ENV CIPD_CACHE_DIR /workspace/__cache",
},
Result: td.StepResultSuccess,
},
{
StepProperties: &td.StepProperties{
Name: "Step 6/7 : USER skia",
},
Result: td.StepResultSuccess,
},
{
StepProperties: &td.StepProperties{
Name: "Step 7/7 : RUN printenv && cd /tmp && git clone 'https://chromium.googlesource.com/chromium/tools/depot_tools.git' && mkdir -p /tmp/skia && cd /tmp/skia && export PATH=$PATH:/tmp/depot_tools && touch noop.py && vpython noop.py && ls -al /tmp/depot_tools && /tmp/depot_tools/fetch skia && ls -al /workspace/__cache && printenv",
},
Result: td.StepResultFailure,
},
},
wantErr: true,
buildArgs: nil,
},
{
name: "failure_no_output",
args: args{
tag: "failure_no_output",
},
timeout: time.Minute,
expected: td.StepResultFailure,
expectedSteps: []td.StepReport{},
wantErr: true,
buildArgs: nil,
},
{
name: "timeout",
args: args{
tag: "timeout",
},
timeout: 100 * time.Millisecond,
expected: td.StepResultFailure,
expectedSteps: []td.StepReport{
{
StepProperties: &td.StepProperties{
Name: "Step 1/7 : FROM debian:testing-slim",
},
Result: td.StepResultSuccess,
},
{
StepProperties: &td.StepProperties{
Name: "Step 2/7 : RUN apt-get update && apt-get upgrade -y && apt-get install -y git python curl",
},
Result: td.StepResultSuccess,
},
{
StepProperties: &td.StepProperties{
Name: "Step 3/7 : RUN mkdir -p --mode=0777 /workspace/__cache && groupadd -g 2000 skia && useradd -u 2000 -g 2000 --home /workspace/__cache skia",
},
Result: td.StepResultSuccess,
},
{
StepProperties: &td.StepProperties{
Name: "Step 4/7 : ENV VPYTHON_VIRTUALENV_ROOT /workspace/__cache",
},
Result: td.StepResultSuccess,
},
{
StepProperties: &td.StepProperties{
Name: "Step 5/7 : ENV CIPD_CACHE_DIR /workspace/__cache",
},
Result: td.StepResultSuccess,
},
{
StepProperties: &td.StepProperties{
Name: "Step 6/7 : USER skia",
},
Result: td.StepResultSuccess,
},
{
StepProperties: &td.StepProperties{
Name: "Step 7/7 : RUN printenv && cd /tmp && git clone 'https://chromium.googlesource.com/chromium/tools/depot_tools.git' && mkdir -p /tmp/skia && cd /tmp/skia && export PATH=$PATH:/tmp/depot_tools && touch noop.py && vpython noop.py && ls -al /tmp/depot_tools && /tmp/depot_tools/fetch skia && ls -al /workspace/__cache && printenv",
},
Result: td.StepResultFailure,
},
},
wantErr: true,
buildArgs: nil,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tr := td.StartTestRun(t)
defer tr.Cleanup()
// Root-level step.
ctx := tr.Root()
// Add a timeout.
ctx, cancel := context.WithTimeout(ctx, tt.timeout)
defer cancel()
if err := BuildHelper(ctx, ".", tt.args.tag, "test_config_dir", tt.buildArgs); (err != nil) != tt.wantErr {
t.Errorf("Build() error = %v, wantErr %v", err, tt.wantErr)
}
// Ensure that we got the expected step results.
results := tr.EndRun(false, nil)
// The root step is always successful, since we don't
// do td.FailStep or td.Fatal.
require.Equal(t, td.StepResultSuccess, results.Result)
// We should have exactly one sub-step, which is the
// "docker run" as a whole.
require.Equal(t, 1, len(results.Steps))
dockerRun := results.Steps[0]
require.Equal(t, tt.expected, results.Steps[0].Result)
// Individual build steps.
require.Equal(t, len(tt.expectedSteps), len(dockerRun.Steps))
for idx, expectResult := range tt.expectedSteps {
require.Equal(t, expectResult.Name, dockerRun.Steps[idx].Name)
require.Equal(t, expectResult.Result, dockerRun.Steps[idx].Result)
}
})
}
}
func TestLogin(t *testing.T) {
unittest.SmallTest(t)
_ = td.RunTestSteps(t, false, func(ctx context.Context) error {
mockRun := &exec.CommandCollector{}
mockRun.SetDelegateRun(func(ctx context.Context, cmd *exec.Command) error {
require.Equal(t, dockerCmd, cmd.Name)
require.Equal(t, []string{"--config", "test_config_dir", "login", "-u", "oauth2accesstoken", "--password-stdin", "https://gcr.io"}, cmd.Args)
require.Equal(t, "", cmd.Dir)
require.Equal(t, strings.NewReader("token"), cmd.Stdin)
return nil
})
ctx = td.WithExecRunFn(ctx, mockRun.Run)
err := Login(ctx, "token", "https://gcr.io", "test_config_dir")
require.NoError(t, err)
return nil
})
}
func TestRun(t *testing.T) {
unittest.SmallTest(t)
_ = td.RunTestSteps(t, false, func(ctx context.Context) error {
mockRun := &exec.CommandCollector{}
mockRun.SetDelegateRun(func(ctx context.Context, cmd *exec.Command) error {
require.Equal(t, dockerCmd, cmd.Name)
require.Equal(t, []string{"--config", "test_config_dir", "run", "--volume", "/tmp/test:/OUT", "--env", "SKIP_BUILD=1", "https://gcr.io/skia-public/skia-release:123", "test_cmd"}, cmd.Args)
return nil
})
ctx = td.WithExecRunFn(ctx, mockRun.Run)
err := Run(ctx, "https://gcr.io/skia-public/skia-release:123", "test_config_dir", []string{"test_cmd"}, []string{"/tmp/test:/OUT"}, []string{"SKIP_BUILD=1"})
require.NoError(t, err)
return nil
})
}
func TestPull(t *testing.T) {
unittest.SmallTest(t)
_ = td.RunTestSteps(t, false, func(ctx context.Context) error {
mockRun := &exec.CommandCollector{}
mockRun.SetDelegateRun(func(ctx context.Context, cmd *exec.Command) error {
require.Equal(t, dockerCmd, cmd.Name)
require.Equal(t, []string{"--config", "test_config_dir", "pull", "https://gcr.io/skia-public/skia-release:123"}, cmd.Args)
require.Equal(t, "", cmd.Dir)
return nil
})
ctx = td.WithExecRunFn(ctx, mockRun.Run)
err := Pull(ctx, "https://gcr.io/skia-public/skia-release:123", "test_config_dir")
require.NoError(t, err)
return nil
})
}
func TestPush(t *testing.T) {
unittest.SmallTest(t)
_ = td.RunTestSteps(t, false, func(ctx context.Context) error {
mockRun := &exec.CommandCollector{}
mockRun.SetDelegateRun(func(ctx context.Context, cmd *exec.Command) error {
require.Equal(t, dockerCmd, cmd.Name)
require.Equal(t, []string{"--config", "test_config_dir", "push", "https://gcr.io/skia-public/skia-release:123"}, cmd.Args)
require.Equal(t, ".", cmd.Dir)
_, err := cmd.CombinedOutput.Write([]byte(`The push refers to repository [gcr.io/skia-public/linux-run]
d75098a9b75c: Preparing
22f92a22a0a1: Preparing
7c18f43554d6: Preparing
c90191647a49: Preparing
22f92a22a0a1: Layer already exists
c90191647a49: Layer already exists
7c18f43554d6: Layer already exists
d75098a9b75c: Layer already exists
latest: digest: sha256:9f856122da361de5a737c4dd5b0ef582df3e051e6586d971a068e72657ddd0d2 size: 1166`))
return err
})
ctx = td.WithExecRunFn(ctx, mockRun.Run)
sha256, err := Push(ctx, "https://gcr.io/skia-public/skia-release:123", "test_config_dir")
require.NoError(t, err)
require.Equal(t, "sha256:9f856122da361de5a737c4dd5b0ef582df3e051e6586d971a068e72657ddd0d2", sha256)
return nil
})
}