evaluator_test.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. package dockerfile
  2. import (
  3. "io/ioutil"
  4. "os"
  5. "strings"
  6. "testing"
  7. "github.com/docker/docker/builder"
  8. "github.com/docker/docker/builder/dockerfile/parser"
  9. "github.com/docker/docker/pkg/archive"
  10. "github.com/docker/docker/pkg/reexec"
  11. "github.com/docker/engine-api/types"
  12. "github.com/docker/engine-api/types/container"
  13. )
  14. type dispatchTestCase struct {
  15. name, dockerfile, expectedError string
  16. }
  17. func init() {
  18. reexec.Init()
  19. }
  20. func initDispatchTestCases() []dispatchTestCase {
  21. dispatchTestCases := []dispatchTestCase{{
  22. name: "copyEmptyWhitespace",
  23. dockerfile: `COPY
  24. quux \
  25. bar`,
  26. expectedError: "COPY requires at least one argument",
  27. },
  28. {
  29. name: "ONBUILD forbidden FROM",
  30. dockerfile: "ONBUILD FROM scratch",
  31. expectedError: "FROM isn't allowed as an ONBUILD trigger",
  32. },
  33. {
  34. name: "ONBUILD forbidden MAINTAINER",
  35. dockerfile: "ONBUILD MAINTAINER docker.io",
  36. expectedError: "MAINTAINER isn't allowed as an ONBUILD trigger",
  37. },
  38. {
  39. name: "ARG two arguments",
  40. dockerfile: "ARG foo bar",
  41. expectedError: "ARG requires exactly one argument definition",
  42. },
  43. {
  44. name: "MAINTAINER unknown flag",
  45. dockerfile: "MAINTAINER --boo joe@example.com",
  46. expectedError: "Unknown flag: boo",
  47. }}
  48. return dispatchTestCases
  49. }
  50. func TestDispatch(t *testing.T) {
  51. testCases := initDispatchTestCases()
  52. for _, testCase := range testCases {
  53. executeTestCase(t, testCase)
  54. }
  55. }
  56. func executeTestCase(t *testing.T, testCase dispatchTestCase) {
  57. contextDir, cleanup := createTestTempDir(t, "", "builder-dockerfile-test")
  58. defer cleanup()
  59. tarStream, err := archive.Tar(contextDir, archive.Uncompressed)
  60. if err != nil {
  61. t.Fatalf("Error when creating tar stream: %s", err)
  62. }
  63. defer func() {
  64. if err = tarStream.Close(); err != nil {
  65. t.Fatalf("Error when closing tar stream: %s", err)
  66. }
  67. }()
  68. context, err := builder.MakeTarSumContext(tarStream)
  69. if err != nil {
  70. t.Fatalf("Error when creating tar context: %s", err)
  71. }
  72. defer func() {
  73. if err = context.Close(); err != nil {
  74. t.Fatalf("Error when closing tar context: %s", err)
  75. }
  76. }()
  77. r := strings.NewReader(testCase.dockerfile)
  78. n, err := parser.Parse(r)
  79. if err != nil {
  80. t.Fatalf("Error when parsing Dockerfile: %s", err)
  81. }
  82. config := &container.Config{}
  83. options := &types.ImageBuildOptions{}
  84. b := &Builder{runConfig: config, options: options, Stdout: ioutil.Discard, context: context}
  85. err = b.dispatch(0, n.Children[0])
  86. if err == nil {
  87. t.Fatalf("No error when executing test %s", testCase.name)
  88. }
  89. if !strings.Contains(err.Error(), testCase.expectedError) {
  90. t.Fatalf("Wrong error message. Should be \"%s\". Got \"%s\"", testCase.expectedError, err.Error())
  91. }
  92. }
  93. // createTestTempDir creates a temporary directory for testing.
  94. // It returns the created path and a cleanup function which is meant to be used as deferred call.
  95. // When an error occurs, it terminates the test.
  96. func createTestTempDir(t *testing.T, dir, prefix string) (string, func()) {
  97. path, err := ioutil.TempDir(dir, prefix)
  98. if err != nil {
  99. t.Fatalf("Error when creating directory %s with prefix %s: %s", dir, prefix, err)
  100. }
  101. return path, func() {
  102. err = os.RemoveAll(path)
  103. if err != nil {
  104. t.Fatalf("Error when removing directory %s: %s", path, err)
  105. }
  106. }
  107. }