evaluator_test.go 4.5 KB

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