github.com/zhouyu0/docker-note@v0.0.0-20190722021225-b8d3825084db/builder/dockerfile/evaluator_test.go (about)

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