1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00
moby--moby/builder/dockerfile/parser/parser_test.go
Yong Tang 3e1b539e8d Fix dockerfile parser with empty line after escape
This fix tries to fix the bug reported by #24693 where an empty
line after escape will not be stopped by the parser.

This fix addresses this issue by stop the parser from continue
with an empty line after escape.

An additional integration test has been added.

This fix fixes #24693.

Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
2016-10-27 10:43:08 -07:00

173 lines
4.3 KiB
Go

package parser
import (
"bytes"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"runtime"
"testing"
)
const testDir = "testfiles"
const negativeTestDir = "testfiles-negative"
const testFileLineInfo = "testfile-line/Dockerfile"
func getDirs(t *testing.T, dir string) []string {
f, err := os.Open(dir)
if err != nil {
t.Fatal(err)
}
defer f.Close()
dirs, err := f.Readdirnames(0)
if err != nil {
t.Fatal(err)
}
return dirs
}
func TestTestNegative(t *testing.T) {
for _, dir := range getDirs(t, negativeTestDir) {
dockerfile := filepath.Join(negativeTestDir, dir, "Dockerfile")
df, err := os.Open(dockerfile)
if err != nil {
t.Fatalf("Dockerfile missing for %s: %v", dir, err)
}
defer df.Close()
d := Directive{LookingForDirectives: true}
SetEscapeToken(DefaultEscapeToken, &d)
_, err = Parse(df, &d)
if err == nil {
t.Fatalf("No error parsing broken dockerfile for %s", dir)
}
}
}
func TestTestData(t *testing.T) {
for _, dir := range getDirs(t, testDir) {
dockerfile := filepath.Join(testDir, dir, "Dockerfile")
resultfile := filepath.Join(testDir, dir, "result")
df, err := os.Open(dockerfile)
if err != nil {
t.Fatalf("Dockerfile missing for %s: %v", dir, err)
}
defer df.Close()
d := Directive{LookingForDirectives: true}
SetEscapeToken(DefaultEscapeToken, &d)
ast, err := Parse(df, &d)
if err != nil {
t.Fatalf("Error parsing %s's dockerfile: %v", dir, err)
}
content, err := ioutil.ReadFile(resultfile)
if err != nil {
t.Fatalf("Error reading %s's result file: %v", dir, err)
}
if runtime.GOOS == "windows" {
// CRLF --> CR to match Unix behavior
content = bytes.Replace(content, []byte{'\x0d', '\x0a'}, []byte{'\x0a'}, -1)
}
if ast.Dump()+"\n" != string(content) {
fmt.Fprintln(os.Stderr, "Result:\n"+ast.Dump())
fmt.Fprintln(os.Stderr, "Expected:\n"+string(content))
t.Fatalf("%s: AST dump of dockerfile does not match result", dir)
}
}
}
func TestParseWords(t *testing.T) {
tests := []map[string][]string{
{
"input": {"foo"},
"expect": {"foo"},
},
{
"input": {"foo bar"},
"expect": {"foo", "bar"},
},
{
"input": {"foo\\ bar"},
"expect": {"foo\\ bar"},
},
{
"input": {"foo=bar"},
"expect": {"foo=bar"},
},
{
"input": {"foo bar 'abc xyz'"},
"expect": {"foo", "bar", "'abc xyz'"},
},
{
"input": {`foo bar "abc xyz"`},
"expect": {"foo", "bar", `"abc xyz"`},
},
{
"input": {"àöû"},
"expect": {"àöû"},
},
{
"input": {`föo bàr "âbc xÿz"`},
"expect": {"föo", "bàr", `"âbc xÿz"`},
},
}
for _, test := range tests {
d := Directive{LookingForDirectives: true}
SetEscapeToken(DefaultEscapeToken, &d)
words := parseWords(test["input"][0], &d)
if len(words) != len(test["expect"]) {
t.Fatalf("length check failed. input: %v, expect: %q, output: %q", test["input"][0], test["expect"], words)
}
for i, word := range words {
if word != test["expect"][i] {
t.Fatalf("word check failed for word: %q. input: %q, expect: %q, output: %q", word, test["input"][0], test["expect"], words)
}
}
}
}
func TestLineInformation(t *testing.T) {
df, err := os.Open(testFileLineInfo)
if err != nil {
t.Fatalf("Dockerfile missing for %s: %v", testFileLineInfo, err)
}
defer df.Close()
d := Directive{LookingForDirectives: true}
SetEscapeToken(DefaultEscapeToken, &d)
ast, err := Parse(df, &d)
if err != nil {
t.Fatalf("Error parsing dockerfile %s: %v", testFileLineInfo, err)
}
if ast.StartLine != 5 || ast.EndLine != 27 {
fmt.Fprintf(os.Stderr, "Wrong root line information: expected(%d-%d), actual(%d-%d)\n", 5, 27, ast.StartLine, ast.EndLine)
t.Fatalf("Root line information doesn't match result.")
}
if len(ast.Children) != 3 {
fmt.Fprintf(os.Stderr, "Wrong number of child: expected(%d), actual(%d)\n", 3, len(ast.Children))
t.Fatalf("Root line information doesn't match result for %s", testFileLineInfo)
}
expected := [][]int{
{5, 5},
{11, 12},
{17, 27},
}
for i, child := range ast.Children {
if child.StartLine != expected[i][0] || child.EndLine != expected[i][1] {
t.Logf("Wrong line information for child %d: expected(%d-%d), actual(%d-%d)\n",
i, expected[i][0], expected[i][1], child.StartLine, child.EndLine)
t.Fatalf("Root line information doesn't match result.")
}
}
}