github.com/brahmaroutu/docker@v1.2.1-0.20160809185609-eb28dde01f16/builder/dockerfile/parser/parser_test.go (about)

     1  package parser
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"os"
     8  	"path/filepath"
     9  	"runtime"
    10  	"testing"
    11  )
    12  
    13  const testDir = "testfiles"
    14  const negativeTestDir = "testfiles-negative"
    15  const testFileLineInfo = "testfile-line/Dockerfile"
    16  
    17  func getDirs(t *testing.T, dir string) []string {
    18  	f, err := os.Open(dir)
    19  	if err != nil {
    20  		t.Fatal(err)
    21  	}
    22  
    23  	defer f.Close()
    24  
    25  	dirs, err := f.Readdirnames(0)
    26  	if err != nil {
    27  		t.Fatal(err)
    28  	}
    29  
    30  	return dirs
    31  }
    32  
    33  func TestTestNegative(t *testing.T) {
    34  	for _, dir := range getDirs(t, negativeTestDir) {
    35  		dockerfile := filepath.Join(negativeTestDir, dir, "Dockerfile")
    36  
    37  		df, err := os.Open(dockerfile)
    38  		if err != nil {
    39  			t.Fatalf("Dockerfile missing for %s: %v", dir, err)
    40  		}
    41  
    42  		d := Directive{LookingForDirectives: true}
    43  		SetEscapeToken(DefaultEscapeToken, &d)
    44  		_, err = Parse(df, &d)
    45  		if err == nil {
    46  			t.Fatalf("No error parsing broken dockerfile for %s", dir)
    47  		}
    48  
    49  		df.Close()
    50  	}
    51  }
    52  
    53  func TestTestData(t *testing.T) {
    54  	for _, dir := range getDirs(t, testDir) {
    55  		dockerfile := filepath.Join(testDir, dir, "Dockerfile")
    56  		resultfile := filepath.Join(testDir, dir, "result")
    57  
    58  		df, err := os.Open(dockerfile)
    59  		if err != nil {
    60  			t.Fatalf("Dockerfile missing for %s: %v", dir, err)
    61  		}
    62  		defer df.Close()
    63  
    64  		d := Directive{LookingForDirectives: true}
    65  		SetEscapeToken(DefaultEscapeToken, &d)
    66  		ast, err := Parse(df, &d)
    67  		if err != nil {
    68  			t.Fatalf("Error parsing %s's dockerfile: %v", dir, err)
    69  		}
    70  
    71  		content, err := ioutil.ReadFile(resultfile)
    72  		if err != nil {
    73  			t.Fatalf("Error reading %s's result file: %v", dir, err)
    74  		}
    75  
    76  		if runtime.GOOS == "windows" {
    77  			// CRLF --> CR to match Unix behavior
    78  			content = bytes.Replace(content, []byte{'\x0d', '\x0a'}, []byte{'\x0a'}, -1)
    79  		}
    80  
    81  		if ast.Dump()+"\n" != string(content) {
    82  			fmt.Fprintln(os.Stderr, "Result:\n"+ast.Dump())
    83  			fmt.Fprintln(os.Stderr, "Expected:\n"+string(content))
    84  			t.Fatalf("%s: AST dump of dockerfile does not match result", dir)
    85  		}
    86  	}
    87  }
    88  
    89  func TestParseWords(t *testing.T) {
    90  	tests := []map[string][]string{
    91  		{
    92  			"input":  {"foo"},
    93  			"expect": {"foo"},
    94  		},
    95  		{
    96  			"input":  {"foo bar"},
    97  			"expect": {"foo", "bar"},
    98  		},
    99  		{
   100  			"input":  {"foo\\ bar"},
   101  			"expect": {"foo\\ bar"},
   102  		},
   103  		{
   104  			"input":  {"foo=bar"},
   105  			"expect": {"foo=bar"},
   106  		},
   107  		{
   108  			"input":  {"foo bar 'abc xyz'"},
   109  			"expect": {"foo", "bar", "'abc xyz'"},
   110  		},
   111  		{
   112  			"input":  {`foo bar "abc xyz"`},
   113  			"expect": {"foo", "bar", `"abc xyz"`},
   114  		},
   115  		{
   116  			"input":  {"àöû"},
   117  			"expect": {"àöû"},
   118  		},
   119  		{
   120  			"input":  {`föo bàr "âbc xÿz"`},
   121  			"expect": {"föo", "bàr", `"âbc xÿz"`},
   122  		},
   123  	}
   124  
   125  	for _, test := range tests {
   126  		d := Directive{LookingForDirectives: true}
   127  		SetEscapeToken(DefaultEscapeToken, &d)
   128  		words := parseWords(test["input"][0], &d)
   129  		if len(words) != len(test["expect"]) {
   130  			t.Fatalf("length check failed. input: %v, expect: %q, output: %q", test["input"][0], test["expect"], words)
   131  		}
   132  		for i, word := range words {
   133  			if word != test["expect"][i] {
   134  				t.Fatalf("word check failed for word: %q. input: %q, expect: %q, output: %q", word, test["input"][0], test["expect"], words)
   135  			}
   136  		}
   137  	}
   138  }
   139  
   140  func TestLineInformation(t *testing.T) {
   141  	df, err := os.Open(testFileLineInfo)
   142  	if err != nil {
   143  		t.Fatalf("Dockerfile missing for %s: %v", testFileLineInfo, err)
   144  	}
   145  	defer df.Close()
   146  
   147  	d := Directive{LookingForDirectives: true}
   148  	SetEscapeToken(DefaultEscapeToken, &d)
   149  	ast, err := Parse(df, &d)
   150  	if err != nil {
   151  		t.Fatalf("Error parsing dockerfile %s: %v", testFileLineInfo, err)
   152  	}
   153  
   154  	if ast.StartLine != 5 || ast.EndLine != 31 {
   155  		fmt.Fprintf(os.Stderr, "Wrong root line information: expected(%d-%d), actual(%d-%d)\n", 5, 31, ast.StartLine, ast.EndLine)
   156  		t.Fatalf("Root line information doesn't match result.")
   157  	}
   158  	if len(ast.Children) != 3 {
   159  		fmt.Fprintf(os.Stderr, "Wrong number of child: expected(%d), actual(%d)\n", 3, len(ast.Children))
   160  		t.Fatalf("Root line information doesn't match result for %s", testFileLineInfo)
   161  	}
   162  	expected := [][]int{
   163  		{5, 5},
   164  		{11, 12},
   165  		{17, 31},
   166  	}
   167  	for i, child := range ast.Children {
   168  		if child.StartLine != expected[i][0] || child.EndLine != expected[i][1] {
   169  			t.Logf("Wrong line information for child %d: expected(%d-%d), actual(%d-%d)\n",
   170  				i, expected[i][0], expected[i][1], child.StartLine, child.EndLine)
   171  			t.Fatalf("Root line information doesn't match result.")
   172  		}
   173  	}
   174  }