moby/builder/dockerfile/evaluator_test.go
Cory Snider f77a3274b4
[chore] clean up reexec.Init() calls
Now that most uses of reexec have been replaced with non-reexec
solutions, most of the reexec.Init() calls peppered throughout the test
suites are unnecessary. Furthermore, most of the reexec.Init() calls in
test code neglects to check the return value to determine whether to
exit, which would result in the reexec'ed subprocesses proceeding to run
the tests, which would reexec another subprocess which would proceed to
run the tests, recursively. (That would explain why every reexec
callback used to unconditionally call os.Exit() instead of returning...)

Remove unneeded reexec.Init() calls from test and example code which no
longer needs it, and fix the reexec.Init() calls which are not inert to
exit after a reexec callback is invoked.

Signed-off-by: Cory Snider <csnider@mirantis.com>
(cherry picked from commit 4e0319c878)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-05-11 16:31:41 +02:00

140 lines
4.5 KiB
Go

package dockerfile // import "github.com/docker/docker/builder/dockerfile"
import (
"context"
"os"
"runtime"
"testing"
"github.com/docker/docker/builder/remotecontext"
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/reexec"
"github.com/moby/buildkit/frontend/dockerfile/instructions"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
"gotest.tools/v3/skip"
)
type dispatchTestCase struct {
name, expectedError string
cmd instructions.Command
files map[string]string
}
func TestMain(m *testing.M) {
if reexec.Init() {
return
}
os.Exit(m.Run())
}
func TestDispatch(t *testing.T) {
if runtime.GOOS != "windows" {
skip.If(t, os.Getuid() != 0, "skipping test that requires root")
}
testCases := []dispatchTestCase{
{
name: "ADD multiple files to file",
cmd: &instructions.AddCommand{SourcesAndDest: instructions.SourcesAndDest{
SourcePaths: []string{"file1.txt", "file2.txt"},
DestPath: "test",
}},
expectedError: "When using ADD with more than one source file, the destination must be a directory and end with a /",
files: map[string]string{"file1.txt": "test1", "file2.txt": "test2"},
},
{
name: "Wildcard ADD multiple files to file",
cmd: &instructions.AddCommand{SourcesAndDest: instructions.SourcesAndDest{
SourcePaths: []string{"file*.txt"},
DestPath: "test",
}},
expectedError: "When using ADD with more than one source file, the destination must be a directory and end with a /",
files: map[string]string{"file1.txt": "test1", "file2.txt": "test2"},
},
{
name: "COPY multiple files to file",
cmd: &instructions.CopyCommand{SourcesAndDest: instructions.SourcesAndDest{
SourcePaths: []string{"file1.txt", "file2.txt"},
DestPath: "test",
}},
expectedError: "When using COPY with more than one source file, the destination must be a directory and end with a /",
files: map[string]string{"file1.txt": "test1", "file2.txt": "test2"},
},
{
name: "ADD multiple files to file with whitespace",
cmd: &instructions.AddCommand{SourcesAndDest: instructions.SourcesAndDest{
SourcePaths: []string{"test file1.txt", "test file2.txt"},
DestPath: "test",
}},
expectedError: "When using ADD with more than one source file, the destination must be a directory and end with a /",
files: map[string]string{"test file1.txt": "test1", "test file2.txt": "test2"},
},
{
name: "COPY multiple files to file with whitespace",
cmd: &instructions.CopyCommand{SourcesAndDest: instructions.SourcesAndDest{
SourcePaths: []string{"test file1.txt", "test file2.txt"},
DestPath: "test",
}},
expectedError: "When using COPY with more than one source file, the destination must be a directory and end with a /",
files: map[string]string{"test file1.txt": "test1", "test file2.txt": "test2"},
},
{
name: "COPY wildcard no files",
cmd: &instructions.CopyCommand{SourcesAndDest: instructions.SourcesAndDest{
SourcePaths: []string{"file*.txt"},
DestPath: "/tmp/",
}},
expectedError: "COPY failed: no source files were specified",
files: nil,
},
{
name: "COPY url",
cmd: &instructions.CopyCommand{SourcesAndDest: instructions.SourcesAndDest{
SourcePaths: []string{"https://example.com/index.html"},
DestPath: "/",
}},
expectedError: "source can't be a URL for COPY",
files: nil,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
contextDir, cleanup := createTestTempDir(t, "", "builder-dockerfile-test")
defer cleanup()
for filename, content := range tc.files {
createTestTempFile(t, contextDir, filename, content, 0777)
}
tarStream, err := archive.Tar(contextDir, archive.Uncompressed)
if err != nil {
t.Fatalf("Error when creating tar stream: %s", err)
}
defer func() {
if err = tarStream.Close(); err != nil {
t.Fatalf("Error when closing tar stream: %s", err)
}
}()
buildContext, err := remotecontext.FromArchive(tarStream)
if err != nil {
t.Fatalf("Error when creating tar context: %s", err)
}
defer func() {
if err = buildContext.Close(); err != nil {
t.Fatalf("Error when closing tar context: %s", err)
}
}()
b := newBuilderWithMockBackend(t)
sb := newDispatchRequest(b, '`', buildContext, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
err = dispatch(context.TODO(), sb, tc.cmd)
assert.Check(t, is.ErrorContains(err, tc.expectedError))
})
}
}