blob: e7b0c07c531f873ce191792d7dbb4f7ea64124b4 [file] [log] [blame]
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)
}
d := Directive{LookingForDirectives: true}
SetEscapeToken(DefaultEscapeToken, &d)
_, err = Parse(df, &d)
if err == nil {
t.Fatalf("No error parsing broken dockerfile for %s", dir)
}
df.Close()
}
}
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 != 31 {
fmt.Fprintf(os.Stderr, "Wrong root line information: expected(%d-%d), actual(%d-%d)\n", 5, 31, 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, 31},
}
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.")
}
}
}