github.com/scorpionis/docker@v1.6.0-rc7/integration-cli/docker_cli_build_test.go (about)

     1  package main
     2  
     3  import (
     4  	"archive/tar"
     5  	"bufio"
     6  	"bytes"
     7  	"encoding/json"
     8  	"fmt"
     9  	"io/ioutil"
    10  	"os"
    11  	"os/exec"
    12  	"path/filepath"
    13  	"reflect"
    14  	"regexp"
    15  	"runtime"
    16  	"strconv"
    17  	"strings"
    18  	"sync"
    19  	"testing"
    20  	"text/template"
    21  	"time"
    22  
    23  	"github.com/docker/docker/builder/command"
    24  	"github.com/docker/docker/pkg/archive"
    25  )
    26  
    27  func TestBuildJSONEmptyRun(t *testing.T) {
    28  	name := "testbuildjsonemptyrun"
    29  	defer deleteImages(name)
    30  
    31  	_, err := buildImage(
    32  		name,
    33  		`
    34      FROM busybox
    35      RUN []
    36      `,
    37  		true)
    38  
    39  	if err != nil {
    40  		t.Fatal("error when dealing with a RUN statement with empty JSON array")
    41  	}
    42  
    43  	logDone("build - RUN with an empty array should not panic")
    44  }
    45  
    46  func TestBuildEmptyWhitespace(t *testing.T) {
    47  	name := "testbuildemptywhitespace"
    48  	defer deleteImages(name)
    49  
    50  	_, err := buildImage(
    51  		name,
    52  		`
    53      FROM busybox
    54      COPY
    55        quux \
    56        bar
    57      `,
    58  		true)
    59  
    60  	if err == nil {
    61  		t.Fatal("no error when dealing with a COPY statement with no content on the same line")
    62  	}
    63  
    64  	logDone("build - statements with whitespace and no content should generate a parse error")
    65  }
    66  
    67  func TestBuildShCmdJSONEntrypoint(t *testing.T) {
    68  	name := "testbuildshcmdjsonentrypoint"
    69  	defer deleteImages(name)
    70  
    71  	_, err := buildImage(
    72  		name,
    73  		`
    74      FROM busybox
    75      ENTRYPOINT ["/bin/echo"]
    76      CMD echo test
    77      `,
    78  		true)
    79  
    80  	if err != nil {
    81  		t.Fatal(err)
    82  	}
    83  
    84  	out, _, err := runCommandWithOutput(
    85  		exec.Command(
    86  			dockerBinary,
    87  			"run",
    88  			"--rm",
    89  			name))
    90  
    91  	if err != nil {
    92  		t.Fatal(err)
    93  	}
    94  
    95  	if strings.TrimSpace(out) != "/bin/sh -c echo test" {
    96  		t.Fatal("CMD did not contain /bin/sh -c")
    97  	}
    98  
    99  	logDone("build - CMD should always contain /bin/sh -c when specified without JSON")
   100  }
   101  
   102  func TestBuildEnvironmentReplacementUser(t *testing.T) {
   103  	name := "testbuildenvironmentreplacement"
   104  	defer deleteImages(name)
   105  
   106  	_, err := buildImage(name, `
   107    FROM scratch
   108    ENV user foo
   109    USER ${user}
   110    `, true)
   111  	if err != nil {
   112  		t.Fatal(err)
   113  	}
   114  
   115  	res, err := inspectFieldJSON(name, "Config.User")
   116  	if err != nil {
   117  		t.Fatal(err)
   118  	}
   119  
   120  	if res != `"foo"` {
   121  		t.Fatal("User foo from environment not in Config.User on image")
   122  	}
   123  
   124  	logDone("build - user environment replacement")
   125  }
   126  
   127  func TestBuildEnvironmentReplacementVolume(t *testing.T) {
   128  	name := "testbuildenvironmentreplacement"
   129  	defer deleteImages(name)
   130  
   131  	_, err := buildImage(name, `
   132    FROM scratch
   133    ENV volume /quux
   134    VOLUME ${volume}
   135    `, true)
   136  	if err != nil {
   137  		t.Fatal(err)
   138  	}
   139  
   140  	res, err := inspectFieldJSON(name, "Config.Volumes")
   141  	if err != nil {
   142  		t.Fatal(err)
   143  	}
   144  
   145  	var volumes map[string]interface{}
   146  
   147  	if err := json.Unmarshal([]byte(res), &volumes); err != nil {
   148  		t.Fatal(err)
   149  	}
   150  
   151  	if _, ok := volumes["/quux"]; !ok {
   152  		t.Fatal("Volume /quux from environment not in Config.Volumes on image")
   153  	}
   154  
   155  	logDone("build - volume environment replacement")
   156  }
   157  
   158  func TestBuildEnvironmentReplacementExpose(t *testing.T) {
   159  	name := "testbuildenvironmentreplacement"
   160  	defer deleteImages(name)
   161  
   162  	_, err := buildImage(name, `
   163    FROM scratch
   164    ENV port 80
   165    EXPOSE ${port}
   166    `, true)
   167  	if err != nil {
   168  		t.Fatal(err)
   169  	}
   170  
   171  	res, err := inspectFieldJSON(name, "Config.ExposedPorts")
   172  	if err != nil {
   173  		t.Fatal(err)
   174  	}
   175  
   176  	var exposedPorts map[string]interface{}
   177  
   178  	if err := json.Unmarshal([]byte(res), &exposedPorts); err != nil {
   179  		t.Fatal(err)
   180  	}
   181  
   182  	if _, ok := exposedPorts["80/tcp"]; !ok {
   183  		t.Fatal("Exposed port 80 from environment not in Config.ExposedPorts on image")
   184  	}
   185  
   186  	logDone("build - expose environment replacement")
   187  }
   188  
   189  func TestBuildEnvironmentReplacementWorkdir(t *testing.T) {
   190  	name := "testbuildenvironmentreplacement"
   191  	defer deleteImages(name)
   192  
   193  	_, err := buildImage(name, `
   194    FROM busybox
   195    ENV MYWORKDIR /work
   196    RUN mkdir ${MYWORKDIR}
   197    WORKDIR ${MYWORKDIR}
   198    `, true)
   199  
   200  	if err != nil {
   201  		t.Fatal(err)
   202  	}
   203  
   204  	logDone("build - workdir environment replacement")
   205  }
   206  
   207  func TestBuildEnvironmentReplacementAddCopy(t *testing.T) {
   208  	name := "testbuildenvironmentreplacement"
   209  	defer deleteImages(name)
   210  
   211  	ctx, err := fakeContext(`
   212    FROM scratch
   213    ENV baz foo
   214    ENV quux bar
   215    ENV dot .
   216  
   217    ADD ${baz} ${dot}
   218    COPY ${quux} ${dot}
   219    `,
   220  		map[string]string{
   221  			"foo": "test1",
   222  			"bar": "test2",
   223  		})
   224  
   225  	if err != nil {
   226  		t.Fatal(err)
   227  	}
   228  	defer ctx.Close()
   229  
   230  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
   231  		t.Fatal(err)
   232  	}
   233  
   234  	logDone("build - add/copy environment replacement")
   235  }
   236  
   237  func TestBuildEnvironmentReplacementEnv(t *testing.T) {
   238  	name := "testbuildenvironmentreplacement"
   239  
   240  	defer deleteImages(name)
   241  
   242  	_, err := buildImage(name,
   243  		`
   244    FROM busybox
   245    ENV foo zzz
   246    ENV bar ${foo}
   247    ENV abc1='$foo'
   248    ENV env1=$foo env2=${foo} env3="$foo" env4="${foo}"
   249    RUN [ "$abc1" = '$foo' ] && (echo "$abc1" | grep -q foo)
   250    ENV abc2="\$foo"
   251    RUN [ "$abc2" = '$foo' ] && (echo "$abc2" | grep -q foo)
   252    ENV abc3 '$foo'
   253    RUN [ "$abc3" = '$foo' ] && (echo "$abc3" | grep -q foo)
   254    ENV abc4 "\$foo"
   255    RUN [ "$abc4" = '$foo' ] && (echo "$abc4" | grep -q foo)
   256    `, true)
   257  
   258  	if err != nil {
   259  		t.Fatal(err)
   260  	}
   261  
   262  	res, err := inspectFieldJSON(name, "Config.Env")
   263  	if err != nil {
   264  		t.Fatal(err)
   265  	}
   266  
   267  	envResult := []string{}
   268  
   269  	if err = unmarshalJSON([]byte(res), &envResult); err != nil {
   270  		t.Fatal(err)
   271  	}
   272  
   273  	found := false
   274  	envCount := 0
   275  
   276  	for _, env := range envResult {
   277  		parts := strings.SplitN(env, "=", 2)
   278  		if parts[0] == "bar" {
   279  			found = true
   280  			if parts[1] != "zzz" {
   281  				t.Fatalf("Could not find replaced var for env `bar`: got %q instead of `zzz`", parts[1])
   282  			}
   283  		} else if strings.HasPrefix(parts[0], "env") {
   284  			envCount++
   285  			if parts[1] != "zzz" {
   286  				t.Fatalf("%s should be 'foo' but instead its %q", parts[0], parts[1])
   287  			}
   288  		}
   289  	}
   290  
   291  	if !found {
   292  		t.Fatal("Never found the `bar` env variable")
   293  	}
   294  
   295  	if envCount != 4 {
   296  		t.Fatalf("Didn't find all env vars - only saw %d\n%s", envCount, envResult)
   297  	}
   298  
   299  	logDone("build - env environment replacement")
   300  }
   301  
   302  func TestBuildHandleEscapes(t *testing.T) {
   303  	name := "testbuildhandleescapes"
   304  
   305  	defer deleteImages(name)
   306  
   307  	_, err := buildImage(name,
   308  		`
   309    FROM scratch
   310    ENV FOO bar
   311    VOLUME ${FOO}
   312    `, true)
   313  
   314  	if err != nil {
   315  		t.Fatal(err)
   316  	}
   317  
   318  	var result map[string]map[string]struct{}
   319  
   320  	res, err := inspectFieldJSON(name, "Config.Volumes")
   321  	if err != nil {
   322  		t.Fatal(err)
   323  	}
   324  
   325  	if err = unmarshalJSON([]byte(res), &result); err != nil {
   326  		t.Fatal(err)
   327  	}
   328  
   329  	if _, ok := result["bar"]; !ok {
   330  		t.Fatal("Could not find volume bar set from env foo in volumes table")
   331  	}
   332  
   333  	deleteImages(name)
   334  
   335  	_, err = buildImage(name,
   336  		`
   337    FROM scratch
   338    ENV FOO bar
   339    VOLUME \${FOO}
   340    `, true)
   341  
   342  	if err != nil {
   343  		t.Fatal(err)
   344  	}
   345  
   346  	res, err = inspectFieldJSON(name, "Config.Volumes")
   347  	if err != nil {
   348  		t.Fatal(err)
   349  	}
   350  
   351  	if err = unmarshalJSON([]byte(res), &result); err != nil {
   352  		t.Fatal(err)
   353  	}
   354  
   355  	if _, ok := result["${FOO}"]; !ok {
   356  		t.Fatal("Could not find volume ${FOO} set from env foo in volumes table")
   357  	}
   358  
   359  	deleteImages(name)
   360  
   361  	// this test in particular provides *7* backslashes and expects 6 to come back.
   362  	// Like above, the first escape is swallowed and the rest are treated as
   363  	// literals, this one is just less obvious because of all the character noise.
   364  
   365  	_, err = buildImage(name,
   366  		`
   367    FROM scratch
   368    ENV FOO bar
   369    VOLUME \\\\\\\${FOO}
   370    `, true)
   371  
   372  	if err != nil {
   373  		t.Fatal(err)
   374  	}
   375  
   376  	res, err = inspectFieldJSON(name, "Config.Volumes")
   377  	if err != nil {
   378  		t.Fatal(err)
   379  	}
   380  
   381  	if err = unmarshalJSON([]byte(res), &result); err != nil {
   382  		t.Fatal(err)
   383  	}
   384  
   385  	if _, ok := result[`\\\${FOO}`]; !ok {
   386  		t.Fatal(`Could not find volume \\\${FOO} set from env foo in volumes table`, result)
   387  	}
   388  
   389  	logDone("build - handle escapes")
   390  }
   391  
   392  func TestBuildOnBuildLowercase(t *testing.T) {
   393  	name := "testbuildonbuildlowercase"
   394  	name2 := "testbuildonbuildlowercase2"
   395  
   396  	defer deleteImages(name, name2)
   397  
   398  	_, err := buildImage(name,
   399  		`
   400    FROM busybox
   401    onbuild run echo quux
   402    `, true)
   403  
   404  	if err != nil {
   405  		t.Fatal(err)
   406  	}
   407  
   408  	_, out, err := buildImageWithOut(name2, fmt.Sprintf(`
   409    FROM %s
   410    `, name), true)
   411  
   412  	if err != nil {
   413  		t.Fatal(err)
   414  	}
   415  
   416  	if !strings.Contains(out, "quux") {
   417  		t.Fatalf("Did not receive the expected echo text, got %s", out)
   418  	}
   419  
   420  	if strings.Contains(out, "ONBUILD ONBUILD") {
   421  		t.Fatalf("Got an ONBUILD ONBUILD error with no error: got %s", out)
   422  	}
   423  
   424  	logDone("build - handle case-insensitive onbuild statement")
   425  }
   426  
   427  func TestBuildEnvEscapes(t *testing.T) {
   428  	name := "testbuildenvescapes"
   429  	defer deleteImages(name)
   430  	defer deleteAllContainers()
   431  	_, err := buildImage(name,
   432  		`
   433      FROM busybox
   434      ENV TEST foo
   435      CMD echo \$
   436      `,
   437  		true)
   438  
   439  	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-t", name))
   440  
   441  	if err != nil {
   442  		t.Fatal(err)
   443  	}
   444  
   445  	if strings.TrimSpace(out) != "$" {
   446  		t.Fatalf("Env TEST was not overwritten with bar when foo was supplied to dockerfile: was %q", strings.TrimSpace(out))
   447  	}
   448  
   449  	logDone("build - env should handle \\$ properly")
   450  }
   451  
   452  func TestBuildEnvOverwrite(t *testing.T) {
   453  	name := "testbuildenvoverwrite"
   454  	defer deleteImages(name)
   455  	defer deleteAllContainers()
   456  
   457  	_, err := buildImage(name,
   458  		`
   459      FROM busybox
   460      ENV TEST foo
   461      CMD echo ${TEST}
   462      `,
   463  		true)
   464  
   465  	if err != nil {
   466  		t.Fatal(err)
   467  	}
   468  
   469  	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-e", "TEST=bar", "-t", name))
   470  
   471  	if err != nil {
   472  		t.Fatal(err)
   473  	}
   474  
   475  	if strings.TrimSpace(out) != "bar" {
   476  		t.Fatalf("Env TEST was not overwritten with bar when foo was supplied to dockerfile: was %q", strings.TrimSpace(out))
   477  	}
   478  
   479  	logDone("build - env should overwrite builder ENV during run")
   480  }
   481  
   482  func TestBuildOnBuildForbiddenMaintainerInSourceImage(t *testing.T) {
   483  	name := "testbuildonbuildforbiddenmaintainerinsourceimage"
   484  	defer deleteImages("onbuild")
   485  	defer deleteImages(name)
   486  	defer deleteAllContainers()
   487  
   488  	createCmd := exec.Command(dockerBinary, "create", "busybox", "true")
   489  	out, _, _, err := runCommandWithStdoutStderr(createCmd)
   490  	if err != nil {
   491  		t.Fatal(out, err)
   492  	}
   493  
   494  	cleanedContainerID := stripTrailingCharacters(out)
   495  
   496  	commitCmd := exec.Command(dockerBinary, "commit", "--run", "{\"OnBuild\":[\"MAINTAINER docker.io\"]}", cleanedContainerID, "onbuild")
   497  
   498  	if _, err := runCommand(commitCmd); err != nil {
   499  		t.Fatal(err)
   500  	}
   501  
   502  	_, err = buildImage(name,
   503  		`FROM onbuild`,
   504  		true)
   505  	if err != nil {
   506  		if !strings.Contains(err.Error(), "maintainer isn't allowed as an ONBUILD trigger") {
   507  			t.Fatalf("Wrong error %v, must be about MAINTAINER and ONBUILD in source image", err)
   508  		}
   509  	} else {
   510  		t.Fatal("Error must not be nil")
   511  	}
   512  	logDone("build - onbuild forbidden maintainer in source image")
   513  
   514  }
   515  
   516  func TestBuildOnBuildForbiddenFromInSourceImage(t *testing.T) {
   517  	name := "testbuildonbuildforbiddenfrominsourceimage"
   518  	defer deleteImages("onbuild")
   519  	defer deleteImages(name)
   520  	defer deleteAllContainers()
   521  
   522  	createCmd := exec.Command(dockerBinary, "create", "busybox", "true")
   523  	out, _, _, err := runCommandWithStdoutStderr(createCmd)
   524  	if err != nil {
   525  		t.Fatal(out, err)
   526  	}
   527  
   528  	cleanedContainerID := stripTrailingCharacters(out)
   529  
   530  	commitCmd := exec.Command(dockerBinary, "commit", "--run", "{\"OnBuild\":[\"FROM busybox\"]}", cleanedContainerID, "onbuild")
   531  
   532  	if _, err := runCommand(commitCmd); err != nil {
   533  		t.Fatal(err)
   534  	}
   535  
   536  	_, err = buildImage(name,
   537  		`FROM onbuild`,
   538  		true)
   539  	if err != nil {
   540  		if !strings.Contains(err.Error(), "from isn't allowed as an ONBUILD trigger") {
   541  			t.Fatalf("Wrong error %v, must be about FROM and ONBUILD in source image", err)
   542  		}
   543  	} else {
   544  		t.Fatal("Error must not be nil")
   545  	}
   546  	logDone("build - onbuild forbidden from in source image")
   547  
   548  }
   549  
   550  func TestBuildOnBuildForbiddenChainedInSourceImage(t *testing.T) {
   551  	name := "testbuildonbuildforbiddenchainedinsourceimage"
   552  	defer deleteImages("onbuild")
   553  	defer deleteImages(name)
   554  	defer deleteAllContainers()
   555  
   556  	createCmd := exec.Command(dockerBinary, "create", "busybox", "true")
   557  	out, _, _, err := runCommandWithStdoutStderr(createCmd)
   558  	if err != nil {
   559  		t.Fatal(out, err)
   560  	}
   561  
   562  	cleanedContainerID := stripTrailingCharacters(out)
   563  
   564  	commitCmd := exec.Command(dockerBinary, "commit", "--run", "{\"OnBuild\":[\"ONBUILD RUN ls\"]}", cleanedContainerID, "onbuild")
   565  
   566  	if _, err := runCommand(commitCmd); err != nil {
   567  		t.Fatal(err)
   568  	}
   569  
   570  	_, err = buildImage(name,
   571  		`FROM onbuild`,
   572  		true)
   573  	if err != nil {
   574  		if !strings.Contains(err.Error(), "Chaining ONBUILD via `ONBUILD ONBUILD` isn't allowed") {
   575  			t.Fatalf("Wrong error %v, must be about chaining ONBUILD in source image", err)
   576  		}
   577  	} else {
   578  		t.Fatal("Error must not be nil")
   579  	}
   580  	logDone("build - onbuild forbidden chained in source image")
   581  
   582  }
   583  
   584  func TestBuildOnBuildCmdEntrypointJSON(t *testing.T) {
   585  	name1 := "onbuildcmd"
   586  	name2 := "onbuildgenerated"
   587  
   588  	defer deleteImages(name2)
   589  	defer deleteImages(name1)
   590  	defer deleteAllContainers()
   591  
   592  	_, err := buildImage(name1, `
   593  FROM busybox
   594  ONBUILD CMD ["hello world"]
   595  ONBUILD ENTRYPOINT ["echo"]
   596  ONBUILD RUN ["true"]`,
   597  		false)
   598  
   599  	if err != nil {
   600  		t.Fatal(err)
   601  	}
   602  
   603  	_, err = buildImage(name2, fmt.Sprintf(`FROM %s`, name1), false)
   604  
   605  	if err != nil {
   606  		t.Fatal(err)
   607  	}
   608  
   609  	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-t", name2))
   610  	if err != nil {
   611  		t.Fatal(err)
   612  	}
   613  
   614  	if !regexp.MustCompile(`(?m)^hello world`).MatchString(out) {
   615  		t.Fatal("did not get echo output from onbuild", out)
   616  	}
   617  
   618  	logDone("build - onbuild with json entrypoint/cmd")
   619  }
   620  
   621  func TestBuildOnBuildEntrypointJSON(t *testing.T) {
   622  	name1 := "onbuildcmd"
   623  	name2 := "onbuildgenerated"
   624  
   625  	defer deleteImages(name2)
   626  	defer deleteImages(name1)
   627  	defer deleteAllContainers()
   628  
   629  	_, err := buildImage(name1, `
   630  FROM busybox
   631  ONBUILD ENTRYPOINT ["echo"]`,
   632  		false)
   633  
   634  	if err != nil {
   635  		t.Fatal(err)
   636  	}
   637  
   638  	_, err = buildImage(name2, fmt.Sprintf("FROM %s\nCMD [\"hello world\"]\n", name1), false)
   639  
   640  	if err != nil {
   641  		t.Fatal(err)
   642  	}
   643  
   644  	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-t", name2))
   645  	if err != nil {
   646  		t.Fatal(err)
   647  	}
   648  
   649  	if !regexp.MustCompile(`(?m)^hello world`).MatchString(out) {
   650  		t.Fatal("got malformed output from onbuild", out)
   651  	}
   652  
   653  	logDone("build - onbuild with json entrypoint")
   654  }
   655  
   656  func TestBuildCacheADD(t *testing.T) {
   657  	name := "testbuildtwoimageswithadd"
   658  	defer deleteImages(name)
   659  	server, err := fakeStorage(map[string]string{
   660  		"robots.txt": "hello",
   661  		"index.html": "world",
   662  	})
   663  	if err != nil {
   664  		t.Fatal(err)
   665  	}
   666  	defer server.Close()
   667  
   668  	if _, err := buildImage(name,
   669  		fmt.Sprintf(`FROM scratch
   670  		ADD %s/robots.txt /`, server.URL()),
   671  		true); err != nil {
   672  		t.Fatal(err)
   673  	}
   674  	if err != nil {
   675  		t.Fatal(err)
   676  	}
   677  	deleteImages(name)
   678  	_, out, err := buildImageWithOut(name,
   679  		fmt.Sprintf(`FROM scratch
   680  		ADD %s/index.html /`, server.URL()),
   681  		true)
   682  	if err != nil {
   683  		t.Fatal(err)
   684  	}
   685  	if strings.Contains(out, "Using cache") {
   686  		t.Fatal("2nd build used cache on ADD, it shouldn't")
   687  	}
   688  
   689  	logDone("build - build two images with remote ADD")
   690  }
   691  
   692  func TestBuildLastModified(t *testing.T) {
   693  	name := "testbuildlastmodified"
   694  	defer deleteImages(name)
   695  
   696  	server, err := fakeStorage(map[string]string{
   697  		"file": "hello",
   698  	})
   699  	if err != nil {
   700  		t.Fatal(err)
   701  	}
   702  	defer server.Close()
   703  
   704  	var out, out2 string
   705  
   706  	dFmt := `FROM busybox
   707  ADD %s/file /
   708  RUN ls -le /file`
   709  
   710  	dockerfile := fmt.Sprintf(dFmt, server.URL())
   711  
   712  	if _, out, err = buildImageWithOut(name, dockerfile, false); err != nil {
   713  		t.Fatal(err)
   714  	}
   715  
   716  	originMTime := regexp.MustCompile(`root.*/file.*\n`).FindString(out)
   717  	// Make sure our regexp is correct
   718  	if strings.Index(originMTime, "/file") < 0 {
   719  		t.Fatalf("Missing ls info on 'file':\n%s", out)
   720  	}
   721  
   722  	// Build it again and make sure the mtime of the file didn't change.
   723  	// Wait a few seconds to make sure the time changed enough to notice
   724  	time.Sleep(2 * time.Second)
   725  
   726  	if _, out2, err = buildImageWithOut(name, dockerfile, false); err != nil {
   727  		t.Fatal(err)
   728  	}
   729  
   730  	newMTime := regexp.MustCompile(`root.*/file.*\n`).FindString(out2)
   731  	if newMTime != originMTime {
   732  		t.Fatalf("MTime changed:\nOrigin:%s\nNew:%s", originMTime, newMTime)
   733  	}
   734  
   735  	// Now 'touch' the file and make sure the timestamp DID change this time
   736  	// Create a new fakeStorage instead of just using Add() to help windows
   737  	server, err = fakeStorage(map[string]string{
   738  		"file": "hello",
   739  	})
   740  	if err != nil {
   741  		t.Fatal(err)
   742  	}
   743  	defer server.Close()
   744  
   745  	dockerfile = fmt.Sprintf(dFmt, server.URL())
   746  
   747  	if _, out2, err = buildImageWithOut(name, dockerfile, false); err != nil {
   748  		t.Fatal(err)
   749  	}
   750  
   751  	newMTime = regexp.MustCompile(`root.*/file.*\n`).FindString(out2)
   752  	if newMTime == originMTime {
   753  		t.Fatalf("MTime didn't change:\nOrigin:%s\nNew:%s", originMTime, newMTime)
   754  	}
   755  
   756  	logDone("build - use Last-Modified header")
   757  }
   758  
   759  func TestBuildSixtySteps(t *testing.T) {
   760  	name := "foobuildsixtysteps"
   761  	defer deleteImages(name)
   762  	ctx, err := fakeContext("FROM scratch\n"+strings.Repeat("ADD foo /\n", 60),
   763  		map[string]string{
   764  			"foo": "test1",
   765  		})
   766  	if err != nil {
   767  		t.Fatal(err)
   768  	}
   769  	defer ctx.Close()
   770  
   771  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
   772  		t.Fatal(err)
   773  	}
   774  	logDone("build - build an image with sixty build steps")
   775  }
   776  
   777  func TestBuildAddSingleFileToRoot(t *testing.T) {
   778  	name := "testaddimg"
   779  	defer deleteImages(name)
   780  	ctx, err := fakeContext(fmt.Sprintf(`FROM busybox
   781  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
   782  RUN echo 'dockerio:x:1001:' >> /etc/group
   783  RUN touch /exists
   784  RUN chown dockerio.dockerio /exists
   785  ADD test_file /
   786  RUN [ $(ls -l /test_file | awk '{print $3":"$4}') = 'root:root' ]
   787  RUN [ $(ls -l /test_file | awk '{print $1}') = '%s' ]
   788  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`, expectedFileChmod),
   789  		map[string]string{
   790  			"test_file": "test1",
   791  		})
   792  	if err != nil {
   793  		t.Fatal(err)
   794  	}
   795  	defer ctx.Close()
   796  
   797  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
   798  		t.Fatal(err)
   799  	}
   800  	logDone("build - add single file to root")
   801  }
   802  
   803  // Issue #3960: "ADD src ." hangs
   804  func TestBuildAddSingleFileToWorkdir(t *testing.T) {
   805  	name := "testaddsinglefiletoworkdir"
   806  	defer deleteImages(name)
   807  	ctx, err := fakeContext(`FROM busybox
   808  ADD test_file .`,
   809  		map[string]string{
   810  			"test_file": "test1",
   811  		})
   812  	if err != nil {
   813  		t.Fatal(err)
   814  	}
   815  	defer ctx.Close()
   816  
   817  	done := make(chan struct{})
   818  	go func() {
   819  		if _, err := buildImageFromContext(name, ctx, true); err != nil {
   820  			t.Fatal(err)
   821  		}
   822  		close(done)
   823  	}()
   824  	select {
   825  	case <-time.After(5 * time.Second):
   826  		t.Fatal("Build with adding to workdir timed out")
   827  	case <-done:
   828  	}
   829  	logDone("build - add single file to workdir")
   830  }
   831  
   832  func TestBuildAddSingleFileToExistDir(t *testing.T) {
   833  	name := "testaddsinglefiletoexistdir"
   834  	defer deleteImages(name)
   835  	ctx, err := fakeContext(`FROM busybox
   836  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
   837  RUN echo 'dockerio:x:1001:' >> /etc/group
   838  RUN mkdir /exists
   839  RUN touch /exists/exists_file
   840  RUN chown -R dockerio.dockerio /exists
   841  ADD test_file /exists/
   842  RUN [ $(ls -l / | grep exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
   843  RUN [ $(ls -l /exists/test_file | awk '{print $3":"$4}') = 'root:root' ]
   844  RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`,
   845  		map[string]string{
   846  			"test_file": "test1",
   847  		})
   848  	if err != nil {
   849  		t.Fatal(err)
   850  	}
   851  	defer ctx.Close()
   852  
   853  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
   854  		t.Fatal(err)
   855  	}
   856  	logDone("build - add single file to existing dir")
   857  }
   858  
   859  func TestBuildCopyAddMultipleFiles(t *testing.T) {
   860  	server, err := fakeStorage(map[string]string{
   861  		"robots.txt": "hello",
   862  	})
   863  	if err != nil {
   864  		t.Fatal(err)
   865  	}
   866  	defer server.Close()
   867  
   868  	name := "testcopymultiplefilestofile"
   869  	defer deleteImages(name)
   870  	ctx, err := fakeContext(fmt.Sprintf(`FROM busybox
   871  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
   872  RUN echo 'dockerio:x:1001:' >> /etc/group
   873  RUN mkdir /exists
   874  RUN touch /exists/exists_file
   875  RUN chown -R dockerio.dockerio /exists
   876  COPY test_file1 test_file2 /exists/
   877  ADD test_file3 test_file4 %s/robots.txt /exists/
   878  RUN [ $(ls -l / | grep exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
   879  RUN [ $(ls -l /exists/test_file1 | awk '{print $3":"$4}') = 'root:root' ]
   880  RUN [ $(ls -l /exists/test_file2 | awk '{print $3":"$4}') = 'root:root' ]
   881  
   882  RUN [ $(ls -l /exists/test_file3 | awk '{print $3":"$4}') = 'root:root' ]
   883  RUN [ $(ls -l /exists/test_file4 | awk '{print $3":"$4}') = 'root:root' ]
   884  RUN [ $(ls -l /exists/robots.txt | awk '{print $3":"$4}') = 'root:root' ]
   885  
   886  RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
   887  `, server.URL()),
   888  		map[string]string{
   889  			"test_file1": "test1",
   890  			"test_file2": "test2",
   891  			"test_file3": "test3",
   892  			"test_file4": "test4",
   893  		})
   894  	defer ctx.Close()
   895  	if err != nil {
   896  		t.Fatal(err)
   897  	}
   898  
   899  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
   900  		t.Fatal(err)
   901  	}
   902  	logDone("build - multiple file copy/add tests")
   903  }
   904  
   905  func TestBuildAddMultipleFilesToFile(t *testing.T) {
   906  	name := "testaddmultiplefilestofile"
   907  	defer deleteImages(name)
   908  	ctx, err := fakeContext(`FROM scratch
   909  	ADD file1.txt file2.txt test
   910  	`,
   911  		map[string]string{
   912  			"file1.txt": "test1",
   913  			"file2.txt": "test1",
   914  		})
   915  	defer ctx.Close()
   916  	if err != nil {
   917  		t.Fatal(err)
   918  	}
   919  
   920  	expected := "When using ADD with more than one source file, the destination must be a directory and end with a /"
   921  	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
   922  		t.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
   923  	}
   924  
   925  	logDone("build - multiple add files to file")
   926  }
   927  
   928  func TestBuildJSONAddMultipleFilesToFile(t *testing.T) {
   929  	name := "testjsonaddmultiplefilestofile"
   930  	defer deleteImages(name)
   931  	ctx, err := fakeContext(`FROM scratch
   932  	ADD ["file1.txt", "file2.txt", "test"]
   933  	`,
   934  		map[string]string{
   935  			"file1.txt": "test1",
   936  			"file2.txt": "test1",
   937  		})
   938  	defer ctx.Close()
   939  	if err != nil {
   940  		t.Fatal(err)
   941  	}
   942  
   943  	expected := "When using ADD with more than one source file, the destination must be a directory and end with a /"
   944  	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
   945  		t.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
   946  	}
   947  
   948  	logDone("build - multiple add files to file json syntax")
   949  }
   950  
   951  func TestBuildAddMultipleFilesToFileWild(t *testing.T) {
   952  	name := "testaddmultiplefilestofilewild"
   953  	defer deleteImages(name)
   954  	ctx, err := fakeContext(`FROM scratch
   955  	ADD file*.txt test
   956  	`,
   957  		map[string]string{
   958  			"file1.txt": "test1",
   959  			"file2.txt": "test1",
   960  		})
   961  	defer ctx.Close()
   962  	if err != nil {
   963  		t.Fatal(err)
   964  	}
   965  
   966  	expected := "When using ADD with more than one source file, the destination must be a directory and end with a /"
   967  	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
   968  		t.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
   969  	}
   970  
   971  	logDone("build - multiple add files to file wild")
   972  }
   973  
   974  func TestBuildJSONAddMultipleFilesToFileWild(t *testing.T) {
   975  	name := "testjsonaddmultiplefilestofilewild"
   976  	defer deleteImages(name)
   977  	ctx, err := fakeContext(`FROM scratch
   978  	ADD ["file*.txt", "test"]
   979  	`,
   980  		map[string]string{
   981  			"file1.txt": "test1",
   982  			"file2.txt": "test1",
   983  		})
   984  	defer ctx.Close()
   985  	if err != nil {
   986  		t.Fatal(err)
   987  	}
   988  
   989  	expected := "When using ADD with more than one source file, the destination must be a directory and end with a /"
   990  	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
   991  		t.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
   992  	}
   993  
   994  	logDone("build - multiple add files to file wild json syntax")
   995  }
   996  
   997  func TestBuildCopyMultipleFilesToFile(t *testing.T) {
   998  	name := "testcopymultiplefilestofile"
   999  	defer deleteImages(name)
  1000  	ctx, err := fakeContext(`FROM scratch
  1001  	COPY file1.txt file2.txt test
  1002  	`,
  1003  		map[string]string{
  1004  			"file1.txt": "test1",
  1005  			"file2.txt": "test1",
  1006  		})
  1007  	defer ctx.Close()
  1008  	if err != nil {
  1009  		t.Fatal(err)
  1010  	}
  1011  
  1012  	expected := "When using COPY with more than one source file, the destination must be a directory and end with a /"
  1013  	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
  1014  		t.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
  1015  	}
  1016  
  1017  	logDone("build - multiple copy files to file")
  1018  }
  1019  
  1020  func TestBuildJSONCopyMultipleFilesToFile(t *testing.T) {
  1021  	name := "testjsoncopymultiplefilestofile"
  1022  	defer deleteImages(name)
  1023  	ctx, err := fakeContext(`FROM scratch
  1024  	COPY ["file1.txt", "file2.txt", "test"]
  1025  	`,
  1026  		map[string]string{
  1027  			"file1.txt": "test1",
  1028  			"file2.txt": "test1",
  1029  		})
  1030  	defer ctx.Close()
  1031  	if err != nil {
  1032  		t.Fatal(err)
  1033  	}
  1034  
  1035  	expected := "When using COPY with more than one source file, the destination must be a directory and end with a /"
  1036  	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
  1037  		t.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
  1038  	}
  1039  
  1040  	logDone("build - multiple copy files to file json syntax")
  1041  }
  1042  
  1043  func TestBuildAddFileWithWhitespace(t *testing.T) {
  1044  	name := "testaddfilewithwhitespace"
  1045  	defer deleteImages(name)
  1046  	ctx, err := fakeContext(`FROM busybox
  1047  RUN mkdir "/test dir"
  1048  RUN mkdir "/test_dir"
  1049  ADD [ "test file1", "/test_file1" ]
  1050  ADD [ "test_file2", "/test file2" ]
  1051  ADD [ "test file3", "/test file3" ]
  1052  ADD [ "test dir/test_file4", "/test_dir/test_file4" ]
  1053  ADD [ "test_dir/test_file5", "/test dir/test_file5" ]
  1054  ADD [ "test dir/test_file6", "/test dir/test_file6" ]
  1055  RUN [ $(cat "/test_file1") = 'test1' ]
  1056  RUN [ $(cat "/test file2") = 'test2' ]
  1057  RUN [ $(cat "/test file3") = 'test3' ]
  1058  RUN [ $(cat "/test_dir/test_file4") = 'test4' ]
  1059  RUN [ $(cat "/test dir/test_file5") = 'test5' ]
  1060  RUN [ $(cat "/test dir/test_file6") = 'test6' ]`,
  1061  		map[string]string{
  1062  			"test file1":          "test1",
  1063  			"test_file2":          "test2",
  1064  			"test file3":          "test3",
  1065  			"test dir/test_file4": "test4",
  1066  			"test_dir/test_file5": "test5",
  1067  			"test dir/test_file6": "test6",
  1068  		})
  1069  	defer ctx.Close()
  1070  	if err != nil {
  1071  		t.Fatal(err)
  1072  	}
  1073  
  1074  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1075  		t.Fatal(err)
  1076  	}
  1077  	logDone("build - add file with whitespace")
  1078  }
  1079  
  1080  func TestBuildCopyFileWithWhitespace(t *testing.T) {
  1081  	name := "testcopyfilewithwhitespace"
  1082  	defer deleteImages(name)
  1083  	ctx, err := fakeContext(`FROM busybox
  1084  RUN mkdir "/test dir"
  1085  RUN mkdir "/test_dir"
  1086  COPY [ "test file1", "/test_file1" ]
  1087  COPY [ "test_file2", "/test file2" ]
  1088  COPY [ "test file3", "/test file3" ]
  1089  COPY [ "test dir/test_file4", "/test_dir/test_file4" ]
  1090  COPY [ "test_dir/test_file5", "/test dir/test_file5" ]
  1091  COPY [ "test dir/test_file6", "/test dir/test_file6" ]
  1092  RUN [ $(cat "/test_file1") = 'test1' ]
  1093  RUN [ $(cat "/test file2") = 'test2' ]
  1094  RUN [ $(cat "/test file3") = 'test3' ]
  1095  RUN [ $(cat "/test_dir/test_file4") = 'test4' ]
  1096  RUN [ $(cat "/test dir/test_file5") = 'test5' ]
  1097  RUN [ $(cat "/test dir/test_file6") = 'test6' ]`,
  1098  		map[string]string{
  1099  			"test file1":          "test1",
  1100  			"test_file2":          "test2",
  1101  			"test file3":          "test3",
  1102  			"test dir/test_file4": "test4",
  1103  			"test_dir/test_file5": "test5",
  1104  			"test dir/test_file6": "test6",
  1105  		})
  1106  	defer ctx.Close()
  1107  	if err != nil {
  1108  		t.Fatal(err)
  1109  	}
  1110  
  1111  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1112  		t.Fatal(err)
  1113  	}
  1114  	logDone("build - copy file with whitespace")
  1115  }
  1116  
  1117  func TestBuildAddMultipleFilesToFileWithWhitespace(t *testing.T) {
  1118  	name := "testaddmultiplefilestofilewithwhitespace"
  1119  	defer deleteImages(name)
  1120  	ctx, err := fakeContext(`FROM busybox
  1121  	ADD [ "test file1", "test file2", "test" ]
  1122      `,
  1123  		map[string]string{
  1124  			"test file1": "test1",
  1125  			"test file2": "test2",
  1126  		})
  1127  	defer ctx.Close()
  1128  	if err != nil {
  1129  		t.Fatal(err)
  1130  	}
  1131  
  1132  	expected := "When using ADD with more than one source file, the destination must be a directory and end with a /"
  1133  	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
  1134  		t.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
  1135  	}
  1136  
  1137  	logDone("build - multiple add files to file with whitespace")
  1138  }
  1139  
  1140  func TestBuildCopyMultipleFilesToFileWithWhitespace(t *testing.T) {
  1141  	name := "testcopymultiplefilestofilewithwhitespace"
  1142  	defer deleteImages(name)
  1143  	ctx, err := fakeContext(`FROM busybox
  1144  	COPY [ "test file1", "test file2", "test" ]
  1145          `,
  1146  		map[string]string{
  1147  			"test file1": "test1",
  1148  			"test file2": "test2",
  1149  		})
  1150  	defer ctx.Close()
  1151  	if err != nil {
  1152  		t.Fatal(err)
  1153  	}
  1154  
  1155  	expected := "When using COPY with more than one source file, the destination must be a directory and end with a /"
  1156  	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
  1157  		t.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
  1158  	}
  1159  
  1160  	logDone("build - multiple copy files to file with whitespace")
  1161  }
  1162  
  1163  func TestBuildCopyWildcard(t *testing.T) {
  1164  	name := "testcopywildcard"
  1165  	defer deleteImages(name)
  1166  	server, err := fakeStorage(map[string]string{
  1167  		"robots.txt": "hello",
  1168  		"index.html": "world",
  1169  	})
  1170  	if err != nil {
  1171  		t.Fatal(err)
  1172  	}
  1173  	defer server.Close()
  1174  
  1175  	ctx, err := fakeContext(fmt.Sprintf(`FROM busybox
  1176  	COPY file*.txt /tmp/
  1177  	RUN ls /tmp/file1.txt /tmp/file2.txt
  1178  	RUN mkdir /tmp1
  1179  	COPY dir* /tmp1/
  1180  	RUN ls /tmp1/dirt /tmp1/nested_file /tmp1/nested_dir/nest_nest_file
  1181  	RUN mkdir /tmp2
  1182          ADD dir/*dir %s/robots.txt /tmp2/
  1183  	RUN ls /tmp2/nest_nest_file /tmp2/robots.txt
  1184  	`, server.URL()),
  1185  		map[string]string{
  1186  			"file1.txt":                     "test1",
  1187  			"file2.txt":                     "test2",
  1188  			"dir/nested_file":               "nested file",
  1189  			"dir/nested_dir/nest_nest_file": "2 times nested",
  1190  			"dirt": "dirty",
  1191  		})
  1192  	defer ctx.Close()
  1193  	if err != nil {
  1194  		t.Fatal(err)
  1195  	}
  1196  
  1197  	id1, err := buildImageFromContext(name, ctx, true)
  1198  	if err != nil {
  1199  		t.Fatal(err)
  1200  	}
  1201  
  1202  	// Now make sure we use a cache the 2nd time
  1203  	id2, err := buildImageFromContext(name, ctx, true)
  1204  	if err != nil {
  1205  		t.Fatal(err)
  1206  	}
  1207  
  1208  	if id1 != id2 {
  1209  		t.Fatal("didn't use the cache")
  1210  	}
  1211  
  1212  	logDone("build - copy wild card")
  1213  }
  1214  
  1215  func TestBuildCopyWildcardNoFind(t *testing.T) {
  1216  	name := "testcopywildcardnofind"
  1217  	defer deleteImages(name)
  1218  	ctx, err := fakeContext(`FROM busybox
  1219  	COPY file*.txt /tmp/
  1220  	`, nil)
  1221  	defer ctx.Close()
  1222  	if err != nil {
  1223  		t.Fatal(err)
  1224  	}
  1225  
  1226  	_, err = buildImageFromContext(name, ctx, true)
  1227  	if err == nil {
  1228  		t.Fatal("should have failed to find a file")
  1229  	}
  1230  	if !strings.Contains(err.Error(), "No source files were specified") {
  1231  		t.Fatalf("Wrong error %v, must be about no source files", err)
  1232  	}
  1233  
  1234  	logDone("build - copy wild card no find")
  1235  }
  1236  
  1237  func TestBuildCopyWildcardCache(t *testing.T) {
  1238  	name := "testcopywildcardcache"
  1239  	defer deleteImages(name)
  1240  	ctx, err := fakeContext(`FROM busybox
  1241  	COPY file1.txt /tmp/`,
  1242  		map[string]string{
  1243  			"file1.txt": "test1",
  1244  		})
  1245  	defer ctx.Close()
  1246  	if err != nil {
  1247  		t.Fatal(err)
  1248  	}
  1249  
  1250  	id1, err := buildImageFromContext(name, ctx, true)
  1251  	if err != nil {
  1252  		t.Fatal(err)
  1253  	}
  1254  
  1255  	// Now make sure we use a cache the 2nd time even with wild cards.
  1256  	// Use the same context so the file is the same and the checksum will match
  1257  	ctx.Add("Dockerfile", `FROM busybox
  1258  	COPY file*.txt /tmp/`)
  1259  
  1260  	id2, err := buildImageFromContext(name, ctx, true)
  1261  	if err != nil {
  1262  		t.Fatal(err)
  1263  	}
  1264  
  1265  	if id1 != id2 {
  1266  		t.Fatal("didn't use the cache")
  1267  	}
  1268  
  1269  	logDone("build - copy wild card cache")
  1270  }
  1271  
  1272  func TestBuildAddSingleFileToNonExistingDir(t *testing.T) {
  1273  	name := "testaddsinglefiletononexistingdir"
  1274  	defer deleteImages(name)
  1275  	ctx, err := fakeContext(`FROM busybox
  1276  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  1277  RUN echo 'dockerio:x:1001:' >> /etc/group
  1278  RUN touch /exists
  1279  RUN chown dockerio.dockerio /exists
  1280  ADD test_file /test_dir/
  1281  RUN [ $(ls -l / | grep test_dir | awk '{print $3":"$4}') = 'root:root' ]
  1282  RUN [ $(ls -l /test_dir/test_file | awk '{print $3":"$4}') = 'root:root' ]
  1283  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`,
  1284  		map[string]string{
  1285  			"test_file": "test1",
  1286  		})
  1287  	if err != nil {
  1288  		t.Fatal(err)
  1289  	}
  1290  	defer ctx.Close()
  1291  
  1292  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1293  		t.Fatal(err)
  1294  	}
  1295  
  1296  	logDone("build - add single file to non-existing dir")
  1297  }
  1298  
  1299  func TestBuildAddDirContentToRoot(t *testing.T) {
  1300  	name := "testadddircontenttoroot"
  1301  	defer deleteImages(name)
  1302  	ctx, err := fakeContext(`FROM busybox
  1303  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  1304  RUN echo 'dockerio:x:1001:' >> /etc/group
  1305  RUN touch /exists
  1306  RUN chown dockerio.dockerio exists
  1307  ADD test_dir /
  1308  RUN [ $(ls -l /test_file | awk '{print $3":"$4}') = 'root:root' ]
  1309  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`,
  1310  		map[string]string{
  1311  			"test_dir/test_file": "test1",
  1312  		})
  1313  	if err != nil {
  1314  		t.Fatal(err)
  1315  	}
  1316  	defer ctx.Close()
  1317  
  1318  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1319  		t.Fatal(err)
  1320  	}
  1321  	logDone("build - add directory contents to root")
  1322  }
  1323  
  1324  func TestBuildAddDirContentToExistingDir(t *testing.T) {
  1325  	name := "testadddircontenttoexistingdir"
  1326  	defer deleteImages(name)
  1327  	ctx, err := fakeContext(`FROM busybox
  1328  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  1329  RUN echo 'dockerio:x:1001:' >> /etc/group
  1330  RUN mkdir /exists
  1331  RUN touch /exists/exists_file
  1332  RUN chown -R dockerio.dockerio /exists
  1333  ADD test_dir/ /exists/
  1334  RUN [ $(ls -l / | grep exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
  1335  RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
  1336  RUN [ $(ls -l /exists/test_file | awk '{print $3":"$4}') = 'root:root' ]`,
  1337  		map[string]string{
  1338  			"test_dir/test_file": "test1",
  1339  		})
  1340  	if err != nil {
  1341  		t.Fatal(err)
  1342  	}
  1343  	defer ctx.Close()
  1344  
  1345  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1346  		t.Fatal(err)
  1347  	}
  1348  	logDone("build - add directory contents to existing dir")
  1349  }
  1350  
  1351  func TestBuildAddWholeDirToRoot(t *testing.T) {
  1352  	name := "testaddwholedirtoroot"
  1353  	defer deleteImages(name)
  1354  	ctx, err := fakeContext(fmt.Sprintf(`FROM busybox
  1355  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  1356  RUN echo 'dockerio:x:1001:' >> /etc/group
  1357  RUN touch /exists
  1358  RUN chown dockerio.dockerio exists
  1359  ADD test_dir /test_dir
  1360  RUN [ $(ls -l / | grep test_dir | awk '{print $3":"$4}') = 'root:root' ]
  1361  RUN [ $(ls -l / | grep test_dir | awk '{print $1}') = 'drwxr-xr-x' ]
  1362  RUN [ $(ls -l /test_dir/test_file | awk '{print $3":"$4}') = 'root:root' ]
  1363  RUN [ $(ls -l /test_dir/test_file | awk '{print $1}') = '%s' ]
  1364  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`, expectedFileChmod),
  1365  		map[string]string{
  1366  			"test_dir/test_file": "test1",
  1367  		})
  1368  	if err != nil {
  1369  		t.Fatal(err)
  1370  	}
  1371  	defer ctx.Close()
  1372  
  1373  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1374  		t.Fatal(err)
  1375  	}
  1376  	logDone("build - add whole directory to root")
  1377  }
  1378  
  1379  // Testing #5941
  1380  func TestBuildAddEtcToRoot(t *testing.T) {
  1381  	name := "testaddetctoroot"
  1382  	defer deleteImages(name)
  1383  	ctx, err := fakeContext(`FROM scratch
  1384  ADD . /`,
  1385  		map[string]string{
  1386  			"etc/test_file": "test1",
  1387  		})
  1388  	if err != nil {
  1389  		t.Fatal(err)
  1390  	}
  1391  	defer ctx.Close()
  1392  
  1393  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1394  		t.Fatal(err)
  1395  	}
  1396  	logDone("build - add etc directory to root")
  1397  }
  1398  
  1399  // Testing #9401
  1400  func TestBuildAddPreservesFilesSpecialBits(t *testing.T) {
  1401  	name := "testaddpreservesfilesspecialbits"
  1402  	defer deleteImages(name)
  1403  	ctx, err := fakeContext(`FROM busybox
  1404  ADD suidbin /usr/bin/suidbin
  1405  RUN chmod 4755 /usr/bin/suidbin
  1406  RUN [ $(ls -l /usr/bin/suidbin | awk '{print $1}') = '-rwsr-xr-x' ]
  1407  ADD ./data/ /
  1408  RUN [ $(ls -l /usr/bin/suidbin | awk '{print $1}') = '-rwsr-xr-x' ]`,
  1409  		map[string]string{
  1410  			"suidbin":             "suidbin",
  1411  			"/data/usr/test_file": "test1",
  1412  		})
  1413  	if err != nil {
  1414  		t.Fatal(err)
  1415  	}
  1416  	defer ctx.Close()
  1417  
  1418  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1419  		t.Fatal(err)
  1420  	}
  1421  	logDone("build - add preserves files special bits")
  1422  }
  1423  
  1424  func TestBuildCopySingleFileToRoot(t *testing.T) {
  1425  	name := "testcopysinglefiletoroot"
  1426  	defer deleteImages(name)
  1427  	ctx, err := fakeContext(fmt.Sprintf(`FROM busybox
  1428  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  1429  RUN echo 'dockerio:x:1001:' >> /etc/group
  1430  RUN touch /exists
  1431  RUN chown dockerio.dockerio /exists
  1432  COPY test_file /
  1433  RUN [ $(ls -l /test_file | awk '{print $3":"$4}') = 'root:root' ]
  1434  RUN [ $(ls -l /test_file | awk '{print $1}') = '%s' ]
  1435  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`, expectedFileChmod),
  1436  		map[string]string{
  1437  			"test_file": "test1",
  1438  		})
  1439  	if err != nil {
  1440  		t.Fatal(err)
  1441  	}
  1442  	defer ctx.Close()
  1443  
  1444  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1445  		t.Fatal(err)
  1446  	}
  1447  	logDone("build - copy single file to root")
  1448  }
  1449  
  1450  // Issue #3960: "ADD src ." hangs - adapted for COPY
  1451  func TestBuildCopySingleFileToWorkdir(t *testing.T) {
  1452  	name := "testcopysinglefiletoworkdir"
  1453  	defer deleteImages(name)
  1454  	ctx, err := fakeContext(`FROM busybox
  1455  COPY test_file .`,
  1456  		map[string]string{
  1457  			"test_file": "test1",
  1458  		})
  1459  	if err != nil {
  1460  		t.Fatal(err)
  1461  	}
  1462  	defer ctx.Close()
  1463  
  1464  	done := make(chan struct{})
  1465  	go func() {
  1466  		if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1467  			t.Fatal(err)
  1468  		}
  1469  		close(done)
  1470  	}()
  1471  	select {
  1472  	case <-time.After(5 * time.Second):
  1473  		t.Fatal("Build with adding to workdir timed out")
  1474  	case <-done:
  1475  	}
  1476  	logDone("build - copy single file to workdir")
  1477  }
  1478  
  1479  func TestBuildCopySingleFileToExistDir(t *testing.T) {
  1480  	name := "testcopysinglefiletoexistdir"
  1481  	defer deleteImages(name)
  1482  	ctx, err := fakeContext(`FROM busybox
  1483  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  1484  RUN echo 'dockerio:x:1001:' >> /etc/group
  1485  RUN mkdir /exists
  1486  RUN touch /exists/exists_file
  1487  RUN chown -R dockerio.dockerio /exists
  1488  COPY test_file /exists/
  1489  RUN [ $(ls -l / | grep exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
  1490  RUN [ $(ls -l /exists/test_file | awk '{print $3":"$4}') = 'root:root' ]
  1491  RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`,
  1492  		map[string]string{
  1493  			"test_file": "test1",
  1494  		})
  1495  	if err != nil {
  1496  		t.Fatal(err)
  1497  	}
  1498  	defer ctx.Close()
  1499  
  1500  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1501  		t.Fatal(err)
  1502  	}
  1503  	logDone("build - copy single file to existing dir")
  1504  }
  1505  
  1506  func TestBuildCopySingleFileToNonExistDir(t *testing.T) {
  1507  	name := "testcopysinglefiletononexistdir"
  1508  	defer deleteImages(name)
  1509  	ctx, err := fakeContext(`FROM busybox
  1510  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  1511  RUN echo 'dockerio:x:1001:' >> /etc/group
  1512  RUN touch /exists
  1513  RUN chown dockerio.dockerio /exists
  1514  COPY test_file /test_dir/
  1515  RUN [ $(ls -l / | grep test_dir | awk '{print $3":"$4}') = 'root:root' ]
  1516  RUN [ $(ls -l /test_dir/test_file | awk '{print $3":"$4}') = 'root:root' ]
  1517  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`,
  1518  		map[string]string{
  1519  			"test_file": "test1",
  1520  		})
  1521  	if err != nil {
  1522  		t.Fatal(err)
  1523  	}
  1524  	defer ctx.Close()
  1525  
  1526  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1527  		t.Fatal(err)
  1528  	}
  1529  	logDone("build - copy single file to non-existing dir")
  1530  }
  1531  
  1532  func TestBuildCopyDirContentToRoot(t *testing.T) {
  1533  	name := "testcopydircontenttoroot"
  1534  	defer deleteImages(name)
  1535  	ctx, err := fakeContext(`FROM busybox
  1536  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  1537  RUN echo 'dockerio:x:1001:' >> /etc/group
  1538  RUN touch /exists
  1539  RUN chown dockerio.dockerio exists
  1540  COPY test_dir /
  1541  RUN [ $(ls -l /test_file | awk '{print $3":"$4}') = 'root:root' ]
  1542  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`,
  1543  		map[string]string{
  1544  			"test_dir/test_file": "test1",
  1545  		})
  1546  	if err != nil {
  1547  		t.Fatal(err)
  1548  	}
  1549  	defer ctx.Close()
  1550  
  1551  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1552  		t.Fatal(err)
  1553  	}
  1554  	logDone("build - copy directory contents to root")
  1555  }
  1556  
  1557  func TestBuildCopyDirContentToExistDir(t *testing.T) {
  1558  	name := "testcopydircontenttoexistdir"
  1559  	defer deleteImages(name)
  1560  	ctx, err := fakeContext(`FROM busybox
  1561  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  1562  RUN echo 'dockerio:x:1001:' >> /etc/group
  1563  RUN mkdir /exists
  1564  RUN touch /exists/exists_file
  1565  RUN chown -R dockerio.dockerio /exists
  1566  COPY test_dir/ /exists/
  1567  RUN [ $(ls -l / | grep exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
  1568  RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
  1569  RUN [ $(ls -l /exists/test_file | awk '{print $3":"$4}') = 'root:root' ]`,
  1570  		map[string]string{
  1571  			"test_dir/test_file": "test1",
  1572  		})
  1573  	if err != nil {
  1574  		t.Fatal(err)
  1575  	}
  1576  	defer ctx.Close()
  1577  
  1578  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1579  		t.Fatal(err)
  1580  	}
  1581  	logDone("build - copy directory contents to existing dir")
  1582  }
  1583  
  1584  func TestBuildCopyWholeDirToRoot(t *testing.T) {
  1585  	name := "testcopywholedirtoroot"
  1586  	defer deleteImages(name)
  1587  	ctx, err := fakeContext(fmt.Sprintf(`FROM busybox
  1588  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  1589  RUN echo 'dockerio:x:1001:' >> /etc/group
  1590  RUN touch /exists
  1591  RUN chown dockerio.dockerio exists
  1592  COPY test_dir /test_dir
  1593  RUN [ $(ls -l / | grep test_dir | awk '{print $3":"$4}') = 'root:root' ]
  1594  RUN [ $(ls -l / | grep test_dir | awk '{print $1}') = 'drwxr-xr-x' ]
  1595  RUN [ $(ls -l /test_dir/test_file | awk '{print $3":"$4}') = 'root:root' ]
  1596  RUN [ $(ls -l /test_dir/test_file | awk '{print $1}') = '%s' ]
  1597  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`, expectedFileChmod),
  1598  		map[string]string{
  1599  			"test_dir/test_file": "test1",
  1600  		})
  1601  	if err != nil {
  1602  		t.Fatal(err)
  1603  	}
  1604  	defer ctx.Close()
  1605  
  1606  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1607  		t.Fatal(err)
  1608  	}
  1609  	logDone("build - copy whole directory to root")
  1610  }
  1611  
  1612  func TestBuildCopyEtcToRoot(t *testing.T) {
  1613  	name := "testcopyetctoroot"
  1614  	defer deleteImages(name)
  1615  	ctx, err := fakeContext(`FROM scratch
  1616  COPY . /`,
  1617  		map[string]string{
  1618  			"etc/test_file": "test1",
  1619  		})
  1620  	if err != nil {
  1621  		t.Fatal(err)
  1622  	}
  1623  	defer ctx.Close()
  1624  
  1625  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1626  		t.Fatal(err)
  1627  	}
  1628  	logDone("build - copy etc directory to root")
  1629  }
  1630  
  1631  func TestBuildCopyDisallowRemote(t *testing.T) {
  1632  	name := "testcopydisallowremote"
  1633  	defer deleteImages(name)
  1634  	_, out, err := buildImageWithOut(name, `FROM scratch
  1635  COPY https://index.docker.io/robots.txt /`,
  1636  		true)
  1637  	if err == nil || !strings.Contains(out, "Source can't be a URL for COPY") {
  1638  		t.Fatalf("Error should be about disallowed remote source, got err: %s, out: %q", err, out)
  1639  	}
  1640  	logDone("build - copy - disallow copy from remote")
  1641  }
  1642  
  1643  func TestBuildAddBadLinks(t *testing.T) {
  1644  	const (
  1645  		dockerfile = `
  1646  			FROM scratch
  1647  			ADD links.tar /
  1648  			ADD foo.txt /symlink/
  1649  			`
  1650  		targetFile = "foo.txt"
  1651  	)
  1652  	var (
  1653  		name = "test-link-absolute"
  1654  	)
  1655  	defer deleteImages(name)
  1656  	ctx, err := fakeContext(dockerfile, nil)
  1657  	if err != nil {
  1658  		t.Fatal(err)
  1659  	}
  1660  	defer ctx.Close()
  1661  
  1662  	tempDir, err := ioutil.TempDir("", "test-link-absolute-temp-")
  1663  	if err != nil {
  1664  		t.Fatalf("failed to create temporary directory: %s", tempDir)
  1665  	}
  1666  	defer os.RemoveAll(tempDir)
  1667  
  1668  	var symlinkTarget string
  1669  	if runtime.GOOS == "windows" {
  1670  		var driveLetter string
  1671  		if abs, err := filepath.Abs(tempDir); err != nil {
  1672  			t.Fatal(err)
  1673  		} else {
  1674  			driveLetter = abs[:1]
  1675  		}
  1676  		tempDirWithoutDrive := tempDir[2:]
  1677  		symlinkTarget = fmt.Sprintf(`%s:\..\..\..\..\..\..\..\..\..\..\..\..%s`, driveLetter, tempDirWithoutDrive)
  1678  	} else {
  1679  		symlinkTarget = fmt.Sprintf("/../../../../../../../../../../../..%s", tempDir)
  1680  	}
  1681  
  1682  	tarPath := filepath.Join(ctx.Dir, "links.tar")
  1683  	nonExistingFile := filepath.Join(tempDir, targetFile)
  1684  	fooPath := filepath.Join(ctx.Dir, targetFile)
  1685  
  1686  	tarOut, err := os.Create(tarPath)
  1687  	if err != nil {
  1688  		t.Fatal(err)
  1689  	}
  1690  
  1691  	tarWriter := tar.NewWriter(tarOut)
  1692  
  1693  	header := &tar.Header{
  1694  		Name:     "symlink",
  1695  		Typeflag: tar.TypeSymlink,
  1696  		Linkname: symlinkTarget,
  1697  		Mode:     0755,
  1698  		Uid:      0,
  1699  		Gid:      0,
  1700  	}
  1701  
  1702  	err = tarWriter.WriteHeader(header)
  1703  	if err != nil {
  1704  		t.Fatal(err)
  1705  	}
  1706  
  1707  	tarWriter.Close()
  1708  	tarOut.Close()
  1709  
  1710  	foo, err := os.Create(fooPath)
  1711  	if err != nil {
  1712  		t.Fatal(err)
  1713  	}
  1714  	defer foo.Close()
  1715  
  1716  	if _, err := foo.WriteString("test"); err != nil {
  1717  		t.Fatal(err)
  1718  	}
  1719  
  1720  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1721  		t.Fatal(err)
  1722  	}
  1723  
  1724  	if _, err := os.Stat(nonExistingFile); err == nil || err != nil && !os.IsNotExist(err) {
  1725  		t.Fatalf("%s shouldn't have been written and it shouldn't exist", nonExistingFile)
  1726  	}
  1727  
  1728  	logDone("build - ADD must add files in container")
  1729  }
  1730  
  1731  func TestBuildAddBadLinksVolume(t *testing.T) {
  1732  	const (
  1733  		dockerfileTemplate = `
  1734  		FROM busybox
  1735  		RUN ln -s /../../../../../../../../%s /x
  1736  		VOLUME /x
  1737  		ADD foo.txt /x/`
  1738  		targetFile = "foo.txt"
  1739  	)
  1740  	var (
  1741  		name       = "test-link-absolute-volume"
  1742  		dockerfile = ""
  1743  	)
  1744  	defer deleteImages(name)
  1745  
  1746  	tempDir, err := ioutil.TempDir("", "test-link-absolute-volume-temp-")
  1747  	if err != nil {
  1748  		t.Fatalf("failed to create temporary directory: %s", tempDir)
  1749  	}
  1750  	defer os.RemoveAll(tempDir)
  1751  
  1752  	dockerfile = fmt.Sprintf(dockerfileTemplate, tempDir)
  1753  	nonExistingFile := filepath.Join(tempDir, targetFile)
  1754  
  1755  	ctx, err := fakeContext(dockerfile, nil)
  1756  	if err != nil {
  1757  		t.Fatal(err)
  1758  	}
  1759  	defer ctx.Close()
  1760  	fooPath := filepath.Join(ctx.Dir, targetFile)
  1761  
  1762  	foo, err := os.Create(fooPath)
  1763  	if err != nil {
  1764  		t.Fatal(err)
  1765  	}
  1766  	defer foo.Close()
  1767  
  1768  	if _, err := foo.WriteString("test"); err != nil {
  1769  		t.Fatal(err)
  1770  	}
  1771  
  1772  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1773  		t.Fatal(err)
  1774  	}
  1775  
  1776  	if _, err := os.Stat(nonExistingFile); err == nil || err != nil && !os.IsNotExist(err) {
  1777  		t.Fatalf("%s shouldn't have been written and it shouldn't exist", nonExistingFile)
  1778  	}
  1779  
  1780  	logDone("build - ADD should add files in volume")
  1781  }
  1782  
  1783  // Issue #5270 - ensure we throw a better error than "unexpected EOF"
  1784  // when we can't access files in the context.
  1785  func TestBuildWithInaccessibleFilesInContext(t *testing.T) {
  1786  	testRequires(t, UnixCli) // test uses chown/chmod: not available on windows
  1787  
  1788  	{
  1789  		name := "testbuildinaccessiblefiles"
  1790  		defer deleteImages(name)
  1791  		ctx, err := fakeContext("FROM scratch\nADD . /foo/", map[string]string{"fileWithoutReadAccess": "foo"})
  1792  		if err != nil {
  1793  			t.Fatal(err)
  1794  		}
  1795  		defer ctx.Close()
  1796  		// This is used to ensure we detect inaccessible files early during build in the cli client
  1797  		pathToFileWithoutReadAccess := filepath.Join(ctx.Dir, "fileWithoutReadAccess")
  1798  
  1799  		if err = os.Chown(pathToFileWithoutReadAccess, 0, 0); err != nil {
  1800  			t.Fatalf("failed to chown file to root: %s", err)
  1801  		}
  1802  		if err = os.Chmod(pathToFileWithoutReadAccess, 0700); err != nil {
  1803  			t.Fatalf("failed to chmod file to 700: %s", err)
  1804  		}
  1805  		buildCmd := exec.Command("su", "unprivilegeduser", "-c", fmt.Sprintf("%s build -t %s .", dockerBinary, name))
  1806  		buildCmd.Dir = ctx.Dir
  1807  		out, _, err := runCommandWithOutput(buildCmd)
  1808  		if err == nil {
  1809  			t.Fatalf("build should have failed: %s %s", err, out)
  1810  		}
  1811  
  1812  		// check if we've detected the failure before we started building
  1813  		if !strings.Contains(out, "no permission to read from ") {
  1814  			t.Fatalf("output should've contained the string: no permission to read from but contained: %s", out)
  1815  		}
  1816  
  1817  		if !strings.Contains(out, "Error checking context is accessible") {
  1818  			t.Fatalf("output should've contained the string: Error checking context is accessible")
  1819  		}
  1820  	}
  1821  	{
  1822  		name := "testbuildinaccessibledirectory"
  1823  		defer deleteImages(name)
  1824  		ctx, err := fakeContext("FROM scratch\nADD . /foo/", map[string]string{"directoryWeCantStat/bar": "foo"})
  1825  		if err != nil {
  1826  			t.Fatal(err)
  1827  		}
  1828  		defer ctx.Close()
  1829  		// This is used to ensure we detect inaccessible directories early during build in the cli client
  1830  		pathToDirectoryWithoutReadAccess := filepath.Join(ctx.Dir, "directoryWeCantStat")
  1831  		pathToFileInDirectoryWithoutReadAccess := filepath.Join(pathToDirectoryWithoutReadAccess, "bar")
  1832  
  1833  		if err = os.Chown(pathToDirectoryWithoutReadAccess, 0, 0); err != nil {
  1834  			t.Fatalf("failed to chown directory to root: %s", err)
  1835  		}
  1836  		if err = os.Chmod(pathToDirectoryWithoutReadAccess, 0444); err != nil {
  1837  			t.Fatalf("failed to chmod directory to 444: %s", err)
  1838  		}
  1839  		if err = os.Chmod(pathToFileInDirectoryWithoutReadAccess, 0700); err != nil {
  1840  			t.Fatalf("failed to chmod file to 700: %s", err)
  1841  		}
  1842  
  1843  		buildCmd := exec.Command("su", "unprivilegeduser", "-c", fmt.Sprintf("%s build -t %s .", dockerBinary, name))
  1844  		buildCmd.Dir = ctx.Dir
  1845  		out, _, err := runCommandWithOutput(buildCmd)
  1846  		if err == nil {
  1847  			t.Fatalf("build should have failed: %s %s", err, out)
  1848  		}
  1849  
  1850  		// check if we've detected the failure before we started building
  1851  		if !strings.Contains(out, "can't stat") {
  1852  			t.Fatalf("output should've contained the string: can't access %s", out)
  1853  		}
  1854  
  1855  		if !strings.Contains(out, "Error checking context is accessible") {
  1856  			t.Fatalf("output should've contained the string: Error checking context is accessible")
  1857  		}
  1858  
  1859  	}
  1860  	{
  1861  		name := "testlinksok"
  1862  		defer deleteImages(name)
  1863  		ctx, err := fakeContext("FROM scratch\nADD . /foo/", nil)
  1864  		if err != nil {
  1865  			t.Fatal(err)
  1866  		}
  1867  		defer ctx.Close()
  1868  
  1869  		target := "../../../../../../../../../../../../../../../../../../../azA"
  1870  		if err := os.Symlink(filepath.Join(ctx.Dir, "g"), target); err != nil {
  1871  			t.Fatal(err)
  1872  		}
  1873  		defer os.Remove(target)
  1874  		// This is used to ensure we don't follow links when checking if everything in the context is accessible
  1875  		// This test doesn't require that we run commands as an unprivileged user
  1876  		if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1877  			t.Fatal(err)
  1878  		}
  1879  	}
  1880  	{
  1881  		name := "testbuildignoredinaccessible"
  1882  		defer deleteImages(name)
  1883  		ctx, err := fakeContext("FROM scratch\nADD . /foo/",
  1884  			map[string]string{
  1885  				"directoryWeCantStat/bar": "foo",
  1886  				".dockerignore":           "directoryWeCantStat",
  1887  			})
  1888  		if err != nil {
  1889  			t.Fatal(err)
  1890  		}
  1891  		defer ctx.Close()
  1892  		// This is used to ensure we don't try to add inaccessible files when they are ignored by a .dockerignore pattern
  1893  		pathToDirectoryWithoutReadAccess := filepath.Join(ctx.Dir, "directoryWeCantStat")
  1894  		pathToFileInDirectoryWithoutReadAccess := filepath.Join(pathToDirectoryWithoutReadAccess, "bar")
  1895  		if err = os.Chown(pathToDirectoryWithoutReadAccess, 0, 0); err != nil {
  1896  			t.Fatalf("failed to chown directory to root: %s", err)
  1897  		}
  1898  		if err = os.Chmod(pathToDirectoryWithoutReadAccess, 0444); err != nil {
  1899  			t.Fatalf("failed to chmod directory to 755: %s", err)
  1900  		}
  1901  		if err = os.Chmod(pathToFileInDirectoryWithoutReadAccess, 0700); err != nil {
  1902  			t.Fatalf("failed to chmod file to 444: %s", err)
  1903  		}
  1904  
  1905  		buildCmd := exec.Command("su", "unprivilegeduser", "-c", fmt.Sprintf("%s build -t %s .", dockerBinary, name))
  1906  		buildCmd.Dir = ctx.Dir
  1907  		if out, _, err := runCommandWithOutput(buildCmd); err != nil {
  1908  			t.Fatalf("build should have worked: %s %s", err, out)
  1909  		}
  1910  
  1911  	}
  1912  	logDone("build - ADD from context with inaccessible files must not pass")
  1913  	logDone("build - ADD from context with accessible links must work")
  1914  	logDone("build - ADD from context with ignored inaccessible files must work")
  1915  }
  1916  
  1917  func TestBuildForceRm(t *testing.T) {
  1918  	containerCountBefore, err := getContainerCount()
  1919  	if err != nil {
  1920  		t.Fatalf("failed to get the container count: %s", err)
  1921  	}
  1922  	name := "testbuildforcerm"
  1923  	defer deleteImages(name)
  1924  	ctx, err := fakeContext("FROM scratch\nRUN true\nRUN thiswillfail", nil)
  1925  	if err != nil {
  1926  		t.Fatal(err)
  1927  	}
  1928  	defer ctx.Close()
  1929  
  1930  	buildCmd := exec.Command(dockerBinary, "build", "-t", name, "--force-rm", ".")
  1931  	buildCmd.Dir = ctx.Dir
  1932  	if out, _, err := runCommandWithOutput(buildCmd); err == nil {
  1933  		t.Fatalf("failed to build the image: %s, %v", out, err)
  1934  	}
  1935  
  1936  	containerCountAfter, err := getContainerCount()
  1937  	if err != nil {
  1938  		t.Fatalf("failed to get the container count: %s", err)
  1939  	}
  1940  
  1941  	if containerCountBefore != containerCountAfter {
  1942  		t.Fatalf("--force-rm shouldn't have left containers behind")
  1943  	}
  1944  
  1945  	logDone("build - ensure --force-rm doesn't leave containers behind")
  1946  }
  1947  
  1948  // Test that an infinite sleep during a build is killed if the client disconnects.
  1949  // This test is fairly hairy because there are lots of ways to race.
  1950  // Strategy:
  1951  // * Monitor the output of docker events starting from before
  1952  // * Run a 1-year-long sleep from a docker build.
  1953  // * When docker events sees container start, close the "docker build" command
  1954  // * Wait for docker events to emit a dying event.
  1955  func TestBuildCancelationKillsSleep(t *testing.T) {
  1956  	// TODO(jfrazelle): Make this work on Windows.
  1957  	testRequires(t, SameHostDaemon)
  1958  
  1959  	name := "testbuildcancelation"
  1960  	defer deleteImages(name)
  1961  	defer deleteAllContainers()
  1962  
  1963  	// (Note: one year, will never finish)
  1964  	ctx, err := fakeContext("FROM busybox\nRUN sleep 31536000", nil)
  1965  	if err != nil {
  1966  		t.Fatal(err)
  1967  	}
  1968  	defer ctx.Close()
  1969  
  1970  	var wg sync.WaitGroup
  1971  	defer wg.Wait()
  1972  
  1973  	finish := make(chan struct{})
  1974  	defer close(finish)
  1975  
  1976  	eventStart := make(chan struct{})
  1977  	eventDie := make(chan struct{})
  1978  
  1979  	// Start one second ago, to avoid rounding problems
  1980  	startEpoch := time.Now().Add(-1 * time.Second)
  1981  
  1982  	// Goroutine responsible for watching start/die events from `docker events`
  1983  	wg.Add(1)
  1984  	go func() {
  1985  		defer wg.Done()
  1986  
  1987  		// Watch for events since epoch.
  1988  		eventsCmd := exec.Command(dockerBinary, "events",
  1989  			"-since", fmt.Sprint(startEpoch.Unix()))
  1990  		stdout, err := eventsCmd.StdoutPipe()
  1991  		err = eventsCmd.Start()
  1992  		if err != nil {
  1993  			t.Fatalf("failed to start 'docker events': %s", err)
  1994  		}
  1995  
  1996  		go func() {
  1997  			<-finish
  1998  			eventsCmd.Process.Kill()
  1999  		}()
  2000  
  2001  		var started, died bool
  2002  		matchStart := regexp.MustCompile(" \\(from busybox\\:latest\\) start$")
  2003  		matchDie := regexp.MustCompile(" \\(from busybox\\:latest\\) die$")
  2004  
  2005  		//
  2006  		// Read lines of `docker events` looking for container start and stop.
  2007  		//
  2008  		scanner := bufio.NewScanner(stdout)
  2009  		for scanner.Scan() {
  2010  			if ok := matchStart.MatchString(scanner.Text()); ok {
  2011  				if started {
  2012  					t.Fatal("assertion fail: more than one container started")
  2013  				}
  2014  				close(eventStart)
  2015  				started = true
  2016  			}
  2017  			if ok := matchDie.MatchString(scanner.Text()); ok {
  2018  				if died {
  2019  					t.Fatal("assertion fail: more than one container died")
  2020  				}
  2021  				close(eventDie)
  2022  				died = true
  2023  			}
  2024  		}
  2025  
  2026  		err = eventsCmd.Wait()
  2027  		if err != nil && !IsKilled(err) {
  2028  			t.Fatalf("docker events had bad exit status: %s", err)
  2029  		}
  2030  	}()
  2031  
  2032  	buildCmd := exec.Command(dockerBinary, "build", "-t", name, ".")
  2033  	buildCmd.Dir = ctx.Dir
  2034  	buildCmd.Stdout = os.Stdout
  2035  
  2036  	err = buildCmd.Start()
  2037  	if err != nil {
  2038  		t.Fatalf("failed to run build: %s", err)
  2039  	}
  2040  
  2041  	select {
  2042  	case <-time.After(30 * time.Second):
  2043  		t.Fatal("failed to observe build container start in timely fashion")
  2044  	case <-eventStart:
  2045  		// Proceeds from here when we see the container fly past in the
  2046  		// output of "docker events".
  2047  		// Now we know the container is running.
  2048  	}
  2049  
  2050  	// Send a kill to the `docker build` command.
  2051  	// Causes the underlying build to be cancelled due to socket close.
  2052  	err = buildCmd.Process.Kill()
  2053  	if err != nil {
  2054  		t.Fatalf("error killing build command: %s", err)
  2055  	}
  2056  
  2057  	// Get the exit status of `docker build`, check it exited because killed.
  2058  	err = buildCmd.Wait()
  2059  	if err != nil && !IsKilled(err) {
  2060  		t.Fatalf("wait failed during build run: %T %s", err, err)
  2061  	}
  2062  
  2063  	select {
  2064  	case <-time.After(30 * time.Second):
  2065  		// If we don't get here in a timely fashion, it wasn't killed.
  2066  		t.Fatal("container cancel did not succeed")
  2067  	case <-eventDie:
  2068  		// We saw the container shut down in the `docker events` stream,
  2069  		// as expected.
  2070  	}
  2071  
  2072  	logDone("build - ensure canceled job finishes immediately")
  2073  }
  2074  
  2075  func TestBuildRm(t *testing.T) {
  2076  	name := "testbuildrm"
  2077  	defer deleteImages(name)
  2078  	ctx, err := fakeContext("FROM scratch\nADD foo /\nADD foo /", map[string]string{"foo": "bar"})
  2079  	if err != nil {
  2080  		t.Fatal(err)
  2081  	}
  2082  	defer ctx.Close()
  2083  	{
  2084  		containerCountBefore, err := getContainerCount()
  2085  		if err != nil {
  2086  			t.Fatalf("failed to get the container count: %s", err)
  2087  		}
  2088  
  2089  		out, _, err := dockerCmdInDir(t, ctx.Dir, "build", "--rm", "-t", name, ".")
  2090  
  2091  		if err != nil {
  2092  			t.Fatal("failed to build the image", out)
  2093  		}
  2094  
  2095  		containerCountAfter, err := getContainerCount()
  2096  		if err != nil {
  2097  			t.Fatalf("failed to get the container count: %s", err)
  2098  		}
  2099  
  2100  		if containerCountBefore != containerCountAfter {
  2101  			t.Fatalf("-rm shouldn't have left containers behind")
  2102  		}
  2103  		deleteImages(name)
  2104  	}
  2105  
  2106  	{
  2107  		containerCountBefore, err := getContainerCount()
  2108  		if err != nil {
  2109  			t.Fatalf("failed to get the container count: %s", err)
  2110  		}
  2111  
  2112  		out, _, err := dockerCmdInDir(t, ctx.Dir, "build", "-t", name, ".")
  2113  
  2114  		if err != nil {
  2115  			t.Fatal("failed to build the image", out)
  2116  		}
  2117  
  2118  		containerCountAfter, err := getContainerCount()
  2119  		if err != nil {
  2120  			t.Fatalf("failed to get the container count: %s", err)
  2121  		}
  2122  
  2123  		if containerCountBefore != containerCountAfter {
  2124  			t.Fatalf("--rm shouldn't have left containers behind")
  2125  		}
  2126  		deleteImages(name)
  2127  	}
  2128  
  2129  	{
  2130  		containerCountBefore, err := getContainerCount()
  2131  		if err != nil {
  2132  			t.Fatalf("failed to get the container count: %s", err)
  2133  		}
  2134  
  2135  		out, _, err := dockerCmdInDir(t, ctx.Dir, "build", "--rm=false", "-t", name, ".")
  2136  
  2137  		if err != nil {
  2138  			t.Fatal("failed to build the image", out)
  2139  		}
  2140  
  2141  		containerCountAfter, err := getContainerCount()
  2142  		if err != nil {
  2143  			t.Fatalf("failed to get the container count: %s", err)
  2144  		}
  2145  
  2146  		if containerCountBefore == containerCountAfter {
  2147  			t.Fatalf("--rm=false should have left containers behind")
  2148  		}
  2149  		deleteAllContainers()
  2150  		deleteImages(name)
  2151  
  2152  	}
  2153  
  2154  	logDone("build - ensure --rm doesn't leave containers behind and that --rm=true is the default")
  2155  	logDone("build - ensure --rm=false overrides the default")
  2156  }
  2157  
  2158  func TestBuildWithVolumes(t *testing.T) {
  2159  	var (
  2160  		result   map[string]map[string]struct{}
  2161  		name     = "testbuildvolumes"
  2162  		emptyMap = make(map[string]struct{})
  2163  		expected = map[string]map[string]struct{}{
  2164  			"/test1":  emptyMap,
  2165  			"/test2":  emptyMap,
  2166  			"/test3":  emptyMap,
  2167  			"/test4":  emptyMap,
  2168  			"/test5":  emptyMap,
  2169  			"/test6":  emptyMap,
  2170  			"[/test7": emptyMap,
  2171  			"/test8]": emptyMap,
  2172  		}
  2173  	)
  2174  	defer deleteImages(name)
  2175  	_, err := buildImage(name,
  2176  		`FROM scratch
  2177  		VOLUME /test1
  2178  		VOLUME /test2
  2179      VOLUME /test3 /test4
  2180      VOLUME ["/test5", "/test6"]
  2181      VOLUME [/test7 /test8]
  2182      `,
  2183  		true)
  2184  	if err != nil {
  2185  		t.Fatal(err)
  2186  	}
  2187  	res, err := inspectFieldJSON(name, "Config.Volumes")
  2188  	if err != nil {
  2189  		t.Fatal(err)
  2190  	}
  2191  
  2192  	err = unmarshalJSON([]byte(res), &result)
  2193  	if err != nil {
  2194  		t.Fatal(err)
  2195  	}
  2196  
  2197  	equal := reflect.DeepEqual(&result, &expected)
  2198  
  2199  	if !equal {
  2200  		t.Fatalf("Volumes %s, expected %s", result, expected)
  2201  	}
  2202  
  2203  	logDone("build - with volumes")
  2204  }
  2205  
  2206  func TestBuildMaintainer(t *testing.T) {
  2207  	name := "testbuildmaintainer"
  2208  	expected := "dockerio"
  2209  	defer deleteImages(name)
  2210  	_, err := buildImage(name,
  2211  		`FROM scratch
  2212          MAINTAINER dockerio`,
  2213  		true)
  2214  	if err != nil {
  2215  		t.Fatal(err)
  2216  	}
  2217  	res, err := inspectField(name, "Author")
  2218  	if err != nil {
  2219  		t.Fatal(err)
  2220  	}
  2221  	if res != expected {
  2222  		t.Fatalf("Maintainer %s, expected %s", res, expected)
  2223  	}
  2224  	logDone("build - maintainer")
  2225  }
  2226  
  2227  func TestBuildUser(t *testing.T) {
  2228  	name := "testbuilduser"
  2229  	expected := "dockerio"
  2230  	defer deleteImages(name)
  2231  	_, err := buildImage(name,
  2232  		`FROM busybox
  2233  		RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  2234  		USER dockerio
  2235  		RUN [ $(whoami) = 'dockerio' ]`,
  2236  		true)
  2237  	if err != nil {
  2238  		t.Fatal(err)
  2239  	}
  2240  	res, err := inspectField(name, "Config.User")
  2241  	if err != nil {
  2242  		t.Fatal(err)
  2243  	}
  2244  	if res != expected {
  2245  		t.Fatalf("User %s, expected %s", res, expected)
  2246  	}
  2247  	logDone("build - user")
  2248  }
  2249  
  2250  func TestBuildRelativeWorkdir(t *testing.T) {
  2251  	name := "testbuildrelativeworkdir"
  2252  	expected := "/test2/test3"
  2253  	defer deleteImages(name)
  2254  	_, err := buildImage(name,
  2255  		`FROM busybox
  2256  		RUN [ "$PWD" = '/' ]
  2257  		WORKDIR test1
  2258  		RUN [ "$PWD" = '/test1' ]
  2259  		WORKDIR /test2
  2260  		RUN [ "$PWD" = '/test2' ]
  2261  		WORKDIR test3
  2262  		RUN [ "$PWD" = '/test2/test3' ]`,
  2263  		true)
  2264  	if err != nil {
  2265  		t.Fatal(err)
  2266  	}
  2267  	res, err := inspectField(name, "Config.WorkingDir")
  2268  	if err != nil {
  2269  		t.Fatal(err)
  2270  	}
  2271  	if res != expected {
  2272  		t.Fatalf("Workdir %s, expected %s", res, expected)
  2273  	}
  2274  	logDone("build - relative workdir")
  2275  }
  2276  
  2277  func TestBuildWorkdirWithEnvVariables(t *testing.T) {
  2278  	name := "testbuildworkdirwithenvvariables"
  2279  	expected := "/test1/test2"
  2280  	defer deleteImages(name)
  2281  	_, err := buildImage(name,
  2282  		`FROM busybox
  2283  		ENV DIRPATH /test1
  2284  		ENV SUBDIRNAME test2
  2285  		WORKDIR $DIRPATH
  2286  		WORKDIR $SUBDIRNAME/$MISSING_VAR`,
  2287  		true)
  2288  	if err != nil {
  2289  		t.Fatal(err)
  2290  	}
  2291  	res, err := inspectField(name, "Config.WorkingDir")
  2292  	if err != nil {
  2293  		t.Fatal(err)
  2294  	}
  2295  	if res != expected {
  2296  		t.Fatalf("Workdir %s, expected %s", res, expected)
  2297  	}
  2298  	logDone("build - workdir with env variables")
  2299  }
  2300  
  2301  func TestBuildRelativeCopy(t *testing.T) {
  2302  	name := "testbuildrelativecopy"
  2303  	defer deleteImages(name)
  2304  	dockerfile := `
  2305  		FROM busybox
  2306  			WORKDIR /test1
  2307  			WORKDIR test2
  2308  			RUN [ "$PWD" = '/test1/test2' ]
  2309  			COPY foo ./
  2310  			RUN [ "$(cat /test1/test2/foo)" = 'hello' ]
  2311  			ADD foo ./bar/baz
  2312  			RUN [ "$(cat /test1/test2/bar/baz)" = 'hello' ]
  2313  			COPY foo ./bar/baz2
  2314  			RUN [ "$(cat /test1/test2/bar/baz2)" = 'hello' ]
  2315  			WORKDIR ..
  2316  			COPY foo ./
  2317  			RUN [ "$(cat /test1/foo)" = 'hello' ]
  2318  			COPY foo /test3/
  2319  			RUN [ "$(cat /test3/foo)" = 'hello' ]
  2320  			WORKDIR /test4
  2321  			COPY . .
  2322  			RUN [ "$(cat /test4/foo)" = 'hello' ]
  2323  			WORKDIR /test5/test6
  2324  			COPY foo ../
  2325  			RUN [ "$(cat /test5/foo)" = 'hello' ]
  2326  			`
  2327  	ctx, err := fakeContext(dockerfile, map[string]string{
  2328  		"foo": "hello",
  2329  	})
  2330  	defer ctx.Close()
  2331  	if err != nil {
  2332  		t.Fatal(err)
  2333  	}
  2334  	_, err = buildImageFromContext(name, ctx, false)
  2335  	if err != nil {
  2336  		t.Fatal(err)
  2337  	}
  2338  	logDone("build - relative copy/add")
  2339  }
  2340  
  2341  func TestBuildEnv(t *testing.T) {
  2342  	name := "testbuildenv"
  2343  	expected := "[PATH=/test:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin PORT=2375]"
  2344  	defer deleteImages(name)
  2345  	_, err := buildImage(name,
  2346  		`FROM busybox
  2347  		ENV PATH /test:$PATH
  2348          ENV PORT 2375
  2349  		RUN [ $(env | grep PORT) = 'PORT=2375' ]`,
  2350  		true)
  2351  	if err != nil {
  2352  		t.Fatal(err)
  2353  	}
  2354  	res, err := inspectField(name, "Config.Env")
  2355  	if err != nil {
  2356  		t.Fatal(err)
  2357  	}
  2358  	if res != expected {
  2359  		t.Fatalf("Env %s, expected %s", res, expected)
  2360  	}
  2361  	logDone("build - env")
  2362  }
  2363  
  2364  func TestBuildContextCleanup(t *testing.T) {
  2365  	testRequires(t, SameHostDaemon)
  2366  
  2367  	name := "testbuildcontextcleanup"
  2368  	defer deleteImages(name)
  2369  	entries, err := ioutil.ReadDir("/var/lib/docker/tmp")
  2370  	if err != nil {
  2371  		t.Fatalf("failed to list contents of tmp dir: %s", err)
  2372  	}
  2373  	_, err = buildImage(name,
  2374  		`FROM scratch
  2375          ENTRYPOINT ["/bin/echo"]`,
  2376  		true)
  2377  	if err != nil {
  2378  		t.Fatal(err)
  2379  	}
  2380  	entriesFinal, err := ioutil.ReadDir("/var/lib/docker/tmp")
  2381  	if err != nil {
  2382  		t.Fatalf("failed to list contents of tmp dir: %s", err)
  2383  	}
  2384  	if err = compareDirectoryEntries(entries, entriesFinal); err != nil {
  2385  		t.Fatalf("context should have been deleted, but wasn't")
  2386  	}
  2387  
  2388  	logDone("build - verify context cleanup works properly")
  2389  }
  2390  
  2391  func TestBuildContextCleanupFailedBuild(t *testing.T) {
  2392  	testRequires(t, SameHostDaemon)
  2393  
  2394  	name := "testbuildcontextcleanup"
  2395  	defer deleteImages(name)
  2396  	defer deleteAllContainers()
  2397  	entries, err := ioutil.ReadDir("/var/lib/docker/tmp")
  2398  	if err != nil {
  2399  		t.Fatalf("failed to list contents of tmp dir: %s", err)
  2400  	}
  2401  	_, err = buildImage(name,
  2402  		`FROM scratch
  2403  	RUN /non/existing/command`,
  2404  		true)
  2405  	if err == nil {
  2406  		t.Fatalf("expected build to fail, but it didn't")
  2407  	}
  2408  	entriesFinal, err := ioutil.ReadDir("/var/lib/docker/tmp")
  2409  	if err != nil {
  2410  		t.Fatalf("failed to list contents of tmp dir: %s", err)
  2411  	}
  2412  	if err = compareDirectoryEntries(entries, entriesFinal); err != nil {
  2413  		t.Fatalf("context should have been deleted, but wasn't")
  2414  	}
  2415  
  2416  	logDone("build - verify context cleanup works properly after an unsuccessful build")
  2417  }
  2418  
  2419  func TestBuildCmd(t *testing.T) {
  2420  	name := "testbuildcmd"
  2421  	expected := "[/bin/echo Hello World]"
  2422  	defer deleteImages(name)
  2423  	_, err := buildImage(name,
  2424  		`FROM scratch
  2425          CMD ["/bin/echo", "Hello World"]`,
  2426  		true)
  2427  	if err != nil {
  2428  		t.Fatal(err)
  2429  	}
  2430  	res, err := inspectField(name, "Config.Cmd")
  2431  	if err != nil {
  2432  		t.Fatal(err)
  2433  	}
  2434  	if res != expected {
  2435  		t.Fatalf("Cmd %s, expected %s", res, expected)
  2436  	}
  2437  	logDone("build - cmd")
  2438  }
  2439  
  2440  func TestBuildExpose(t *testing.T) {
  2441  	name := "testbuildexpose"
  2442  	expected := "map[2375/tcp:map[]]"
  2443  	defer deleteImages(name)
  2444  	_, err := buildImage(name,
  2445  		`FROM scratch
  2446          EXPOSE 2375`,
  2447  		true)
  2448  	if err != nil {
  2449  		t.Fatal(err)
  2450  	}
  2451  	res, err := inspectField(name, "Config.ExposedPorts")
  2452  	if err != nil {
  2453  		t.Fatal(err)
  2454  	}
  2455  	if res != expected {
  2456  		t.Fatalf("Exposed ports %s, expected %s", res, expected)
  2457  	}
  2458  	logDone("build - expose")
  2459  }
  2460  
  2461  func TestBuildExposeMorePorts(t *testing.T) {
  2462  	// start building docker file with a large number of ports
  2463  	portList := make([]string, 50)
  2464  	line := make([]string, 100)
  2465  	expectedPorts := make([]int, len(portList)*len(line))
  2466  	for i := 0; i < len(portList); i++ {
  2467  		for j := 0; j < len(line); j++ {
  2468  			p := i*len(line) + j + 1
  2469  			line[j] = strconv.Itoa(p)
  2470  			expectedPorts[p-1] = p
  2471  		}
  2472  		if i == len(portList)-1 {
  2473  			portList[i] = strings.Join(line, " ")
  2474  		} else {
  2475  			portList[i] = strings.Join(line, " ") + ` \`
  2476  		}
  2477  	}
  2478  
  2479  	dockerfile := `FROM scratch
  2480  	EXPOSE {{range .}} {{.}}
  2481  	{{end}}`
  2482  	tmpl := template.Must(template.New("dockerfile").Parse(dockerfile))
  2483  	buf := bytes.NewBuffer(nil)
  2484  	tmpl.Execute(buf, portList)
  2485  
  2486  	name := "testbuildexpose"
  2487  	defer deleteImages(name)
  2488  	_, err := buildImage(name, buf.String(), true)
  2489  	if err != nil {
  2490  		t.Fatal(err)
  2491  	}
  2492  
  2493  	// check if all the ports are saved inside Config.ExposedPorts
  2494  	res, err := inspectFieldJSON(name, "Config.ExposedPorts")
  2495  	if err != nil {
  2496  		t.Fatal(err)
  2497  	}
  2498  	var exposedPorts map[string]interface{}
  2499  	if err := json.Unmarshal([]byte(res), &exposedPorts); err != nil {
  2500  		t.Fatal(err)
  2501  	}
  2502  
  2503  	for _, p := range expectedPorts {
  2504  		ep := fmt.Sprintf("%d/tcp", p)
  2505  		if _, ok := exposedPorts[ep]; !ok {
  2506  			t.Errorf("Port(%s) is not exposed", ep)
  2507  		} else {
  2508  			delete(exposedPorts, ep)
  2509  		}
  2510  	}
  2511  	if len(exposedPorts) != 0 {
  2512  		t.Errorf("Unexpected extra exposed ports %v", exposedPorts)
  2513  	}
  2514  	logDone("build - expose large number of ports")
  2515  }
  2516  
  2517  func TestBuildExposeOrder(t *testing.T) {
  2518  	buildID := func(name, exposed string) string {
  2519  		_, err := buildImage(name, fmt.Sprintf(`FROM scratch
  2520  		EXPOSE %s`, exposed), true)
  2521  		if err != nil {
  2522  			t.Fatal(err)
  2523  		}
  2524  		id, err := inspectField(name, "Id")
  2525  		if err != nil {
  2526  			t.Fatal(err)
  2527  		}
  2528  		return id
  2529  	}
  2530  
  2531  	id1 := buildID("testbuildexpose1", "80 2375")
  2532  	id2 := buildID("testbuildexpose2", "2375 80")
  2533  	defer deleteImages("testbuildexpose1", "testbuildexpose2")
  2534  	if id1 != id2 {
  2535  		t.Errorf("EXPOSE should invalidate the cache only when ports actually changed")
  2536  	}
  2537  	logDone("build - expose order")
  2538  }
  2539  
  2540  func TestBuildExposeUpperCaseProto(t *testing.T) {
  2541  	name := "testbuildexposeuppercaseproto"
  2542  	expected := "map[5678/udp:map[]]"
  2543  	defer deleteImages(name)
  2544  	_, err := buildImage(name,
  2545  		`FROM scratch
  2546          EXPOSE 5678/UDP`,
  2547  		true)
  2548  	if err != nil {
  2549  		t.Fatal(err)
  2550  	}
  2551  	res, err := inspectField(name, "Config.ExposedPorts")
  2552  	if err != nil {
  2553  		t.Fatal(err)
  2554  	}
  2555  	if res != expected {
  2556  		t.Fatalf("Exposed ports %s, expected %s", res, expected)
  2557  	}
  2558  	logDone("build - expose port with upper case proto")
  2559  }
  2560  
  2561  func TestBuildExposeHostPort(t *testing.T) {
  2562  	// start building docker file with ip:hostPort:containerPort
  2563  	name := "testbuildexpose"
  2564  	expected := "map[5678/tcp:map[]]"
  2565  	defer deleteImages(name)
  2566  	_, out, err := buildImageWithOut(name,
  2567  		`FROM scratch
  2568          EXPOSE 192.168.1.2:2375:5678`,
  2569  		true)
  2570  	if err != nil {
  2571  		t.Fatal(err)
  2572  	}
  2573  
  2574  	if !strings.Contains(out, "to map host ports to container ports (ip:hostPort:containerPort) is deprecated.") {
  2575  		t.Fatal("Missing warning message")
  2576  	}
  2577  
  2578  	res, err := inspectField(name, "Config.ExposedPorts")
  2579  	if err != nil {
  2580  		t.Fatal(err)
  2581  	}
  2582  	if res != expected {
  2583  		t.Fatalf("Exposed ports %s, expected %s", res, expected)
  2584  	}
  2585  	logDone("build - ignore exposing host's port")
  2586  }
  2587  
  2588  func TestBuildEmptyEntrypointInheritance(t *testing.T) {
  2589  	name := "testbuildentrypointinheritance"
  2590  	name2 := "testbuildentrypointinheritance2"
  2591  	defer deleteImages(name, name2)
  2592  
  2593  	_, err := buildImage(name,
  2594  		`FROM busybox
  2595          ENTRYPOINT ["/bin/echo"]`,
  2596  		true)
  2597  	if err != nil {
  2598  		t.Fatal(err)
  2599  	}
  2600  	res, err := inspectField(name, "Config.Entrypoint")
  2601  	if err != nil {
  2602  		t.Fatal(err)
  2603  	}
  2604  
  2605  	expected := "[/bin/echo]"
  2606  	if res != expected {
  2607  		t.Fatalf("Entrypoint %s, expected %s", res, expected)
  2608  	}
  2609  
  2610  	_, err = buildImage(name2,
  2611  		fmt.Sprintf(`FROM %s
  2612          ENTRYPOINT []`, name),
  2613  		true)
  2614  	if err != nil {
  2615  		t.Fatal(err)
  2616  	}
  2617  	res, err = inspectField(name2, "Config.Entrypoint")
  2618  	if err != nil {
  2619  		t.Fatal(err)
  2620  	}
  2621  
  2622  	expected = "[]"
  2623  
  2624  	if res != expected {
  2625  		t.Fatalf("Entrypoint %s, expected %s", res, expected)
  2626  	}
  2627  
  2628  	logDone("build - empty entrypoint inheritance")
  2629  }
  2630  
  2631  func TestBuildEmptyEntrypoint(t *testing.T) {
  2632  	name := "testbuildentrypoint"
  2633  	defer deleteImages(name)
  2634  	expected := "[]"
  2635  
  2636  	_, err := buildImage(name,
  2637  		`FROM busybox
  2638          ENTRYPOINT []`,
  2639  		true)
  2640  	if err != nil {
  2641  		t.Fatal(err)
  2642  	}
  2643  	res, err := inspectField(name, "Config.Entrypoint")
  2644  	if err != nil {
  2645  		t.Fatal(err)
  2646  	}
  2647  	if res != expected {
  2648  		t.Fatalf("Entrypoint %s, expected %s", res, expected)
  2649  	}
  2650  
  2651  	logDone("build - empty entrypoint")
  2652  }
  2653  
  2654  func TestBuildEntrypoint(t *testing.T) {
  2655  	name := "testbuildentrypoint"
  2656  	expected := "[/bin/echo]"
  2657  	defer deleteImages(name)
  2658  	_, err := buildImage(name,
  2659  		`FROM scratch
  2660          ENTRYPOINT ["/bin/echo"]`,
  2661  		true)
  2662  	if err != nil {
  2663  		t.Fatal(err)
  2664  	}
  2665  	res, err := inspectField(name, "Config.Entrypoint")
  2666  	if err != nil {
  2667  		t.Fatal(err)
  2668  	}
  2669  	if res != expected {
  2670  		t.Fatalf("Entrypoint %s, expected %s", res, expected)
  2671  	}
  2672  
  2673  	logDone("build - entrypoint")
  2674  }
  2675  
  2676  // #6445 ensure ONBUILD triggers aren't committed to grandchildren
  2677  func TestBuildOnBuildLimitedInheritence(t *testing.T) {
  2678  	var (
  2679  		out2, out3 string
  2680  	)
  2681  	{
  2682  		name1 := "testonbuildtrigger1"
  2683  		dockerfile1 := `
  2684  		FROM busybox
  2685  		RUN echo "GRANDPARENT"
  2686  		ONBUILD RUN echo "ONBUILD PARENT"
  2687  		`
  2688  		ctx, err := fakeContext(dockerfile1, nil)
  2689  		if err != nil {
  2690  			t.Fatal(err)
  2691  		}
  2692  		defer ctx.Close()
  2693  
  2694  		out1, _, err := dockerCmdInDir(t, ctx.Dir, "build", "-t", name1, ".")
  2695  		if err != nil {
  2696  			t.Fatalf("build failed to complete: %s, %v", out1, err)
  2697  		}
  2698  		defer deleteImages(name1)
  2699  	}
  2700  	{
  2701  		name2 := "testonbuildtrigger2"
  2702  		dockerfile2 := `
  2703  		FROM testonbuildtrigger1
  2704  		`
  2705  		ctx, err := fakeContext(dockerfile2, nil)
  2706  		if err != nil {
  2707  			t.Fatal(err)
  2708  		}
  2709  		defer ctx.Close()
  2710  
  2711  		out2, _, err = dockerCmdInDir(t, ctx.Dir, "build", "-t", name2, ".")
  2712  		if err != nil {
  2713  			t.Fatalf("build failed to complete: %s, %v", out2, err)
  2714  		}
  2715  		defer deleteImages(name2)
  2716  	}
  2717  	{
  2718  		name3 := "testonbuildtrigger3"
  2719  		dockerfile3 := `
  2720  		FROM testonbuildtrigger2
  2721  		`
  2722  		ctx, err := fakeContext(dockerfile3, nil)
  2723  		if err != nil {
  2724  			t.Fatal(err)
  2725  		}
  2726  		defer ctx.Close()
  2727  
  2728  		out3, _, err = dockerCmdInDir(t, ctx.Dir, "build", "-t", name3, ".")
  2729  		if err != nil {
  2730  			t.Fatalf("build failed to complete: %s, %v", out3, err)
  2731  		}
  2732  
  2733  		defer deleteImages(name3)
  2734  	}
  2735  
  2736  	// ONBUILD should be run in second build.
  2737  	if !strings.Contains(out2, "ONBUILD PARENT") {
  2738  		t.Fatalf("ONBUILD instruction did not run in child of ONBUILD parent")
  2739  	}
  2740  
  2741  	// ONBUILD should *not* be run in third build.
  2742  	if strings.Contains(out3, "ONBUILD PARENT") {
  2743  		t.Fatalf("ONBUILD instruction ran in grandchild of ONBUILD parent")
  2744  	}
  2745  
  2746  	logDone("build - onbuild")
  2747  }
  2748  
  2749  func TestBuildWithCache(t *testing.T) {
  2750  	name := "testbuildwithcache"
  2751  	defer deleteImages(name)
  2752  	id1, err := buildImage(name,
  2753  		`FROM scratch
  2754  		MAINTAINER dockerio
  2755  		EXPOSE 5432
  2756          ENTRYPOINT ["/bin/echo"]`,
  2757  		true)
  2758  	if err != nil {
  2759  		t.Fatal(err)
  2760  	}
  2761  	id2, err := buildImage(name,
  2762  		`FROM scratch
  2763  		MAINTAINER dockerio
  2764  		EXPOSE 5432
  2765          ENTRYPOINT ["/bin/echo"]`,
  2766  		true)
  2767  	if err != nil {
  2768  		t.Fatal(err)
  2769  	}
  2770  	if id1 != id2 {
  2771  		t.Fatal("The cache should have been used but hasn't.")
  2772  	}
  2773  	logDone("build - with cache")
  2774  }
  2775  
  2776  func TestBuildWithoutCache(t *testing.T) {
  2777  	name := "testbuildwithoutcache"
  2778  	name2 := "testbuildwithoutcache2"
  2779  	defer deleteImages(name, name2)
  2780  	id1, err := buildImage(name,
  2781  		`FROM scratch
  2782  		MAINTAINER dockerio
  2783  		EXPOSE 5432
  2784          ENTRYPOINT ["/bin/echo"]`,
  2785  		true)
  2786  	if err != nil {
  2787  		t.Fatal(err)
  2788  	}
  2789  
  2790  	id2, err := buildImage(name2,
  2791  		`FROM scratch
  2792  		MAINTAINER dockerio
  2793  		EXPOSE 5432
  2794          ENTRYPOINT ["/bin/echo"]`,
  2795  		false)
  2796  	if err != nil {
  2797  		t.Fatal(err)
  2798  	}
  2799  	if id1 == id2 {
  2800  		t.Fatal("The cache should have been invalided but hasn't.")
  2801  	}
  2802  	logDone("build - without cache")
  2803  }
  2804  
  2805  func TestBuildConditionalCache(t *testing.T) {
  2806  	name := "testbuildconditionalcache"
  2807  	name2 := "testbuildconditionalcache2"
  2808  	defer deleteImages(name, name2)
  2809  
  2810  	dockerfile := `
  2811  		FROM busybox
  2812          ADD foo /tmp/`
  2813  	ctx, err := fakeContext(dockerfile, map[string]string{
  2814  		"foo": "hello",
  2815  	})
  2816  	if err != nil {
  2817  		t.Fatal(err)
  2818  	}
  2819  	defer ctx.Close()
  2820  
  2821  	id1, err := buildImageFromContext(name, ctx, true)
  2822  	if err != nil {
  2823  		t.Fatalf("Error building #1: %s", err)
  2824  	}
  2825  
  2826  	if err := ctx.Add("foo", "bye"); err != nil {
  2827  		t.Fatalf("Error modifying foo: %s", err)
  2828  	}
  2829  
  2830  	id2, err := buildImageFromContext(name, ctx, false)
  2831  	if err != nil {
  2832  		t.Fatalf("Error building #2: %s", err)
  2833  	}
  2834  	if id2 == id1 {
  2835  		t.Fatal("Should not have used the cache")
  2836  	}
  2837  
  2838  	id3, err := buildImageFromContext(name, ctx, true)
  2839  	if err != nil {
  2840  		t.Fatalf("Error building #3: %s", err)
  2841  	}
  2842  	if id3 != id2 {
  2843  		t.Fatal("Should have used the cache")
  2844  	}
  2845  
  2846  	logDone("build - conditional cache")
  2847  }
  2848  
  2849  func TestBuildADDLocalFileWithCache(t *testing.T) {
  2850  	name := "testbuildaddlocalfilewithcache"
  2851  	name2 := "testbuildaddlocalfilewithcache2"
  2852  	defer deleteImages(name, name2)
  2853  	dockerfile := `
  2854  		FROM busybox
  2855          MAINTAINER dockerio
  2856          ADD foo /usr/lib/bla/bar
  2857  		RUN [ "$(cat /usr/lib/bla/bar)" = "hello" ]`
  2858  	ctx, err := fakeContext(dockerfile, map[string]string{
  2859  		"foo": "hello",
  2860  	})
  2861  	defer ctx.Close()
  2862  	if err != nil {
  2863  		t.Fatal(err)
  2864  	}
  2865  	id1, err := buildImageFromContext(name, ctx, true)
  2866  	if err != nil {
  2867  		t.Fatal(err)
  2868  	}
  2869  	id2, err := buildImageFromContext(name2, ctx, true)
  2870  	if err != nil {
  2871  		t.Fatal(err)
  2872  	}
  2873  	if id1 != id2 {
  2874  		t.Fatal("The cache should have been used but hasn't.")
  2875  	}
  2876  	logDone("build - add local file with cache")
  2877  }
  2878  
  2879  func TestBuildADDMultipleLocalFileWithCache(t *testing.T) {
  2880  	name := "testbuildaddmultiplelocalfilewithcache"
  2881  	name2 := "testbuildaddmultiplelocalfilewithcache2"
  2882  	defer deleteImages(name, name2)
  2883  	dockerfile := `
  2884  		FROM busybox
  2885          MAINTAINER dockerio
  2886          ADD foo Dockerfile /usr/lib/bla/
  2887  		RUN [ "$(cat /usr/lib/bla/foo)" = "hello" ]`
  2888  	ctx, err := fakeContext(dockerfile, map[string]string{
  2889  		"foo": "hello",
  2890  	})
  2891  	defer ctx.Close()
  2892  	if err != nil {
  2893  		t.Fatal(err)
  2894  	}
  2895  	id1, err := buildImageFromContext(name, ctx, true)
  2896  	if err != nil {
  2897  		t.Fatal(err)
  2898  	}
  2899  	id2, err := buildImageFromContext(name2, ctx, true)
  2900  	if err != nil {
  2901  		t.Fatal(err)
  2902  	}
  2903  	if id1 != id2 {
  2904  		t.Fatal("The cache should have been used but hasn't.")
  2905  	}
  2906  	logDone("build - add multiple local files with cache")
  2907  }
  2908  
  2909  func TestBuildADDLocalFileWithoutCache(t *testing.T) {
  2910  	name := "testbuildaddlocalfilewithoutcache"
  2911  	name2 := "testbuildaddlocalfilewithoutcache2"
  2912  	defer deleteImages(name, name2)
  2913  	dockerfile := `
  2914  		FROM busybox
  2915          MAINTAINER dockerio
  2916          ADD foo /usr/lib/bla/bar
  2917  		RUN [ "$(cat /usr/lib/bla/bar)" = "hello" ]`
  2918  	ctx, err := fakeContext(dockerfile, map[string]string{
  2919  		"foo": "hello",
  2920  	})
  2921  	defer ctx.Close()
  2922  	if err != nil {
  2923  		t.Fatal(err)
  2924  	}
  2925  	id1, err := buildImageFromContext(name, ctx, true)
  2926  	if err != nil {
  2927  		t.Fatal(err)
  2928  	}
  2929  	id2, err := buildImageFromContext(name2, ctx, false)
  2930  	if err != nil {
  2931  		t.Fatal(err)
  2932  	}
  2933  	if id1 == id2 {
  2934  		t.Fatal("The cache should have been invalided but hasn't.")
  2935  	}
  2936  	logDone("build - add local file without cache")
  2937  }
  2938  
  2939  func TestBuildCopyDirButNotFile(t *testing.T) {
  2940  	name := "testbuildcopydirbutnotfile"
  2941  	name2 := "testbuildcopydirbutnotfile2"
  2942  	defer deleteImages(name, name2)
  2943  	dockerfile := `
  2944          FROM scratch
  2945          COPY dir /tmp/`
  2946  	ctx, err := fakeContext(dockerfile, map[string]string{
  2947  		"dir/foo": "hello",
  2948  	})
  2949  	defer ctx.Close()
  2950  	if err != nil {
  2951  		t.Fatal(err)
  2952  	}
  2953  	id1, err := buildImageFromContext(name, ctx, true)
  2954  	if err != nil {
  2955  		t.Fatal(err)
  2956  	}
  2957  	// Check that adding file with similar name doesn't mess with cache
  2958  	if err := ctx.Add("dir_file", "hello2"); err != nil {
  2959  		t.Fatal(err)
  2960  	}
  2961  	id2, err := buildImageFromContext(name2, ctx, true)
  2962  	if err != nil {
  2963  		t.Fatal(err)
  2964  	}
  2965  	if id1 != id2 {
  2966  		t.Fatal("The cache should have been used but wasn't")
  2967  	}
  2968  	logDone("build - add current directory but not file")
  2969  }
  2970  
  2971  func TestBuildADDCurrentDirWithCache(t *testing.T) {
  2972  	name := "testbuildaddcurrentdirwithcache"
  2973  	name2 := name + "2"
  2974  	name3 := name + "3"
  2975  	name4 := name + "4"
  2976  	name5 := name + "5"
  2977  	defer deleteImages(name, name2, name3, name4, name5)
  2978  	dockerfile := `
  2979          FROM scratch
  2980          MAINTAINER dockerio
  2981          ADD . /usr/lib/bla`
  2982  	ctx, err := fakeContext(dockerfile, map[string]string{
  2983  		"foo": "hello",
  2984  	})
  2985  	defer ctx.Close()
  2986  	if err != nil {
  2987  		t.Fatal(err)
  2988  	}
  2989  	id1, err := buildImageFromContext(name, ctx, true)
  2990  	if err != nil {
  2991  		t.Fatal(err)
  2992  	}
  2993  	// Check that adding file invalidate cache of "ADD ."
  2994  	if err := ctx.Add("bar", "hello2"); err != nil {
  2995  		t.Fatal(err)
  2996  	}
  2997  	id2, err := buildImageFromContext(name2, ctx, true)
  2998  	if err != nil {
  2999  		t.Fatal(err)
  3000  	}
  3001  	if id1 == id2 {
  3002  		t.Fatal("The cache should have been invalided but hasn't.")
  3003  	}
  3004  	// Check that changing file invalidate cache of "ADD ."
  3005  	if err := ctx.Add("foo", "hello1"); err != nil {
  3006  		t.Fatal(err)
  3007  	}
  3008  	id3, err := buildImageFromContext(name3, ctx, true)
  3009  	if err != nil {
  3010  		t.Fatal(err)
  3011  	}
  3012  	if id2 == id3 {
  3013  		t.Fatal("The cache should have been invalided but hasn't.")
  3014  	}
  3015  	// Check that changing file to same content invalidate cache of "ADD ."
  3016  	time.Sleep(1 * time.Second) // wait second because of mtime precision
  3017  	if err := ctx.Add("foo", "hello1"); err != nil {
  3018  		t.Fatal(err)
  3019  	}
  3020  	id4, err := buildImageFromContext(name4, ctx, true)
  3021  	if err != nil {
  3022  		t.Fatal(err)
  3023  	}
  3024  	if id3 == id4 {
  3025  		t.Fatal("The cache should have been invalided but hasn't.")
  3026  	}
  3027  	id5, err := buildImageFromContext(name5, ctx, true)
  3028  	if err != nil {
  3029  		t.Fatal(err)
  3030  	}
  3031  	if id4 != id5 {
  3032  		t.Fatal("The cache should have been used but hasn't.")
  3033  	}
  3034  	logDone("build - add current directory with cache")
  3035  }
  3036  
  3037  func TestBuildADDCurrentDirWithoutCache(t *testing.T) {
  3038  	name := "testbuildaddcurrentdirwithoutcache"
  3039  	name2 := "testbuildaddcurrentdirwithoutcache2"
  3040  	defer deleteImages(name, name2)
  3041  	dockerfile := `
  3042          FROM scratch
  3043          MAINTAINER dockerio
  3044          ADD . /usr/lib/bla`
  3045  	ctx, err := fakeContext(dockerfile, map[string]string{
  3046  		"foo": "hello",
  3047  	})
  3048  	defer ctx.Close()
  3049  	if err != nil {
  3050  		t.Fatal(err)
  3051  	}
  3052  	id1, err := buildImageFromContext(name, ctx, true)
  3053  	if err != nil {
  3054  		t.Fatal(err)
  3055  	}
  3056  	id2, err := buildImageFromContext(name2, ctx, false)
  3057  	if err != nil {
  3058  		t.Fatal(err)
  3059  	}
  3060  	if id1 == id2 {
  3061  		t.Fatal("The cache should have been invalided but hasn't.")
  3062  	}
  3063  	logDone("build - add current directory without cache")
  3064  }
  3065  
  3066  func TestBuildADDRemoteFileWithCache(t *testing.T) {
  3067  	name := "testbuildaddremotefilewithcache"
  3068  	defer deleteImages(name)
  3069  	server, err := fakeStorage(map[string]string{
  3070  		"baz": "hello",
  3071  	})
  3072  	if err != nil {
  3073  		t.Fatal(err)
  3074  	}
  3075  	defer server.Close()
  3076  
  3077  	id1, err := buildImage(name,
  3078  		fmt.Sprintf(`FROM scratch
  3079          MAINTAINER dockerio
  3080          ADD %s/baz /usr/lib/baz/quux`, server.URL()),
  3081  		true)
  3082  	if err != nil {
  3083  		t.Fatal(err)
  3084  	}
  3085  	id2, err := buildImage(name,
  3086  		fmt.Sprintf(`FROM scratch
  3087          MAINTAINER dockerio
  3088          ADD %s/baz /usr/lib/baz/quux`, server.URL()),
  3089  		true)
  3090  	if err != nil {
  3091  		t.Fatal(err)
  3092  	}
  3093  	if id1 != id2 {
  3094  		t.Fatal("The cache should have been used but hasn't.")
  3095  	}
  3096  	logDone("build - add remote file with cache")
  3097  }
  3098  
  3099  func TestBuildADDRemoteFileWithoutCache(t *testing.T) {
  3100  	name := "testbuildaddremotefilewithoutcache"
  3101  	name2 := "testbuildaddremotefilewithoutcache2"
  3102  	defer deleteImages(name, name2)
  3103  	server, err := fakeStorage(map[string]string{
  3104  		"baz": "hello",
  3105  	})
  3106  	if err != nil {
  3107  		t.Fatal(err)
  3108  	}
  3109  	defer server.Close()
  3110  
  3111  	id1, err := buildImage(name,
  3112  		fmt.Sprintf(`FROM scratch
  3113          MAINTAINER dockerio
  3114          ADD %s/baz /usr/lib/baz/quux`, server.URL()),
  3115  		true)
  3116  	if err != nil {
  3117  		t.Fatal(err)
  3118  	}
  3119  	id2, err := buildImage(name2,
  3120  		fmt.Sprintf(`FROM scratch
  3121          MAINTAINER dockerio
  3122          ADD %s/baz /usr/lib/baz/quux`, server.URL()),
  3123  		false)
  3124  	if err != nil {
  3125  		t.Fatal(err)
  3126  	}
  3127  	if id1 == id2 {
  3128  		t.Fatal("The cache should have been invalided but hasn't.")
  3129  	}
  3130  	logDone("build - add remote file without cache")
  3131  }
  3132  
  3133  func TestBuildADDRemoteFileMTime(t *testing.T) {
  3134  	name := "testbuildaddremotefilemtime"
  3135  	name2 := name + "2"
  3136  	name3 := name + "3"
  3137  	name4 := name + "4"
  3138  
  3139  	defer deleteImages(name, name2, name3, name4)
  3140  
  3141  	files := map[string]string{"baz": "hello"}
  3142  	server, err := fakeStorage(files)
  3143  	if err != nil {
  3144  		t.Fatal(err)
  3145  	}
  3146  	defer server.Close()
  3147  
  3148  	ctx, err := fakeContext(fmt.Sprintf(`FROM scratch
  3149          MAINTAINER dockerio
  3150          ADD %s/baz /usr/lib/baz/quux`, server.URL()), nil)
  3151  	if err != nil {
  3152  		t.Fatal(err)
  3153  	}
  3154  	defer ctx.Close()
  3155  
  3156  	id1, err := buildImageFromContext(name, ctx, true)
  3157  	if err != nil {
  3158  		t.Fatal(err)
  3159  	}
  3160  
  3161  	id2, err := buildImageFromContext(name2, ctx, true)
  3162  	if err != nil {
  3163  		t.Fatal(err)
  3164  	}
  3165  	if id1 != id2 {
  3166  		t.Fatal("The cache should have been used but wasn't - #1")
  3167  	}
  3168  
  3169  	// Now create a different server withsame contents (causes different mtim)
  3170  	// This time the cache should not be used
  3171  
  3172  	// allow some time for clock to pass as mtime precision is only 1s
  3173  	time.Sleep(2 * time.Second)
  3174  
  3175  	server2, err := fakeStorage(files)
  3176  	if err != nil {
  3177  		t.Fatal(err)
  3178  	}
  3179  	defer server2.Close()
  3180  
  3181  	ctx2, err := fakeContext(fmt.Sprintf(`FROM scratch
  3182          MAINTAINER dockerio
  3183          ADD %s/baz /usr/lib/baz/quux`, server2.URL()), nil)
  3184  	if err != nil {
  3185  		t.Fatal(err)
  3186  	}
  3187  	defer ctx2.Close()
  3188  	id3, err := buildImageFromContext(name3, ctx2, true)
  3189  	if err != nil {
  3190  		t.Fatal(err)
  3191  	}
  3192  	if id1 == id3 {
  3193  		t.Fatal("The cache should not have been used but was")
  3194  	}
  3195  
  3196  	// And for good measure do it again and make sure cache is used this time
  3197  	id4, err := buildImageFromContext(name4, ctx2, true)
  3198  	if err != nil {
  3199  		t.Fatal(err)
  3200  	}
  3201  	if id3 != id4 {
  3202  		t.Fatal("The cache should have been used but wasn't - #2")
  3203  	}
  3204  	logDone("build - add remote file testing mtime")
  3205  }
  3206  
  3207  func TestBuildADDLocalAndRemoteFilesWithCache(t *testing.T) {
  3208  	name := "testbuildaddlocalandremotefilewithcache"
  3209  	defer deleteImages(name)
  3210  	server, err := fakeStorage(map[string]string{
  3211  		"baz": "hello",
  3212  	})
  3213  	if err != nil {
  3214  		t.Fatal(err)
  3215  	}
  3216  	defer server.Close()
  3217  
  3218  	ctx, err := fakeContext(fmt.Sprintf(`FROM scratch
  3219          MAINTAINER dockerio
  3220          ADD foo /usr/lib/bla/bar
  3221          ADD %s/baz /usr/lib/baz/quux`, server.URL()),
  3222  		map[string]string{
  3223  			"foo": "hello world",
  3224  		})
  3225  	if err != nil {
  3226  		t.Fatal(err)
  3227  	}
  3228  	defer ctx.Close()
  3229  	id1, err := buildImageFromContext(name, ctx, true)
  3230  	if err != nil {
  3231  		t.Fatal(err)
  3232  	}
  3233  	id2, err := buildImageFromContext(name, ctx, true)
  3234  	if err != nil {
  3235  		t.Fatal(err)
  3236  	}
  3237  	if id1 != id2 {
  3238  		t.Fatal("The cache should have been used but hasn't.")
  3239  	}
  3240  	logDone("build - add local and remote file with cache")
  3241  }
  3242  
  3243  func testContextTar(t *testing.T, compression archive.Compression) {
  3244  	ctx, err := fakeContext(
  3245  		`FROM busybox
  3246  ADD foo /foo
  3247  CMD ["cat", "/foo"]`,
  3248  		map[string]string{
  3249  			"foo": "bar",
  3250  		},
  3251  	)
  3252  	defer ctx.Close()
  3253  	if err != nil {
  3254  		t.Fatal(err)
  3255  	}
  3256  	context, err := archive.Tar(ctx.Dir, compression)
  3257  	if err != nil {
  3258  		t.Fatalf("failed to build context tar: %v", err)
  3259  	}
  3260  	name := "contexttar"
  3261  	buildCmd := exec.Command(dockerBinary, "build", "-t", name, "-")
  3262  	defer deleteImages(name)
  3263  	buildCmd.Stdin = context
  3264  
  3265  	if out, _, err := runCommandWithOutput(buildCmd); err != nil {
  3266  		t.Fatalf("build failed to complete: %v %v", out, err)
  3267  	}
  3268  	logDone(fmt.Sprintf("build - build an image with a context tar, compression: %v", compression))
  3269  }
  3270  
  3271  func TestBuildContextTarGzip(t *testing.T) {
  3272  	testContextTar(t, archive.Gzip)
  3273  }
  3274  
  3275  func TestBuildContextTarNoCompression(t *testing.T) {
  3276  	testContextTar(t, archive.Uncompressed)
  3277  }
  3278  
  3279  func TestBuildNoContext(t *testing.T) {
  3280  	buildCmd := exec.Command(dockerBinary, "build", "-t", "nocontext", "-")
  3281  	buildCmd.Stdin = strings.NewReader("FROM busybox\nCMD echo ok\n")
  3282  
  3283  	if out, _, err := runCommandWithOutput(buildCmd); err != nil {
  3284  		t.Fatalf("build failed to complete: %v %v", out, err)
  3285  	}
  3286  
  3287  	if out, _, err := dockerCmd(t, "run", "--rm", "nocontext"); out != "ok\n" || err != nil {
  3288  		t.Fatalf("run produced invalid output: %q, expected %q", out, "ok")
  3289  	}
  3290  
  3291  	deleteImages("nocontext")
  3292  	logDone("build - build an image with no context")
  3293  }
  3294  
  3295  // TODO: TestCaching
  3296  func TestBuildADDLocalAndRemoteFilesWithoutCache(t *testing.T) {
  3297  	name := "testbuildaddlocalandremotefilewithoutcache"
  3298  	name2 := "testbuildaddlocalandremotefilewithoutcache2"
  3299  	defer deleteImages(name, name2)
  3300  	server, err := fakeStorage(map[string]string{
  3301  		"baz": "hello",
  3302  	})
  3303  	if err != nil {
  3304  		t.Fatal(err)
  3305  	}
  3306  	defer server.Close()
  3307  
  3308  	ctx, err := fakeContext(fmt.Sprintf(`FROM scratch
  3309          MAINTAINER dockerio
  3310          ADD foo /usr/lib/bla/bar
  3311          ADD %s/baz /usr/lib/baz/quux`, server.URL()),
  3312  		map[string]string{
  3313  			"foo": "hello world",
  3314  		})
  3315  	if err != nil {
  3316  		t.Fatal(err)
  3317  	}
  3318  	defer ctx.Close()
  3319  	id1, err := buildImageFromContext(name, ctx, true)
  3320  	if err != nil {
  3321  		t.Fatal(err)
  3322  	}
  3323  	id2, err := buildImageFromContext(name2, ctx, false)
  3324  	if err != nil {
  3325  		t.Fatal(err)
  3326  	}
  3327  	if id1 == id2 {
  3328  		t.Fatal("The cache should have been invalided but hasn't.")
  3329  	}
  3330  	logDone("build - add local and remote file without cache")
  3331  }
  3332  
  3333  func TestBuildWithVolumeOwnership(t *testing.T) {
  3334  	name := "testbuildimg"
  3335  	defer deleteImages(name)
  3336  
  3337  	_, err := buildImage(name,
  3338  		`FROM busybox:latest
  3339          RUN mkdir /test && chown daemon:daemon /test && chmod 0600 /test
  3340          VOLUME /test`,
  3341  		true)
  3342  
  3343  	if err != nil {
  3344  		t.Fatal(err)
  3345  	}
  3346  
  3347  	cmd := exec.Command(dockerBinary, "run", "--rm", "testbuildimg", "ls", "-la", "/test")
  3348  	out, _, err := runCommandWithOutput(cmd)
  3349  	if err != nil {
  3350  		t.Fatal(out, err)
  3351  	}
  3352  
  3353  	if expected := "drw-------"; !strings.Contains(out, expected) {
  3354  		t.Fatalf("expected %s received %s", expected, out)
  3355  	}
  3356  
  3357  	if expected := "daemon   daemon"; !strings.Contains(out, expected) {
  3358  		t.Fatalf("expected %s received %s", expected, out)
  3359  	}
  3360  
  3361  	logDone("build - volume ownership")
  3362  }
  3363  
  3364  // testing #1405 - config.Cmd does not get cleaned up if
  3365  // utilizing cache
  3366  func TestBuildEntrypointRunCleanup(t *testing.T) {
  3367  	name := "testbuildcmdcleanup"
  3368  	defer deleteImages(name)
  3369  	if _, err := buildImage(name,
  3370  		`FROM busybox
  3371          RUN echo "hello"`,
  3372  		true); err != nil {
  3373  		t.Fatal(err)
  3374  	}
  3375  
  3376  	ctx, err := fakeContext(`FROM busybox
  3377          RUN echo "hello"
  3378          ADD foo /foo
  3379          ENTRYPOINT ["/bin/echo"]`,
  3380  		map[string]string{
  3381  			"foo": "hello",
  3382  		})
  3383  	defer ctx.Close()
  3384  	if err != nil {
  3385  		t.Fatal(err)
  3386  	}
  3387  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  3388  		t.Fatal(err)
  3389  	}
  3390  	res, err := inspectField(name, "Config.Cmd")
  3391  	if err != nil {
  3392  		t.Fatal(err)
  3393  	}
  3394  	// Cmd must be cleaned up
  3395  	if expected := "<no value>"; res != expected {
  3396  		t.Fatalf("Cmd %s, expected %s", res, expected)
  3397  	}
  3398  	logDone("build - cleanup cmd after RUN")
  3399  }
  3400  
  3401  func TestBuildForbiddenContextPath(t *testing.T) {
  3402  	name := "testbuildforbidpath"
  3403  	defer deleteImages(name)
  3404  	ctx, err := fakeContext(`FROM scratch
  3405          ADD ../../ test/
  3406          `,
  3407  		map[string]string{
  3408  			"test.txt":  "test1",
  3409  			"other.txt": "other",
  3410  		})
  3411  	defer ctx.Close()
  3412  	if err != nil {
  3413  		t.Fatal(err)
  3414  	}
  3415  
  3416  	expected := "Forbidden path outside the build context: ../../ "
  3417  	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
  3418  		t.Fatalf("Wrong error: (should contain \"%s\") got:\n%v", expected, err)
  3419  	}
  3420  
  3421  	logDone("build - forbidden context path")
  3422  }
  3423  
  3424  func TestBuildADDFileNotFound(t *testing.T) {
  3425  	name := "testbuildaddnotfound"
  3426  	defer deleteImages(name)
  3427  	ctx, err := fakeContext(`FROM scratch
  3428          ADD foo /usr/local/bar`,
  3429  		map[string]string{"bar": "hello"})
  3430  	defer ctx.Close()
  3431  	if err != nil {
  3432  		t.Fatal(err)
  3433  	}
  3434  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  3435  		if !strings.Contains(err.Error(), "foo: no such file or directory") {
  3436  			t.Fatalf("Wrong error %v, must be about missing foo file or directory", err)
  3437  		}
  3438  	} else {
  3439  		t.Fatal("Error must not be nil")
  3440  	}
  3441  	logDone("build - add file not found")
  3442  }
  3443  
  3444  func TestBuildInheritance(t *testing.T) {
  3445  	name := "testbuildinheritance"
  3446  	defer deleteImages(name)
  3447  
  3448  	_, err := buildImage(name,
  3449  		`FROM scratch
  3450  		EXPOSE 2375`,
  3451  		true)
  3452  	if err != nil {
  3453  		t.Fatal(err)
  3454  	}
  3455  	ports1, err := inspectField(name, "Config.ExposedPorts")
  3456  	if err != nil {
  3457  		t.Fatal(err)
  3458  	}
  3459  
  3460  	_, err = buildImage(name,
  3461  		fmt.Sprintf(`FROM %s
  3462  		ENTRYPOINT ["/bin/echo"]`, name),
  3463  		true)
  3464  	if err != nil {
  3465  		t.Fatal(err)
  3466  	}
  3467  
  3468  	res, err := inspectField(name, "Config.Entrypoint")
  3469  	if err != nil {
  3470  		t.Fatal(err)
  3471  	}
  3472  	if expected := "[/bin/echo]"; res != expected {
  3473  		t.Fatalf("Entrypoint %s, expected %s", res, expected)
  3474  	}
  3475  	ports2, err := inspectField(name, "Config.ExposedPorts")
  3476  	if err != nil {
  3477  		t.Fatal(err)
  3478  	}
  3479  	if ports1 != ports2 {
  3480  		t.Fatalf("Ports must be same: %s != %s", ports1, ports2)
  3481  	}
  3482  	logDone("build - inheritance")
  3483  }
  3484  
  3485  func TestBuildFails(t *testing.T) {
  3486  	name := "testbuildfails"
  3487  	defer deleteImages(name)
  3488  	defer deleteAllContainers()
  3489  	_, err := buildImage(name,
  3490  		`FROM busybox
  3491  		RUN sh -c "exit 23"`,
  3492  		true)
  3493  	if err != nil {
  3494  		if !strings.Contains(err.Error(), "returned a non-zero code: 23") {
  3495  			t.Fatalf("Wrong error %v, must be about non-zero code 23", err)
  3496  		}
  3497  	} else {
  3498  		t.Fatal("Error must not be nil")
  3499  	}
  3500  	logDone("build - unsuccessful")
  3501  }
  3502  
  3503  func TestBuildFailsDockerfileEmpty(t *testing.T) {
  3504  	name := "testbuildfails"
  3505  	defer deleteImages(name)
  3506  	_, err := buildImage(name, ``, true)
  3507  	if err != nil {
  3508  		if !strings.Contains(err.Error(), "Dockerfile cannot be empty") {
  3509  			t.Fatalf("Wrong error %v, must be about empty Dockerfile", err)
  3510  		}
  3511  	} else {
  3512  		t.Fatal("Error must not be nil")
  3513  	}
  3514  	logDone("build - unsuccessful with empty dockerfile")
  3515  }
  3516  
  3517  func TestBuildOnBuild(t *testing.T) {
  3518  	name := "testbuildonbuild"
  3519  	defer deleteImages(name)
  3520  	_, err := buildImage(name,
  3521  		`FROM busybox
  3522  		ONBUILD RUN touch foobar`,
  3523  		true)
  3524  	if err != nil {
  3525  		t.Fatal(err)
  3526  	}
  3527  	_, err = buildImage(name,
  3528  		fmt.Sprintf(`FROM %s
  3529  		RUN [ -f foobar ]`, name),
  3530  		true)
  3531  	if err != nil {
  3532  		t.Fatal(err)
  3533  	}
  3534  	logDone("build - onbuild")
  3535  }
  3536  
  3537  func TestBuildOnBuildForbiddenChained(t *testing.T) {
  3538  	name := "testbuildonbuildforbiddenchained"
  3539  	defer deleteImages(name)
  3540  	_, err := buildImage(name,
  3541  		`FROM busybox
  3542  		ONBUILD ONBUILD RUN touch foobar`,
  3543  		true)
  3544  	if err != nil {
  3545  		if !strings.Contains(err.Error(), "Chaining ONBUILD via `ONBUILD ONBUILD` isn't allowed") {
  3546  			t.Fatalf("Wrong error %v, must be about chaining ONBUILD", err)
  3547  		}
  3548  	} else {
  3549  		t.Fatal("Error must not be nil")
  3550  	}
  3551  	logDone("build - onbuild forbidden chained")
  3552  }
  3553  
  3554  func TestBuildOnBuildForbiddenFrom(t *testing.T) {
  3555  	name := "testbuildonbuildforbiddenfrom"
  3556  	defer deleteImages(name)
  3557  	_, err := buildImage(name,
  3558  		`FROM busybox
  3559  		ONBUILD FROM scratch`,
  3560  		true)
  3561  	if err != nil {
  3562  		if !strings.Contains(err.Error(), "FROM isn't allowed as an ONBUILD trigger") {
  3563  			t.Fatalf("Wrong error %v, must be about FROM forbidden", err)
  3564  		}
  3565  	} else {
  3566  		t.Fatal("Error must not be nil")
  3567  	}
  3568  	logDone("build - onbuild forbidden from")
  3569  }
  3570  
  3571  func TestBuildOnBuildForbiddenMaintainer(t *testing.T) {
  3572  	name := "testbuildonbuildforbiddenmaintainer"
  3573  	defer deleteImages(name)
  3574  	_, err := buildImage(name,
  3575  		`FROM busybox
  3576  		ONBUILD MAINTAINER docker.io`,
  3577  		true)
  3578  	if err != nil {
  3579  		if !strings.Contains(err.Error(), "MAINTAINER isn't allowed as an ONBUILD trigger") {
  3580  			t.Fatalf("Wrong error %v, must be about MAINTAINER forbidden", err)
  3581  		}
  3582  	} else {
  3583  		t.Fatal("Error must not be nil")
  3584  	}
  3585  	logDone("build - onbuild forbidden maintainer")
  3586  }
  3587  
  3588  // gh #2446
  3589  func TestBuildAddToSymlinkDest(t *testing.T) {
  3590  	name := "testbuildaddtosymlinkdest"
  3591  	defer deleteImages(name)
  3592  	ctx, err := fakeContext(`FROM busybox
  3593          RUN mkdir /foo
  3594          RUN ln -s /foo /bar
  3595          ADD foo /bar/
  3596          RUN [ -f /bar/foo ]
  3597          RUN [ -f /foo/foo ]`,
  3598  		map[string]string{
  3599  			"foo": "hello",
  3600  		})
  3601  	if err != nil {
  3602  		t.Fatal(err)
  3603  	}
  3604  	defer ctx.Close()
  3605  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  3606  		t.Fatal(err)
  3607  	}
  3608  	logDone("build - add to symlink destination")
  3609  }
  3610  
  3611  func TestBuildEscapeWhitespace(t *testing.T) {
  3612  	name := "testbuildescaping"
  3613  	defer deleteImages(name)
  3614  
  3615  	_, err := buildImage(name, `
  3616    FROM busybox
  3617    MAINTAINER "Docker \
  3618  IO <io@\
  3619  docker.com>"
  3620    `, true)
  3621  
  3622  	res, err := inspectField(name, "Author")
  3623  
  3624  	if err != nil {
  3625  		t.Fatal(err)
  3626  	}
  3627  
  3628  	if res != "\"Docker IO <io@docker.com>\"" {
  3629  		t.Fatalf("Parsed string did not match the escaped string. Got: %q", res)
  3630  	}
  3631  
  3632  	logDone("build - validate escaping whitespace")
  3633  }
  3634  
  3635  func TestBuildVerifyIntString(t *testing.T) {
  3636  	// Verify that strings that look like ints are still passed as strings
  3637  	name := "testbuildstringing"
  3638  	defer deleteImages(name)
  3639  
  3640  	_, err := buildImage(name, `
  3641    FROM busybox
  3642    MAINTAINER 123
  3643    `, true)
  3644  
  3645  	out, rc, err := runCommandWithOutput(exec.Command(dockerBinary, "inspect", name))
  3646  	if rc != 0 || err != nil {
  3647  		t.Fatalf("Unexcepted error from inspect: rc: %v  err: %v", rc, err)
  3648  	}
  3649  
  3650  	if !strings.Contains(out, "\"123\"") {
  3651  		t.Fatalf("Output does not contain the int as a string:\n%s", out)
  3652  	}
  3653  
  3654  	logDone("build - verify int/strings as strings")
  3655  }
  3656  
  3657  func TestBuildDockerignore(t *testing.T) {
  3658  	name := "testbuilddockerignore"
  3659  	defer deleteImages(name)
  3660  	dockerfile := `
  3661          FROM busybox
  3662          ADD . /bla
  3663  		RUN [[ -f /bla/src/x.go ]]
  3664  		RUN [[ -f /bla/Makefile ]]
  3665  		RUN [[ ! -e /bla/src/_vendor ]]
  3666  		RUN [[ ! -e /bla/.gitignore ]]
  3667  		RUN [[ ! -e /bla/README.md ]]
  3668  		RUN [[ ! -e /bla/.git ]]`
  3669  	ctx, err := fakeContext(dockerfile, map[string]string{
  3670  		"Makefile":         "all:",
  3671  		".git/HEAD":        "ref: foo",
  3672  		"src/x.go":         "package main",
  3673  		"src/_vendor/v.go": "package main",
  3674  		".gitignore":       "",
  3675  		"README.md":        "readme",
  3676  		".dockerignore":    ".git\npkg\n.gitignore\nsrc/_vendor\n*.md",
  3677  	})
  3678  	defer ctx.Close()
  3679  	if err != nil {
  3680  		t.Fatal(err)
  3681  	}
  3682  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  3683  		t.Fatal(err)
  3684  	}
  3685  	logDone("build - test .dockerignore")
  3686  }
  3687  
  3688  func TestBuildDockerignoreCleanPaths(t *testing.T) {
  3689  	name := "testbuilddockerignorecleanpaths"
  3690  	defer deleteImages(name)
  3691  	dockerfile := `
  3692          FROM busybox
  3693          ADD . /tmp/
  3694          RUN (! ls /tmp/foo) && (! ls /tmp/foo2) && (! ls /tmp/dir1/foo)`
  3695  	ctx, err := fakeContext(dockerfile, map[string]string{
  3696  		"foo":           "foo",
  3697  		"foo2":          "foo2",
  3698  		"dir1/foo":      "foo in dir1",
  3699  		".dockerignore": "./foo\ndir1//foo\n./dir1/../foo2",
  3700  	})
  3701  	if err != nil {
  3702  		t.Fatal(err)
  3703  	}
  3704  	defer ctx.Close()
  3705  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  3706  		t.Fatal(err)
  3707  	}
  3708  	logDone("build - test .dockerignore with clean paths")
  3709  }
  3710  
  3711  func TestBuildDockerignoringDockerfile(t *testing.T) {
  3712  	name := "testbuilddockerignoredockerfile"
  3713  	defer deleteImages(name)
  3714  	dockerfile := `
  3715          FROM busybox
  3716  		ADD . /tmp/
  3717  		RUN ! ls /tmp/Dockerfile
  3718  		RUN ls /tmp/.dockerignore`
  3719  	ctx, err := fakeContext(dockerfile, map[string]string{
  3720  		"Dockerfile":    dockerfile,
  3721  		".dockerignore": "Dockerfile\n",
  3722  	})
  3723  	if err != nil {
  3724  		t.Fatal(err)
  3725  	}
  3726  	defer ctx.Close()
  3727  
  3728  	if _, err = buildImageFromContext(name, ctx, true); err != nil {
  3729  		t.Fatalf("Didn't ignore Dockerfile correctly:%s", err)
  3730  	}
  3731  
  3732  	// now try it with ./Dockerfile
  3733  	ctx.Add(".dockerignore", "./Dockerfile\n")
  3734  	if _, err = buildImageFromContext(name, ctx, true); err != nil {
  3735  		t.Fatalf("Didn't ignore ./Dockerfile correctly:%s", err)
  3736  	}
  3737  
  3738  	logDone("build - test .dockerignore of Dockerfile")
  3739  }
  3740  
  3741  func TestBuildDockerignoringRenamedDockerfile(t *testing.T) {
  3742  	name := "testbuilddockerignoredockerfile"
  3743  	defer deleteImages(name)
  3744  	dockerfile := `
  3745          FROM busybox
  3746  		ADD . /tmp/
  3747  		RUN ls /tmp/Dockerfile
  3748  		RUN ! ls /tmp/MyDockerfile
  3749  		RUN ls /tmp/.dockerignore`
  3750  	ctx, err := fakeContext(dockerfile, map[string]string{
  3751  		"Dockerfile":    "Should not use me",
  3752  		"MyDockerfile":  dockerfile,
  3753  		".dockerignore": "MyDockerfile\n",
  3754  	})
  3755  	if err != nil {
  3756  		t.Fatal(err)
  3757  	}
  3758  	defer ctx.Close()
  3759  
  3760  	if _, err = buildImageFromContext(name, ctx, true); err != nil {
  3761  		t.Fatalf("Didn't ignore MyDockerfile correctly:%s", err)
  3762  	}
  3763  
  3764  	// now try it with ./MyDockerfile
  3765  	ctx.Add(".dockerignore", "./MyDockerfile\n")
  3766  	if _, err = buildImageFromContext(name, ctx, true); err != nil {
  3767  		t.Fatalf("Didn't ignore ./MyDockerfile correctly:%s", err)
  3768  	}
  3769  
  3770  	logDone("build - test .dockerignore of renamed Dockerfile")
  3771  }
  3772  
  3773  func TestBuildDockerignoringDockerignore(t *testing.T) {
  3774  	name := "testbuilddockerignoredockerignore"
  3775  	defer deleteImages(name)
  3776  	dockerfile := `
  3777          FROM busybox
  3778  		ADD . /tmp/
  3779  		RUN ! ls /tmp/.dockerignore
  3780  		RUN ls /tmp/Dockerfile`
  3781  	ctx, err := fakeContext(dockerfile, map[string]string{
  3782  		"Dockerfile":    dockerfile,
  3783  		".dockerignore": ".dockerignore\n",
  3784  	})
  3785  	defer ctx.Close()
  3786  	if err != nil {
  3787  		t.Fatal(err)
  3788  	}
  3789  	if _, err = buildImageFromContext(name, ctx, true); err != nil {
  3790  		t.Fatalf("Didn't ignore .dockerignore correctly:%s", err)
  3791  	}
  3792  	logDone("build - test .dockerignore of .dockerignore")
  3793  }
  3794  
  3795  func TestBuildDockerignoreTouchDockerfile(t *testing.T) {
  3796  	var id1 string
  3797  	var id2 string
  3798  
  3799  	name := "testbuilddockerignoretouchdockerfile"
  3800  	defer deleteImages(name)
  3801  	dockerfile := `
  3802          FROM busybox
  3803  		ADD . /tmp/`
  3804  	ctx, err := fakeContext(dockerfile, map[string]string{
  3805  		"Dockerfile":    dockerfile,
  3806  		".dockerignore": "Dockerfile\n",
  3807  	})
  3808  	defer ctx.Close()
  3809  	if err != nil {
  3810  		t.Fatal(err)
  3811  	}
  3812  
  3813  	if id1, err = buildImageFromContext(name, ctx, true); err != nil {
  3814  		t.Fatalf("Didn't build it correctly:%s", err)
  3815  	}
  3816  
  3817  	if id2, err = buildImageFromContext(name, ctx, true); err != nil {
  3818  		t.Fatalf("Didn't build it correctly:%s", err)
  3819  	}
  3820  	if id1 != id2 {
  3821  		t.Fatalf("Didn't use the cache - 1")
  3822  	}
  3823  
  3824  	// Now make sure touching Dockerfile doesn't invalidate the cache
  3825  	if err = ctx.Add("Dockerfile", dockerfile+"\n# hi"); err != nil {
  3826  		t.Fatalf("Didn't add Dockerfile: %s", err)
  3827  	}
  3828  	if id2, err = buildImageFromContext(name, ctx, true); err != nil {
  3829  		t.Fatalf("Didn't build it correctly:%s", err)
  3830  	}
  3831  	if id1 != id2 {
  3832  		t.Fatalf("Didn't use the cache - 2")
  3833  	}
  3834  
  3835  	// One more time but just 'touch' it instead of changing the content
  3836  	if err = ctx.Add("Dockerfile", dockerfile+"\n# hi"); err != nil {
  3837  		t.Fatalf("Didn't add Dockerfile: %s", err)
  3838  	}
  3839  	if id2, err = buildImageFromContext(name, ctx, true); err != nil {
  3840  		t.Fatalf("Didn't build it correctly:%s", err)
  3841  	}
  3842  	if id1 != id2 {
  3843  		t.Fatalf("Didn't use the cache - 3")
  3844  	}
  3845  
  3846  	logDone("build - test .dockerignore touch dockerfile")
  3847  }
  3848  
  3849  func TestBuildDockerignoringWholeDir(t *testing.T) {
  3850  	name := "testbuilddockerignorewholedir"
  3851  	defer deleteImages(name)
  3852  	dockerfile := `
  3853          FROM busybox
  3854  		COPY . /
  3855  		RUN [[ ! -e /.gitignore ]]
  3856  		RUN [[ -f /Makefile ]]`
  3857  	ctx, err := fakeContext(dockerfile, map[string]string{
  3858  		"Dockerfile":    "FROM scratch",
  3859  		"Makefile":      "all:",
  3860  		".dockerignore": ".*\n",
  3861  	})
  3862  	defer ctx.Close()
  3863  	if err != nil {
  3864  		t.Fatal(err)
  3865  	}
  3866  	if _, err = buildImageFromContext(name, ctx, true); err != nil {
  3867  		t.Fatal(err)
  3868  	}
  3869  	logDone("build - test .dockerignore whole dir with .*")
  3870  }
  3871  
  3872  func TestBuildLineBreak(t *testing.T) {
  3873  	name := "testbuildlinebreak"
  3874  	defer deleteImages(name)
  3875  	_, err := buildImage(name,
  3876  		`FROM  busybox
  3877  RUN    sh -c 'echo root:testpass \
  3878  	> /tmp/passwd'
  3879  RUN    mkdir -p /var/run/sshd
  3880  RUN    [ "$(cat /tmp/passwd)" = "root:testpass" ]
  3881  RUN    [ "$(ls -d /var/run/sshd)" = "/var/run/sshd" ]`,
  3882  		true)
  3883  	if err != nil {
  3884  		t.Fatal(err)
  3885  	}
  3886  	logDone("build - line break with \\")
  3887  }
  3888  
  3889  func TestBuildEOLInLine(t *testing.T) {
  3890  	name := "testbuildeolinline"
  3891  	defer deleteImages(name)
  3892  	_, err := buildImage(name,
  3893  		`FROM   busybox
  3894  RUN    sh -c 'echo root:testpass > /tmp/passwd'
  3895  RUN    echo "foo \n bar"; echo "baz"
  3896  RUN    mkdir -p /var/run/sshd
  3897  RUN    [ "$(cat /tmp/passwd)" = "root:testpass" ]
  3898  RUN    [ "$(ls -d /var/run/sshd)" = "/var/run/sshd" ]`,
  3899  		true)
  3900  	if err != nil {
  3901  		t.Fatal(err)
  3902  	}
  3903  	logDone("build - end of line in dockerfile instruction")
  3904  }
  3905  
  3906  func TestBuildCommentsShebangs(t *testing.T) {
  3907  	name := "testbuildcomments"
  3908  	defer deleteImages(name)
  3909  	_, err := buildImage(name,
  3910  		`FROM busybox
  3911  # This is an ordinary comment.
  3912  RUN { echo '#!/bin/sh'; echo 'echo hello world'; } > /hello.sh
  3913  RUN [ ! -x /hello.sh ]
  3914  # comment with line break \
  3915  RUN chmod +x /hello.sh
  3916  RUN [ -x /hello.sh ]
  3917  RUN [ "$(cat /hello.sh)" = $'#!/bin/sh\necho hello world' ]
  3918  RUN [ "$(/hello.sh)" = "hello world" ]`,
  3919  		true)
  3920  	if err != nil {
  3921  		t.Fatal(err)
  3922  	}
  3923  	logDone("build - comments and shebangs")
  3924  }
  3925  
  3926  func TestBuildUsersAndGroups(t *testing.T) {
  3927  	name := "testbuildusers"
  3928  	defer deleteImages(name)
  3929  	_, err := buildImage(name,
  3930  		`FROM busybox
  3931  
  3932  # Make sure our defaults work
  3933  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)" = '0:0/root:root' ]
  3934  
  3935  # TODO decide if "args.user = strconv.Itoa(syscall.Getuid())" is acceptable behavior for changeUser in sysvinit instead of "return nil" when "USER" isn't specified (so that we get the proper group list even if that is the empty list, even in the default case of not supplying an explicit USER to run as, which implies USER 0)
  3936  USER root
  3937  RUN [ "$(id -G):$(id -Gn)" = '0 10:root wheel' ]
  3938  
  3939  # Setup dockerio user and group
  3940  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  3941  RUN echo 'dockerio:x:1001:' >> /etc/group
  3942  
  3943  # Make sure we can switch to our user and all the information is exactly as we expect it to be
  3944  USER dockerio
  3945  RUN id -G
  3946  RUN id -Gn
  3947  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001:dockerio' ]
  3948  
  3949  # Switch back to root and double check that worked exactly as we might expect it to
  3950  USER root
  3951  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '0:0/root:root/0 10:root wheel' ]
  3952  
  3953  # Add a "supplementary" group for our dockerio user
  3954  RUN echo 'supplementary:x:1002:dockerio' >> /etc/group
  3955  
  3956  # ... and then go verify that we get it like we expect
  3957  USER dockerio
  3958  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001 1002:dockerio supplementary' ]
  3959  USER 1001
  3960  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001 1002:dockerio supplementary' ]
  3961  
  3962  # super test the new "user:group" syntax
  3963  USER dockerio:dockerio
  3964  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001:dockerio' ]
  3965  USER 1001:dockerio
  3966  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001:dockerio' ]
  3967  USER dockerio:1001
  3968  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001:dockerio' ]
  3969  USER 1001:1001
  3970  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001:dockerio' ]
  3971  USER dockerio:supplementary
  3972  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1002/dockerio:supplementary/1002:supplementary' ]
  3973  USER dockerio:1002
  3974  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1002/dockerio:supplementary/1002:supplementary' ]
  3975  USER 1001:supplementary
  3976  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1002/dockerio:supplementary/1002:supplementary' ]
  3977  USER 1001:1002
  3978  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1002/dockerio:supplementary/1002:supplementary' ]
  3979  
  3980  # make sure unknown uid/gid still works properly
  3981  USER 1042:1043
  3982  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1042:1043/1042:1043/1043:1043' ]`,
  3983  		true)
  3984  	if err != nil {
  3985  		t.Fatal(err)
  3986  	}
  3987  	logDone("build - users and groups")
  3988  }
  3989  
  3990  func TestBuildEnvUsage(t *testing.T) {
  3991  	name := "testbuildenvusage"
  3992  	defer deleteImages(name)
  3993  	dockerfile := `FROM busybox
  3994  ENV    HOME /root
  3995  ENV    PATH $HOME/bin:$PATH
  3996  ENV    PATH /tmp:$PATH
  3997  RUN    [ "$PATH" = "/tmp:$HOME/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ]
  3998  ENV    FOO /foo/baz
  3999  ENV    BAR /bar
  4000  ENV    BAZ $BAR
  4001  ENV    FOOPATH $PATH:$FOO
  4002  RUN    [ "$BAR" = "$BAZ" ]
  4003  RUN    [ "$FOOPATH" = "$PATH:/foo/baz" ]
  4004  ENV	   FROM hello/docker/world
  4005  ENV    TO /docker/world/hello
  4006  ADD    $FROM $TO
  4007  RUN    [ "$(cat $TO)" = "hello" ]
  4008  ENV    abc=def
  4009  ENV    ghi=$abc
  4010  RUN    [ "$ghi" = "def" ]
  4011  `
  4012  	ctx, err := fakeContext(dockerfile, map[string]string{
  4013  		"hello/docker/world": "hello",
  4014  	})
  4015  	if err != nil {
  4016  		t.Fatal(err)
  4017  	}
  4018  	defer ctx.Close()
  4019  
  4020  	_, err = buildImageFromContext(name, ctx, true)
  4021  	if err != nil {
  4022  		t.Fatal(err)
  4023  	}
  4024  	logDone("build - environment variables usage")
  4025  }
  4026  
  4027  func TestBuildEnvUsage2(t *testing.T) {
  4028  	name := "testbuildenvusage2"
  4029  	defer deleteImages(name)
  4030  	dockerfile := `FROM busybox
  4031  ENV    abc=def
  4032  RUN    [ "$abc" = "def" ]
  4033  ENV    def="hello world"
  4034  RUN    [ "$def" = "hello world" ]
  4035  ENV    def=hello\ world
  4036  RUN    [ "$def" = "hello world" ]
  4037  ENV    v1=abc v2="hi there"
  4038  RUN    [ "$v1" = "abc" ]
  4039  RUN    [ "$v2" = "hi there" ]
  4040  ENV    v3='boogie nights' v4="with'quotes too"
  4041  RUN    [ "$v3" = "boogie nights" ]
  4042  RUN    [ "$v4" = "with'quotes too" ]
  4043  ENV    abc=zzz FROM=hello/docker/world
  4044  ENV    abc=zzz TO=/docker/world/hello
  4045  ADD    $FROM $TO
  4046  RUN    [ "$(cat $TO)" = "hello" ]
  4047  ENV    abc "zzz"
  4048  RUN    [ $abc = "zzz" ]
  4049  ENV    abc 'yyy'
  4050  RUN    [ $abc = 'yyy' ]
  4051  ENV    abc=
  4052  RUN    [ "$abc" = "" ]
  4053  
  4054  # use grep to make sure if the builder substitutes \$foo by mistake
  4055  # we don't get a false positive
  4056  ENV    abc=\$foo
  4057  RUN    [ "$abc" = "\$foo" ] && (echo "$abc" | grep foo)
  4058  ENV    abc \$foo
  4059  RUN    [ "$abc" = "\$foo" ] && (echo "$abc" | grep foo)
  4060  
  4061  ENV    abc=\'foo\'
  4062  RUN    [ "$abc" = "'foo'" ]
  4063  ENV    abc=\"foo\"
  4064  RUN    [ "$abc" = "\"foo\"" ]
  4065  ENV    abc "foo"
  4066  RUN    [ "$abc" = "foo" ]
  4067  ENV    abc 'foo'
  4068  RUN    [ "$abc" = 'foo' ]
  4069  ENV    abc \'foo\'
  4070  RUN    [ "$abc" = "'foo'" ]
  4071  ENV    abc \"foo\"
  4072  RUN    [ "$abc" = '"foo"' ]
  4073  
  4074  ENV    e1=bar
  4075  ENV    e2=$e1
  4076  ENV    e3=$e11
  4077  ENV    e4=\$e1
  4078  ENV    e5=\$e11
  4079  RUN    [ "$e0,$e1,$e2,$e3,$e4,$e5" = ',bar,bar,,$e1,$e11' ]
  4080  
  4081  ENV    ee1 bar
  4082  ENV    ee2 $ee1
  4083  ENV    ee3 $ee11
  4084  ENV    ee4 \$ee1
  4085  ENV    ee5 \$ee11
  4086  RUN    [ "$ee1,$ee2,$ee3,$ee4,$ee5" = 'bar,bar,,$ee1,$ee11' ]
  4087  
  4088  ENV    eee1="foo"
  4089  ENV    eee2='foo'
  4090  ENV    eee3 "foo"
  4091  ENV    eee4 'foo'
  4092  RUN    [ "$eee1,$eee2,$eee3,$eee4" = 'foo,foo,foo,foo' ]
  4093  
  4094  `
  4095  	ctx, err := fakeContext(dockerfile, map[string]string{
  4096  		"hello/docker/world": "hello",
  4097  	})
  4098  	if err != nil {
  4099  		t.Fatal(err)
  4100  	}
  4101  	defer ctx.Close()
  4102  
  4103  	_, err = buildImageFromContext(name, ctx, true)
  4104  	if err != nil {
  4105  		t.Fatal(err)
  4106  	}
  4107  	logDone("build - environment variables usage2")
  4108  }
  4109  
  4110  func TestBuildAddScript(t *testing.T) {
  4111  	name := "testbuildaddscript"
  4112  	defer deleteImages(name)
  4113  	dockerfile := `
  4114  FROM busybox
  4115  ADD test /test
  4116  RUN ["chmod","+x","/test"]
  4117  RUN ["/test"]
  4118  RUN [ "$(cat /testfile)" = 'test!' ]`
  4119  	ctx, err := fakeContext(dockerfile, map[string]string{
  4120  		"test": "#!/bin/sh\necho 'test!' > /testfile",
  4121  	})
  4122  	if err != nil {
  4123  		t.Fatal(err)
  4124  	}
  4125  	defer ctx.Close()
  4126  
  4127  	_, err = buildImageFromContext(name, ctx, true)
  4128  	if err != nil {
  4129  		t.Fatal(err)
  4130  	}
  4131  	logDone("build - add and run script")
  4132  }
  4133  
  4134  func TestBuildAddTar(t *testing.T) {
  4135  	name := "testbuildaddtar"
  4136  	defer deleteImages(name)
  4137  
  4138  	ctx := func() *FakeContext {
  4139  		dockerfile := `
  4140  FROM busybox
  4141  ADD test.tar /
  4142  RUN cat /test/foo | grep Hi
  4143  ADD test.tar /test.tar
  4144  RUN cat /test.tar/test/foo | grep Hi
  4145  ADD test.tar /unlikely-to-exist
  4146  RUN cat /unlikely-to-exist/test/foo | grep Hi
  4147  ADD test.tar /unlikely-to-exist-trailing-slash/
  4148  RUN cat /unlikely-to-exist-trailing-slash/test/foo | grep Hi
  4149  RUN mkdir /existing-directory
  4150  ADD test.tar /existing-directory
  4151  RUN cat /existing-directory/test/foo | grep Hi
  4152  ADD test.tar /existing-directory-trailing-slash/
  4153  RUN cat /existing-directory-trailing-slash/test/foo | grep Hi`
  4154  		tmpDir, err := ioutil.TempDir("", "fake-context")
  4155  		testTar, err := os.Create(filepath.Join(tmpDir, "test.tar"))
  4156  		if err != nil {
  4157  			t.Fatalf("failed to create test.tar archive: %v", err)
  4158  		}
  4159  		defer testTar.Close()
  4160  
  4161  		tw := tar.NewWriter(testTar)
  4162  
  4163  		if err := tw.WriteHeader(&tar.Header{
  4164  			Name: "test/foo",
  4165  			Size: 2,
  4166  		}); err != nil {
  4167  			t.Fatalf("failed to write tar file header: %v", err)
  4168  		}
  4169  		if _, err := tw.Write([]byte("Hi")); err != nil {
  4170  			t.Fatalf("failed to write tar file content: %v", err)
  4171  		}
  4172  		if err := tw.Close(); err != nil {
  4173  			t.Fatalf("failed to close tar archive: %v", err)
  4174  		}
  4175  
  4176  		if err := ioutil.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644); err != nil {
  4177  			t.Fatalf("failed to open destination dockerfile: %v", err)
  4178  		}
  4179  		return fakeContextFromDir(tmpDir)
  4180  	}()
  4181  	defer ctx.Close()
  4182  
  4183  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  4184  		t.Fatalf("build failed to complete for TestBuildAddTar: %v", err)
  4185  	}
  4186  
  4187  	logDone("build - ADD tar")
  4188  }
  4189  
  4190  func TestBuildAddTarXz(t *testing.T) {
  4191  	name := "testbuildaddtarxz"
  4192  	defer deleteImages(name)
  4193  
  4194  	ctx := func() *FakeContext {
  4195  		dockerfile := `
  4196  			FROM busybox
  4197  			ADD test.tar.xz /
  4198  			RUN cat /test/foo | grep Hi`
  4199  		tmpDir, err := ioutil.TempDir("", "fake-context")
  4200  		testTar, err := os.Create(filepath.Join(tmpDir, "test.tar"))
  4201  		if err != nil {
  4202  			t.Fatalf("failed to create test.tar archive: %v", err)
  4203  		}
  4204  		defer testTar.Close()
  4205  
  4206  		tw := tar.NewWriter(testTar)
  4207  
  4208  		if err := tw.WriteHeader(&tar.Header{
  4209  			Name: "test/foo",
  4210  			Size: 2,
  4211  		}); err != nil {
  4212  			t.Fatalf("failed to write tar file header: %v", err)
  4213  		}
  4214  		if _, err := tw.Write([]byte("Hi")); err != nil {
  4215  			t.Fatalf("failed to write tar file content: %v", err)
  4216  		}
  4217  		if err := tw.Close(); err != nil {
  4218  			t.Fatalf("failed to close tar archive: %v", err)
  4219  		}
  4220  		xzCompressCmd := exec.Command("xz", "-k", "test.tar")
  4221  		xzCompressCmd.Dir = tmpDir
  4222  		out, _, err := runCommandWithOutput(xzCompressCmd)
  4223  		if err != nil {
  4224  			t.Fatal(err, out)
  4225  		}
  4226  
  4227  		if err := ioutil.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644); err != nil {
  4228  			t.Fatalf("failed to open destination dockerfile: %v", err)
  4229  		}
  4230  		return fakeContextFromDir(tmpDir)
  4231  	}()
  4232  
  4233  	defer ctx.Close()
  4234  
  4235  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  4236  		t.Fatalf("build failed to complete for TestBuildAddTarXz: %v", err)
  4237  	}
  4238  
  4239  	logDone("build - ADD tar.xz")
  4240  }
  4241  
  4242  func TestBuildAddTarXzGz(t *testing.T) {
  4243  	name := "testbuildaddtarxzgz"
  4244  	defer deleteImages(name)
  4245  
  4246  	ctx := func() *FakeContext {
  4247  		dockerfile := `
  4248  			FROM busybox
  4249  			ADD test.tar.xz.gz /
  4250  			RUN ls /test.tar.xz.gz`
  4251  		tmpDir, err := ioutil.TempDir("", "fake-context")
  4252  		testTar, err := os.Create(filepath.Join(tmpDir, "test.tar"))
  4253  		if err != nil {
  4254  			t.Fatalf("failed to create test.tar archive: %v", err)
  4255  		}
  4256  		defer testTar.Close()
  4257  
  4258  		tw := tar.NewWriter(testTar)
  4259  
  4260  		if err := tw.WriteHeader(&tar.Header{
  4261  			Name: "test/foo",
  4262  			Size: 2,
  4263  		}); err != nil {
  4264  			t.Fatalf("failed to write tar file header: %v", err)
  4265  		}
  4266  		if _, err := tw.Write([]byte("Hi")); err != nil {
  4267  			t.Fatalf("failed to write tar file content: %v", err)
  4268  		}
  4269  		if err := tw.Close(); err != nil {
  4270  			t.Fatalf("failed to close tar archive: %v", err)
  4271  		}
  4272  
  4273  		xzCompressCmd := exec.Command("xz", "-k", "test.tar")
  4274  		xzCompressCmd.Dir = tmpDir
  4275  		out, _, err := runCommandWithOutput(xzCompressCmd)
  4276  		if err != nil {
  4277  			t.Fatal(err, out)
  4278  		}
  4279  
  4280  		gzipCompressCmd := exec.Command("gzip", "test.tar.xz")
  4281  		gzipCompressCmd.Dir = tmpDir
  4282  		out, _, err = runCommandWithOutput(gzipCompressCmd)
  4283  		if err != nil {
  4284  			t.Fatal(err, out)
  4285  		}
  4286  
  4287  		if err := ioutil.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644); err != nil {
  4288  			t.Fatalf("failed to open destination dockerfile: %v", err)
  4289  		}
  4290  		return fakeContextFromDir(tmpDir)
  4291  	}()
  4292  
  4293  	defer ctx.Close()
  4294  
  4295  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  4296  		t.Fatalf("build failed to complete for TestBuildAddTarXz: %v", err)
  4297  	}
  4298  
  4299  	logDone("build - ADD tar.xz.gz")
  4300  }
  4301  
  4302  func TestBuildFromGIT(t *testing.T) {
  4303  	name := "testbuildfromgit"
  4304  	defer deleteImages(name)
  4305  	git, err := fakeGIT("repo", map[string]string{
  4306  		"Dockerfile": `FROM busybox
  4307  					ADD first /first
  4308  					RUN [ -f /first ]
  4309  					MAINTAINER docker`,
  4310  		"first": "test git data",
  4311  	}, true)
  4312  	if err != nil {
  4313  		t.Fatal(err)
  4314  	}
  4315  	defer git.Close()
  4316  
  4317  	_, err = buildImageFromPath(name, git.RepoURL, true)
  4318  	if err != nil {
  4319  		t.Fatal(err)
  4320  	}
  4321  	res, err := inspectField(name, "Author")
  4322  	if err != nil {
  4323  		t.Fatal(err)
  4324  	}
  4325  	if res != "docker" {
  4326  		t.Fatalf("Maintainer should be docker, got %s", res)
  4327  	}
  4328  	logDone("build - build from GIT")
  4329  }
  4330  
  4331  func TestBuildCleanupCmdOnEntrypoint(t *testing.T) {
  4332  	name := "testbuildcmdcleanuponentrypoint"
  4333  	defer deleteImages(name)
  4334  	if _, err := buildImage(name,
  4335  		`FROM scratch
  4336          CMD ["test"]
  4337  		ENTRYPOINT ["echo"]`,
  4338  		true); err != nil {
  4339  		t.Fatal(err)
  4340  	}
  4341  	if _, err := buildImage(name,
  4342  		fmt.Sprintf(`FROM %s
  4343  		ENTRYPOINT ["cat"]`, name),
  4344  		true); err != nil {
  4345  		t.Fatal(err)
  4346  	}
  4347  	res, err := inspectField(name, "Config.Cmd")
  4348  	if err != nil {
  4349  		t.Fatal(err)
  4350  	}
  4351  	if expected := "<no value>"; res != expected {
  4352  		t.Fatalf("Cmd %s, expected %s", res, expected)
  4353  	}
  4354  	res, err = inspectField(name, "Config.Entrypoint")
  4355  	if err != nil {
  4356  		t.Fatal(err)
  4357  	}
  4358  	if expected := "[cat]"; res != expected {
  4359  		t.Fatalf("Entrypoint %s, expected %s", res, expected)
  4360  	}
  4361  	logDone("build - cleanup cmd on ENTRYPOINT")
  4362  }
  4363  
  4364  func TestBuildClearCmd(t *testing.T) {
  4365  	name := "testbuildclearcmd"
  4366  	defer deleteImages(name)
  4367  	_, err := buildImage(name,
  4368  		`From scratch
  4369     ENTRYPOINT ["/bin/bash"]
  4370     CMD []`,
  4371  		true)
  4372  	if err != nil {
  4373  		t.Fatal(err)
  4374  	}
  4375  	res, err := inspectFieldJSON(name, "Config.Cmd")
  4376  	if err != nil {
  4377  		t.Fatal(err)
  4378  	}
  4379  	if res != "[]" {
  4380  		t.Fatalf("Cmd %s, expected %s", res, "[]")
  4381  	}
  4382  	logDone("build - clearcmd")
  4383  }
  4384  
  4385  func TestBuildEmptyCmd(t *testing.T) {
  4386  	name := "testbuildemptycmd"
  4387  	defer deleteImages(name)
  4388  	if _, err := buildImage(name, "FROM scratch\nMAINTAINER quux\n", true); err != nil {
  4389  		t.Fatal(err)
  4390  	}
  4391  	res, err := inspectFieldJSON(name, "Config.Cmd")
  4392  	if err != nil {
  4393  		t.Fatal(err)
  4394  	}
  4395  	if res != "null" {
  4396  		t.Fatalf("Cmd %s, expected %s", res, "null")
  4397  	}
  4398  	logDone("build - empty cmd")
  4399  }
  4400  
  4401  func TestBuildOnBuildOutput(t *testing.T) {
  4402  	name := "testbuildonbuildparent"
  4403  	defer deleteImages(name)
  4404  	if _, err := buildImage(name, "FROM busybox\nONBUILD RUN echo foo\n", true); err != nil {
  4405  		t.Fatal(err)
  4406  	}
  4407  
  4408  	childname := "testbuildonbuildchild"
  4409  	defer deleteImages(childname)
  4410  
  4411  	_, out, err := buildImageWithOut(name, "FROM "+name+"\nMAINTAINER quux\n", true)
  4412  	if err != nil {
  4413  		t.Fatal(err)
  4414  	}
  4415  
  4416  	if !strings.Contains(out, "Trigger 0, RUN echo foo") {
  4417  		t.Fatal("failed to find the ONBUILD output", out)
  4418  	}
  4419  
  4420  	logDone("build - onbuild output")
  4421  }
  4422  
  4423  func TestBuildInvalidTag(t *testing.T) {
  4424  	name := "abcd:" + makeRandomString(200)
  4425  	defer deleteImages(name)
  4426  	_, out, err := buildImageWithOut(name, "FROM scratch\nMAINTAINER quux\n", true)
  4427  	// if the error doesnt check for illegal tag name, or the image is built
  4428  	// then this should fail
  4429  	if !strings.Contains(out, "Illegal tag name") || strings.Contains(out, "Sending build context to Docker daemon") {
  4430  		t.Fatalf("failed to stop before building. Error: %s, Output: %s", err, out)
  4431  	}
  4432  	logDone("build - invalid tag")
  4433  }
  4434  
  4435  func TestBuildCmdShDashC(t *testing.T) {
  4436  	name := "testbuildcmdshc"
  4437  	defer deleteImages(name)
  4438  	if _, err := buildImage(name, "FROM busybox\nCMD echo cmd\n", true); err != nil {
  4439  		t.Fatal(err)
  4440  	}
  4441  
  4442  	res, err := inspectFieldJSON(name, "Config.Cmd")
  4443  	if err != nil {
  4444  		t.Fatal(err, res)
  4445  	}
  4446  
  4447  	expected := `["/bin/sh","-c","echo cmd"]`
  4448  
  4449  	if res != expected {
  4450  		t.Fatalf("Expected value %s not in Config.Cmd: %s", expected, res)
  4451  	}
  4452  
  4453  	logDone("build - cmd should have sh -c for non-json")
  4454  }
  4455  
  4456  func TestBuildCmdSpaces(t *testing.T) {
  4457  	// Test to make sure that when we strcat arrays we take into account
  4458  	// the arg separator to make sure ["echo","hi"] and ["echo hi"] don't
  4459  	// look the same
  4460  	name := "testbuildcmdspaces"
  4461  	defer deleteImages(name)
  4462  	var id1 string
  4463  	var id2 string
  4464  	var err error
  4465  
  4466  	if id1, err = buildImage(name, "FROM busybox\nCMD [\"echo hi\"]\n", true); err != nil {
  4467  		t.Fatal(err)
  4468  	}
  4469  
  4470  	if id2, err = buildImage(name, "FROM busybox\nCMD [\"echo\", \"hi\"]\n", true); err != nil {
  4471  		t.Fatal(err)
  4472  	}
  4473  
  4474  	if id1 == id2 {
  4475  		t.Fatal("Should not have resulted in the same CMD")
  4476  	}
  4477  
  4478  	// Now do the same with ENTRYPOINT
  4479  	if id1, err = buildImage(name, "FROM busybox\nENTRYPOINT [\"echo hi\"]\n", true); err != nil {
  4480  		t.Fatal(err)
  4481  	}
  4482  
  4483  	if id2, err = buildImage(name, "FROM busybox\nENTRYPOINT [\"echo\", \"hi\"]\n", true); err != nil {
  4484  		t.Fatal(err)
  4485  	}
  4486  
  4487  	if id1 == id2 {
  4488  		t.Fatal("Should not have resulted in the same ENTRYPOINT")
  4489  	}
  4490  
  4491  	logDone("build - cmd with spaces")
  4492  }
  4493  
  4494  func TestBuildCmdJSONNoShDashC(t *testing.T) {
  4495  	name := "testbuildcmdjson"
  4496  	defer deleteImages(name)
  4497  	if _, err := buildImage(name, "FROM busybox\nCMD [\"echo\", \"cmd\"]", true); err != nil {
  4498  		t.Fatal(err)
  4499  	}
  4500  
  4501  	res, err := inspectFieldJSON(name, "Config.Cmd")
  4502  	if err != nil {
  4503  		t.Fatal(err, res)
  4504  	}
  4505  
  4506  	expected := `["echo","cmd"]`
  4507  
  4508  	if res != expected {
  4509  		t.Fatalf("Expected value %s not in Config.Cmd: %s", expected, res)
  4510  	}
  4511  
  4512  	logDone("build - cmd should not have /bin/sh -c for json")
  4513  }
  4514  
  4515  func TestBuildErrorInvalidInstruction(t *testing.T) {
  4516  	name := "testbuildignoreinvalidinstruction"
  4517  	defer deleteImages(name)
  4518  
  4519  	out, _, err := buildImageWithOut(name, "FROM busybox\nfoo bar", true)
  4520  	if err == nil {
  4521  		t.Fatalf("Should have failed: %s", out)
  4522  	}
  4523  
  4524  	logDone("build - error invalid Dockerfile instruction")
  4525  }
  4526  
  4527  func TestBuildEntrypointInheritance(t *testing.T) {
  4528  	defer deleteImages("parent", "child")
  4529  	defer deleteAllContainers()
  4530  
  4531  	if _, err := buildImage("parent", `
  4532      FROM busybox
  4533      ENTRYPOINT exit 130
  4534      `, true); err != nil {
  4535  		t.Fatal(err)
  4536  	}
  4537  
  4538  	status, _ := runCommand(exec.Command(dockerBinary, "run", "parent"))
  4539  
  4540  	if status != 130 {
  4541  		t.Fatalf("expected exit code 130 but received %d", status)
  4542  	}
  4543  
  4544  	if _, err := buildImage("child", `
  4545      FROM parent
  4546      ENTRYPOINT exit 5
  4547      `, true); err != nil {
  4548  		t.Fatal(err)
  4549  	}
  4550  
  4551  	status, _ = runCommand(exec.Command(dockerBinary, "run", "child"))
  4552  
  4553  	if status != 5 {
  4554  		t.Fatalf("expected exit code 5 but received %d", status)
  4555  	}
  4556  
  4557  	logDone("build - clear entrypoint")
  4558  }
  4559  
  4560  func TestBuildEntrypointInheritanceInspect(t *testing.T) {
  4561  	var (
  4562  		name     = "testbuildepinherit"
  4563  		name2    = "testbuildepinherit2"
  4564  		expected = `["/bin/sh","-c","echo quux"]`
  4565  	)
  4566  
  4567  	defer deleteImages(name, name2)
  4568  	defer deleteAllContainers()
  4569  
  4570  	if _, err := buildImage(name, "FROM busybox\nENTRYPOINT /foo/bar", true); err != nil {
  4571  		t.Fatal(err)
  4572  	}
  4573  
  4574  	if _, err := buildImage(name2, fmt.Sprintf("FROM %s\nENTRYPOINT echo quux", name), true); err != nil {
  4575  		t.Fatal(err)
  4576  	}
  4577  
  4578  	res, err := inspectFieldJSON(name2, "Config.Entrypoint")
  4579  	if err != nil {
  4580  		t.Fatal(err, res)
  4581  	}
  4582  
  4583  	if res != expected {
  4584  		t.Fatalf("Expected value %s not in Config.Entrypoint: %s", expected, res)
  4585  	}
  4586  
  4587  	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-t", name2))
  4588  	if err != nil {
  4589  		t.Fatal(err, out)
  4590  	}
  4591  
  4592  	expected = "quux"
  4593  
  4594  	if strings.TrimSpace(out) != expected {
  4595  		t.Fatalf("Expected output is %s, got %s", expected, out)
  4596  	}
  4597  
  4598  	logDone("build - entrypoint override inheritance properly")
  4599  }
  4600  
  4601  func TestBuildRunShEntrypoint(t *testing.T) {
  4602  	name := "testbuildentrypoint"
  4603  	defer deleteImages(name)
  4604  	_, err := buildImage(name,
  4605  		`FROM busybox
  4606                                  ENTRYPOINT /bin/echo`,
  4607  		true)
  4608  	if err != nil {
  4609  		t.Fatal(err)
  4610  	}
  4611  
  4612  	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "--rm", name))
  4613  
  4614  	if err != nil {
  4615  		t.Fatal(err, out)
  4616  	}
  4617  
  4618  	logDone("build - entrypoint with /bin/echo running successfully")
  4619  }
  4620  
  4621  func TestBuildExoticShellInterpolation(t *testing.T) {
  4622  	name := "testbuildexoticshellinterpolation"
  4623  	defer deleteImages(name)
  4624  
  4625  	_, err := buildImage(name, `
  4626  		FROM busybox
  4627  
  4628  		ENV SOME_VAR a.b.c
  4629  
  4630  		RUN [ "$SOME_VAR"       = 'a.b.c' ]
  4631  		RUN [ "${SOME_VAR}"     = 'a.b.c' ]
  4632  		RUN [ "${SOME_VAR%.*}"  = 'a.b'   ]
  4633  		RUN [ "${SOME_VAR%%.*}" = 'a'     ]
  4634  		RUN [ "${SOME_VAR#*.}"  = 'b.c'   ]
  4635  		RUN [ "${SOME_VAR##*.}" = 'c'     ]
  4636  		RUN [ "${SOME_VAR/c/d}" = 'a.b.d' ]
  4637  		RUN [ "${#SOME_VAR}"    = '5'     ]
  4638  
  4639  		RUN [ "${SOME_UNSET_VAR:-$SOME_VAR}" = 'a.b.c' ]
  4640  		RUN [ "${SOME_VAR:+Version: ${SOME_VAR}}" = 'Version: a.b.c' ]
  4641  		RUN [ "${SOME_UNSET_VAR:+${SOME_VAR}}" = '' ]
  4642  		RUN [ "${SOME_UNSET_VAR:-${SOME_VAR:-d.e.f}}" = 'a.b.c' ]
  4643  	`, false)
  4644  	if err != nil {
  4645  		t.Fatal(err)
  4646  	}
  4647  
  4648  	logDone("build - exotic shell interpolation")
  4649  }
  4650  
  4651  func TestBuildVerifySingleQuoteFails(t *testing.T) {
  4652  	// This testcase is supposed to generate an error because the
  4653  	// JSON array we're passing in on the CMD uses single quotes instead
  4654  	// of double quotes (per the JSON spec). This means we interpret it
  4655  	// as a "string" insead of "JSON array" and pass it on to "sh -c" and
  4656  	// it should barf on it.
  4657  	name := "testbuildsinglequotefails"
  4658  	defer deleteImages(name)
  4659  	defer deleteAllContainers()
  4660  
  4661  	_, err := buildImage(name,
  4662  		`FROM busybox
  4663  		CMD [ '/bin/sh', '-c', 'echo hi' ]`,
  4664  		true)
  4665  	_, _, err = runCommandWithOutput(exec.Command(dockerBinary, "run", "--rm", name))
  4666  
  4667  	if err == nil {
  4668  		t.Fatal("The image was not supposed to be able to run")
  4669  	}
  4670  
  4671  	logDone("build - verify single quotes break the build")
  4672  }
  4673  
  4674  func TestBuildVerboseOut(t *testing.T) {
  4675  	name := "testbuildverboseout"
  4676  	defer deleteImages(name)
  4677  
  4678  	_, out, err := buildImageWithOut(name,
  4679  		`FROM busybox
  4680  RUN echo 123`,
  4681  		false)
  4682  
  4683  	if err != nil {
  4684  		t.Fatal(err)
  4685  	}
  4686  	if !strings.Contains(out, "\n123\n") {
  4687  		t.Fatalf("Output should contain %q: %q", "123", out)
  4688  	}
  4689  
  4690  	logDone("build - verbose output from commands")
  4691  }
  4692  
  4693  func TestBuildWithTabs(t *testing.T) {
  4694  	name := "testbuildwithtabs"
  4695  	defer deleteImages(name)
  4696  	_, err := buildImage(name,
  4697  		"FROM busybox\nRUN echo\tone\t\ttwo", true)
  4698  	if err != nil {
  4699  		t.Fatal(err)
  4700  	}
  4701  	res, err := inspectFieldJSON(name, "ContainerConfig.Cmd")
  4702  	if err != nil {
  4703  		t.Fatal(err)
  4704  	}
  4705  	expected1 := `["/bin/sh","-c","echo\tone\t\ttwo"]`
  4706  	expected2 := `["/bin/sh","-c","echo\u0009one\u0009\u0009two"]` // syntactically equivalent, and what Go 1.3 generates
  4707  	if res != expected1 && res != expected2 {
  4708  		t.Fatalf("Missing tabs.\nGot: %s\nExp: %s or %s", res, expected1, expected2)
  4709  	}
  4710  	logDone("build - with tabs")
  4711  }
  4712  
  4713  func TestBuildLabels(t *testing.T) {
  4714  	name := "testbuildlabel"
  4715  	expected := `{"License":"GPL","Vendor":"Acme"}`
  4716  	defer deleteImages(name)
  4717  	_, err := buildImage(name,
  4718  		`FROM busybox
  4719  		LABEL Vendor=Acme
  4720                  LABEL License GPL`,
  4721  		true)
  4722  	if err != nil {
  4723  		t.Fatal(err)
  4724  	}
  4725  	res, err := inspectFieldJSON(name, "Config.Labels")
  4726  	if err != nil {
  4727  		t.Fatal(err)
  4728  	}
  4729  	if res != expected {
  4730  		t.Fatalf("Labels %s, expected %s", res, expected)
  4731  	}
  4732  	logDone("build - label")
  4733  }
  4734  
  4735  func TestBuildLabelsCache(t *testing.T) {
  4736  	name := "testbuildlabelcache"
  4737  	defer deleteImages(name)
  4738  
  4739  	id1, err := buildImage(name,
  4740  		`FROM busybox
  4741  		LABEL Vendor=Acme`, false)
  4742  	if err != nil {
  4743  		t.Fatalf("Build 1 should have worked: %v", err)
  4744  	}
  4745  
  4746  	id2, err := buildImage(name,
  4747  		`FROM busybox
  4748  		LABEL Vendor=Acme`, true)
  4749  	if err != nil || id1 != id2 {
  4750  		t.Fatalf("Build 2 should have worked & used cache(%s,%s): %v", id1, id2, err)
  4751  	}
  4752  
  4753  	id2, err = buildImage(name,
  4754  		`FROM busybox
  4755  		LABEL Vendor=Acme1`, true)
  4756  	if err != nil || id1 == id2 {
  4757  		t.Fatalf("Build 3 should have worked & NOT used cache(%s,%s): %v", id1, id2, err)
  4758  	}
  4759  
  4760  	id2, err = buildImage(name,
  4761  		`FROM busybox
  4762  		LABEL Vendor Acme`, true) // Note: " " and "=" should be same
  4763  	if err != nil || id1 != id2 {
  4764  		t.Fatalf("Build 4 should have worked & used cache(%s,%s): %v", id1, id2, err)
  4765  	}
  4766  
  4767  	// Now make sure the cache isn't used by mistake
  4768  	id1, err = buildImage(name,
  4769  		`FROM busybox
  4770         LABEL f1=b1 f2=b2`, false)
  4771  	if err != nil {
  4772  		t.Fatalf("Build 5 should have worked: %q", err)
  4773  	}
  4774  
  4775  	id2, err = buildImage(name,
  4776  		`FROM busybox
  4777         LABEL f1="b1 f2=b2"`, true)
  4778  	if err != nil || id1 == id2 {
  4779  		t.Fatalf("Build 6 should have worked & NOT used the cache(%s,%s): %q", id1, id2, err)
  4780  	}
  4781  
  4782  	logDone("build - label cache")
  4783  }
  4784  
  4785  func TestBuildStderr(t *testing.T) {
  4786  	// This test just makes sure that no non-error output goes
  4787  	// to stderr
  4788  	name := "testbuildstderr"
  4789  	defer deleteImages(name)
  4790  	_, _, stderr, err := buildImageWithStdoutStderr(name,
  4791  		"FROM busybox\nRUN echo one", true)
  4792  	if err != nil {
  4793  		t.Fatal(err)
  4794  	}
  4795  
  4796  	if runtime.GOOS == "windows" {
  4797  		// stderr might contain a security warning on windows
  4798  		lines := strings.Split(stderr, "\n")
  4799  		for _, v := range lines {
  4800  			if v != "" && !strings.Contains(v, "SECURITY WARNING:") {
  4801  				t.Fatalf("Stderr contains unexpected output line: %q", v)
  4802  			}
  4803  		}
  4804  	} else {
  4805  		if stderr != "" {
  4806  			t.Fatalf("Stderr should have been empty, instead its: %q", stderr)
  4807  		}
  4808  	}
  4809  	logDone("build - testing stderr")
  4810  }
  4811  
  4812  func TestBuildChownSingleFile(t *testing.T) {
  4813  	testRequires(t, UnixCli) // test uses chown: not available on windows
  4814  
  4815  	name := "testbuildchownsinglefile"
  4816  	defer deleteImages(name)
  4817  
  4818  	ctx, err := fakeContext(`
  4819  FROM busybox
  4820  COPY test /
  4821  RUN ls -l /test
  4822  RUN [ $(ls -l /test | awk '{print $3":"$4}') = 'root:root' ]
  4823  `, map[string]string{
  4824  		"test": "test",
  4825  	})
  4826  	if err != nil {
  4827  		t.Fatal(err)
  4828  	}
  4829  	defer ctx.Close()
  4830  
  4831  	if err := os.Chown(filepath.Join(ctx.Dir, "test"), 4242, 4242); err != nil {
  4832  		t.Fatal(err)
  4833  	}
  4834  
  4835  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  4836  		t.Fatal(err)
  4837  	}
  4838  
  4839  	logDone("build - change permission on single file")
  4840  }
  4841  
  4842  func TestBuildSymlinkBreakout(t *testing.T) {
  4843  	name := "testbuildsymlinkbreakout"
  4844  	tmpdir, err := ioutil.TempDir("", name)
  4845  	if err != nil {
  4846  		t.Fatal(err)
  4847  	}
  4848  	defer os.RemoveAll(tmpdir)
  4849  	ctx := filepath.Join(tmpdir, "context")
  4850  	if err := os.MkdirAll(ctx, 0755); err != nil {
  4851  		t.Fatal(err)
  4852  	}
  4853  	if err := ioutil.WriteFile(filepath.Join(ctx, "Dockerfile"), []byte(`
  4854  	from busybox
  4855  	add symlink.tar /
  4856  	add inject /symlink/
  4857  	`), 0644); err != nil {
  4858  		t.Fatal(err)
  4859  	}
  4860  	inject := filepath.Join(ctx, "inject")
  4861  	if err := ioutil.WriteFile(inject, nil, 0644); err != nil {
  4862  		t.Fatal(err)
  4863  	}
  4864  	f, err := os.Create(filepath.Join(ctx, "symlink.tar"))
  4865  	if err != nil {
  4866  		t.Fatal(err)
  4867  	}
  4868  	w := tar.NewWriter(f)
  4869  	w.WriteHeader(&tar.Header{
  4870  		Name:     "symlink2",
  4871  		Typeflag: tar.TypeSymlink,
  4872  		Linkname: "/../../../../../../../../../../../../../../",
  4873  		Uid:      os.Getuid(),
  4874  		Gid:      os.Getgid(),
  4875  	})
  4876  	w.WriteHeader(&tar.Header{
  4877  		Name:     "symlink",
  4878  		Typeflag: tar.TypeSymlink,
  4879  		Linkname: filepath.Join("symlink2", tmpdir),
  4880  		Uid:      os.Getuid(),
  4881  		Gid:      os.Getgid(),
  4882  	})
  4883  	w.Close()
  4884  	f.Close()
  4885  	if _, err := buildImageFromContext(name, fakeContextFromDir(ctx), false); err != nil {
  4886  		t.Fatal(err)
  4887  	}
  4888  	if _, err := os.Lstat(filepath.Join(tmpdir, "inject")); err == nil {
  4889  		t.Fatal("symlink breakout - inject")
  4890  	} else if !os.IsNotExist(err) {
  4891  		t.Fatalf("unexpected error: %v", err)
  4892  	}
  4893  	logDone("build - symlink breakout")
  4894  }
  4895  
  4896  func TestBuildXZHost(t *testing.T) {
  4897  	name := "testbuildxzhost"
  4898  	defer deleteImages(name)
  4899  
  4900  	ctx, err := fakeContext(`
  4901  FROM busybox
  4902  ADD xz /usr/local/sbin/
  4903  RUN chmod 755 /usr/local/sbin/xz
  4904  ADD test.xz /
  4905  RUN [ ! -e /injected ]`,
  4906  		map[string]string{
  4907  			"test.xz": "\xfd\x37\x7a\x58\x5a\x00\x00\x04\xe6\xd6\xb4\x46\x02\x00" +
  4908  				"\x21\x01\x16\x00\x00\x00\x74\x2f\xe5\xa3\x01\x00\x3f\xfd" +
  4909  				"\x37\x7a\x58\x5a\x00\x00\x04\xe6\xd6\xb4\x46\x02\x00\x21",
  4910  			"xz": "#!/bin/sh\ntouch /injected",
  4911  		})
  4912  
  4913  	if err != nil {
  4914  		t.Fatal(err)
  4915  	}
  4916  	defer ctx.Close()
  4917  
  4918  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  4919  		t.Fatal(err)
  4920  	}
  4921  
  4922  	logDone("build - xz host is being used")
  4923  }
  4924  
  4925  func TestBuildVolumesRetainContents(t *testing.T) {
  4926  	var (
  4927  		name     = "testbuildvolumescontent"
  4928  		expected = "some text"
  4929  	)
  4930  	defer deleteImages(name)
  4931  	ctx, err := fakeContext(`
  4932  FROM busybox
  4933  COPY content /foo/file
  4934  VOLUME /foo
  4935  CMD cat /foo/file`,
  4936  		map[string]string{
  4937  			"content": expected,
  4938  		})
  4939  	if err != nil {
  4940  		t.Fatal(err)
  4941  	}
  4942  	defer ctx.Close()
  4943  
  4944  	if _, err := buildImageFromContext(name, ctx, false); err != nil {
  4945  		t.Fatal(err)
  4946  	}
  4947  
  4948  	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "--rm", name))
  4949  	if err != nil {
  4950  		t.Fatal(err)
  4951  	}
  4952  	if out != expected {
  4953  		t.Fatalf("expected file contents for /foo/file to be %q but received %q", expected, out)
  4954  	}
  4955  
  4956  	logDone("build - volumes retain contents in build")
  4957  }
  4958  
  4959  func TestBuildRenamedDockerfile(t *testing.T) {
  4960  	defer deleteAllContainers()
  4961  
  4962  	ctx, err := fakeContext(`FROM busybox
  4963  	RUN echo from Dockerfile`,
  4964  		map[string]string{
  4965  			"Dockerfile":       "FROM busybox\nRUN echo from Dockerfile",
  4966  			"files/Dockerfile": "FROM busybox\nRUN echo from files/Dockerfile",
  4967  			"files/dFile":      "FROM busybox\nRUN echo from files/dFile",
  4968  			"dFile":            "FROM busybox\nRUN echo from dFile",
  4969  			"files/dFile2":     "FROM busybox\nRUN echo from files/dFile2",
  4970  		})
  4971  	defer ctx.Close()
  4972  	if err != nil {
  4973  		t.Fatal(err)
  4974  	}
  4975  
  4976  	out, _, err := dockerCmdInDir(t, ctx.Dir, "build", "-t", "test1", ".")
  4977  	if err != nil {
  4978  		t.Fatalf("Failed to build: %s\n%s", out, err)
  4979  	}
  4980  	if !strings.Contains(out, "from Dockerfile") {
  4981  		t.Fatalf("test1 should have used Dockerfile, output:%s", out)
  4982  	}
  4983  
  4984  	out, _, err = dockerCmdInDir(t, ctx.Dir, "build", "-f", filepath.Join("files", "Dockerfile"), "-t", "test2", ".")
  4985  	if err != nil {
  4986  		t.Fatal(err)
  4987  	}
  4988  	if !strings.Contains(out, "from files/Dockerfile") {
  4989  		t.Fatalf("test2 should have used files/Dockerfile, output:%s", out)
  4990  	}
  4991  
  4992  	out, _, err = dockerCmdInDir(t, ctx.Dir, "build", fmt.Sprintf("--file=%s", filepath.Join("files", "dFile")), "-t", "test3", ".")
  4993  	if err != nil {
  4994  		t.Fatal(err)
  4995  	}
  4996  	if !strings.Contains(out, "from files/dFile") {
  4997  		t.Fatalf("test3 should have used files/dFile, output:%s", out)
  4998  	}
  4999  
  5000  	out, _, err = dockerCmdInDir(t, ctx.Dir, "build", "--file=dFile", "-t", "test4", ".")
  5001  	if err != nil {
  5002  		t.Fatal(err)
  5003  	}
  5004  	if !strings.Contains(out, "from dFile") {
  5005  		t.Fatalf("test4 should have used dFile, output:%s", out)
  5006  	}
  5007  
  5008  	dirWithNoDockerfile, _ := ioutil.TempDir(os.TempDir(), "test5")
  5009  	nonDockerfileFile := filepath.Join(dirWithNoDockerfile, "notDockerfile")
  5010  	if _, err = os.Create(nonDockerfileFile); err != nil {
  5011  		t.Fatal(err)
  5012  	}
  5013  	out, _, err = dockerCmdInDir(t, ctx.Dir, "build", fmt.Sprintf("--file=%s", nonDockerfileFile), "-t", "test5", ".")
  5014  
  5015  	if err == nil {
  5016  		t.Fatalf("test5 was supposed to fail to find passwd")
  5017  	}
  5018  
  5019  	if expected := fmt.Sprintf("The Dockerfile (%s) must be within the build context (.)", strings.Replace(nonDockerfileFile, `\`, `\\`, -1)); !strings.Contains(out, expected) {
  5020  		t.Fatalf("wrong error messsage:%v\nexpected to contain=%v", out, expected)
  5021  	}
  5022  
  5023  	out, _, err = dockerCmdInDir(t, filepath.Join(ctx.Dir, "files"), "build", "-f", filepath.Join("..", "Dockerfile"), "-t", "test6", "..")
  5024  	if err != nil {
  5025  		t.Fatalf("test6 failed: %s", err)
  5026  	}
  5027  	if !strings.Contains(out, "from Dockerfile") {
  5028  		t.Fatalf("test6 should have used root Dockerfile, output:%s", out)
  5029  	}
  5030  
  5031  	out, _, err = dockerCmdInDir(t, filepath.Join(ctx.Dir, "files"), "build", "-f", filepath.Join(ctx.Dir, "files", "Dockerfile"), "-t", "test7", "..")
  5032  	if err != nil {
  5033  		t.Fatalf("test7 failed: %s", err)
  5034  	}
  5035  	if !strings.Contains(out, "from files/Dockerfile") {
  5036  		t.Fatalf("test7 should have used files Dockerfile, output:%s", out)
  5037  	}
  5038  
  5039  	out, _, err = dockerCmdInDir(t, filepath.Join(ctx.Dir, "files"), "build", "-f", filepath.Join("..", "Dockerfile"), "-t", "test8", ".")
  5040  	if err == nil || !strings.Contains(out, "must be within the build context") {
  5041  		t.Fatalf("test8 should have failed with Dockerfile out of context: %s", err)
  5042  	}
  5043  
  5044  	tmpDir := os.TempDir()
  5045  	out, _, err = dockerCmdInDir(t, tmpDir, "build", "-t", "test9", ctx.Dir)
  5046  	if err != nil {
  5047  		t.Fatalf("test9 - failed: %s", err)
  5048  	}
  5049  	if !strings.Contains(out, "from Dockerfile") {
  5050  		t.Fatalf("test9 should have used root Dockerfile, output:%s", out)
  5051  	}
  5052  
  5053  	out, _, err = dockerCmdInDir(t, filepath.Join(ctx.Dir, "files"), "build", "-f", "dFile2", "-t", "test10", ".")
  5054  	if err != nil {
  5055  		t.Fatalf("test10 should have worked: %s", err)
  5056  	}
  5057  	if !strings.Contains(out, "from files/dFile2") {
  5058  		t.Fatalf("test10 should have used files/dFile2, output:%s", out)
  5059  	}
  5060  
  5061  	logDone("build - rename dockerfile")
  5062  }
  5063  
  5064  func TestBuildFromMixedcaseDockerfile(t *testing.T) {
  5065  	testRequires(t, UnixCli) // Dockerfile overwrites dockerfile on windows
  5066  	defer deleteImages("test1")
  5067  
  5068  	ctx, err := fakeContext(`FROM busybox
  5069  	RUN echo from dockerfile`,
  5070  		map[string]string{
  5071  			"dockerfile": "FROM busybox\nRUN echo from dockerfile",
  5072  		})
  5073  	defer ctx.Close()
  5074  	if err != nil {
  5075  		t.Fatal(err)
  5076  	}
  5077  
  5078  	out, _, err := dockerCmdInDir(t, ctx.Dir, "build", "-t", "test1", ".")
  5079  	if err != nil {
  5080  		t.Fatalf("Failed to build: %s\n%s", out, err)
  5081  	}
  5082  
  5083  	if !strings.Contains(out, "from dockerfile") {
  5084  		t.Fatalf("Missing proper output: %s", out)
  5085  	}
  5086  
  5087  	logDone("build - mixedcase Dockerfile")
  5088  }
  5089  
  5090  func TestBuildWithTwoDockerfiles(t *testing.T) {
  5091  	testRequires(t, UnixCli) // Dockerfile overwrites dockerfile on windows
  5092  	defer deleteImages("test1")
  5093  
  5094  	ctx, err := fakeContext(`FROM busybox
  5095  RUN echo from Dockerfile`,
  5096  		map[string]string{
  5097  			"dockerfile": "FROM busybox\nRUN echo from dockerfile",
  5098  		})
  5099  	defer ctx.Close()
  5100  	if err != nil {
  5101  		t.Fatal(err)
  5102  	}
  5103  
  5104  	out, _, err := dockerCmdInDir(t, ctx.Dir, "build", "-t", "test1", ".")
  5105  	if err != nil {
  5106  		t.Fatalf("Failed to build: %s\n%s", out, err)
  5107  	}
  5108  
  5109  	if !strings.Contains(out, "from Dockerfile") {
  5110  		t.Fatalf("Missing proper output: %s", out)
  5111  	}
  5112  
  5113  	logDone("build - two Dockerfiles")
  5114  }
  5115  
  5116  func TestBuildFromURLWithF(t *testing.T) {
  5117  	defer deleteImages("test1")
  5118  
  5119  	server, err := fakeStorage(map[string]string{"baz": `FROM busybox
  5120  RUN echo from baz
  5121  COPY * /tmp/
  5122  RUN find /tmp/`})
  5123  	if err != nil {
  5124  		t.Fatal(err)
  5125  	}
  5126  	defer server.Close()
  5127  
  5128  	ctx, err := fakeContext(`FROM busybox
  5129  RUN echo from Dockerfile`,
  5130  		map[string]string{})
  5131  	defer ctx.Close()
  5132  	if err != nil {
  5133  		t.Fatal(err)
  5134  	}
  5135  
  5136  	// Make sure that -f is ignored and that we don't use the Dockerfile
  5137  	// that's in the current dir
  5138  	out, _, err := dockerCmdInDir(t, ctx.Dir, "build", "-f", "baz", "-t", "test1", server.URL()+"/baz")
  5139  	if err != nil {
  5140  		t.Fatalf("Failed to build: %s\n%s", out, err)
  5141  	}
  5142  
  5143  	if !strings.Contains(out, "from baz") ||
  5144  		strings.Contains(out, "/tmp/baz") ||
  5145  		!strings.Contains(out, "/tmp/Dockerfile") {
  5146  		t.Fatalf("Missing proper output: %s", out)
  5147  	}
  5148  
  5149  	logDone("build - from URL with -f")
  5150  }
  5151  
  5152  func TestBuildFromStdinWithF(t *testing.T) {
  5153  	defer deleteImages("test1")
  5154  
  5155  	ctx, err := fakeContext(`FROM busybox
  5156  RUN echo from Dockerfile`,
  5157  		map[string]string{})
  5158  	defer ctx.Close()
  5159  	if err != nil {
  5160  		t.Fatal(err)
  5161  	}
  5162  
  5163  	// Make sure that -f is ignored and that we don't use the Dockerfile
  5164  	// that's in the current dir
  5165  	dockerCommand := exec.Command(dockerBinary, "build", "-f", "baz", "-t", "test1", "-")
  5166  	dockerCommand.Dir = ctx.Dir
  5167  	dockerCommand.Stdin = strings.NewReader(`FROM busybox
  5168  RUN echo from baz
  5169  COPY * /tmp/
  5170  RUN find /tmp/`)
  5171  	out, status, err := runCommandWithOutput(dockerCommand)
  5172  	if err != nil || status != 0 {
  5173  		t.Fatalf("Error building: %s", err)
  5174  	}
  5175  
  5176  	if !strings.Contains(out, "from baz") ||
  5177  		strings.Contains(out, "/tmp/baz") ||
  5178  		!strings.Contains(out, "/tmp/Dockerfile") {
  5179  		t.Fatalf("Missing proper output: %s", out)
  5180  	}
  5181  
  5182  	logDone("build - from stdin with -f")
  5183  }
  5184  
  5185  func TestBuildFromOfficialNames(t *testing.T) {
  5186  	name := "testbuildfromofficial"
  5187  	fromNames := []string{
  5188  		"busybox",
  5189  		"docker.io/busybox",
  5190  		"index.docker.io/busybox",
  5191  		"library/busybox",
  5192  		"docker.io/library/busybox",
  5193  		"index.docker.io/library/busybox",
  5194  	}
  5195  	for idx, fromName := range fromNames {
  5196  		imgName := fmt.Sprintf("%s%d", name, idx)
  5197  		_, err := buildImage(imgName, "FROM "+fromName, true)
  5198  		if err != nil {
  5199  			t.Errorf("Build failed using FROM %s: %s", fromName, err)
  5200  		}
  5201  		deleteImages(imgName)
  5202  	}
  5203  	logDone("build - from official names")
  5204  }
  5205  
  5206  func TestBuildDockerfileOutsideContext(t *testing.T) {
  5207  	testRequires(t, UnixCli) // uses os.Symlink: not implemented in windows at the time of writing (go-1.4.2)
  5208  
  5209  	name := "testbuilddockerfileoutsidecontext"
  5210  	tmpdir, err := ioutil.TempDir("", name)
  5211  	if err != nil {
  5212  		t.Fatal(err)
  5213  	}
  5214  	defer os.RemoveAll(tmpdir)
  5215  	ctx := filepath.Join(tmpdir, "context")
  5216  	if err := os.MkdirAll(ctx, 0755); err != nil {
  5217  		t.Fatal(err)
  5218  	}
  5219  	if err := ioutil.WriteFile(filepath.Join(ctx, "Dockerfile"), []byte("FROM scratch\nENV X Y"), 0644); err != nil {
  5220  		t.Fatal(err)
  5221  	}
  5222  	wd, err := os.Getwd()
  5223  	if err != nil {
  5224  		t.Fatal(err)
  5225  	}
  5226  	defer os.Chdir(wd)
  5227  	if err := os.Chdir(ctx); err != nil {
  5228  		t.Fatal(err)
  5229  	}
  5230  	if err := ioutil.WriteFile(filepath.Join(tmpdir, "outsideDockerfile"), []byte("FROM scratch\nENV x y"), 0644); err != nil {
  5231  		t.Fatal(err)
  5232  	}
  5233  	if err := os.Symlink(filepath.Join("..", "outsideDockerfile"), filepath.Join(ctx, "dockerfile1")); err != nil {
  5234  		t.Fatal(err)
  5235  	}
  5236  	if err := os.Symlink(filepath.Join(tmpdir, "outsideDockerfile"), filepath.Join(ctx, "dockerfile2")); err != nil {
  5237  		t.Fatal(err)
  5238  	}
  5239  
  5240  	for _, dockerfilePath := range []string{
  5241  		filepath.Join("..", "outsideDockerfile"),
  5242  		filepath.Join(ctx, "dockerfile1"),
  5243  		filepath.Join(ctx, "dockerfile2"),
  5244  	} {
  5245  		out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "build", "-t", name, "--no-cache", "-f", dockerfilePath, "."))
  5246  		if err == nil {
  5247  			t.Fatalf("Expected error with %s. Out: %s", dockerfilePath, out)
  5248  		}
  5249  		if !strings.Contains(out, "must be within the build context") && !strings.Contains(out, "Cannot locate Dockerfile") {
  5250  			t.Fatalf("Unexpected error with %s. Out: %s", dockerfilePath, out)
  5251  		}
  5252  		deleteImages(name)
  5253  	}
  5254  
  5255  	os.Chdir(tmpdir)
  5256  
  5257  	// Path to Dockerfile should be resolved relative to working directory, not relative to context.
  5258  	// There is a Dockerfile in the context, but since there is no Dockerfile in the current directory, the following should fail
  5259  	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "build", "-t", name, "--no-cache", "-f", "Dockerfile", ctx))
  5260  	if err == nil {
  5261  		t.Fatalf("Expected error. Out: %s", out)
  5262  	}
  5263  	deleteImages(name)
  5264  
  5265  	logDone("build - Dockerfile outside context")
  5266  }
  5267  
  5268  func TestBuildSpaces(t *testing.T) {
  5269  	// Test to make sure that leading/trailing spaces on a command
  5270  	// doesn't change the error msg we get
  5271  	var (
  5272  		err1 error
  5273  		err2 error
  5274  	)
  5275  
  5276  	name := "testspaces"
  5277  	defer deleteImages(name)
  5278  	ctx, err := fakeContext("FROM busybox\nCOPY\n",
  5279  		map[string]string{
  5280  			"Dockerfile": "FROM busybox\nCOPY\n",
  5281  		})
  5282  	if err != nil {
  5283  		t.Fatal(err)
  5284  	}
  5285  	defer ctx.Close()
  5286  
  5287  	if _, err1 = buildImageFromContext(name, ctx, false); err1 == nil {
  5288  		t.Fatal("Build 1 was supposed to fail, but didn't")
  5289  	}
  5290  
  5291  	ctx.Add("Dockerfile", "FROM busybox\nCOPY    ")
  5292  	if _, err2 = buildImageFromContext(name, ctx, false); err2 == nil {
  5293  		t.Fatal("Build 2 was supposed to fail, but didn't")
  5294  	}
  5295  
  5296  	removeLogTimestamps := func(s string) string {
  5297  		return regexp.MustCompile(`time="(.*?)"`).ReplaceAllString(s, `time=[TIMESTAMP]`)
  5298  	}
  5299  
  5300  	// Skip over the times
  5301  	e1 := removeLogTimestamps(err1.Error())
  5302  	e2 := removeLogTimestamps(err2.Error())
  5303  
  5304  	// Ignore whitespace since that's what were verifying doesn't change stuff
  5305  	if strings.Replace(e1, " ", "", -1) != strings.Replace(e2, " ", "", -1) {
  5306  		t.Fatalf("Build 2's error wasn't the same as build 1's\n1:%s\n2:%s", err1, err2)
  5307  	}
  5308  
  5309  	ctx.Add("Dockerfile", "FROM busybox\n   COPY")
  5310  	if _, err2 = buildImageFromContext(name, ctx, false); err2 == nil {
  5311  		t.Fatal("Build 3 was supposed to fail, but didn't")
  5312  	}
  5313  
  5314  	// Skip over the times
  5315  	e1 = removeLogTimestamps(err1.Error())
  5316  	e2 = removeLogTimestamps(err2.Error())
  5317  
  5318  	// Ignore whitespace since that's what were verifying doesn't change stuff
  5319  	if strings.Replace(e1, " ", "", -1) != strings.Replace(e2, " ", "", -1) {
  5320  		t.Fatalf("Build 3's error wasn't the same as build 1's\n1:%s\n3:%s", err1, err2)
  5321  	}
  5322  
  5323  	ctx.Add("Dockerfile", "FROM busybox\n   COPY    ")
  5324  	if _, err2 = buildImageFromContext(name, ctx, false); err2 == nil {
  5325  		t.Fatal("Build 4 was supposed to fail, but didn't")
  5326  	}
  5327  
  5328  	// Skip over the times
  5329  	e1 = removeLogTimestamps(err1.Error())
  5330  	e2 = removeLogTimestamps(err2.Error())
  5331  
  5332  	// Ignore whitespace since that's what were verifying doesn't change stuff
  5333  	if strings.Replace(e1, " ", "", -1) != strings.Replace(e2, " ", "", -1) {
  5334  		t.Fatalf("Build 4's error wasn't the same as build 1's\n1:%s\n4:%s", err1, err2)
  5335  	}
  5336  
  5337  	logDone("build - test spaces")
  5338  }
  5339  
  5340  func TestBuildSpacesWithQuotes(t *testing.T) {
  5341  	// Test to make sure that spaces in quotes aren't lost
  5342  	name := "testspacesquotes"
  5343  	defer deleteImages(name)
  5344  
  5345  	dockerfile := `FROM busybox
  5346  RUN echo "  \
  5347    foo  "`
  5348  
  5349  	_, out, err := buildImageWithOut(name, dockerfile, false)
  5350  	if err != nil {
  5351  		t.Fatal("Build failed:", err)
  5352  	}
  5353  
  5354  	expecting := "\n    foo  \n"
  5355  	if !strings.Contains(out, expecting) {
  5356  		t.Fatalf("Bad output: %q expecting to contian %q", out, expecting)
  5357  	}
  5358  
  5359  	logDone("build - test spaces with quotes")
  5360  }
  5361  
  5362  // #4393
  5363  func TestBuildVolumeFileExistsinContainer(t *testing.T) {
  5364  	buildCmd := exec.Command(dockerBinary, "build", "-t", "docker-test-errcreatevolumewithfile", "-")
  5365  	buildCmd.Stdin = strings.NewReader(`
  5366  	FROM busybox
  5367  	RUN touch /foo
  5368  	VOLUME /foo
  5369  	`)
  5370  
  5371  	out, _, err := runCommandWithOutput(buildCmd)
  5372  	if err == nil || !strings.Contains(out, "file exists") {
  5373  		t.Fatalf("expected build to fail when file exists in container at requested volume path")
  5374  	}
  5375  
  5376  	logDone("build - errors when volume is specified where a file exists")
  5377  }
  5378  
  5379  func TestBuildMissingArgs(t *testing.T) {
  5380  	// Test to make sure that all Dockerfile commands (except the ones listed
  5381  	// in skipCmds) will generate an error if no args are provided.
  5382  	// Note: INSERT is deprecated so we exclude it because of that.
  5383  	skipCmds := map[string]struct{}{
  5384  		"CMD":        {},
  5385  		"RUN":        {},
  5386  		"ENTRYPOINT": {},
  5387  		"INSERT":     {},
  5388  	}
  5389  
  5390  	defer deleteAllContainers()
  5391  
  5392  	for cmd := range command.Commands {
  5393  		cmd = strings.ToUpper(cmd)
  5394  		if _, ok := skipCmds[cmd]; ok {
  5395  			continue
  5396  		}
  5397  
  5398  		var dockerfile string
  5399  		if cmd == "FROM" {
  5400  			dockerfile = cmd
  5401  		} else {
  5402  			// Add FROM to make sure we don't complain about it missing
  5403  			dockerfile = "FROM busybox\n" + cmd
  5404  		}
  5405  
  5406  		ctx, err := fakeContext(dockerfile, map[string]string{})
  5407  		if err != nil {
  5408  			t.Fatal(err)
  5409  		}
  5410  		defer ctx.Close()
  5411  		var out string
  5412  		if out, err = buildImageFromContext("args", ctx, true); err == nil {
  5413  			t.Fatalf("%s was supposed to fail. Out:%s", cmd, out)
  5414  		}
  5415  		if !strings.Contains(err.Error(), cmd+" requires") {
  5416  			t.Fatalf("%s returned the wrong type of error:%s", cmd, err)
  5417  		}
  5418  	}
  5419  
  5420  	logDone("build - verify missing args")
  5421  }
  5422  
  5423  func TestBuildEmptyScratch(t *testing.T) {
  5424  	defer deleteImages("sc")
  5425  	_, out, err := buildImageWithOut("sc", "FROM scratch", true)
  5426  	if err == nil {
  5427  		t.Fatalf("Build was supposed to fail")
  5428  	}
  5429  	if !strings.Contains(out, "No image was generated") {
  5430  		t.Fatalf("Wrong error message: %v", out)
  5431  	}
  5432  	logDone("build - empty scratch Dockerfile")
  5433  }
  5434  
  5435  func TestBuildDotDotFile(t *testing.T) {
  5436  	defer deleteImages("sc")
  5437  	ctx, err := fakeContext("FROM busybox\n",
  5438  		map[string]string{
  5439  			"..gitme": "",
  5440  		})
  5441  	if err != nil {
  5442  		t.Fatal(err)
  5443  	}
  5444  	defer ctx.Close()
  5445  
  5446  	if _, err = buildImageFromContext("sc", ctx, false); err != nil {
  5447  		t.Fatalf("Build was supposed to work: %s", err)
  5448  	}
  5449  	logDone("build - ..file")
  5450  }
  5451  
  5452  func TestBuildNotVerbose(t *testing.T) {
  5453  	defer deleteAllContainers()
  5454  	defer deleteImages("verbose")
  5455  
  5456  	ctx, err := fakeContext("FROM busybox\nENV abc=hi\nRUN echo $abc there", map[string]string{})
  5457  	if err != nil {
  5458  		t.Fatal(err)
  5459  	}
  5460  	defer ctx.Close()
  5461  
  5462  	// First do it w/verbose - baseline
  5463  	buildCmd := exec.Command(dockerBinary, "build", "--no-cache", "-t", "verbose", ".")
  5464  	buildCmd.Dir = ctx.Dir
  5465  	out, _, err := runCommandWithOutput(buildCmd)
  5466  	if err != nil {
  5467  		t.Fatalf("failed to build the image w/o -q: %s, %v", out, err)
  5468  	}
  5469  	if !strings.Contains(out, "hi there") {
  5470  		t.Fatalf("missing output:%s\n", out)
  5471  	}
  5472  
  5473  	// Now do it w/o verbose
  5474  	buildCmd = exec.Command(dockerBinary, "build", "--no-cache", "-q", "-t", "verbose", ".")
  5475  	buildCmd.Dir = ctx.Dir
  5476  	out, _, err = runCommandWithOutput(buildCmd)
  5477  	if err != nil {
  5478  		t.Fatalf("failed to build the image w/ -q: %s, %v", out, err)
  5479  	}
  5480  	if strings.Contains(out, "hi there") {
  5481  		t.Fatalf("Bad output, should not contain 'hi there':%s", out)
  5482  	}
  5483  
  5484  	logDone("build - not verbose")
  5485  }
  5486  
  5487  func TestBuildRUNoneJSON(t *testing.T) {
  5488  	name := "testbuildrunonejson"
  5489  
  5490  	defer deleteAllContainers()
  5491  	defer deleteImages(name)
  5492  
  5493  	ctx, err := fakeContext(`FROM hello-world:frozen
  5494  RUN [ "/hello" ]`, map[string]string{})
  5495  	if err != nil {
  5496  		t.Fatal(err)
  5497  	}
  5498  	defer ctx.Close()
  5499  
  5500  	buildCmd := exec.Command(dockerBinary, "build", "--no-cache", "-t", name, ".")
  5501  	buildCmd.Dir = ctx.Dir
  5502  	out, _, err := runCommandWithOutput(buildCmd)
  5503  	if err != nil {
  5504  		t.Fatalf("failed to build the image: %s, %v", out, err)
  5505  	}
  5506  
  5507  	if !strings.Contains(out, "Hello from Docker") {
  5508  		t.Fatalf("bad output: %s", out)
  5509  	}
  5510  
  5511  	logDone("build - RUN with one JSON arg")
  5512  }
  5513  
  5514  func TestBuildResourceConstraintsAreUsed(t *testing.T) {
  5515  	name := "testbuildresourceconstraints"
  5516  	defer deleteAllContainers()
  5517  	defer deleteImages(name)
  5518  
  5519  	ctx, err := fakeContext(`
  5520  	FROM hello-world:frozen
  5521  	RUN ["/hello"]
  5522  	`, map[string]string{})
  5523  	if err != nil {
  5524  		t.Fatal(err)
  5525  	}
  5526  
  5527  	cmd := exec.Command(dockerBinary, "build", "--rm=false", "--memory=64m", "--memory-swap=-1", "--cpuset-cpus=1", "--cpu-shares=100", "-t", name, ".")
  5528  	cmd.Dir = ctx.Dir
  5529  
  5530  	out, _, err := runCommandWithOutput(cmd)
  5531  	if err != nil {
  5532  		t.Fatal(err, out)
  5533  	}
  5534  	out, _, err = dockerCmd(t, "ps", "-lq")
  5535  	if err != nil {
  5536  		t.Fatal(err, out)
  5537  	}
  5538  
  5539  	cID := stripTrailingCharacters(out)
  5540  
  5541  	type hostConfig struct {
  5542  		Memory     float64 // Use float64 here since the json decoder sees it that way
  5543  		MemorySwap int
  5544  		CpusetCpus string
  5545  		CpuShares  int
  5546  	}
  5547  
  5548  	cfg, err := inspectFieldJSON(cID, "HostConfig")
  5549  	if err != nil {
  5550  		t.Fatal(err)
  5551  	}
  5552  
  5553  	var c1 hostConfig
  5554  	if err := json.Unmarshal([]byte(cfg), &c1); err != nil {
  5555  		t.Fatal(err, cfg)
  5556  	}
  5557  	mem := int64(c1.Memory)
  5558  	if mem != 67108864 || c1.MemorySwap != -1 || c1.CpusetCpus != "1" || c1.CpuShares != 100 {
  5559  		t.Fatalf("resource constraints not set properly:\nMemory: %d, MemSwap: %d, CpusetCpus: %s, CpuShares: %d",
  5560  			mem, c1.MemorySwap, c1.CpusetCpus, c1.CpuShares)
  5561  	}
  5562  
  5563  	// Make sure constraints aren't saved to image
  5564  	_, _, err = dockerCmd(t, "run", "--name=test", name)
  5565  	if err != nil {
  5566  		t.Fatal(err)
  5567  	}
  5568  	cfg, err = inspectFieldJSON("test", "HostConfig")
  5569  	if err != nil {
  5570  		t.Fatal(err)
  5571  	}
  5572  	var c2 hostConfig
  5573  	if err := json.Unmarshal([]byte(cfg), &c2); err != nil {
  5574  		t.Fatal(err, cfg)
  5575  	}
  5576  	mem = int64(c2.Memory)
  5577  	if mem == 67108864 || c2.MemorySwap == -1 || c2.CpusetCpus == "1" || c2.CpuShares == 100 {
  5578  		t.Fatalf("resource constraints leaked from build:\nMemory: %d, MemSwap: %d, CpusetCpus: %s, CpuShares: %d",
  5579  			mem, c2.MemorySwap, c2.CpusetCpus, c2.CpuShares)
  5580  	}
  5581  
  5582  	logDone("build - resource constraints applied")
  5583  }
  5584  
  5585  func TestBuildEmptyStringVolume(t *testing.T) {
  5586  	name := "testbuildemptystringvolume"
  5587  	defer deleteImages(name)
  5588  
  5589  	_, err := buildImage(name, `
  5590    FROM busybox
  5591    ENV foo=""
  5592    VOLUME $foo
  5593    `, false)
  5594  	if err == nil {
  5595  		t.Fatal("Should have failed to build")
  5596  	}
  5597  
  5598  	logDone("build - empty string volume")
  5599  }