github.com/Prakhar-Agarwal-byte/moby@v0.0.0-20231027092010-a14e3e8ab87e/builder/dockerfile/evaluator_test.go (about)

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