github.com/jwhonce/docker@v0.6.7-0.20190327063223-da823cf3a5a3/builder/dockerfile/evaluator_test.go (about)

     1  package dockerfile // import "github.com/docker/docker/builder/dockerfile"
     2  
     3  import (
     4  	"os"
     5  	"runtime"
     6  	"testing"
     7  
     8  	"github.com/docker/docker/builder/remotecontext"
     9  	"github.com/docker/docker/pkg/archive"
    10  	"github.com/docker/docker/pkg/reexec"
    11  	"github.com/moby/buildkit/frontend/dockerfile/instructions"
    12  	"gotest.tools/assert"
    13  	is "gotest.tools/assert/cmp"
    14  	"gotest.tools/skip"
    15  )
    16  
    17  type dispatchTestCase struct {
    18  	name, expectedError string
    19  	cmd                 instructions.Command
    20  	files               map[string]string
    21  }
    22  
    23  func init() {
    24  	reexec.Init()
    25  }
    26  
    27  func initDispatchTestCases() []dispatchTestCase {
    28  	dispatchTestCases := []dispatchTestCase{
    29  		{
    30  			name: "ADD multiple files to file",
    31  			cmd: &instructions.AddCommand{SourcesAndDest: instructions.SourcesAndDest{
    32  				"file1.txt",
    33  				"file2.txt",
    34  				"test",
    35  			}},
    36  			expectedError: "When using ADD with more than one source file, the destination must be a directory and end with a /",
    37  			files:         map[string]string{"file1.txt": "test1", "file2.txt": "test2"},
    38  		},
    39  		{
    40  			name: "Wildcard ADD multiple files to file",
    41  			cmd: &instructions.AddCommand{SourcesAndDest: instructions.SourcesAndDest{
    42  				"file*.txt",
    43  				"test",
    44  			}},
    45  			expectedError: "When using ADD with more than one source file, the destination must be a directory and end with a /",
    46  			files:         map[string]string{"file1.txt": "test1", "file2.txt": "test2"},
    47  		},
    48  		{
    49  			name: "COPY multiple files to file",
    50  			cmd: &instructions.CopyCommand{SourcesAndDest: instructions.SourcesAndDest{
    51  				"file1.txt",
    52  				"file2.txt",
    53  				"test",
    54  			}},
    55  			expectedError: "When using COPY with more than one source file, the destination must be a directory and end with a /",
    56  			files:         map[string]string{"file1.txt": "test1", "file2.txt": "test2"},
    57  		},
    58  		{
    59  			name: "ADD multiple files to file with whitespace",
    60  			cmd: &instructions.AddCommand{SourcesAndDest: instructions.SourcesAndDest{
    61  				"test file1.txt",
    62  				"test file2.txt",
    63  				"test",
    64  			}},
    65  			expectedError: "When using ADD with more than one source file, the destination must be a directory and end with a /",
    66  			files:         map[string]string{"test file1.txt": "test1", "test file2.txt": "test2"},
    67  		},
    68  		{
    69  			name: "COPY multiple files to file with whitespace",
    70  			cmd: &instructions.CopyCommand{SourcesAndDest: instructions.SourcesAndDest{
    71  				"test file1.txt",
    72  				"test file2.txt",
    73  				"test",
    74  			}},
    75  			expectedError: "When using COPY with more than one source file, the destination must be a directory and end with a /",
    76  			files:         map[string]string{"test file1.txt": "test1", "test file2.txt": "test2"},
    77  		},
    78  		{
    79  			name: "COPY wildcard no files",
    80  			cmd: &instructions.CopyCommand{SourcesAndDest: instructions.SourcesAndDest{
    81  				"file*.txt",
    82  				"/tmp/",
    83  			}},
    84  			expectedError: "COPY failed: no source files were specified",
    85  			files:         nil,
    86  		},
    87  		{
    88  			name: "COPY url",
    89  			cmd: &instructions.CopyCommand{SourcesAndDest: instructions.SourcesAndDest{
    90  				"https://index.docker.io/robots.txt",
    91  				"/",
    92  			}},
    93  			expectedError: "source can't be a URL for COPY",
    94  			files:         nil,
    95  		}}
    96  
    97  	return dispatchTestCases
    98  }
    99  
   100  func TestDispatch(t *testing.T) {
   101  	if runtime.GOOS != "windows" {
   102  		skip.If(t, os.Getuid() != 0, "skipping test that requires root")
   103  	}
   104  	testCases := initDispatchTestCases()
   105  
   106  	for _, testCase := range testCases {
   107  		executeTestCase(t, testCase)
   108  	}
   109  }
   110  
   111  func executeTestCase(t *testing.T, testCase dispatchTestCase) {
   112  	contextDir, cleanup := createTestTempDir(t, "", "builder-dockerfile-test")
   113  	defer cleanup()
   114  
   115  	for filename, content := range testCase.files {
   116  		createTestTempFile(t, contextDir, filename, content, 0777)
   117  	}
   118  
   119  	tarStream, err := archive.Tar(contextDir, archive.Uncompressed)
   120  
   121  	if err != nil {
   122  		t.Fatalf("Error when creating tar stream: %s", err)
   123  	}
   124  
   125  	defer func() {
   126  		if err = tarStream.Close(); err != nil {
   127  			t.Fatalf("Error when closing tar stream: %s", err)
   128  		}
   129  	}()
   130  
   131  	context, err := remotecontext.FromArchive(tarStream)
   132  
   133  	if err != nil {
   134  		t.Fatalf("Error when creating tar context: %s", err)
   135  	}
   136  
   137  	defer func() {
   138  		if err = context.Close(); err != nil {
   139  			t.Fatalf("Error when closing tar context: %s", err)
   140  		}
   141  	}()
   142  
   143  	b := newBuilderWithMockBackend()
   144  	sb := newDispatchRequest(b, '`', context, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
   145  	err = dispatch(sb, testCase.cmd)
   146  	assert.Check(t, is.ErrorContains(err, testCase.expectedError))
   147  }