evaluator_test.go 4.5 KB

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