parser_test.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. package parser
  2. import (
  3. "bytes"
  4. "fmt"
  5. "io/ioutil"
  6. "os"
  7. "path/filepath"
  8. "runtime"
  9. "testing"
  10. "github.com/stretchr/testify/assert"
  11. "github.com/stretchr/testify/require"
  12. )
  13. const testDir = "testfiles"
  14. const negativeTestDir = "testfiles-negative"
  15. const testFileLineInfo = "testfile-line/Dockerfile"
  16. func getDirs(t *testing.T, dir string) []string {
  17. f, err := os.Open(dir)
  18. require.NoError(t, err)
  19. defer f.Close()
  20. dirs, err := f.Readdirnames(0)
  21. require.NoError(t, err)
  22. return dirs
  23. }
  24. func TestParseErrorCases(t *testing.T) {
  25. for _, dir := range getDirs(t, negativeTestDir) {
  26. dockerfile := filepath.Join(negativeTestDir, dir, "Dockerfile")
  27. df, err := os.Open(dockerfile)
  28. require.NoError(t, err, dockerfile)
  29. defer df.Close()
  30. _, err = Parse(df)
  31. assert.Error(t, err, dockerfile)
  32. }
  33. }
  34. func TestParseCases(t *testing.T) {
  35. for _, dir := range getDirs(t, testDir) {
  36. dockerfile := filepath.Join(testDir, dir, "Dockerfile")
  37. resultfile := filepath.Join(testDir, dir, "result")
  38. df, err := os.Open(dockerfile)
  39. require.NoError(t, err, dockerfile)
  40. defer df.Close()
  41. result, err := Parse(df)
  42. require.NoError(t, err, dockerfile)
  43. content, err := ioutil.ReadFile(resultfile)
  44. require.NoError(t, err, resultfile)
  45. if runtime.GOOS == "windows" {
  46. // CRLF --> CR to match Unix behavior
  47. content = bytes.Replace(content, []byte{'\x0d', '\x0a'}, []byte{'\x0a'}, -1)
  48. }
  49. assert.Equal(t, result.AST.Dump()+"\n", string(content), "In "+dockerfile)
  50. }
  51. }
  52. func TestParseWords(t *testing.T) {
  53. tests := []map[string][]string{
  54. {
  55. "input": {"foo"},
  56. "expect": {"foo"},
  57. },
  58. {
  59. "input": {"foo bar"},
  60. "expect": {"foo", "bar"},
  61. },
  62. {
  63. "input": {"foo\\ bar"},
  64. "expect": {"foo\\ bar"},
  65. },
  66. {
  67. "input": {"foo=bar"},
  68. "expect": {"foo=bar"},
  69. },
  70. {
  71. "input": {"foo bar 'abc xyz'"},
  72. "expect": {"foo", "bar", "'abc xyz'"},
  73. },
  74. {
  75. "input": {`foo bar "abc xyz"`},
  76. "expect": {"foo", "bar", `"abc xyz"`},
  77. },
  78. {
  79. "input": {"àöû"},
  80. "expect": {"àöû"},
  81. },
  82. {
  83. "input": {`föo bàr "âbc xÿz"`},
  84. "expect": {"föo", "bàr", `"âbc xÿz"`},
  85. },
  86. }
  87. for _, test := range tests {
  88. words := parseWords(test["input"][0], NewDefaultDirective())
  89. assert.Equal(t, test["expect"], words)
  90. }
  91. }
  92. func TestParseIncludesLineNumbers(t *testing.T) {
  93. df, err := os.Open(testFileLineInfo)
  94. require.NoError(t, err)
  95. defer df.Close()
  96. result, err := Parse(df)
  97. require.NoError(t, err)
  98. ast := result.AST
  99. assert.Equal(t, 5, ast.StartLine)
  100. assert.Equal(t, 31, ast.endLine)
  101. assert.Len(t, ast.Children, 3)
  102. expected := [][]int{
  103. {5, 5},
  104. {11, 12},
  105. {17, 31},
  106. }
  107. for i, child := range ast.Children {
  108. msg := fmt.Sprintf("Child %d", i)
  109. assert.Equal(t, expected[i], []int{child.StartLine, child.endLine}, msg)
  110. }
  111. }
  112. func TestParseWarnsOnEmptyContinutationLine(t *testing.T) {
  113. dockerfile := bytes.NewBufferString(`
  114. FROM alpine:3.6
  115. RUN something \
  116. following \
  117. more
  118. RUN another \
  119. thing
  120. RUN non-indented \
  121. # this is a comment
  122. after-comment
  123. RUN indented \
  124. # this is an indented comment
  125. comment
  126. `)
  127. result, err := Parse(dockerfile)
  128. require.NoError(t, err)
  129. warnings := result.Warnings
  130. assert.Len(t, warnings, 3)
  131. assert.Contains(t, warnings[0], "Empty continuation line found in")
  132. assert.Contains(t, warnings[0], "RUN something following more")
  133. assert.Contains(t, warnings[1], "RUN another thing")
  134. assert.Contains(t, warnings[2], "will become errors in a future release")
  135. }