github.com/powellquiring/docker@v1.6.0-rc1/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  
  1962  	// (Note: one year, will never finish)
  1963  	ctx, err := fakeContext("FROM busybox\nRUN sleep 31536000", nil)
  1964  	if err != nil {
  1965  		t.Fatal(err)
  1966  	}
  1967  	defer ctx.Close()
  1968  
  1969  	var wg sync.WaitGroup
  1970  	defer wg.Wait()
  1971  
  1972  	finish := make(chan struct{})
  1973  	defer close(finish)
  1974  
  1975  	eventStart := make(chan struct{})
  1976  	eventDie := make(chan struct{})
  1977  
  1978  	// Start one second ago, to avoid rounding problems
  1979  	startEpoch := time.Now().Add(-1 * time.Second)
  1980  
  1981  	// Goroutine responsible for watching start/die events from `docker events`
  1982  	wg.Add(1)
  1983  	go func() {
  1984  		defer wg.Done()
  1985  
  1986  		// Watch for events since epoch.
  1987  		eventsCmd := exec.Command(dockerBinary, "events",
  1988  			"-since", fmt.Sprint(startEpoch.Unix()))
  1989  		stdout, err := eventsCmd.StdoutPipe()
  1990  		err = eventsCmd.Start()
  1991  		if err != nil {
  1992  			t.Fatalf("failed to start 'docker events': %s", err)
  1993  		}
  1994  
  1995  		go func() {
  1996  			<-finish
  1997  			eventsCmd.Process.Kill()
  1998  		}()
  1999  
  2000  		var started, died bool
  2001  		matchStart := regexp.MustCompile(" \\(from busybox\\:latest\\) start$")
  2002  		matchDie := regexp.MustCompile(" \\(from busybox\\:latest\\) die$")
  2003  
  2004  		//
  2005  		// Read lines of `docker events` looking for container start and stop.
  2006  		//
  2007  		scanner := bufio.NewScanner(stdout)
  2008  		for scanner.Scan() {
  2009  			if ok := matchStart.MatchString(scanner.Text()); ok {
  2010  				if started {
  2011  					t.Fatal("assertion fail: more than one container started")
  2012  				}
  2013  				close(eventStart)
  2014  				started = true
  2015  			}
  2016  			if ok := matchDie.MatchString(scanner.Text()); ok {
  2017  				if died {
  2018  					t.Fatal("assertion fail: more than one container died")
  2019  				}
  2020  				close(eventDie)
  2021  				died = true
  2022  			}
  2023  		}
  2024  
  2025  		err = eventsCmd.Wait()
  2026  		if err != nil && !IsKilled(err) {
  2027  			t.Fatalf("docker events had bad exit status: %s", err)
  2028  		}
  2029  	}()
  2030  
  2031  	buildCmd := exec.Command(dockerBinary, "build", "-t", name, ".")
  2032  	buildCmd.Dir = ctx.Dir
  2033  	buildCmd.Stdout = os.Stdout
  2034  
  2035  	err = buildCmd.Start()
  2036  	if err != nil {
  2037  		t.Fatalf("failed to run build: %s", err)
  2038  	}
  2039  
  2040  	select {
  2041  	case <-time.After(30 * time.Second):
  2042  		t.Fatal("failed to observe build container start in timely fashion")
  2043  	case <-eventStart:
  2044  		// Proceeds from here when we see the container fly past in the
  2045  		// output of "docker events".
  2046  		// Now we know the container is running.
  2047  	}
  2048  
  2049  	// Send a kill to the `docker build` command.
  2050  	// Causes the underlying build to be cancelled due to socket close.
  2051  	err = buildCmd.Process.Kill()
  2052  	if err != nil {
  2053  		t.Fatalf("error killing build command: %s", err)
  2054  	}
  2055  
  2056  	// Get the exit status of `docker build`, check it exited because killed.
  2057  	err = buildCmd.Wait()
  2058  	if err != nil && !IsKilled(err) {
  2059  		t.Fatalf("wait failed during build run: %T %s", err, err)
  2060  	}
  2061  
  2062  	select {
  2063  	case <-time.After(30 * time.Second):
  2064  		// If we don't get here in a timely fashion, it wasn't killed.
  2065  		t.Fatal("container cancel did not succeed")
  2066  	case <-eventDie:
  2067  		// We saw the container shut down in the `docker events` stream,
  2068  		// as expected.
  2069  	}
  2070  
  2071  	logDone("build - ensure canceled job finishes immediately")
  2072  }
  2073  
  2074  func TestBuildRm(t *testing.T) {
  2075  	name := "testbuildrm"
  2076  	defer deleteImages(name)
  2077  	ctx, err := fakeContext("FROM scratch\nADD foo /\nADD foo /", map[string]string{"foo": "bar"})
  2078  	if err != nil {
  2079  		t.Fatal(err)
  2080  	}
  2081  	defer ctx.Close()
  2082  	{
  2083  		containerCountBefore, err := getContainerCount()
  2084  		if err != nil {
  2085  			t.Fatalf("failed to get the container count: %s", err)
  2086  		}
  2087  
  2088  		out, _, err := dockerCmdInDir(t, ctx.Dir, "build", "--rm", "-t", name, ".")
  2089  
  2090  		if err != nil {
  2091  			t.Fatal("failed to build the image", out)
  2092  		}
  2093  
  2094  		containerCountAfter, err := getContainerCount()
  2095  		if err != nil {
  2096  			t.Fatalf("failed to get the container count: %s", err)
  2097  		}
  2098  
  2099  		if containerCountBefore != containerCountAfter {
  2100  			t.Fatalf("-rm shouldn't have left containers behind")
  2101  		}
  2102  		deleteImages(name)
  2103  	}
  2104  
  2105  	{
  2106  		containerCountBefore, err := getContainerCount()
  2107  		if err != nil {
  2108  			t.Fatalf("failed to get the container count: %s", err)
  2109  		}
  2110  
  2111  		out, _, err := dockerCmdInDir(t, ctx.Dir, "build", "-t", name, ".")
  2112  
  2113  		if err != nil {
  2114  			t.Fatal("failed to build the image", out)
  2115  		}
  2116  
  2117  		containerCountAfter, err := getContainerCount()
  2118  		if err != nil {
  2119  			t.Fatalf("failed to get the container count: %s", err)
  2120  		}
  2121  
  2122  		if containerCountBefore != containerCountAfter {
  2123  			t.Fatalf("--rm shouldn't have left containers behind")
  2124  		}
  2125  		deleteImages(name)
  2126  	}
  2127  
  2128  	{
  2129  		containerCountBefore, err := getContainerCount()
  2130  		if err != nil {
  2131  			t.Fatalf("failed to get the container count: %s", err)
  2132  		}
  2133  
  2134  		out, _, err := dockerCmdInDir(t, ctx.Dir, "build", "--rm=false", "-t", name, ".")
  2135  
  2136  		if err != nil {
  2137  			t.Fatal("failed to build the image", out)
  2138  		}
  2139  
  2140  		containerCountAfter, err := getContainerCount()
  2141  		if err != nil {
  2142  			t.Fatalf("failed to get the container count: %s", err)
  2143  		}
  2144  
  2145  		if containerCountBefore == containerCountAfter {
  2146  			t.Fatalf("--rm=false should have left containers behind")
  2147  		}
  2148  		deleteAllContainers()
  2149  		deleteImages(name)
  2150  
  2151  	}
  2152  
  2153  	logDone("build - ensure --rm doesn't leave containers behind and that --rm=true is the default")
  2154  	logDone("build - ensure --rm=false overrides the default")
  2155  }
  2156  
  2157  func TestBuildWithVolumes(t *testing.T) {
  2158  	var (
  2159  		result   map[string]map[string]struct{}
  2160  		name     = "testbuildvolumes"
  2161  		emptyMap = make(map[string]struct{})
  2162  		expected = map[string]map[string]struct{}{
  2163  			"/test1":  emptyMap,
  2164  			"/test2":  emptyMap,
  2165  			"/test3":  emptyMap,
  2166  			"/test4":  emptyMap,
  2167  			"/test5":  emptyMap,
  2168  			"/test6":  emptyMap,
  2169  			"[/test7": emptyMap,
  2170  			"/test8]": emptyMap,
  2171  		}
  2172  	)
  2173  	defer deleteImages(name)
  2174  	_, err := buildImage(name,
  2175  		`FROM scratch
  2176  		VOLUME /test1
  2177  		VOLUME /test2
  2178      VOLUME /test3 /test4
  2179      VOLUME ["/test5", "/test6"]
  2180      VOLUME [/test7 /test8]
  2181      `,
  2182  		true)
  2183  	if err != nil {
  2184  		t.Fatal(err)
  2185  	}
  2186  	res, err := inspectFieldJSON(name, "Config.Volumes")
  2187  	if err != nil {
  2188  		t.Fatal(err)
  2189  	}
  2190  
  2191  	err = unmarshalJSON([]byte(res), &result)
  2192  	if err != nil {
  2193  		t.Fatal(err)
  2194  	}
  2195  
  2196  	equal := reflect.DeepEqual(&result, &expected)
  2197  
  2198  	if !equal {
  2199  		t.Fatalf("Volumes %s, expected %s", result, expected)
  2200  	}
  2201  
  2202  	logDone("build - with volumes")
  2203  }
  2204  
  2205  func TestBuildMaintainer(t *testing.T) {
  2206  	name := "testbuildmaintainer"
  2207  	expected := "dockerio"
  2208  	defer deleteImages(name)
  2209  	_, err := buildImage(name,
  2210  		`FROM scratch
  2211          MAINTAINER dockerio`,
  2212  		true)
  2213  	if err != nil {
  2214  		t.Fatal(err)
  2215  	}
  2216  	res, err := inspectField(name, "Author")
  2217  	if err != nil {
  2218  		t.Fatal(err)
  2219  	}
  2220  	if res != expected {
  2221  		t.Fatalf("Maintainer %s, expected %s", res, expected)
  2222  	}
  2223  	logDone("build - maintainer")
  2224  }
  2225  
  2226  func TestBuildUser(t *testing.T) {
  2227  	name := "testbuilduser"
  2228  	expected := "dockerio"
  2229  	defer deleteImages(name)
  2230  	_, err := buildImage(name,
  2231  		`FROM busybox
  2232  		RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  2233  		USER dockerio
  2234  		RUN [ $(whoami) = 'dockerio' ]`,
  2235  		true)
  2236  	if err != nil {
  2237  		t.Fatal(err)
  2238  	}
  2239  	res, err := inspectField(name, "Config.User")
  2240  	if err != nil {
  2241  		t.Fatal(err)
  2242  	}
  2243  	if res != expected {
  2244  		t.Fatalf("User %s, expected %s", res, expected)
  2245  	}
  2246  	logDone("build - user")
  2247  }
  2248  
  2249  func TestBuildRelativeWorkdir(t *testing.T) {
  2250  	name := "testbuildrelativeworkdir"
  2251  	expected := "/test2/test3"
  2252  	defer deleteImages(name)
  2253  	_, err := buildImage(name,
  2254  		`FROM busybox
  2255  		RUN [ "$PWD" = '/' ]
  2256  		WORKDIR test1
  2257  		RUN [ "$PWD" = '/test1' ]
  2258  		WORKDIR /test2
  2259  		RUN [ "$PWD" = '/test2' ]
  2260  		WORKDIR test3
  2261  		RUN [ "$PWD" = '/test2/test3' ]`,
  2262  		true)
  2263  	if err != nil {
  2264  		t.Fatal(err)
  2265  	}
  2266  	res, err := inspectField(name, "Config.WorkingDir")
  2267  	if err != nil {
  2268  		t.Fatal(err)
  2269  	}
  2270  	if res != expected {
  2271  		t.Fatalf("Workdir %s, expected %s", res, expected)
  2272  	}
  2273  	logDone("build - relative workdir")
  2274  }
  2275  
  2276  func TestBuildWorkdirWithEnvVariables(t *testing.T) {
  2277  	name := "testbuildworkdirwithenvvariables"
  2278  	expected := "/test1/test2"
  2279  	defer deleteImages(name)
  2280  	_, err := buildImage(name,
  2281  		`FROM busybox
  2282  		ENV DIRPATH /test1
  2283  		ENV SUBDIRNAME test2
  2284  		WORKDIR $DIRPATH
  2285  		WORKDIR $SUBDIRNAME/$MISSING_VAR`,
  2286  		true)
  2287  	if err != nil {
  2288  		t.Fatal(err)
  2289  	}
  2290  	res, err := inspectField(name, "Config.WorkingDir")
  2291  	if err != nil {
  2292  		t.Fatal(err)
  2293  	}
  2294  	if res != expected {
  2295  		t.Fatalf("Workdir %s, expected %s", res, expected)
  2296  	}
  2297  	logDone("build - workdir with env variables")
  2298  }
  2299  
  2300  func TestBuildRelativeCopy(t *testing.T) {
  2301  	name := "testbuildrelativecopy"
  2302  	defer deleteImages(name)
  2303  	dockerfile := `
  2304  		FROM busybox
  2305  			WORKDIR /test1
  2306  			WORKDIR test2
  2307  			RUN [ "$PWD" = '/test1/test2' ]
  2308  			COPY foo ./
  2309  			RUN [ "$(cat /test1/test2/foo)" = 'hello' ]
  2310  			ADD foo ./bar/baz
  2311  			RUN [ "$(cat /test1/test2/bar/baz)" = 'hello' ]
  2312  			COPY foo ./bar/baz2
  2313  			RUN [ "$(cat /test1/test2/bar/baz2)" = 'hello' ]
  2314  			WORKDIR ..
  2315  			COPY foo ./
  2316  			RUN [ "$(cat /test1/foo)" = 'hello' ]
  2317  			COPY foo /test3/
  2318  			RUN [ "$(cat /test3/foo)" = 'hello' ]
  2319  			WORKDIR /test4
  2320  			COPY . .
  2321  			RUN [ "$(cat /test4/foo)" = 'hello' ]
  2322  			WORKDIR /test5/test6
  2323  			COPY foo ../
  2324  			RUN [ "$(cat /test5/foo)" = 'hello' ]
  2325  			`
  2326  	ctx, err := fakeContext(dockerfile, map[string]string{
  2327  		"foo": "hello",
  2328  	})
  2329  	defer ctx.Close()
  2330  	if err != nil {
  2331  		t.Fatal(err)
  2332  	}
  2333  	_, err = buildImageFromContext(name, ctx, false)
  2334  	if err != nil {
  2335  		t.Fatal(err)
  2336  	}
  2337  	logDone("build - relative copy/add")
  2338  }
  2339  
  2340  func TestBuildEnv(t *testing.T) {
  2341  	name := "testbuildenv"
  2342  	expected := "[PATH=/test:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin PORT=2375]"
  2343  	defer deleteImages(name)
  2344  	_, err := buildImage(name,
  2345  		`FROM busybox
  2346  		ENV PATH /test:$PATH
  2347          ENV PORT 2375
  2348  		RUN [ $(env | grep PORT) = 'PORT=2375' ]`,
  2349  		true)
  2350  	if err != nil {
  2351  		t.Fatal(err)
  2352  	}
  2353  	res, err := inspectField(name, "Config.Env")
  2354  	if err != nil {
  2355  		t.Fatal(err)
  2356  	}
  2357  	if res != expected {
  2358  		t.Fatalf("Env %s, expected %s", res, expected)
  2359  	}
  2360  	logDone("build - env")
  2361  }
  2362  
  2363  func TestBuildContextCleanup(t *testing.T) {
  2364  	testRequires(t, SameHostDaemon)
  2365  
  2366  	name := "testbuildcontextcleanup"
  2367  	defer deleteImages(name)
  2368  	entries, err := ioutil.ReadDir("/var/lib/docker/tmp")
  2369  	if err != nil {
  2370  		t.Fatalf("failed to list contents of tmp dir: %s", err)
  2371  	}
  2372  	_, err = buildImage(name,
  2373  		`FROM scratch
  2374          ENTRYPOINT ["/bin/echo"]`,
  2375  		true)
  2376  	if err != nil {
  2377  		t.Fatal(err)
  2378  	}
  2379  	entriesFinal, err := ioutil.ReadDir("/var/lib/docker/tmp")
  2380  	if err != nil {
  2381  		t.Fatalf("failed to list contents of tmp dir: %s", err)
  2382  	}
  2383  	if err = compareDirectoryEntries(entries, entriesFinal); err != nil {
  2384  		t.Fatalf("context should have been deleted, but wasn't")
  2385  	}
  2386  
  2387  	logDone("build - verify context cleanup works properly")
  2388  }
  2389  
  2390  func TestBuildContextCleanupFailedBuild(t *testing.T) {
  2391  	testRequires(t, SameHostDaemon)
  2392  
  2393  	name := "testbuildcontextcleanup"
  2394  	defer deleteImages(name)
  2395  	defer deleteAllContainers()
  2396  	entries, err := ioutil.ReadDir("/var/lib/docker/tmp")
  2397  	if err != nil {
  2398  		t.Fatalf("failed to list contents of tmp dir: %s", err)
  2399  	}
  2400  	_, err = buildImage(name,
  2401  		`FROM scratch
  2402  	RUN /non/existing/command`,
  2403  		true)
  2404  	if err == nil {
  2405  		t.Fatalf("expected build to fail, but it didn't")
  2406  	}
  2407  	entriesFinal, err := ioutil.ReadDir("/var/lib/docker/tmp")
  2408  	if err != nil {
  2409  		t.Fatalf("failed to list contents of tmp dir: %s", err)
  2410  	}
  2411  	if err = compareDirectoryEntries(entries, entriesFinal); err != nil {
  2412  		t.Fatalf("context should have been deleted, but wasn't")
  2413  	}
  2414  
  2415  	logDone("build - verify context cleanup works properly after an unsuccessful build")
  2416  }
  2417  
  2418  func TestBuildCmd(t *testing.T) {
  2419  	name := "testbuildcmd"
  2420  	expected := "[/bin/echo Hello World]"
  2421  	defer deleteImages(name)
  2422  	_, err := buildImage(name,
  2423  		`FROM scratch
  2424          CMD ["/bin/echo", "Hello World"]`,
  2425  		true)
  2426  	if err != nil {
  2427  		t.Fatal(err)
  2428  	}
  2429  	res, err := inspectField(name, "Config.Cmd")
  2430  	if err != nil {
  2431  		t.Fatal(err)
  2432  	}
  2433  	if res != expected {
  2434  		t.Fatalf("Cmd %s, expected %s", res, expected)
  2435  	}
  2436  	logDone("build - cmd")
  2437  }
  2438  
  2439  func TestBuildExpose(t *testing.T) {
  2440  	name := "testbuildexpose"
  2441  	expected := "map[2375/tcp:map[]]"
  2442  	defer deleteImages(name)
  2443  	_, err := buildImage(name,
  2444  		`FROM scratch
  2445          EXPOSE 2375`,
  2446  		true)
  2447  	if err != nil {
  2448  		t.Fatal(err)
  2449  	}
  2450  	res, err := inspectField(name, "Config.ExposedPorts")
  2451  	if err != nil {
  2452  		t.Fatal(err)
  2453  	}
  2454  	if res != expected {
  2455  		t.Fatalf("Exposed ports %s, expected %s", res, expected)
  2456  	}
  2457  	logDone("build - expose")
  2458  }
  2459  
  2460  func TestBuildExposeMorePorts(t *testing.T) {
  2461  	// start building docker file with a large number of ports
  2462  	portList := make([]string, 50)
  2463  	line := make([]string, 100)
  2464  	expectedPorts := make([]int, len(portList)*len(line))
  2465  	for i := 0; i < len(portList); i++ {
  2466  		for j := 0; j < len(line); j++ {
  2467  			p := i*len(line) + j + 1
  2468  			line[j] = strconv.Itoa(p)
  2469  			expectedPorts[p-1] = p
  2470  		}
  2471  		if i == len(portList)-1 {
  2472  			portList[i] = strings.Join(line, " ")
  2473  		} else {
  2474  			portList[i] = strings.Join(line, " ") + ` \`
  2475  		}
  2476  	}
  2477  
  2478  	dockerfile := `FROM scratch
  2479  	EXPOSE {{range .}} {{.}}
  2480  	{{end}}`
  2481  	tmpl := template.Must(template.New("dockerfile").Parse(dockerfile))
  2482  	buf := bytes.NewBuffer(nil)
  2483  	tmpl.Execute(buf, portList)
  2484  
  2485  	name := "testbuildexpose"
  2486  	defer deleteImages(name)
  2487  	_, err := buildImage(name, buf.String(), true)
  2488  	if err != nil {
  2489  		t.Fatal(err)
  2490  	}
  2491  
  2492  	// check if all the ports are saved inside Config.ExposedPorts
  2493  	res, err := inspectFieldJSON(name, "Config.ExposedPorts")
  2494  	if err != nil {
  2495  		t.Fatal(err)
  2496  	}
  2497  	var exposedPorts map[string]interface{}
  2498  	if err := json.Unmarshal([]byte(res), &exposedPorts); err != nil {
  2499  		t.Fatal(err)
  2500  	}
  2501  
  2502  	for _, p := range expectedPorts {
  2503  		ep := fmt.Sprintf("%d/tcp", p)
  2504  		if _, ok := exposedPorts[ep]; !ok {
  2505  			t.Errorf("Port(%s) is not exposed", ep)
  2506  		} else {
  2507  			delete(exposedPorts, ep)
  2508  		}
  2509  	}
  2510  	if len(exposedPorts) != 0 {
  2511  		t.Errorf("Unexpected extra exposed ports %v", exposedPorts)
  2512  	}
  2513  	logDone("build - expose large number of ports")
  2514  }
  2515  
  2516  func TestBuildExposeOrder(t *testing.T) {
  2517  	buildID := func(name, exposed string) string {
  2518  		_, err := buildImage(name, fmt.Sprintf(`FROM scratch
  2519  		EXPOSE %s`, exposed), true)
  2520  		if err != nil {
  2521  			t.Fatal(err)
  2522  		}
  2523  		id, err := inspectField(name, "Id")
  2524  		if err != nil {
  2525  			t.Fatal(err)
  2526  		}
  2527  		return id
  2528  	}
  2529  
  2530  	id1 := buildID("testbuildexpose1", "80 2375")
  2531  	id2 := buildID("testbuildexpose2", "2375 80")
  2532  	defer deleteImages("testbuildexpose1", "testbuildexpose2")
  2533  	if id1 != id2 {
  2534  		t.Errorf("EXPOSE should invalidate the cache only when ports actually changed")
  2535  	}
  2536  	logDone("build - expose order")
  2537  }
  2538  
  2539  func TestBuildExposeUpperCaseProto(t *testing.T) {
  2540  	name := "testbuildexposeuppercaseproto"
  2541  	expected := "map[5678/udp:map[]]"
  2542  	defer deleteImages(name)
  2543  	_, err := buildImage(name,
  2544  		`FROM scratch
  2545          EXPOSE 5678/UDP`,
  2546  		true)
  2547  	if err != nil {
  2548  		t.Fatal(err)
  2549  	}
  2550  	res, err := inspectField(name, "Config.ExposedPorts")
  2551  	if err != nil {
  2552  		t.Fatal(err)
  2553  	}
  2554  	if res != expected {
  2555  		t.Fatalf("Exposed ports %s, expected %s", res, expected)
  2556  	}
  2557  	logDone("build - expose port with upper case proto")
  2558  }
  2559  
  2560  func TestBuildExposeHostPort(t *testing.T) {
  2561  	// start building docker file with ip:hostPort:containerPort
  2562  	name := "testbuildexpose"
  2563  	expected := "map[5678/tcp:map[]]"
  2564  	defer deleteImages(name)
  2565  	_, out, err := buildImageWithOut(name,
  2566  		`FROM scratch
  2567          EXPOSE 192.168.1.2:2375:5678`,
  2568  		true)
  2569  	if err != nil {
  2570  		t.Fatal(err)
  2571  	}
  2572  
  2573  	if !strings.Contains(out, "to map host ports to container ports (ip:hostPort:containerPort) is deprecated.") {
  2574  		t.Fatal("Missing warning message")
  2575  	}
  2576  
  2577  	res, err := inspectField(name, "Config.ExposedPorts")
  2578  	if err != nil {
  2579  		t.Fatal(err)
  2580  	}
  2581  	if res != expected {
  2582  		t.Fatalf("Exposed ports %s, expected %s", res, expected)
  2583  	}
  2584  	logDone("build - ignore exposing host's port")
  2585  }
  2586  
  2587  func TestBuildEmptyEntrypointInheritance(t *testing.T) {
  2588  	name := "testbuildentrypointinheritance"
  2589  	name2 := "testbuildentrypointinheritance2"
  2590  	defer deleteImages(name, name2)
  2591  
  2592  	_, err := buildImage(name,
  2593  		`FROM busybox
  2594          ENTRYPOINT ["/bin/echo"]`,
  2595  		true)
  2596  	if err != nil {
  2597  		t.Fatal(err)
  2598  	}
  2599  	res, err := inspectField(name, "Config.Entrypoint")
  2600  	if err != nil {
  2601  		t.Fatal(err)
  2602  	}
  2603  
  2604  	expected := "[/bin/echo]"
  2605  	if res != expected {
  2606  		t.Fatalf("Entrypoint %s, expected %s", res, expected)
  2607  	}
  2608  
  2609  	_, err = buildImage(name2,
  2610  		fmt.Sprintf(`FROM %s
  2611          ENTRYPOINT []`, name),
  2612  		true)
  2613  	if err != nil {
  2614  		t.Fatal(err)
  2615  	}
  2616  	res, err = inspectField(name2, "Config.Entrypoint")
  2617  	if err != nil {
  2618  		t.Fatal(err)
  2619  	}
  2620  
  2621  	expected = "[]"
  2622  
  2623  	if res != expected {
  2624  		t.Fatalf("Entrypoint %s, expected %s", res, expected)
  2625  	}
  2626  
  2627  	logDone("build - empty entrypoint inheritance")
  2628  }
  2629  
  2630  func TestBuildEmptyEntrypoint(t *testing.T) {
  2631  	name := "testbuildentrypoint"
  2632  	defer deleteImages(name)
  2633  	expected := "[]"
  2634  
  2635  	_, err := buildImage(name,
  2636  		`FROM busybox
  2637          ENTRYPOINT []`,
  2638  		true)
  2639  	if err != nil {
  2640  		t.Fatal(err)
  2641  	}
  2642  	res, err := inspectField(name, "Config.Entrypoint")
  2643  	if err != nil {
  2644  		t.Fatal(err)
  2645  	}
  2646  	if res != expected {
  2647  		t.Fatalf("Entrypoint %s, expected %s", res, expected)
  2648  	}
  2649  
  2650  	logDone("build - empty entrypoint")
  2651  }
  2652  
  2653  func TestBuildEntrypoint(t *testing.T) {
  2654  	name := "testbuildentrypoint"
  2655  	expected := "[/bin/echo]"
  2656  	defer deleteImages(name)
  2657  	_, err := buildImage(name,
  2658  		`FROM scratch
  2659          ENTRYPOINT ["/bin/echo"]`,
  2660  		true)
  2661  	if err != nil {
  2662  		t.Fatal(err)
  2663  	}
  2664  	res, err := inspectField(name, "Config.Entrypoint")
  2665  	if err != nil {
  2666  		t.Fatal(err)
  2667  	}
  2668  	if res != expected {
  2669  		t.Fatalf("Entrypoint %s, expected %s", res, expected)
  2670  	}
  2671  
  2672  	logDone("build - entrypoint")
  2673  }
  2674  
  2675  // #6445 ensure ONBUILD triggers aren't committed to grandchildren
  2676  func TestBuildOnBuildLimitedInheritence(t *testing.T) {
  2677  	var (
  2678  		out2, out3 string
  2679  	)
  2680  	{
  2681  		name1 := "testonbuildtrigger1"
  2682  		dockerfile1 := `
  2683  		FROM busybox
  2684  		RUN echo "GRANDPARENT"
  2685  		ONBUILD RUN echo "ONBUILD PARENT"
  2686  		`
  2687  		ctx, err := fakeContext(dockerfile1, nil)
  2688  		if err != nil {
  2689  			t.Fatal(err)
  2690  		}
  2691  		defer ctx.Close()
  2692  
  2693  		out1, _, err := dockerCmdInDir(t, ctx.Dir, "build", "-t", name1, ".")
  2694  		if err != nil {
  2695  			t.Fatalf("build failed to complete: %s, %v", out1, err)
  2696  		}
  2697  		defer deleteImages(name1)
  2698  	}
  2699  	{
  2700  		name2 := "testonbuildtrigger2"
  2701  		dockerfile2 := `
  2702  		FROM testonbuildtrigger1
  2703  		`
  2704  		ctx, err := fakeContext(dockerfile2, nil)
  2705  		if err != nil {
  2706  			t.Fatal(err)
  2707  		}
  2708  		defer ctx.Close()
  2709  
  2710  		out2, _, err = dockerCmdInDir(t, ctx.Dir, "build", "-t", name2, ".")
  2711  		if err != nil {
  2712  			t.Fatalf("build failed to complete: %s, %v", out2, err)
  2713  		}
  2714  		defer deleteImages(name2)
  2715  	}
  2716  	{
  2717  		name3 := "testonbuildtrigger3"
  2718  		dockerfile3 := `
  2719  		FROM testonbuildtrigger2
  2720  		`
  2721  		ctx, err := fakeContext(dockerfile3, nil)
  2722  		if err != nil {
  2723  			t.Fatal(err)
  2724  		}
  2725  		defer ctx.Close()
  2726  
  2727  		out3, _, err = dockerCmdInDir(t, ctx.Dir, "build", "-t", name3, ".")
  2728  		if err != nil {
  2729  			t.Fatalf("build failed to complete: %s, %v", out3, err)
  2730  		}
  2731  
  2732  		defer deleteImages(name3)
  2733  	}
  2734  
  2735  	// ONBUILD should be run in second build.
  2736  	if !strings.Contains(out2, "ONBUILD PARENT") {
  2737  		t.Fatalf("ONBUILD instruction did not run in child of ONBUILD parent")
  2738  	}
  2739  
  2740  	// ONBUILD should *not* be run in third build.
  2741  	if strings.Contains(out3, "ONBUILD PARENT") {
  2742  		t.Fatalf("ONBUILD instruction ran in grandchild of ONBUILD parent")
  2743  	}
  2744  
  2745  	logDone("build - onbuild")
  2746  }
  2747  
  2748  func TestBuildWithCache(t *testing.T) {
  2749  	name := "testbuildwithcache"
  2750  	defer deleteImages(name)
  2751  	id1, err := buildImage(name,
  2752  		`FROM scratch
  2753  		MAINTAINER dockerio
  2754  		EXPOSE 5432
  2755          ENTRYPOINT ["/bin/echo"]`,
  2756  		true)
  2757  	if err != nil {
  2758  		t.Fatal(err)
  2759  	}
  2760  	id2, err := buildImage(name,
  2761  		`FROM scratch
  2762  		MAINTAINER dockerio
  2763  		EXPOSE 5432
  2764          ENTRYPOINT ["/bin/echo"]`,
  2765  		true)
  2766  	if err != nil {
  2767  		t.Fatal(err)
  2768  	}
  2769  	if id1 != id2 {
  2770  		t.Fatal("The cache should have been used but hasn't.")
  2771  	}
  2772  	logDone("build - with cache")
  2773  }
  2774  
  2775  func TestBuildWithoutCache(t *testing.T) {
  2776  	name := "testbuildwithoutcache"
  2777  	name2 := "testbuildwithoutcache2"
  2778  	defer deleteImages(name, name2)
  2779  	id1, err := buildImage(name,
  2780  		`FROM scratch
  2781  		MAINTAINER dockerio
  2782  		EXPOSE 5432
  2783          ENTRYPOINT ["/bin/echo"]`,
  2784  		true)
  2785  	if err != nil {
  2786  		t.Fatal(err)
  2787  	}
  2788  
  2789  	id2, err := buildImage(name2,
  2790  		`FROM scratch
  2791  		MAINTAINER dockerio
  2792  		EXPOSE 5432
  2793          ENTRYPOINT ["/bin/echo"]`,
  2794  		false)
  2795  	if err != nil {
  2796  		t.Fatal(err)
  2797  	}
  2798  	if id1 == id2 {
  2799  		t.Fatal("The cache should have been invalided but hasn't.")
  2800  	}
  2801  	logDone("build - without cache")
  2802  }
  2803  
  2804  func TestBuildConditionalCache(t *testing.T) {
  2805  	name := "testbuildconditionalcache"
  2806  	name2 := "testbuildconditionalcache2"
  2807  	defer deleteImages(name, name2)
  2808  
  2809  	dockerfile := `
  2810  		FROM busybox
  2811          ADD foo /tmp/`
  2812  	ctx, err := fakeContext(dockerfile, map[string]string{
  2813  		"foo": "hello",
  2814  	})
  2815  	if err != nil {
  2816  		t.Fatal(err)
  2817  	}
  2818  	defer ctx.Close()
  2819  
  2820  	id1, err := buildImageFromContext(name, ctx, true)
  2821  	if err != nil {
  2822  		t.Fatalf("Error building #1: %s", err)
  2823  	}
  2824  
  2825  	if err := ctx.Add("foo", "bye"); err != nil {
  2826  		t.Fatalf("Error modifying foo: %s", err)
  2827  	}
  2828  
  2829  	id2, err := buildImageFromContext(name, ctx, false)
  2830  	if err != nil {
  2831  		t.Fatalf("Error building #2: %s", err)
  2832  	}
  2833  	if id2 == id1 {
  2834  		t.Fatal("Should not have used the cache")
  2835  	}
  2836  
  2837  	id3, err := buildImageFromContext(name, ctx, true)
  2838  	if err != nil {
  2839  		t.Fatalf("Error building #3: %s", err)
  2840  	}
  2841  	if id3 != id2 {
  2842  		t.Fatal("Should have used the cache")
  2843  	}
  2844  
  2845  	logDone("build - conditional cache")
  2846  }
  2847  
  2848  func TestBuildADDLocalFileWithCache(t *testing.T) {
  2849  	name := "testbuildaddlocalfilewithcache"
  2850  	name2 := "testbuildaddlocalfilewithcache2"
  2851  	defer deleteImages(name, name2)
  2852  	dockerfile := `
  2853  		FROM busybox
  2854          MAINTAINER dockerio
  2855          ADD foo /usr/lib/bla/bar
  2856  		RUN [ "$(cat /usr/lib/bla/bar)" = "hello" ]`
  2857  	ctx, err := fakeContext(dockerfile, map[string]string{
  2858  		"foo": "hello",
  2859  	})
  2860  	defer ctx.Close()
  2861  	if err != nil {
  2862  		t.Fatal(err)
  2863  	}
  2864  	id1, err := buildImageFromContext(name, ctx, true)
  2865  	if err != nil {
  2866  		t.Fatal(err)
  2867  	}
  2868  	id2, err := buildImageFromContext(name2, ctx, true)
  2869  	if err != nil {
  2870  		t.Fatal(err)
  2871  	}
  2872  	if id1 != id2 {
  2873  		t.Fatal("The cache should have been used but hasn't.")
  2874  	}
  2875  	logDone("build - add local file with cache")
  2876  }
  2877  
  2878  func TestBuildADDMultipleLocalFileWithCache(t *testing.T) {
  2879  	name := "testbuildaddmultiplelocalfilewithcache"
  2880  	name2 := "testbuildaddmultiplelocalfilewithcache2"
  2881  	defer deleteImages(name, name2)
  2882  	dockerfile := `
  2883  		FROM busybox
  2884          MAINTAINER dockerio
  2885          ADD foo Dockerfile /usr/lib/bla/
  2886  		RUN [ "$(cat /usr/lib/bla/foo)" = "hello" ]`
  2887  	ctx, err := fakeContext(dockerfile, map[string]string{
  2888  		"foo": "hello",
  2889  	})
  2890  	defer ctx.Close()
  2891  	if err != nil {
  2892  		t.Fatal(err)
  2893  	}
  2894  	id1, err := buildImageFromContext(name, ctx, true)
  2895  	if err != nil {
  2896  		t.Fatal(err)
  2897  	}
  2898  	id2, err := buildImageFromContext(name2, ctx, true)
  2899  	if err != nil {
  2900  		t.Fatal(err)
  2901  	}
  2902  	if id1 != id2 {
  2903  		t.Fatal("The cache should have been used but hasn't.")
  2904  	}
  2905  	logDone("build - add multiple local files with cache")
  2906  }
  2907  
  2908  func TestBuildADDLocalFileWithoutCache(t *testing.T) {
  2909  	name := "testbuildaddlocalfilewithoutcache"
  2910  	name2 := "testbuildaddlocalfilewithoutcache2"
  2911  	defer deleteImages(name, name2)
  2912  	dockerfile := `
  2913  		FROM busybox
  2914          MAINTAINER dockerio
  2915          ADD foo /usr/lib/bla/bar
  2916  		RUN [ "$(cat /usr/lib/bla/bar)" = "hello" ]`
  2917  	ctx, err := fakeContext(dockerfile, map[string]string{
  2918  		"foo": "hello",
  2919  	})
  2920  	defer ctx.Close()
  2921  	if err != nil {
  2922  		t.Fatal(err)
  2923  	}
  2924  	id1, err := buildImageFromContext(name, ctx, true)
  2925  	if err != nil {
  2926  		t.Fatal(err)
  2927  	}
  2928  	id2, err := buildImageFromContext(name2, ctx, false)
  2929  	if err != nil {
  2930  		t.Fatal(err)
  2931  	}
  2932  	if id1 == id2 {
  2933  		t.Fatal("The cache should have been invalided but hasn't.")
  2934  	}
  2935  	logDone("build - add local file without cache")
  2936  }
  2937  
  2938  func TestBuildCopyDirButNotFile(t *testing.T) {
  2939  	name := "testbuildcopydirbutnotfile"
  2940  	name2 := "testbuildcopydirbutnotfile2"
  2941  	defer deleteImages(name, name2)
  2942  	dockerfile := `
  2943          FROM scratch
  2944          COPY dir /tmp/`
  2945  	ctx, err := fakeContext(dockerfile, map[string]string{
  2946  		"dir/foo": "hello",
  2947  	})
  2948  	defer ctx.Close()
  2949  	if err != nil {
  2950  		t.Fatal(err)
  2951  	}
  2952  	id1, err := buildImageFromContext(name, ctx, true)
  2953  	if err != nil {
  2954  		t.Fatal(err)
  2955  	}
  2956  	// Check that adding file with similar name doesn't mess with cache
  2957  	if err := ctx.Add("dir_file", "hello2"); err != nil {
  2958  		t.Fatal(err)
  2959  	}
  2960  	id2, err := buildImageFromContext(name2, ctx, true)
  2961  	if err != nil {
  2962  		t.Fatal(err)
  2963  	}
  2964  	if id1 != id2 {
  2965  		t.Fatal("The cache should have been used but wasn't")
  2966  	}
  2967  	logDone("build - add current directory but not file")
  2968  }
  2969  
  2970  func TestBuildADDCurrentDirWithCache(t *testing.T) {
  2971  	name := "testbuildaddcurrentdirwithcache"
  2972  	name2 := name + "2"
  2973  	name3 := name + "3"
  2974  	name4 := name + "4"
  2975  	name5 := name + "5"
  2976  	defer deleteImages(name, name2, name3, name4, name5)
  2977  	dockerfile := `
  2978          FROM scratch
  2979          MAINTAINER dockerio
  2980          ADD . /usr/lib/bla`
  2981  	ctx, err := fakeContext(dockerfile, map[string]string{
  2982  		"foo": "hello",
  2983  	})
  2984  	defer ctx.Close()
  2985  	if err != nil {
  2986  		t.Fatal(err)
  2987  	}
  2988  	id1, err := buildImageFromContext(name, ctx, true)
  2989  	if err != nil {
  2990  		t.Fatal(err)
  2991  	}
  2992  	// Check that adding file invalidate cache of "ADD ."
  2993  	if err := ctx.Add("bar", "hello2"); err != nil {
  2994  		t.Fatal(err)
  2995  	}
  2996  	id2, err := buildImageFromContext(name2, ctx, true)
  2997  	if err != nil {
  2998  		t.Fatal(err)
  2999  	}
  3000  	if id1 == id2 {
  3001  		t.Fatal("The cache should have been invalided but hasn't.")
  3002  	}
  3003  	// Check that changing file invalidate cache of "ADD ."
  3004  	if err := ctx.Add("foo", "hello1"); err != nil {
  3005  		t.Fatal(err)
  3006  	}
  3007  	id3, err := buildImageFromContext(name3, ctx, true)
  3008  	if err != nil {
  3009  		t.Fatal(err)
  3010  	}
  3011  	if id2 == id3 {
  3012  		t.Fatal("The cache should have been invalided but hasn't.")
  3013  	}
  3014  	// Check that changing file to same content invalidate cache of "ADD ."
  3015  	time.Sleep(1 * time.Second) // wait second because of mtime precision
  3016  	if err := ctx.Add("foo", "hello1"); err != nil {
  3017  		t.Fatal(err)
  3018  	}
  3019  	id4, err := buildImageFromContext(name4, ctx, true)
  3020  	if err != nil {
  3021  		t.Fatal(err)
  3022  	}
  3023  	if id3 == id4 {
  3024  		t.Fatal("The cache should have been invalided but hasn't.")
  3025  	}
  3026  	id5, err := buildImageFromContext(name5, ctx, true)
  3027  	if err != nil {
  3028  		t.Fatal(err)
  3029  	}
  3030  	if id4 != id5 {
  3031  		t.Fatal("The cache should have been used but hasn't.")
  3032  	}
  3033  	logDone("build - add current directory with cache")
  3034  }
  3035  
  3036  func TestBuildADDCurrentDirWithoutCache(t *testing.T) {
  3037  	name := "testbuildaddcurrentdirwithoutcache"
  3038  	name2 := "testbuildaddcurrentdirwithoutcache2"
  3039  	defer deleteImages(name, name2)
  3040  	dockerfile := `
  3041          FROM scratch
  3042          MAINTAINER dockerio
  3043          ADD . /usr/lib/bla`
  3044  	ctx, err := fakeContext(dockerfile, map[string]string{
  3045  		"foo": "hello",
  3046  	})
  3047  	defer ctx.Close()
  3048  	if err != nil {
  3049  		t.Fatal(err)
  3050  	}
  3051  	id1, err := buildImageFromContext(name, ctx, true)
  3052  	if err != nil {
  3053  		t.Fatal(err)
  3054  	}
  3055  	id2, err := buildImageFromContext(name2, ctx, false)
  3056  	if err != nil {
  3057  		t.Fatal(err)
  3058  	}
  3059  	if id1 == id2 {
  3060  		t.Fatal("The cache should have been invalided but hasn't.")
  3061  	}
  3062  	logDone("build - add current directory without cache")
  3063  }
  3064  
  3065  func TestBuildADDRemoteFileWithCache(t *testing.T) {
  3066  	name := "testbuildaddremotefilewithcache"
  3067  	defer deleteImages(name)
  3068  	server, err := fakeStorage(map[string]string{
  3069  		"baz": "hello",
  3070  	})
  3071  	if err != nil {
  3072  		t.Fatal(err)
  3073  	}
  3074  	defer server.Close()
  3075  
  3076  	id1, err := buildImage(name,
  3077  		fmt.Sprintf(`FROM scratch
  3078          MAINTAINER dockerio
  3079          ADD %s/baz /usr/lib/baz/quux`, server.URL()),
  3080  		true)
  3081  	if err != nil {
  3082  		t.Fatal(err)
  3083  	}
  3084  	id2, err := buildImage(name,
  3085  		fmt.Sprintf(`FROM scratch
  3086          MAINTAINER dockerio
  3087          ADD %s/baz /usr/lib/baz/quux`, server.URL()),
  3088  		true)
  3089  	if err != nil {
  3090  		t.Fatal(err)
  3091  	}
  3092  	if id1 != id2 {
  3093  		t.Fatal("The cache should have been used but hasn't.")
  3094  	}
  3095  	logDone("build - add remote file with cache")
  3096  }
  3097  
  3098  func TestBuildADDRemoteFileWithoutCache(t *testing.T) {
  3099  	name := "testbuildaddremotefilewithoutcache"
  3100  	name2 := "testbuildaddremotefilewithoutcache2"
  3101  	defer deleteImages(name, name2)
  3102  	server, err := fakeStorage(map[string]string{
  3103  		"baz": "hello",
  3104  	})
  3105  	if err != nil {
  3106  		t.Fatal(err)
  3107  	}
  3108  	defer server.Close()
  3109  
  3110  	id1, err := buildImage(name,
  3111  		fmt.Sprintf(`FROM scratch
  3112          MAINTAINER dockerio
  3113          ADD %s/baz /usr/lib/baz/quux`, server.URL()),
  3114  		true)
  3115  	if err != nil {
  3116  		t.Fatal(err)
  3117  	}
  3118  	id2, err := buildImage(name2,
  3119  		fmt.Sprintf(`FROM scratch
  3120          MAINTAINER dockerio
  3121          ADD %s/baz /usr/lib/baz/quux`, server.URL()),
  3122  		false)
  3123  	if err != nil {
  3124  		t.Fatal(err)
  3125  	}
  3126  	if id1 == id2 {
  3127  		t.Fatal("The cache should have been invalided but hasn't.")
  3128  	}
  3129  	logDone("build - add remote file without cache")
  3130  }
  3131  
  3132  func TestBuildADDRemoteFileMTime(t *testing.T) {
  3133  	name := "testbuildaddremotefilemtime"
  3134  	name2 := name + "2"
  3135  	name3 := name + "3"
  3136  	name4 := name + "4"
  3137  
  3138  	defer deleteImages(name, name2, name3, name4)
  3139  
  3140  	files := map[string]string{"baz": "hello"}
  3141  	server, err := fakeStorage(files)
  3142  	if err != nil {
  3143  		t.Fatal(err)
  3144  	}
  3145  	defer server.Close()
  3146  
  3147  	ctx, err := fakeContext(fmt.Sprintf(`FROM scratch
  3148          MAINTAINER dockerio
  3149          ADD %s/baz /usr/lib/baz/quux`, server.URL()), nil)
  3150  	if err != nil {
  3151  		t.Fatal(err)
  3152  	}
  3153  	defer ctx.Close()
  3154  
  3155  	id1, err := buildImageFromContext(name, ctx, true)
  3156  	if err != nil {
  3157  		t.Fatal(err)
  3158  	}
  3159  
  3160  	id2, err := buildImageFromContext(name2, ctx, true)
  3161  	if err != nil {
  3162  		t.Fatal(err)
  3163  	}
  3164  	if id1 != id2 {
  3165  		t.Fatal("The cache should have been used but wasn't - #1")
  3166  	}
  3167  
  3168  	// Now create a different server withsame contents (causes different mtim)
  3169  	// This time the cache should not be used
  3170  
  3171  	// allow some time for clock to pass as mtime precision is only 1s
  3172  	time.Sleep(2 * time.Second)
  3173  
  3174  	server2, err := fakeStorage(files)
  3175  	if err != nil {
  3176  		t.Fatal(err)
  3177  	}
  3178  	defer server2.Close()
  3179  
  3180  	ctx2, err := fakeContext(fmt.Sprintf(`FROM scratch
  3181          MAINTAINER dockerio
  3182          ADD %s/baz /usr/lib/baz/quux`, server2.URL()), nil)
  3183  	if err != nil {
  3184  		t.Fatal(err)
  3185  	}
  3186  	defer ctx2.Close()
  3187  	id3, err := buildImageFromContext(name3, ctx2, true)
  3188  	if err != nil {
  3189  		t.Fatal(err)
  3190  	}
  3191  	if id1 == id3 {
  3192  		t.Fatal("The cache should not have been used but was")
  3193  	}
  3194  
  3195  	// And for good measure do it again and make sure cache is used this time
  3196  	id4, err := buildImageFromContext(name4, ctx2, true)
  3197  	if err != nil {
  3198  		t.Fatal(err)
  3199  	}
  3200  	if id3 != id4 {
  3201  		t.Fatal("The cache should have been used but wasn't - #2")
  3202  	}
  3203  	logDone("build - add remote file testing mtime")
  3204  }
  3205  
  3206  func TestBuildADDLocalAndRemoteFilesWithCache(t *testing.T) {
  3207  	name := "testbuildaddlocalandremotefilewithcache"
  3208  	defer deleteImages(name)
  3209  	server, err := fakeStorage(map[string]string{
  3210  		"baz": "hello",
  3211  	})
  3212  	if err != nil {
  3213  		t.Fatal(err)
  3214  	}
  3215  	defer server.Close()
  3216  
  3217  	ctx, err := fakeContext(fmt.Sprintf(`FROM scratch
  3218          MAINTAINER dockerio
  3219          ADD foo /usr/lib/bla/bar
  3220          ADD %s/baz /usr/lib/baz/quux`, server.URL()),
  3221  		map[string]string{
  3222  			"foo": "hello world",
  3223  		})
  3224  	if err != nil {
  3225  		t.Fatal(err)
  3226  	}
  3227  	defer ctx.Close()
  3228  	id1, err := buildImageFromContext(name, ctx, true)
  3229  	if err != nil {
  3230  		t.Fatal(err)
  3231  	}
  3232  	id2, err := buildImageFromContext(name, ctx, true)
  3233  	if err != nil {
  3234  		t.Fatal(err)
  3235  	}
  3236  	if id1 != id2 {
  3237  		t.Fatal("The cache should have been used but hasn't.")
  3238  	}
  3239  	logDone("build - add local and remote file with cache")
  3240  }
  3241  
  3242  func testContextTar(t *testing.T, compression archive.Compression) {
  3243  	ctx, err := fakeContext(
  3244  		`FROM busybox
  3245  ADD foo /foo
  3246  CMD ["cat", "/foo"]`,
  3247  		map[string]string{
  3248  			"foo": "bar",
  3249  		},
  3250  	)
  3251  	defer ctx.Close()
  3252  	if err != nil {
  3253  		t.Fatal(err)
  3254  	}
  3255  	context, err := archive.Tar(ctx.Dir, compression)
  3256  	if err != nil {
  3257  		t.Fatalf("failed to build context tar: %v", err)
  3258  	}
  3259  	name := "contexttar"
  3260  	buildCmd := exec.Command(dockerBinary, "build", "-t", name, "-")
  3261  	defer deleteImages(name)
  3262  	buildCmd.Stdin = context
  3263  
  3264  	if out, _, err := runCommandWithOutput(buildCmd); err != nil {
  3265  		t.Fatalf("build failed to complete: %v %v", out, err)
  3266  	}
  3267  	logDone(fmt.Sprintf("build - build an image with a context tar, compression: %v", compression))
  3268  }
  3269  
  3270  func TestBuildContextTarGzip(t *testing.T) {
  3271  	testContextTar(t, archive.Gzip)
  3272  }
  3273  
  3274  func TestBuildContextTarNoCompression(t *testing.T) {
  3275  	testContextTar(t, archive.Uncompressed)
  3276  }
  3277  
  3278  func TestBuildNoContext(t *testing.T) {
  3279  	buildCmd := exec.Command(dockerBinary, "build", "-t", "nocontext", "-")
  3280  	buildCmd.Stdin = strings.NewReader("FROM busybox\nCMD echo ok\n")
  3281  
  3282  	if out, _, err := runCommandWithOutput(buildCmd); err != nil {
  3283  		t.Fatalf("build failed to complete: %v %v", out, err)
  3284  	}
  3285  
  3286  	if out, _, err := dockerCmd(t, "run", "--rm", "nocontext"); out != "ok\n" || err != nil {
  3287  		t.Fatalf("run produced invalid output: %q, expected %q", out, "ok")
  3288  	}
  3289  
  3290  	deleteImages("nocontext")
  3291  	logDone("build - build an image with no context")
  3292  }
  3293  
  3294  // TODO: TestCaching
  3295  func TestBuildADDLocalAndRemoteFilesWithoutCache(t *testing.T) {
  3296  	name := "testbuildaddlocalandremotefilewithoutcache"
  3297  	name2 := "testbuildaddlocalandremotefilewithoutcache2"
  3298  	defer deleteImages(name, name2)
  3299  	server, err := fakeStorage(map[string]string{
  3300  		"baz": "hello",
  3301  	})
  3302  	if err != nil {
  3303  		t.Fatal(err)
  3304  	}
  3305  	defer server.Close()
  3306  
  3307  	ctx, err := fakeContext(fmt.Sprintf(`FROM scratch
  3308          MAINTAINER dockerio
  3309          ADD foo /usr/lib/bla/bar
  3310          ADD %s/baz /usr/lib/baz/quux`, server.URL()),
  3311  		map[string]string{
  3312  			"foo": "hello world",
  3313  		})
  3314  	if err != nil {
  3315  		t.Fatal(err)
  3316  	}
  3317  	defer ctx.Close()
  3318  	id1, err := buildImageFromContext(name, ctx, true)
  3319  	if err != nil {
  3320  		t.Fatal(err)
  3321  	}
  3322  	id2, err := buildImageFromContext(name2, ctx, false)
  3323  	if err != nil {
  3324  		t.Fatal(err)
  3325  	}
  3326  	if id1 == id2 {
  3327  		t.Fatal("The cache should have been invalided but hasn't.")
  3328  	}
  3329  	logDone("build - add local and remote file without cache")
  3330  }
  3331  
  3332  func TestBuildWithVolumeOwnership(t *testing.T) {
  3333  	name := "testbuildimg"
  3334  	defer deleteImages(name)
  3335  
  3336  	_, err := buildImage(name,
  3337  		`FROM busybox:latest
  3338          RUN mkdir /test && chown daemon:daemon /test && chmod 0600 /test
  3339          VOLUME /test`,
  3340  		true)
  3341  
  3342  	if err != nil {
  3343  		t.Fatal(err)
  3344  	}
  3345  
  3346  	cmd := exec.Command(dockerBinary, "run", "--rm", "testbuildimg", "ls", "-la", "/test")
  3347  	out, _, err := runCommandWithOutput(cmd)
  3348  	if err != nil {
  3349  		t.Fatal(out, err)
  3350  	}
  3351  
  3352  	if expected := "drw-------"; !strings.Contains(out, expected) {
  3353  		t.Fatalf("expected %s received %s", expected, out)
  3354  	}
  3355  
  3356  	if expected := "daemon   daemon"; !strings.Contains(out, expected) {
  3357  		t.Fatalf("expected %s received %s", expected, out)
  3358  	}
  3359  
  3360  	logDone("build - volume ownership")
  3361  }
  3362  
  3363  // testing #1405 - config.Cmd does not get cleaned up if
  3364  // utilizing cache
  3365  func TestBuildEntrypointRunCleanup(t *testing.T) {
  3366  	name := "testbuildcmdcleanup"
  3367  	defer deleteImages(name)
  3368  	if _, err := buildImage(name,
  3369  		`FROM busybox
  3370          RUN echo "hello"`,
  3371  		true); err != nil {
  3372  		t.Fatal(err)
  3373  	}
  3374  
  3375  	ctx, err := fakeContext(`FROM busybox
  3376          RUN echo "hello"
  3377          ADD foo /foo
  3378          ENTRYPOINT ["/bin/echo"]`,
  3379  		map[string]string{
  3380  			"foo": "hello",
  3381  		})
  3382  	defer ctx.Close()
  3383  	if err != nil {
  3384  		t.Fatal(err)
  3385  	}
  3386  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  3387  		t.Fatal(err)
  3388  	}
  3389  	res, err := inspectField(name, "Config.Cmd")
  3390  	if err != nil {
  3391  		t.Fatal(err)
  3392  	}
  3393  	// Cmd must be cleaned up
  3394  	if expected := "<no value>"; res != expected {
  3395  		t.Fatalf("Cmd %s, expected %s", res, expected)
  3396  	}
  3397  	logDone("build - cleanup cmd after RUN")
  3398  }
  3399  
  3400  func TestBuildForbiddenContextPath(t *testing.T) {
  3401  	name := "testbuildforbidpath"
  3402  	defer deleteImages(name)
  3403  	ctx, err := fakeContext(`FROM scratch
  3404          ADD ../../ test/
  3405          `,
  3406  		map[string]string{
  3407  			"test.txt":  "test1",
  3408  			"other.txt": "other",
  3409  		})
  3410  	defer ctx.Close()
  3411  	if err != nil {
  3412  		t.Fatal(err)
  3413  	}
  3414  
  3415  	expected := "Forbidden path outside the build context: ../../ "
  3416  	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
  3417  		t.Fatalf("Wrong error: (should contain \"%s\") got:\n%v", expected, err)
  3418  	}
  3419  
  3420  	logDone("build - forbidden context path")
  3421  }
  3422  
  3423  func TestBuildADDFileNotFound(t *testing.T) {
  3424  	name := "testbuildaddnotfound"
  3425  	defer deleteImages(name)
  3426  	ctx, err := fakeContext(`FROM scratch
  3427          ADD foo /usr/local/bar`,
  3428  		map[string]string{"bar": "hello"})
  3429  	defer ctx.Close()
  3430  	if err != nil {
  3431  		t.Fatal(err)
  3432  	}
  3433  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  3434  		if !strings.Contains(err.Error(), "foo: no such file or directory") {
  3435  			t.Fatalf("Wrong error %v, must be about missing foo file or directory", err)
  3436  		}
  3437  	} else {
  3438  		t.Fatal("Error must not be nil")
  3439  	}
  3440  	logDone("build - add file not found")
  3441  }
  3442  
  3443  func TestBuildInheritance(t *testing.T) {
  3444  	name := "testbuildinheritance"
  3445  	defer deleteImages(name)
  3446  
  3447  	_, err := buildImage(name,
  3448  		`FROM scratch
  3449  		EXPOSE 2375`,
  3450  		true)
  3451  	if err != nil {
  3452  		t.Fatal(err)
  3453  	}
  3454  	ports1, err := inspectField(name, "Config.ExposedPorts")
  3455  	if err != nil {
  3456  		t.Fatal(err)
  3457  	}
  3458  
  3459  	_, err = buildImage(name,
  3460  		fmt.Sprintf(`FROM %s
  3461  		ENTRYPOINT ["/bin/echo"]`, name),
  3462  		true)
  3463  	if err != nil {
  3464  		t.Fatal(err)
  3465  	}
  3466  
  3467  	res, err := inspectField(name, "Config.Entrypoint")
  3468  	if err != nil {
  3469  		t.Fatal(err)
  3470  	}
  3471  	if expected := "[/bin/echo]"; res != expected {
  3472  		t.Fatalf("Entrypoint %s, expected %s", res, expected)
  3473  	}
  3474  	ports2, err := inspectField(name, "Config.ExposedPorts")
  3475  	if err != nil {
  3476  		t.Fatal(err)
  3477  	}
  3478  	if ports1 != ports2 {
  3479  		t.Fatalf("Ports must be same: %s != %s", ports1, ports2)
  3480  	}
  3481  	logDone("build - inheritance")
  3482  }
  3483  
  3484  func TestBuildFails(t *testing.T) {
  3485  	name := "testbuildfails"
  3486  	defer deleteImages(name)
  3487  	defer deleteAllContainers()
  3488  	_, err := buildImage(name,
  3489  		`FROM busybox
  3490  		RUN sh -c "exit 23"`,
  3491  		true)
  3492  	if err != nil {
  3493  		if !strings.Contains(err.Error(), "returned a non-zero code: 23") {
  3494  			t.Fatalf("Wrong error %v, must be about non-zero code 23", err)
  3495  		}
  3496  	} else {
  3497  		t.Fatal("Error must not be nil")
  3498  	}
  3499  	logDone("build - unsuccessful")
  3500  }
  3501  
  3502  func TestBuildFailsDockerfileEmpty(t *testing.T) {
  3503  	name := "testbuildfails"
  3504  	defer deleteImages(name)
  3505  	_, err := buildImage(name, ``, true)
  3506  	if err != nil {
  3507  		if !strings.Contains(err.Error(), "Dockerfile cannot be empty") {
  3508  			t.Fatalf("Wrong error %v, must be about empty Dockerfile", err)
  3509  		}
  3510  	} else {
  3511  		t.Fatal("Error must not be nil")
  3512  	}
  3513  	logDone("build - unsuccessful with empty dockerfile")
  3514  }
  3515  
  3516  func TestBuildOnBuild(t *testing.T) {
  3517  	name := "testbuildonbuild"
  3518  	defer deleteImages(name)
  3519  	_, err := buildImage(name,
  3520  		`FROM busybox
  3521  		ONBUILD RUN touch foobar`,
  3522  		true)
  3523  	if err != nil {
  3524  		t.Fatal(err)
  3525  	}
  3526  	_, err = buildImage(name,
  3527  		fmt.Sprintf(`FROM %s
  3528  		RUN [ -f foobar ]`, name),
  3529  		true)
  3530  	if err != nil {
  3531  		t.Fatal(err)
  3532  	}
  3533  	logDone("build - onbuild")
  3534  }
  3535  
  3536  func TestBuildOnBuildForbiddenChained(t *testing.T) {
  3537  	name := "testbuildonbuildforbiddenchained"
  3538  	defer deleteImages(name)
  3539  	_, err := buildImage(name,
  3540  		`FROM busybox
  3541  		ONBUILD ONBUILD RUN touch foobar`,
  3542  		true)
  3543  	if err != nil {
  3544  		if !strings.Contains(err.Error(), "Chaining ONBUILD via `ONBUILD ONBUILD` isn't allowed") {
  3545  			t.Fatalf("Wrong error %v, must be about chaining ONBUILD", err)
  3546  		}
  3547  	} else {
  3548  		t.Fatal("Error must not be nil")
  3549  	}
  3550  	logDone("build - onbuild forbidden chained")
  3551  }
  3552  
  3553  func TestBuildOnBuildForbiddenFrom(t *testing.T) {
  3554  	name := "testbuildonbuildforbiddenfrom"
  3555  	defer deleteImages(name)
  3556  	_, err := buildImage(name,
  3557  		`FROM busybox
  3558  		ONBUILD FROM scratch`,
  3559  		true)
  3560  	if err != nil {
  3561  		if !strings.Contains(err.Error(), "FROM isn't allowed as an ONBUILD trigger") {
  3562  			t.Fatalf("Wrong error %v, must be about FROM forbidden", err)
  3563  		}
  3564  	} else {
  3565  		t.Fatal("Error must not be nil")
  3566  	}
  3567  	logDone("build - onbuild forbidden from")
  3568  }
  3569  
  3570  func TestBuildOnBuildForbiddenMaintainer(t *testing.T) {
  3571  	name := "testbuildonbuildforbiddenmaintainer"
  3572  	defer deleteImages(name)
  3573  	_, err := buildImage(name,
  3574  		`FROM busybox
  3575  		ONBUILD MAINTAINER docker.io`,
  3576  		true)
  3577  	if err != nil {
  3578  		if !strings.Contains(err.Error(), "MAINTAINER isn't allowed as an ONBUILD trigger") {
  3579  			t.Fatalf("Wrong error %v, must be about MAINTAINER forbidden", err)
  3580  		}
  3581  	} else {
  3582  		t.Fatal("Error must not be nil")
  3583  	}
  3584  	logDone("build - onbuild forbidden maintainer")
  3585  }
  3586  
  3587  // gh #2446
  3588  func TestBuildAddToSymlinkDest(t *testing.T) {
  3589  	name := "testbuildaddtosymlinkdest"
  3590  	defer deleteImages(name)
  3591  	ctx, err := fakeContext(`FROM busybox
  3592          RUN mkdir /foo
  3593          RUN ln -s /foo /bar
  3594          ADD foo /bar/
  3595          RUN [ -f /bar/foo ]
  3596          RUN [ -f /foo/foo ]`,
  3597  		map[string]string{
  3598  			"foo": "hello",
  3599  		})
  3600  	if err != nil {
  3601  		t.Fatal(err)
  3602  	}
  3603  	defer ctx.Close()
  3604  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  3605  		t.Fatal(err)
  3606  	}
  3607  	logDone("build - add to symlink destination")
  3608  }
  3609  
  3610  func TestBuildEscapeWhitespace(t *testing.T) {
  3611  	name := "testbuildescaping"
  3612  	defer deleteImages(name)
  3613  
  3614  	_, err := buildImage(name, `
  3615    FROM busybox
  3616    MAINTAINER "Docker \
  3617  IO <io@\
  3618  docker.com>"
  3619    `, true)
  3620  
  3621  	res, err := inspectField(name, "Author")
  3622  
  3623  	if err != nil {
  3624  		t.Fatal(err)
  3625  	}
  3626  
  3627  	if res != "\"Docker IO <io@docker.com>\"" {
  3628  		t.Fatalf("Parsed string did not match the escaped string. Got: %q", res)
  3629  	}
  3630  
  3631  	logDone("build - validate escaping whitespace")
  3632  }
  3633  
  3634  func TestBuildVerifyIntString(t *testing.T) {
  3635  	// Verify that strings that look like ints are still passed as strings
  3636  	name := "testbuildstringing"
  3637  	defer deleteImages(name)
  3638  
  3639  	_, err := buildImage(name, `
  3640    FROM busybox
  3641    MAINTAINER 123
  3642    `, true)
  3643  
  3644  	out, rc, err := runCommandWithOutput(exec.Command(dockerBinary, "inspect", name))
  3645  	if rc != 0 || err != nil {
  3646  		t.Fatalf("Unexcepted error from inspect: rc: %v  err: %v", rc, err)
  3647  	}
  3648  
  3649  	if !strings.Contains(out, "\"123\"") {
  3650  		t.Fatalf("Output does not contain the int as a string:\n%s", out)
  3651  	}
  3652  
  3653  	logDone("build - verify int/strings as strings")
  3654  }
  3655  
  3656  func TestBuildDockerignore(t *testing.T) {
  3657  	name := "testbuilddockerignore"
  3658  	defer deleteImages(name)
  3659  	dockerfile := `
  3660          FROM busybox
  3661          ADD . /bla
  3662  		RUN [[ -f /bla/src/x.go ]]
  3663  		RUN [[ -f /bla/Makefile ]]
  3664  		RUN [[ ! -e /bla/src/_vendor ]]
  3665  		RUN [[ ! -e /bla/.gitignore ]]
  3666  		RUN [[ ! -e /bla/README.md ]]
  3667  		RUN [[ ! -e /bla/.git ]]`
  3668  	ctx, err := fakeContext(dockerfile, map[string]string{
  3669  		"Makefile":         "all:",
  3670  		".git/HEAD":        "ref: foo",
  3671  		"src/x.go":         "package main",
  3672  		"src/_vendor/v.go": "package main",
  3673  		".gitignore":       "",
  3674  		"README.md":        "readme",
  3675  		".dockerignore":    ".git\npkg\n.gitignore\nsrc/_vendor\n*.md",
  3676  	})
  3677  	defer ctx.Close()
  3678  	if err != nil {
  3679  		t.Fatal(err)
  3680  	}
  3681  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  3682  		t.Fatal(err)
  3683  	}
  3684  	logDone("build - test .dockerignore")
  3685  }
  3686  
  3687  func TestBuildDockerignoreCleanPaths(t *testing.T) {
  3688  	name := "testbuilddockerignorecleanpaths"
  3689  	defer deleteImages(name)
  3690  	dockerfile := `
  3691          FROM busybox
  3692          ADD . /tmp/
  3693          RUN (! ls /tmp/foo) && (! ls /tmp/foo2) && (! ls /tmp/dir1/foo)`
  3694  	ctx, err := fakeContext(dockerfile, map[string]string{
  3695  		"foo":           "foo",
  3696  		"foo2":          "foo2",
  3697  		"dir1/foo":      "foo in dir1",
  3698  		".dockerignore": "./foo\ndir1//foo\n./dir1/../foo2",
  3699  	})
  3700  	if err != nil {
  3701  		t.Fatal(err)
  3702  	}
  3703  	defer ctx.Close()
  3704  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  3705  		t.Fatal(err)
  3706  	}
  3707  	logDone("build - test .dockerignore with clean paths")
  3708  }
  3709  
  3710  func TestBuildDockerignoringDockerfile(t *testing.T) {
  3711  	name := "testbuilddockerignoredockerfile"
  3712  	defer deleteImages(name)
  3713  	dockerfile := `
  3714          FROM busybox
  3715  		ADD . /tmp/
  3716  		RUN ! ls /tmp/Dockerfile
  3717  		RUN ls /tmp/.dockerignore`
  3718  	ctx, err := fakeContext(dockerfile, map[string]string{
  3719  		"Dockerfile":    dockerfile,
  3720  		".dockerignore": "Dockerfile\n",
  3721  	})
  3722  	if err != nil {
  3723  		t.Fatal(err)
  3724  	}
  3725  	defer ctx.Close()
  3726  
  3727  	if _, err = buildImageFromContext(name, ctx, true); err != nil {
  3728  		t.Fatalf("Didn't ignore Dockerfile correctly:%s", err)
  3729  	}
  3730  
  3731  	// now try it with ./Dockerfile
  3732  	ctx.Add(".dockerignore", "./Dockerfile\n")
  3733  	if _, err = buildImageFromContext(name, ctx, true); err != nil {
  3734  		t.Fatalf("Didn't ignore ./Dockerfile correctly:%s", err)
  3735  	}
  3736  
  3737  	logDone("build - test .dockerignore of Dockerfile")
  3738  }
  3739  
  3740  func TestBuildDockerignoringRenamedDockerfile(t *testing.T) {
  3741  	name := "testbuilddockerignoredockerfile"
  3742  	defer deleteImages(name)
  3743  	dockerfile := `
  3744          FROM busybox
  3745  		ADD . /tmp/
  3746  		RUN ls /tmp/Dockerfile
  3747  		RUN ! ls /tmp/MyDockerfile
  3748  		RUN ls /tmp/.dockerignore`
  3749  	ctx, err := fakeContext(dockerfile, map[string]string{
  3750  		"Dockerfile":    "Should not use me",
  3751  		"MyDockerfile":  dockerfile,
  3752  		".dockerignore": "MyDockerfile\n",
  3753  	})
  3754  	if err != nil {
  3755  		t.Fatal(err)
  3756  	}
  3757  	defer ctx.Close()
  3758  
  3759  	if _, err = buildImageFromContext(name, ctx, true); err != nil {
  3760  		t.Fatalf("Didn't ignore MyDockerfile correctly:%s", err)
  3761  	}
  3762  
  3763  	// now try it with ./MyDockerfile
  3764  	ctx.Add(".dockerignore", "./MyDockerfile\n")
  3765  	if _, err = buildImageFromContext(name, ctx, true); err != nil {
  3766  		t.Fatalf("Didn't ignore ./MyDockerfile correctly:%s", err)
  3767  	}
  3768  
  3769  	logDone("build - test .dockerignore of renamed Dockerfile")
  3770  }
  3771  
  3772  func TestBuildDockerignoringDockerignore(t *testing.T) {
  3773  	name := "testbuilddockerignoredockerignore"
  3774  	defer deleteImages(name)
  3775  	dockerfile := `
  3776          FROM busybox
  3777  		ADD . /tmp/
  3778  		RUN ! ls /tmp/.dockerignore
  3779  		RUN ls /tmp/Dockerfile`
  3780  	ctx, err := fakeContext(dockerfile, map[string]string{
  3781  		"Dockerfile":    dockerfile,
  3782  		".dockerignore": ".dockerignore\n",
  3783  	})
  3784  	defer ctx.Close()
  3785  	if err != nil {
  3786  		t.Fatal(err)
  3787  	}
  3788  	if _, err = buildImageFromContext(name, ctx, true); err != nil {
  3789  		t.Fatalf("Didn't ignore .dockerignore correctly:%s", err)
  3790  	}
  3791  	logDone("build - test .dockerignore of .dockerignore")
  3792  }
  3793  
  3794  func TestBuildDockerignoreTouchDockerfile(t *testing.T) {
  3795  	var id1 string
  3796  	var id2 string
  3797  
  3798  	name := "testbuilddockerignoretouchdockerfile"
  3799  	defer deleteImages(name)
  3800  	dockerfile := `
  3801          FROM busybox
  3802  		ADD . /tmp/`
  3803  	ctx, err := fakeContext(dockerfile, map[string]string{
  3804  		"Dockerfile":    dockerfile,
  3805  		".dockerignore": "Dockerfile\n",
  3806  	})
  3807  	defer ctx.Close()
  3808  	if err != nil {
  3809  		t.Fatal(err)
  3810  	}
  3811  
  3812  	if id1, err = buildImageFromContext(name, ctx, true); err != nil {
  3813  		t.Fatalf("Didn't build it correctly:%s", err)
  3814  	}
  3815  
  3816  	if id2, err = buildImageFromContext(name, ctx, true); err != nil {
  3817  		t.Fatalf("Didn't build it correctly:%s", err)
  3818  	}
  3819  	if id1 != id2 {
  3820  		t.Fatalf("Didn't use the cache - 1")
  3821  	}
  3822  
  3823  	// Now make sure touching Dockerfile doesn't invalidate the cache
  3824  	if err = ctx.Add("Dockerfile", dockerfile+"\n# hi"); err != nil {
  3825  		t.Fatalf("Didn't add Dockerfile: %s", err)
  3826  	}
  3827  	if id2, err = buildImageFromContext(name, ctx, true); err != nil {
  3828  		t.Fatalf("Didn't build it correctly:%s", err)
  3829  	}
  3830  	if id1 != id2 {
  3831  		t.Fatalf("Didn't use the cache - 2")
  3832  	}
  3833  
  3834  	// One more time but just 'touch' it instead of changing the content
  3835  	if err = ctx.Add("Dockerfile", dockerfile+"\n# hi"); err != nil {
  3836  		t.Fatalf("Didn't add Dockerfile: %s", err)
  3837  	}
  3838  	if id2, err = buildImageFromContext(name, ctx, true); err != nil {
  3839  		t.Fatalf("Didn't build it correctly:%s", err)
  3840  	}
  3841  	if id1 != id2 {
  3842  		t.Fatalf("Didn't use the cache - 3")
  3843  	}
  3844  
  3845  	logDone("build - test .dockerignore touch dockerfile")
  3846  }
  3847  
  3848  func TestBuildDockerignoringWholeDir(t *testing.T) {
  3849  	name := "testbuilddockerignorewholedir"
  3850  	defer deleteImages(name)
  3851  	dockerfile := `
  3852          FROM busybox
  3853  		COPY . /
  3854  		RUN [[ ! -e /.gitignore ]]
  3855  		RUN [[ -f /Makefile ]]`
  3856  	ctx, err := fakeContext(dockerfile, map[string]string{
  3857  		"Dockerfile":    "FROM scratch",
  3858  		"Makefile":      "all:",
  3859  		".dockerignore": ".*\n",
  3860  	})
  3861  	defer ctx.Close()
  3862  	if err != nil {
  3863  		t.Fatal(err)
  3864  	}
  3865  	if _, err = buildImageFromContext(name, ctx, true); err != nil {
  3866  		t.Fatal(err)
  3867  	}
  3868  	logDone("build - test .dockerignore whole dir with .*")
  3869  }
  3870  
  3871  func TestBuildLineBreak(t *testing.T) {
  3872  	name := "testbuildlinebreak"
  3873  	defer deleteImages(name)
  3874  	_, err := buildImage(name,
  3875  		`FROM  busybox
  3876  RUN    sh -c 'echo root:testpass \
  3877  	> /tmp/passwd'
  3878  RUN    mkdir -p /var/run/sshd
  3879  RUN    [ "$(cat /tmp/passwd)" = "root:testpass" ]
  3880  RUN    [ "$(ls -d /var/run/sshd)" = "/var/run/sshd" ]`,
  3881  		true)
  3882  	if err != nil {
  3883  		t.Fatal(err)
  3884  	}
  3885  	logDone("build - line break with \\")
  3886  }
  3887  
  3888  func TestBuildEOLInLine(t *testing.T) {
  3889  	name := "testbuildeolinline"
  3890  	defer deleteImages(name)
  3891  	_, err := buildImage(name,
  3892  		`FROM   busybox
  3893  RUN    sh -c 'echo root:testpass > /tmp/passwd'
  3894  RUN    echo "foo \n bar"; echo "baz"
  3895  RUN    mkdir -p /var/run/sshd
  3896  RUN    [ "$(cat /tmp/passwd)" = "root:testpass" ]
  3897  RUN    [ "$(ls -d /var/run/sshd)" = "/var/run/sshd" ]`,
  3898  		true)
  3899  	if err != nil {
  3900  		t.Fatal(err)
  3901  	}
  3902  	logDone("build - end of line in dockerfile instruction")
  3903  }
  3904  
  3905  func TestBuildCommentsShebangs(t *testing.T) {
  3906  	name := "testbuildcomments"
  3907  	defer deleteImages(name)
  3908  	_, err := buildImage(name,
  3909  		`FROM busybox
  3910  # This is an ordinary comment.
  3911  RUN { echo '#!/bin/sh'; echo 'echo hello world'; } > /hello.sh
  3912  RUN [ ! -x /hello.sh ]
  3913  # comment with line break \
  3914  RUN chmod +x /hello.sh
  3915  RUN [ -x /hello.sh ]
  3916  RUN [ "$(cat /hello.sh)" = $'#!/bin/sh\necho hello world' ]
  3917  RUN [ "$(/hello.sh)" = "hello world" ]`,
  3918  		true)
  3919  	if err != nil {
  3920  		t.Fatal(err)
  3921  	}
  3922  	logDone("build - comments and shebangs")
  3923  }
  3924  
  3925  func TestBuildUsersAndGroups(t *testing.T) {
  3926  	name := "testbuildusers"
  3927  	defer deleteImages(name)
  3928  	_, err := buildImage(name,
  3929  		`FROM busybox
  3930  
  3931  # Make sure our defaults work
  3932  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)" = '0:0/root:root' ]
  3933  
  3934  # 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)
  3935  USER root
  3936  RUN [ "$(id -G):$(id -Gn)" = '0 10:root wheel' ]
  3937  
  3938  # Setup dockerio user and group
  3939  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  3940  RUN echo 'dockerio:x:1001:' >> /etc/group
  3941  
  3942  # Make sure we can switch to our user and all the information is exactly as we expect it to be
  3943  USER dockerio
  3944  RUN id -G
  3945  RUN id -Gn
  3946  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001:dockerio' ]
  3947  
  3948  # Switch back to root and double check that worked exactly as we might expect it to
  3949  USER root
  3950  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '0:0/root:root/0 10:root wheel' ]
  3951  
  3952  # Add a "supplementary" group for our dockerio user
  3953  RUN echo 'supplementary:x:1002:dockerio' >> /etc/group
  3954  
  3955  # ... and then go verify that we get it like we expect
  3956  USER dockerio
  3957  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001 1002:dockerio supplementary' ]
  3958  USER 1001
  3959  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001 1002:dockerio supplementary' ]
  3960  
  3961  # super test the new "user:group" syntax
  3962  USER dockerio:dockerio
  3963  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001:dockerio' ]
  3964  USER 1001:dockerio
  3965  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001:dockerio' ]
  3966  USER dockerio:1001
  3967  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001:dockerio' ]
  3968  USER 1001:1001
  3969  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001:dockerio' ]
  3970  USER dockerio:supplementary
  3971  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1002/dockerio:supplementary/1002:supplementary' ]
  3972  USER dockerio:1002
  3973  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1002/dockerio:supplementary/1002:supplementary' ]
  3974  USER 1001:supplementary
  3975  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1002/dockerio:supplementary/1002:supplementary' ]
  3976  USER 1001:1002
  3977  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1002/dockerio:supplementary/1002:supplementary' ]
  3978  
  3979  # make sure unknown uid/gid still works properly
  3980  USER 1042:1043
  3981  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1042:1043/1042:1043/1043:1043' ]`,
  3982  		true)
  3983  	if err != nil {
  3984  		t.Fatal(err)
  3985  	}
  3986  	logDone("build - users and groups")
  3987  }
  3988  
  3989  func TestBuildEnvUsage(t *testing.T) {
  3990  	name := "testbuildenvusage"
  3991  	defer deleteImages(name)
  3992  	dockerfile := `FROM busybox
  3993  ENV    HOME /root
  3994  ENV    PATH $HOME/bin:$PATH
  3995  ENV    PATH /tmp:$PATH
  3996  RUN    [ "$PATH" = "/tmp:$HOME/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ]
  3997  ENV    FOO /foo/baz
  3998  ENV    BAR /bar
  3999  ENV    BAZ $BAR
  4000  ENV    FOOPATH $PATH:$FOO
  4001  RUN    [ "$BAR" = "$BAZ" ]
  4002  RUN    [ "$FOOPATH" = "$PATH:/foo/baz" ]
  4003  ENV	   FROM hello/docker/world
  4004  ENV    TO /docker/world/hello
  4005  ADD    $FROM $TO
  4006  RUN    [ "$(cat $TO)" = "hello" ]
  4007  ENV    abc=def
  4008  ENV    ghi=$abc
  4009  RUN    [ "$ghi" = "def" ]
  4010  `
  4011  	ctx, err := fakeContext(dockerfile, map[string]string{
  4012  		"hello/docker/world": "hello",
  4013  	})
  4014  	if err != nil {
  4015  		t.Fatal(err)
  4016  	}
  4017  	defer ctx.Close()
  4018  
  4019  	_, err = buildImageFromContext(name, ctx, true)
  4020  	if err != nil {
  4021  		t.Fatal(err)
  4022  	}
  4023  	logDone("build - environment variables usage")
  4024  }
  4025  
  4026  func TestBuildEnvUsage2(t *testing.T) {
  4027  	name := "testbuildenvusage2"
  4028  	defer deleteImages(name)
  4029  	dockerfile := `FROM busybox
  4030  ENV    abc=def
  4031  RUN    [ "$abc" = "def" ]
  4032  ENV    def="hello world"
  4033  RUN    [ "$def" = "hello world" ]
  4034  ENV    def=hello\ world
  4035  RUN    [ "$def" = "hello world" ]
  4036  ENV    v1=abc v2="hi there"
  4037  RUN    [ "$v1" = "abc" ]
  4038  RUN    [ "$v2" = "hi there" ]
  4039  ENV    v3='boogie nights' v4="with'quotes too"
  4040  RUN    [ "$v3" = "boogie nights" ]
  4041  RUN    [ "$v4" = "with'quotes too" ]
  4042  ENV    abc=zzz FROM=hello/docker/world
  4043  ENV    abc=zzz TO=/docker/world/hello
  4044  ADD    $FROM $TO
  4045  RUN    [ "$(cat $TO)" = "hello" ]
  4046  ENV    abc "zzz"
  4047  RUN    [ $abc = "zzz" ]
  4048  ENV    abc 'yyy'
  4049  RUN    [ $abc = 'yyy' ]
  4050  ENV    abc=
  4051  RUN    [ "$abc" = "" ]
  4052  
  4053  # use grep to make sure if the builder substitutes \$foo by mistake
  4054  # we don't get a false positive
  4055  ENV    abc=\$foo
  4056  RUN    [ "$abc" = "\$foo" ] && (echo "$abc" | grep foo)
  4057  ENV    abc \$foo
  4058  RUN    [ "$abc" = "\$foo" ] && (echo "$abc" | grep foo)
  4059  
  4060  ENV    abc=\'foo\'
  4061  RUN    [ "$abc" = "'foo'" ]
  4062  ENV    abc=\"foo\"
  4063  RUN    [ "$abc" = "\"foo\"" ]
  4064  ENV    abc "foo"
  4065  RUN    [ "$abc" = "foo" ]
  4066  ENV    abc 'foo'
  4067  RUN    [ "$abc" = 'foo' ]
  4068  ENV    abc \'foo\'
  4069  RUN    [ "$abc" = "'foo'" ]
  4070  ENV    abc \"foo\"
  4071  RUN    [ "$abc" = '"foo"' ]
  4072  
  4073  ENV    e1=bar
  4074  ENV    e2=$e1
  4075  ENV    e3=$e11
  4076  ENV    e4=\$e1
  4077  ENV    e5=\$e11
  4078  RUN    [ "$e0,$e1,$e2,$e3,$e4,$e5" = ',bar,bar,,$e1,$e11' ]
  4079  
  4080  ENV    ee1 bar
  4081  ENV    ee2 $ee1
  4082  ENV    ee3 $ee11
  4083  ENV    ee4 \$ee1
  4084  ENV    ee5 \$ee11
  4085  RUN    [ "$ee1,$ee2,$ee3,$ee4,$ee5" = 'bar,bar,,$ee1,$ee11' ]
  4086  
  4087  ENV    eee1="foo"
  4088  ENV    eee2='foo'
  4089  ENV    eee3 "foo"
  4090  ENV    eee4 'foo'
  4091  RUN    [ "$eee1,$eee2,$eee3,$eee4" = 'foo,foo,foo,foo' ]
  4092  
  4093  `
  4094  	ctx, err := fakeContext(dockerfile, map[string]string{
  4095  		"hello/docker/world": "hello",
  4096  	})
  4097  	if err != nil {
  4098  		t.Fatal(err)
  4099  	}
  4100  	defer ctx.Close()
  4101  
  4102  	_, err = buildImageFromContext(name, ctx, true)
  4103  	if err != nil {
  4104  		t.Fatal(err)
  4105  	}
  4106  	logDone("build - environment variables usage2")
  4107  }
  4108  
  4109  func TestBuildAddScript(t *testing.T) {
  4110  	name := "testbuildaddscript"
  4111  	defer deleteImages(name)
  4112  	dockerfile := `
  4113  FROM busybox
  4114  ADD test /test
  4115  RUN ["chmod","+x","/test"]
  4116  RUN ["/test"]
  4117  RUN [ "$(cat /testfile)" = 'test!' ]`
  4118  	ctx, err := fakeContext(dockerfile, map[string]string{
  4119  		"test": "#!/bin/sh\necho 'test!' > /testfile",
  4120  	})
  4121  	if err != nil {
  4122  		t.Fatal(err)
  4123  	}
  4124  	defer ctx.Close()
  4125  
  4126  	_, err = buildImageFromContext(name, ctx, true)
  4127  	if err != nil {
  4128  		t.Fatal(err)
  4129  	}
  4130  	logDone("build - add and run script")
  4131  }
  4132  
  4133  func TestBuildAddTar(t *testing.T) {
  4134  	name := "testbuildaddtar"
  4135  	defer deleteImages(name)
  4136  
  4137  	ctx := func() *FakeContext {
  4138  		dockerfile := `
  4139  FROM busybox
  4140  ADD test.tar /
  4141  RUN cat /test/foo | grep Hi
  4142  ADD test.tar /test.tar
  4143  RUN cat /test.tar/test/foo | grep Hi
  4144  ADD test.tar /unlikely-to-exist
  4145  RUN cat /unlikely-to-exist/test/foo | grep Hi
  4146  ADD test.tar /unlikely-to-exist-trailing-slash/
  4147  RUN cat /unlikely-to-exist-trailing-slash/test/foo | grep Hi
  4148  RUN mkdir /existing-directory
  4149  ADD test.tar /existing-directory
  4150  RUN cat /existing-directory/test/foo | grep Hi
  4151  ADD test.tar /existing-directory-trailing-slash/
  4152  RUN cat /existing-directory-trailing-slash/test/foo | grep Hi`
  4153  		tmpDir, err := ioutil.TempDir("", "fake-context")
  4154  		testTar, err := os.Create(filepath.Join(tmpDir, "test.tar"))
  4155  		if err != nil {
  4156  			t.Fatalf("failed to create test.tar archive: %v", err)
  4157  		}
  4158  		defer testTar.Close()
  4159  
  4160  		tw := tar.NewWriter(testTar)
  4161  
  4162  		if err := tw.WriteHeader(&tar.Header{
  4163  			Name: "test/foo",
  4164  			Size: 2,
  4165  		}); err != nil {
  4166  			t.Fatalf("failed to write tar file header: %v", err)
  4167  		}
  4168  		if _, err := tw.Write([]byte("Hi")); err != nil {
  4169  			t.Fatalf("failed to write tar file content: %v", err)
  4170  		}
  4171  		if err := tw.Close(); err != nil {
  4172  			t.Fatalf("failed to close tar archive: %v", err)
  4173  		}
  4174  
  4175  		if err := ioutil.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644); err != nil {
  4176  			t.Fatalf("failed to open destination dockerfile: %v", err)
  4177  		}
  4178  		return fakeContextFromDir(tmpDir)
  4179  	}()
  4180  	defer ctx.Close()
  4181  
  4182  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  4183  		t.Fatalf("build failed to complete for TestBuildAddTar: %v", err)
  4184  	}
  4185  
  4186  	logDone("build - ADD tar")
  4187  }
  4188  
  4189  func TestBuildAddTarXz(t *testing.T) {
  4190  	name := "testbuildaddtarxz"
  4191  	defer deleteImages(name)
  4192  
  4193  	ctx := func() *FakeContext {
  4194  		dockerfile := `
  4195  			FROM busybox
  4196  			ADD test.tar.xz /
  4197  			RUN cat /test/foo | grep Hi`
  4198  		tmpDir, err := ioutil.TempDir("", "fake-context")
  4199  		testTar, err := os.Create(filepath.Join(tmpDir, "test.tar"))
  4200  		if err != nil {
  4201  			t.Fatalf("failed to create test.tar archive: %v", err)
  4202  		}
  4203  		defer testTar.Close()
  4204  
  4205  		tw := tar.NewWriter(testTar)
  4206  
  4207  		if err := tw.WriteHeader(&tar.Header{
  4208  			Name: "test/foo",
  4209  			Size: 2,
  4210  		}); err != nil {
  4211  			t.Fatalf("failed to write tar file header: %v", err)
  4212  		}
  4213  		if _, err := tw.Write([]byte("Hi")); err != nil {
  4214  			t.Fatalf("failed to write tar file content: %v", err)
  4215  		}
  4216  		if err := tw.Close(); err != nil {
  4217  			t.Fatalf("failed to close tar archive: %v", err)
  4218  		}
  4219  		xzCompressCmd := exec.Command("xz", "-k", "test.tar")
  4220  		xzCompressCmd.Dir = tmpDir
  4221  		out, _, err := runCommandWithOutput(xzCompressCmd)
  4222  		if err != nil {
  4223  			t.Fatal(err, out)
  4224  		}
  4225  
  4226  		if err := ioutil.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644); err != nil {
  4227  			t.Fatalf("failed to open destination dockerfile: %v", err)
  4228  		}
  4229  		return fakeContextFromDir(tmpDir)
  4230  	}()
  4231  
  4232  	defer ctx.Close()
  4233  
  4234  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  4235  		t.Fatalf("build failed to complete for TestBuildAddTarXz: %v", err)
  4236  	}
  4237  
  4238  	logDone("build - ADD tar.xz")
  4239  }
  4240  
  4241  func TestBuildAddTarXzGz(t *testing.T) {
  4242  	name := "testbuildaddtarxzgz"
  4243  	defer deleteImages(name)
  4244  
  4245  	ctx := func() *FakeContext {
  4246  		dockerfile := `
  4247  			FROM busybox
  4248  			ADD test.tar.xz.gz /
  4249  			RUN ls /test.tar.xz.gz`
  4250  		tmpDir, err := ioutil.TempDir("", "fake-context")
  4251  		testTar, err := os.Create(filepath.Join(tmpDir, "test.tar"))
  4252  		if err != nil {
  4253  			t.Fatalf("failed to create test.tar archive: %v", err)
  4254  		}
  4255  		defer testTar.Close()
  4256  
  4257  		tw := tar.NewWriter(testTar)
  4258  
  4259  		if err := tw.WriteHeader(&tar.Header{
  4260  			Name: "test/foo",
  4261  			Size: 2,
  4262  		}); err != nil {
  4263  			t.Fatalf("failed to write tar file header: %v", err)
  4264  		}
  4265  		if _, err := tw.Write([]byte("Hi")); err != nil {
  4266  			t.Fatalf("failed to write tar file content: %v", err)
  4267  		}
  4268  		if err := tw.Close(); err != nil {
  4269  			t.Fatalf("failed to close tar archive: %v", err)
  4270  		}
  4271  
  4272  		xzCompressCmd := exec.Command("xz", "-k", "test.tar")
  4273  		xzCompressCmd.Dir = tmpDir
  4274  		out, _, err := runCommandWithOutput(xzCompressCmd)
  4275  		if err != nil {
  4276  			t.Fatal(err, out)
  4277  		}
  4278  
  4279  		gzipCompressCmd := exec.Command("gzip", "test.tar.xz")
  4280  		gzipCompressCmd.Dir = tmpDir
  4281  		out, _, err = runCommandWithOutput(gzipCompressCmd)
  4282  		if err != nil {
  4283  			t.Fatal(err, out)
  4284  		}
  4285  
  4286  		if err := ioutil.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644); err != nil {
  4287  			t.Fatalf("failed to open destination dockerfile: %v", err)
  4288  		}
  4289  		return fakeContextFromDir(tmpDir)
  4290  	}()
  4291  
  4292  	defer ctx.Close()
  4293  
  4294  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  4295  		t.Fatalf("build failed to complete for TestBuildAddTarXz: %v", err)
  4296  	}
  4297  
  4298  	logDone("build - ADD tar.xz.gz")
  4299  }
  4300  
  4301  func TestBuildFromGIT(t *testing.T) {
  4302  	name := "testbuildfromgit"
  4303  	defer deleteImages(name)
  4304  	git, err := fakeGIT("repo", map[string]string{
  4305  		"Dockerfile": `FROM busybox
  4306  					ADD first /first
  4307  					RUN [ -f /first ]
  4308  					MAINTAINER docker`,
  4309  		"first": "test git data",
  4310  	}, true)
  4311  	if err != nil {
  4312  		t.Fatal(err)
  4313  	}
  4314  	defer git.Close()
  4315  
  4316  	_, err = buildImageFromPath(name, git.RepoURL, true)
  4317  	if err != nil {
  4318  		t.Fatal(err)
  4319  	}
  4320  	res, err := inspectField(name, "Author")
  4321  	if err != nil {
  4322  		t.Fatal(err)
  4323  	}
  4324  	if res != "docker" {
  4325  		t.Fatalf("Maintainer should be docker, got %s", res)
  4326  	}
  4327  	logDone("build - build from GIT")
  4328  }
  4329  
  4330  func TestBuildCleanupCmdOnEntrypoint(t *testing.T) {
  4331  	name := "testbuildcmdcleanuponentrypoint"
  4332  	defer deleteImages(name)
  4333  	if _, err := buildImage(name,
  4334  		`FROM scratch
  4335          CMD ["test"]
  4336  		ENTRYPOINT ["echo"]`,
  4337  		true); err != nil {
  4338  		t.Fatal(err)
  4339  	}
  4340  	if _, err := buildImage(name,
  4341  		fmt.Sprintf(`FROM %s
  4342  		ENTRYPOINT ["cat"]`, name),
  4343  		true); err != nil {
  4344  		t.Fatal(err)
  4345  	}
  4346  	res, err := inspectField(name, "Config.Cmd")
  4347  	if err != nil {
  4348  		t.Fatal(err)
  4349  	}
  4350  	if expected := "<no value>"; res != expected {
  4351  		t.Fatalf("Cmd %s, expected %s", res, expected)
  4352  	}
  4353  	res, err = inspectField(name, "Config.Entrypoint")
  4354  	if err != nil {
  4355  		t.Fatal(err)
  4356  	}
  4357  	if expected := "[cat]"; res != expected {
  4358  		t.Fatalf("Entrypoint %s, expected %s", res, expected)
  4359  	}
  4360  	logDone("build - cleanup cmd on ENTRYPOINT")
  4361  }
  4362  
  4363  func TestBuildClearCmd(t *testing.T) {
  4364  	name := "testbuildclearcmd"
  4365  	defer deleteImages(name)
  4366  	_, err := buildImage(name,
  4367  		`From scratch
  4368     ENTRYPOINT ["/bin/bash"]
  4369     CMD []`,
  4370  		true)
  4371  	if err != nil {
  4372  		t.Fatal(err)
  4373  	}
  4374  	res, err := inspectFieldJSON(name, "Config.Cmd")
  4375  	if err != nil {
  4376  		t.Fatal(err)
  4377  	}
  4378  	if res != "[]" {
  4379  		t.Fatalf("Cmd %s, expected %s", res, "[]")
  4380  	}
  4381  	logDone("build - clearcmd")
  4382  }
  4383  
  4384  func TestBuildEmptyCmd(t *testing.T) {
  4385  	name := "testbuildemptycmd"
  4386  	defer deleteImages(name)
  4387  	if _, err := buildImage(name, "FROM scratch\nMAINTAINER quux\n", true); err != nil {
  4388  		t.Fatal(err)
  4389  	}
  4390  	res, err := inspectFieldJSON(name, "Config.Cmd")
  4391  	if err != nil {
  4392  		t.Fatal(err)
  4393  	}
  4394  	if res != "null" {
  4395  		t.Fatalf("Cmd %s, expected %s", res, "null")
  4396  	}
  4397  	logDone("build - empty cmd")
  4398  }
  4399  
  4400  func TestBuildOnBuildOutput(t *testing.T) {
  4401  	name := "testbuildonbuildparent"
  4402  	defer deleteImages(name)
  4403  	if _, err := buildImage(name, "FROM busybox\nONBUILD RUN echo foo\n", true); err != nil {
  4404  		t.Fatal(err)
  4405  	}
  4406  
  4407  	childname := "testbuildonbuildchild"
  4408  	defer deleteImages(childname)
  4409  
  4410  	_, out, err := buildImageWithOut(name, "FROM "+name+"\nMAINTAINER quux\n", true)
  4411  	if err != nil {
  4412  		t.Fatal(err)
  4413  	}
  4414  
  4415  	if !strings.Contains(out, "Trigger 0, RUN echo foo") {
  4416  		t.Fatal("failed to find the ONBUILD output", out)
  4417  	}
  4418  
  4419  	logDone("build - onbuild output")
  4420  }
  4421  
  4422  func TestBuildInvalidTag(t *testing.T) {
  4423  	name := "abcd:" + makeRandomString(200)
  4424  	defer deleteImages(name)
  4425  	_, out, err := buildImageWithOut(name, "FROM scratch\nMAINTAINER quux\n", true)
  4426  	// if the error doesnt check for illegal tag name, or the image is built
  4427  	// then this should fail
  4428  	if !strings.Contains(out, "Illegal tag name") || strings.Contains(out, "Sending build context to Docker daemon") {
  4429  		t.Fatalf("failed to stop before building. Error: %s, Output: %s", err, out)
  4430  	}
  4431  	logDone("build - invalid tag")
  4432  }
  4433  
  4434  func TestBuildCmdShDashC(t *testing.T) {
  4435  	name := "testbuildcmdshc"
  4436  	defer deleteImages(name)
  4437  	if _, err := buildImage(name, "FROM busybox\nCMD echo cmd\n", true); err != nil {
  4438  		t.Fatal(err)
  4439  	}
  4440  
  4441  	res, err := inspectFieldJSON(name, "Config.Cmd")
  4442  	if err != nil {
  4443  		t.Fatal(err, res)
  4444  	}
  4445  
  4446  	expected := `["/bin/sh","-c","echo cmd"]`
  4447  
  4448  	if res != expected {
  4449  		t.Fatalf("Expected value %s not in Config.Cmd: %s", expected, res)
  4450  	}
  4451  
  4452  	logDone("build - cmd should have sh -c for non-json")
  4453  }
  4454  
  4455  func TestBuildCmdSpaces(t *testing.T) {
  4456  	// Test to make sure that when we strcat arrays we take into account
  4457  	// the arg separator to make sure ["echo","hi"] and ["echo hi"] don't
  4458  	// look the same
  4459  	name := "testbuildcmdspaces"
  4460  	defer deleteImages(name)
  4461  	var id1 string
  4462  	var id2 string
  4463  	var err error
  4464  
  4465  	if id1, err = buildImage(name, "FROM busybox\nCMD [\"echo hi\"]\n", true); err != nil {
  4466  		t.Fatal(err)
  4467  	}
  4468  
  4469  	if id2, err = buildImage(name, "FROM busybox\nCMD [\"echo\", \"hi\"]\n", true); err != nil {
  4470  		t.Fatal(err)
  4471  	}
  4472  
  4473  	if id1 == id2 {
  4474  		t.Fatal("Should not have resulted in the same CMD")
  4475  	}
  4476  
  4477  	// Now do the same with ENTRYPOINT
  4478  	if id1, err = buildImage(name, "FROM busybox\nENTRYPOINT [\"echo hi\"]\n", true); err != nil {
  4479  		t.Fatal(err)
  4480  	}
  4481  
  4482  	if id2, err = buildImage(name, "FROM busybox\nENTRYPOINT [\"echo\", \"hi\"]\n", true); err != nil {
  4483  		t.Fatal(err)
  4484  	}
  4485  
  4486  	if id1 == id2 {
  4487  		t.Fatal("Should not have resulted in the same ENTRYPOINT")
  4488  	}
  4489  
  4490  	logDone("build - cmd with spaces")
  4491  }
  4492  
  4493  func TestBuildCmdJSONNoShDashC(t *testing.T) {
  4494  	name := "testbuildcmdjson"
  4495  	defer deleteImages(name)
  4496  	if _, err := buildImage(name, "FROM busybox\nCMD [\"echo\", \"cmd\"]", true); err != nil {
  4497  		t.Fatal(err)
  4498  	}
  4499  
  4500  	res, err := inspectFieldJSON(name, "Config.Cmd")
  4501  	if err != nil {
  4502  		t.Fatal(err, res)
  4503  	}
  4504  
  4505  	expected := `["echo","cmd"]`
  4506  
  4507  	if res != expected {
  4508  		t.Fatalf("Expected value %s not in Config.Cmd: %s", expected, res)
  4509  	}
  4510  
  4511  	logDone("build - cmd should not have /bin/sh -c for json")
  4512  }
  4513  
  4514  func TestBuildErrorInvalidInstruction(t *testing.T) {
  4515  	name := "testbuildignoreinvalidinstruction"
  4516  	defer deleteImages(name)
  4517  
  4518  	out, _, err := buildImageWithOut(name, "FROM busybox\nfoo bar", true)
  4519  	if err == nil {
  4520  		t.Fatalf("Should have failed: %s", out)
  4521  	}
  4522  
  4523  	logDone("build - error invalid Dockerfile instruction")
  4524  }
  4525  
  4526  func TestBuildEntrypointInheritance(t *testing.T) {
  4527  	defer deleteImages("parent", "child")
  4528  	defer deleteAllContainers()
  4529  
  4530  	if _, err := buildImage("parent", `
  4531      FROM busybox
  4532      ENTRYPOINT exit 130
  4533      `, true); err != nil {
  4534  		t.Fatal(err)
  4535  	}
  4536  
  4537  	status, _ := runCommand(exec.Command(dockerBinary, "run", "parent"))
  4538  
  4539  	if status != 130 {
  4540  		t.Fatalf("expected exit code 130 but received %d", status)
  4541  	}
  4542  
  4543  	if _, err := buildImage("child", `
  4544      FROM parent
  4545      ENTRYPOINT exit 5
  4546      `, true); err != nil {
  4547  		t.Fatal(err)
  4548  	}
  4549  
  4550  	status, _ = runCommand(exec.Command(dockerBinary, "run", "child"))
  4551  
  4552  	if status != 5 {
  4553  		t.Fatalf("expected exit code 5 but received %d", status)
  4554  	}
  4555  
  4556  	logDone("build - clear entrypoint")
  4557  }
  4558  
  4559  func TestBuildEntrypointInheritanceInspect(t *testing.T) {
  4560  	var (
  4561  		name     = "testbuildepinherit"
  4562  		name2    = "testbuildepinherit2"
  4563  		expected = `["/bin/sh","-c","echo quux"]`
  4564  	)
  4565  
  4566  	defer deleteImages(name, name2)
  4567  	defer deleteAllContainers()
  4568  
  4569  	if _, err := buildImage(name, "FROM busybox\nENTRYPOINT /foo/bar", true); err != nil {
  4570  		t.Fatal(err)
  4571  	}
  4572  
  4573  	if _, err := buildImage(name2, fmt.Sprintf("FROM %s\nENTRYPOINT echo quux", name), true); err != nil {
  4574  		t.Fatal(err)
  4575  	}
  4576  
  4577  	res, err := inspectFieldJSON(name2, "Config.Entrypoint")
  4578  	if err != nil {
  4579  		t.Fatal(err, res)
  4580  	}
  4581  
  4582  	if res != expected {
  4583  		t.Fatalf("Expected value %s not in Config.Entrypoint: %s", expected, res)
  4584  	}
  4585  
  4586  	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-t", name2))
  4587  	if err != nil {
  4588  		t.Fatal(err, out)
  4589  	}
  4590  
  4591  	expected = "quux"
  4592  
  4593  	if strings.TrimSpace(out) != expected {
  4594  		t.Fatalf("Expected output is %s, got %s", expected, out)
  4595  	}
  4596  
  4597  	logDone("build - entrypoint override inheritance properly")
  4598  }
  4599  
  4600  func TestBuildRunShEntrypoint(t *testing.T) {
  4601  	name := "testbuildentrypoint"
  4602  	defer deleteImages(name)
  4603  	_, err := buildImage(name,
  4604  		`FROM busybox
  4605                                  ENTRYPOINT /bin/echo`,
  4606  		true)
  4607  	if err != nil {
  4608  		t.Fatal(err)
  4609  	}
  4610  
  4611  	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "--rm", name))
  4612  
  4613  	if err != nil {
  4614  		t.Fatal(err, out)
  4615  	}
  4616  
  4617  	logDone("build - entrypoint with /bin/echo running successfully")
  4618  }
  4619  
  4620  func TestBuildExoticShellInterpolation(t *testing.T) {
  4621  	name := "testbuildexoticshellinterpolation"
  4622  	defer deleteImages(name)
  4623  
  4624  	_, err := buildImage(name, `
  4625  		FROM busybox
  4626  
  4627  		ENV SOME_VAR a.b.c
  4628  
  4629  		RUN [ "$SOME_VAR"       = 'a.b.c' ]
  4630  		RUN [ "${SOME_VAR}"     = 'a.b.c' ]
  4631  		RUN [ "${SOME_VAR%.*}"  = 'a.b'   ]
  4632  		RUN [ "${SOME_VAR%%.*}" = 'a'     ]
  4633  		RUN [ "${SOME_VAR#*.}"  = 'b.c'   ]
  4634  		RUN [ "${SOME_VAR##*.}" = 'c'     ]
  4635  		RUN [ "${SOME_VAR/c/d}" = 'a.b.d' ]
  4636  		RUN [ "${#SOME_VAR}"    = '5'     ]
  4637  
  4638  		RUN [ "${SOME_UNSET_VAR:-$SOME_VAR}" = 'a.b.c' ]
  4639  		RUN [ "${SOME_VAR:+Version: ${SOME_VAR}}" = 'Version: a.b.c' ]
  4640  		RUN [ "${SOME_UNSET_VAR:+${SOME_VAR}}" = '' ]
  4641  		RUN [ "${SOME_UNSET_VAR:-${SOME_VAR:-d.e.f}}" = 'a.b.c' ]
  4642  	`, false)
  4643  	if err != nil {
  4644  		t.Fatal(err)
  4645  	}
  4646  
  4647  	logDone("build - exotic shell interpolation")
  4648  }
  4649  
  4650  func TestBuildVerifySingleQuoteFails(t *testing.T) {
  4651  	// This testcase is supposed to generate an error because the
  4652  	// JSON array we're passing in on the CMD uses single quotes instead
  4653  	// of double quotes (per the JSON spec). This means we interpret it
  4654  	// as a "string" insead of "JSON array" and pass it on to "sh -c" and
  4655  	// it should barf on it.
  4656  	name := "testbuildsinglequotefails"
  4657  	defer deleteImages(name)
  4658  	defer deleteAllContainers()
  4659  
  4660  	_, err := buildImage(name,
  4661  		`FROM busybox
  4662  		CMD [ '/bin/sh', '-c', 'echo hi' ]`,
  4663  		true)
  4664  	_, _, err = runCommandWithOutput(exec.Command(dockerBinary, "run", "--rm", name))
  4665  
  4666  	if err == nil {
  4667  		t.Fatal("The image was not supposed to be able to run")
  4668  	}
  4669  
  4670  	logDone("build - verify single quotes break the build")
  4671  }
  4672  
  4673  func TestBuildVerboseOut(t *testing.T) {
  4674  	name := "testbuildverboseout"
  4675  	defer deleteImages(name)
  4676  
  4677  	_, out, err := buildImageWithOut(name,
  4678  		`FROM busybox
  4679  RUN echo 123`,
  4680  		false)
  4681  
  4682  	if err != nil {
  4683  		t.Fatal(err)
  4684  	}
  4685  	if !strings.Contains(out, "\n123\n") {
  4686  		t.Fatalf("Output should contain %q: %q", "123", out)
  4687  	}
  4688  
  4689  	logDone("build - verbose output from commands")
  4690  }
  4691  
  4692  func TestBuildWithTabs(t *testing.T) {
  4693  	name := "testbuildwithtabs"
  4694  	defer deleteImages(name)
  4695  	_, err := buildImage(name,
  4696  		"FROM busybox\nRUN echo\tone\t\ttwo", true)
  4697  	if err != nil {
  4698  		t.Fatal(err)
  4699  	}
  4700  	res, err := inspectFieldJSON(name, "ContainerConfig.Cmd")
  4701  	if err != nil {
  4702  		t.Fatal(err)
  4703  	}
  4704  	expected1 := `["/bin/sh","-c","echo\tone\t\ttwo"]`
  4705  	expected2 := `["/bin/sh","-c","echo\u0009one\u0009\u0009two"]` // syntactically equivalent, and what Go 1.3 generates
  4706  	if res != expected1 && res != expected2 {
  4707  		t.Fatalf("Missing tabs.\nGot: %s\nExp: %s or %s", res, expected1, expected2)
  4708  	}
  4709  	logDone("build - with tabs")
  4710  }
  4711  
  4712  func TestBuildLabels(t *testing.T) {
  4713  	name := "testbuildlabel"
  4714  	expected := `{"License":"GPL","Vendor":"Acme"}`
  4715  	defer deleteImages(name)
  4716  	_, err := buildImage(name,
  4717  		`FROM busybox
  4718  		LABEL Vendor=Acme
  4719                  LABEL License GPL`,
  4720  		true)
  4721  	if err != nil {
  4722  		t.Fatal(err)
  4723  	}
  4724  	res, err := inspectFieldJSON(name, "Config.Labels")
  4725  	if err != nil {
  4726  		t.Fatal(err)
  4727  	}
  4728  	if res != expected {
  4729  		t.Fatalf("Labels %s, expected %s", res, expected)
  4730  	}
  4731  	logDone("build - label")
  4732  }
  4733  
  4734  func TestBuildLabelsCache(t *testing.T) {
  4735  	name := "testbuildlabelcache"
  4736  	defer deleteImages(name)
  4737  
  4738  	id1, err := buildImage(name,
  4739  		`FROM busybox
  4740  		LABEL Vendor=Acme`, false)
  4741  	if err != nil {
  4742  		t.Fatalf("Build 1 should have worked: %v", err)
  4743  	}
  4744  
  4745  	id2, err := buildImage(name,
  4746  		`FROM busybox
  4747  		LABEL Vendor=Acme`, true)
  4748  	if err != nil || id1 != id2 {
  4749  		t.Fatalf("Build 2 should have worked & used cache(%s,%s): %v", id1, id2, err)
  4750  	}
  4751  
  4752  	id2, err = buildImage(name,
  4753  		`FROM busybox
  4754  		LABEL Vendor=Acme1`, true)
  4755  	if err != nil || id1 == id2 {
  4756  		t.Fatalf("Build 3 should have worked & NOT used cache(%s,%s): %v", id1, id2, err)
  4757  	}
  4758  
  4759  	id2, err = buildImage(name,
  4760  		`FROM busybox
  4761  		LABEL Vendor Acme`, true) // Note: " " and "=" should be same
  4762  	if err != nil || id1 != id2 {
  4763  		t.Fatalf("Build 4 should have worked & used cache(%s,%s): %v", id1, id2, err)
  4764  	}
  4765  
  4766  	// Now make sure the cache isn't used by mistake
  4767  	id1, err = buildImage(name,
  4768  		`FROM busybox
  4769         LABEL f1=b1 f2=b2`, false)
  4770  	if err != nil {
  4771  		t.Fatalf("Build 5 should have worked: %q", err)
  4772  	}
  4773  
  4774  	id2, err = buildImage(name,
  4775  		`FROM busybox
  4776         LABEL f1="b1 f2=b2"`, true)
  4777  	if err != nil || id1 == id2 {
  4778  		t.Fatalf("Build 6 should have worked & NOT used the cache(%s,%s): %q", id1, id2, err)
  4779  	}
  4780  
  4781  	logDone("build - label cache")
  4782  }
  4783  
  4784  func TestBuildStderr(t *testing.T) {
  4785  	// This test just makes sure that no non-error output goes
  4786  	// to stderr
  4787  	name := "testbuildstderr"
  4788  	defer deleteImages(name)
  4789  	_, _, stderr, err := buildImageWithStdoutStderr(name,
  4790  		"FROM busybox\nRUN echo one", true)
  4791  	if err != nil {
  4792  		t.Fatal(err)
  4793  	}
  4794  
  4795  	if runtime.GOOS == "windows" {
  4796  		// stderr might contain a security warning on windows
  4797  		lines := strings.Split(stderr, "\n")
  4798  		for _, v := range lines {
  4799  			if v != "" && !strings.Contains(v, "SECURITY WARNING:") {
  4800  				t.Fatalf("Stderr contains unexpected output line: %q", v)
  4801  			}
  4802  		}
  4803  	} else {
  4804  		if stderr != "" {
  4805  			t.Fatalf("Stderr should have been empty, instead its: %q", stderr)
  4806  		}
  4807  	}
  4808  	logDone("build - testing stderr")
  4809  }
  4810  
  4811  func TestBuildChownSingleFile(t *testing.T) {
  4812  	testRequires(t, UnixCli) // test uses chown: not available on windows
  4813  
  4814  	name := "testbuildchownsinglefile"
  4815  	defer deleteImages(name)
  4816  
  4817  	ctx, err := fakeContext(`
  4818  FROM busybox
  4819  COPY test /
  4820  RUN ls -l /test
  4821  RUN [ $(ls -l /test | awk '{print $3":"$4}') = 'root:root' ]
  4822  `, map[string]string{
  4823  		"test": "test",
  4824  	})
  4825  	if err != nil {
  4826  		t.Fatal(err)
  4827  	}
  4828  	defer ctx.Close()
  4829  
  4830  	if err := os.Chown(filepath.Join(ctx.Dir, "test"), 4242, 4242); err != nil {
  4831  		t.Fatal(err)
  4832  	}
  4833  
  4834  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  4835  		t.Fatal(err)
  4836  	}
  4837  
  4838  	logDone("build - change permission on single file")
  4839  }
  4840  
  4841  func TestBuildSymlinkBreakout(t *testing.T) {
  4842  	name := "testbuildsymlinkbreakout"
  4843  	tmpdir, err := ioutil.TempDir("", name)
  4844  	if err != nil {
  4845  		t.Fatal(err)
  4846  	}
  4847  	defer os.RemoveAll(tmpdir)
  4848  	ctx := filepath.Join(tmpdir, "context")
  4849  	if err := os.MkdirAll(ctx, 0755); err != nil {
  4850  		t.Fatal(err)
  4851  	}
  4852  	if err := ioutil.WriteFile(filepath.Join(ctx, "Dockerfile"), []byte(`
  4853  	from busybox
  4854  	add symlink.tar /
  4855  	add inject /symlink/
  4856  	`), 0644); err != nil {
  4857  		t.Fatal(err)
  4858  	}
  4859  	inject := filepath.Join(ctx, "inject")
  4860  	if err := ioutil.WriteFile(inject, nil, 0644); err != nil {
  4861  		t.Fatal(err)
  4862  	}
  4863  	f, err := os.Create(filepath.Join(ctx, "symlink.tar"))
  4864  	if err != nil {
  4865  		t.Fatal(err)
  4866  	}
  4867  	w := tar.NewWriter(f)
  4868  	w.WriteHeader(&tar.Header{
  4869  		Name:     "symlink2",
  4870  		Typeflag: tar.TypeSymlink,
  4871  		Linkname: "/../../../../../../../../../../../../../../",
  4872  		Uid:      os.Getuid(),
  4873  		Gid:      os.Getgid(),
  4874  	})
  4875  	w.WriteHeader(&tar.Header{
  4876  		Name:     "symlink",
  4877  		Typeflag: tar.TypeSymlink,
  4878  		Linkname: filepath.Join("symlink2", tmpdir),
  4879  		Uid:      os.Getuid(),
  4880  		Gid:      os.Getgid(),
  4881  	})
  4882  	w.Close()
  4883  	f.Close()
  4884  	if _, err := buildImageFromContext(name, fakeContextFromDir(ctx), false); err != nil {
  4885  		t.Fatal(err)
  4886  	}
  4887  	if _, err := os.Lstat(filepath.Join(tmpdir, "inject")); err == nil {
  4888  		t.Fatal("symlink breakout - inject")
  4889  	} else if !os.IsNotExist(err) {
  4890  		t.Fatalf("unexpected error: %v", err)
  4891  	}
  4892  	logDone("build - symlink breakout")
  4893  }
  4894  
  4895  func TestBuildXZHost(t *testing.T) {
  4896  	name := "testbuildxzhost"
  4897  	defer deleteImages(name)
  4898  
  4899  	ctx, err := fakeContext(`
  4900  FROM busybox
  4901  ADD xz /usr/local/sbin/
  4902  RUN chmod 755 /usr/local/sbin/xz
  4903  ADD test.xz /
  4904  RUN [ ! -e /injected ]`,
  4905  		map[string]string{
  4906  			"test.xz": "\xfd\x37\x7a\x58\x5a\x00\x00\x04\xe6\xd6\xb4\x46\x02\x00" +
  4907  				"\x21\x01\x16\x00\x00\x00\x74\x2f\xe5\xa3\x01\x00\x3f\xfd" +
  4908  				"\x37\x7a\x58\x5a\x00\x00\x04\xe6\xd6\xb4\x46\x02\x00\x21",
  4909  			"xz": "#!/bin/sh\ntouch /injected",
  4910  		})
  4911  
  4912  	if err != nil {
  4913  		t.Fatal(err)
  4914  	}
  4915  	defer ctx.Close()
  4916  
  4917  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  4918  		t.Fatal(err)
  4919  	}
  4920  
  4921  	logDone("build - xz host is being used")
  4922  }
  4923  
  4924  func TestBuildVolumesRetainContents(t *testing.T) {
  4925  	var (
  4926  		name     = "testbuildvolumescontent"
  4927  		expected = "some text"
  4928  	)
  4929  	defer deleteImages(name)
  4930  	ctx, err := fakeContext(`
  4931  FROM busybox
  4932  COPY content /foo/file
  4933  VOLUME /foo
  4934  CMD cat /foo/file`,
  4935  		map[string]string{
  4936  			"content": expected,
  4937  		})
  4938  	if err != nil {
  4939  		t.Fatal(err)
  4940  	}
  4941  	defer ctx.Close()
  4942  
  4943  	if _, err := buildImageFromContext(name, ctx, false); err != nil {
  4944  		t.Fatal(err)
  4945  	}
  4946  
  4947  	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "--rm", name))
  4948  	if err != nil {
  4949  		t.Fatal(err)
  4950  	}
  4951  	if out != expected {
  4952  		t.Fatalf("expected file contents for /foo/file to be %q but received %q", expected, out)
  4953  	}
  4954  
  4955  	logDone("build - volumes retain contents in build")
  4956  }
  4957  
  4958  func TestBuildRenamedDockerfile(t *testing.T) {
  4959  	defer deleteAllContainers()
  4960  
  4961  	ctx, err := fakeContext(`FROM busybox
  4962  	RUN echo from Dockerfile`,
  4963  		map[string]string{
  4964  			"Dockerfile":       "FROM busybox\nRUN echo from Dockerfile",
  4965  			"files/Dockerfile": "FROM busybox\nRUN echo from files/Dockerfile",
  4966  			"files/dFile":      "FROM busybox\nRUN echo from files/dFile",
  4967  			"dFile":            "FROM busybox\nRUN echo from dFile",
  4968  			"files/dFile2":     "FROM busybox\nRUN echo from files/dFile2",
  4969  		})
  4970  	defer ctx.Close()
  4971  	if err != nil {
  4972  		t.Fatal(err)
  4973  	}
  4974  
  4975  	out, _, err := dockerCmdInDir(t, ctx.Dir, "build", "-t", "test1", ".")
  4976  	if err != nil {
  4977  		t.Fatalf("Failed to build: %s\n%s", out, err)
  4978  	}
  4979  	if !strings.Contains(out, "from Dockerfile") {
  4980  		t.Fatalf("test1 should have used Dockerfile, output:%s", out)
  4981  	}
  4982  
  4983  	out, _, err = dockerCmdInDir(t, ctx.Dir, "build", "-f", filepath.Join("files", "Dockerfile"), "-t", "test2", ".")
  4984  	if err != nil {
  4985  		t.Fatal(err)
  4986  	}
  4987  	if !strings.Contains(out, "from files/Dockerfile") {
  4988  		t.Fatalf("test2 should have used files/Dockerfile, output:%s", out)
  4989  	}
  4990  
  4991  	out, _, err = dockerCmdInDir(t, ctx.Dir, "build", fmt.Sprintf("--file=%s", filepath.Join("files", "dFile")), "-t", "test3", ".")
  4992  	if err != nil {
  4993  		t.Fatal(err)
  4994  	}
  4995  	if !strings.Contains(out, "from files/dFile") {
  4996  		t.Fatalf("test3 should have used files/dFile, output:%s", out)
  4997  	}
  4998  
  4999  	out, _, err = dockerCmdInDir(t, ctx.Dir, "build", "--file=dFile", "-t", "test4", ".")
  5000  	if err != nil {
  5001  		t.Fatal(err)
  5002  	}
  5003  	if !strings.Contains(out, "from dFile") {
  5004  		t.Fatalf("test4 should have used dFile, output:%s", out)
  5005  	}
  5006  
  5007  	dirWithNoDockerfile, _ := ioutil.TempDir(os.TempDir(), "test5")
  5008  	nonDockerfileFile := filepath.Join(dirWithNoDockerfile, "notDockerfile")
  5009  	if _, err = os.Create(nonDockerfileFile); err != nil {
  5010  		t.Fatal(err)
  5011  	}
  5012  	out, _, err = dockerCmdInDir(t, ctx.Dir, "build", fmt.Sprintf("--file=%s", nonDockerfileFile), "-t", "test5", ".")
  5013  
  5014  	if err == nil {
  5015  		t.Fatalf("test5 was supposed to fail to find passwd")
  5016  	}
  5017  
  5018  	if expected := fmt.Sprintf("The Dockerfile (%s) must be within the build context (.)", strings.Replace(nonDockerfileFile, `\`, `\\`, -1)); !strings.Contains(out, expected) {
  5019  		t.Fatalf("wrong error messsage:%v\nexpected to contain=%v", out, expected)
  5020  	}
  5021  
  5022  	out, _, err = dockerCmdInDir(t, filepath.Join(ctx.Dir, "files"), "build", "-f", filepath.Join("..", "Dockerfile"), "-t", "test6", "..")
  5023  	if err != nil {
  5024  		t.Fatalf("test6 failed: %s", err)
  5025  	}
  5026  	if !strings.Contains(out, "from Dockerfile") {
  5027  		t.Fatalf("test6 should have used root Dockerfile, output:%s", out)
  5028  	}
  5029  
  5030  	out, _, err = dockerCmdInDir(t, filepath.Join(ctx.Dir, "files"), "build", "-f", filepath.Join(ctx.Dir, "files", "Dockerfile"), "-t", "test7", "..")
  5031  	if err != nil {
  5032  		t.Fatalf("test7 failed: %s", err)
  5033  	}
  5034  	if !strings.Contains(out, "from files/Dockerfile") {
  5035  		t.Fatalf("test7 should have used files Dockerfile, output:%s", out)
  5036  	}
  5037  
  5038  	out, _, err = dockerCmdInDir(t, filepath.Join(ctx.Dir, "files"), "build", "-f", filepath.Join("..", "Dockerfile"), "-t", "test8", ".")
  5039  	if err == nil || !strings.Contains(out, "must be within the build context") {
  5040  		t.Fatalf("test8 should have failed with Dockerfile out of context: %s", err)
  5041  	}
  5042  
  5043  	tmpDir := os.TempDir()
  5044  	out, _, err = dockerCmdInDir(t, tmpDir, "build", "-t", "test9", ctx.Dir)
  5045  	if err != nil {
  5046  		t.Fatalf("test9 - failed: %s", err)
  5047  	}
  5048  	if !strings.Contains(out, "from Dockerfile") {
  5049  		t.Fatalf("test9 should have used root Dockerfile, output:%s", out)
  5050  	}
  5051  
  5052  	out, _, err = dockerCmdInDir(t, filepath.Join(ctx.Dir, "files"), "build", "-f", "dFile2", "-t", "test10", ".")
  5053  	if err != nil {
  5054  		t.Fatalf("test10 should have worked: %s", err)
  5055  	}
  5056  	if !strings.Contains(out, "from files/dFile2") {
  5057  		t.Fatalf("test10 should have used files/dFile2, output:%s", out)
  5058  	}
  5059  
  5060  	logDone("build - rename dockerfile")
  5061  }
  5062  
  5063  func TestBuildFromMixedcaseDockerfile(t *testing.T) {
  5064  	testRequires(t, UnixCli) // Dockerfile overwrites dockerfile on windows
  5065  	defer deleteImages("test1")
  5066  
  5067  	ctx, err := fakeContext(`FROM busybox
  5068  	RUN echo from dockerfile`,
  5069  		map[string]string{
  5070  			"dockerfile": "FROM busybox\nRUN echo from dockerfile",
  5071  		})
  5072  	defer ctx.Close()
  5073  	if err != nil {
  5074  		t.Fatal(err)
  5075  	}
  5076  
  5077  	out, _, err := dockerCmdInDir(t, ctx.Dir, "build", "-t", "test1", ".")
  5078  	if err != nil {
  5079  		t.Fatalf("Failed to build: %s\n%s", out, err)
  5080  	}
  5081  
  5082  	if !strings.Contains(out, "from dockerfile") {
  5083  		t.Fatalf("Missing proper output: %s", out)
  5084  	}
  5085  
  5086  	logDone("build - mixedcase Dockerfile")
  5087  }
  5088  
  5089  func TestBuildWithTwoDockerfiles(t *testing.T) {
  5090  	testRequires(t, UnixCli) // Dockerfile overwrites dockerfile on windows
  5091  	defer deleteImages("test1")
  5092  
  5093  	ctx, err := fakeContext(`FROM busybox
  5094  RUN echo from Dockerfile`,
  5095  		map[string]string{
  5096  			"dockerfile": "FROM busybox\nRUN echo from dockerfile",
  5097  		})
  5098  	defer ctx.Close()
  5099  	if err != nil {
  5100  		t.Fatal(err)
  5101  	}
  5102  
  5103  	out, _, err := dockerCmdInDir(t, ctx.Dir, "build", "-t", "test1", ".")
  5104  	if err != nil {
  5105  		t.Fatalf("Failed to build: %s\n%s", out, err)
  5106  	}
  5107  
  5108  	if !strings.Contains(out, "from Dockerfile") {
  5109  		t.Fatalf("Missing proper output: %s", out)
  5110  	}
  5111  
  5112  	logDone("build - two Dockerfiles")
  5113  }
  5114  
  5115  func TestBuildFromURLWithF(t *testing.T) {
  5116  	defer deleteImages("test1")
  5117  
  5118  	server, err := fakeStorage(map[string]string{"baz": `FROM busybox
  5119  RUN echo from baz
  5120  COPY * /tmp/
  5121  RUN find /tmp/`})
  5122  	if err != nil {
  5123  		t.Fatal(err)
  5124  	}
  5125  	defer server.Close()
  5126  
  5127  	ctx, err := fakeContext(`FROM busybox
  5128  RUN echo from Dockerfile`,
  5129  		map[string]string{})
  5130  	defer ctx.Close()
  5131  	if err != nil {
  5132  		t.Fatal(err)
  5133  	}
  5134  
  5135  	// Make sure that -f is ignored and that we don't use the Dockerfile
  5136  	// that's in the current dir
  5137  	out, _, err := dockerCmdInDir(t, ctx.Dir, "build", "-f", "baz", "-t", "test1", server.URL()+"/baz")
  5138  	if err != nil {
  5139  		t.Fatalf("Failed to build: %s\n%s", out, err)
  5140  	}
  5141  
  5142  	if !strings.Contains(out, "from baz") ||
  5143  		strings.Contains(out, "/tmp/baz") ||
  5144  		!strings.Contains(out, "/tmp/Dockerfile") {
  5145  		t.Fatalf("Missing proper output: %s", out)
  5146  	}
  5147  
  5148  	logDone("build - from URL with -f")
  5149  }
  5150  
  5151  func TestBuildFromStdinWithF(t *testing.T) {
  5152  	defer deleteImages("test1")
  5153  
  5154  	ctx, err := fakeContext(`FROM busybox
  5155  RUN echo from Dockerfile`,
  5156  		map[string]string{})
  5157  	defer ctx.Close()
  5158  	if err != nil {
  5159  		t.Fatal(err)
  5160  	}
  5161  
  5162  	// Make sure that -f is ignored and that we don't use the Dockerfile
  5163  	// that's in the current dir
  5164  	dockerCommand := exec.Command(dockerBinary, "build", "-f", "baz", "-t", "test1", "-")
  5165  	dockerCommand.Dir = ctx.Dir
  5166  	dockerCommand.Stdin = strings.NewReader(`FROM busybox
  5167  RUN echo from baz
  5168  COPY * /tmp/
  5169  RUN find /tmp/`)
  5170  	out, status, err := runCommandWithOutput(dockerCommand)
  5171  	if err != nil || status != 0 {
  5172  		t.Fatalf("Error building: %s", err)
  5173  	}
  5174  
  5175  	if !strings.Contains(out, "from baz") ||
  5176  		strings.Contains(out, "/tmp/baz") ||
  5177  		!strings.Contains(out, "/tmp/Dockerfile") {
  5178  		t.Fatalf("Missing proper output: %s", out)
  5179  	}
  5180  
  5181  	logDone("build - from stdin with -f")
  5182  }
  5183  
  5184  func TestBuildFromOfficialNames(t *testing.T) {
  5185  	name := "testbuildfromofficial"
  5186  	fromNames := []string{
  5187  		"busybox",
  5188  		"docker.io/busybox",
  5189  		"index.docker.io/busybox",
  5190  		"library/busybox",
  5191  		"docker.io/library/busybox",
  5192  		"index.docker.io/library/busybox",
  5193  	}
  5194  	for idx, fromName := range fromNames {
  5195  		imgName := fmt.Sprintf("%s%d", name, idx)
  5196  		_, err := buildImage(imgName, "FROM "+fromName, true)
  5197  		if err != nil {
  5198  			t.Errorf("Build failed using FROM %s: %s", fromName, err)
  5199  		}
  5200  		deleteImages(imgName)
  5201  	}
  5202  	logDone("build - from official names")
  5203  }
  5204  
  5205  func TestBuildDockerfileOutsideContext(t *testing.T) {
  5206  	testRequires(t, UnixCli) // uses os.Symlink: not implemented in windows at the time of writing (go-1.4.2)
  5207  
  5208  	name := "testbuilddockerfileoutsidecontext"
  5209  	tmpdir, err := ioutil.TempDir("", name)
  5210  	if err != nil {
  5211  		t.Fatal(err)
  5212  	}
  5213  	defer os.RemoveAll(tmpdir)
  5214  	ctx := filepath.Join(tmpdir, "context")
  5215  	if err := os.MkdirAll(ctx, 0755); err != nil {
  5216  		t.Fatal(err)
  5217  	}
  5218  	if err := ioutil.WriteFile(filepath.Join(ctx, "Dockerfile"), []byte("FROM scratch\nENV X Y"), 0644); err != nil {
  5219  		t.Fatal(err)
  5220  	}
  5221  	wd, err := os.Getwd()
  5222  	if err != nil {
  5223  		t.Fatal(err)
  5224  	}
  5225  	defer os.Chdir(wd)
  5226  	if err := os.Chdir(ctx); err != nil {
  5227  		t.Fatal(err)
  5228  	}
  5229  	if err := ioutil.WriteFile(filepath.Join(tmpdir, "outsideDockerfile"), []byte("FROM scratch\nENV x y"), 0644); err != nil {
  5230  		t.Fatal(err)
  5231  	}
  5232  	if err := os.Symlink(filepath.Join("..", "outsideDockerfile"), filepath.Join(ctx, "dockerfile1")); err != nil {
  5233  		t.Fatal(err)
  5234  	}
  5235  	if err := os.Symlink(filepath.Join(tmpdir, "outsideDockerfile"), filepath.Join(ctx, "dockerfile2")); err != nil {
  5236  		t.Fatal(err)
  5237  	}
  5238  
  5239  	for _, dockerfilePath := range []string{
  5240  		filepath.Join("..", "outsideDockerfile"),
  5241  		filepath.Join(ctx, "dockerfile1"),
  5242  		filepath.Join(ctx, "dockerfile2"),
  5243  	} {
  5244  		out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "build", "-t", name, "--no-cache", "-f", dockerfilePath, "."))
  5245  		if err == nil {
  5246  			t.Fatalf("Expected error with %s. Out: %s", dockerfilePath, out)
  5247  		}
  5248  		if !strings.Contains(out, "must be within the build context") && !strings.Contains(out, "Cannot locate Dockerfile") {
  5249  			t.Fatalf("Unexpected error with %s. Out: %s", dockerfilePath, out)
  5250  		}
  5251  		deleteImages(name)
  5252  	}
  5253  
  5254  	os.Chdir(tmpdir)
  5255  
  5256  	// Path to Dockerfile should be resolved relative to working directory, not relative to context.
  5257  	// There is a Dockerfile in the context, but since there is no Dockerfile in the current directory, the following should fail
  5258  	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "build", "-t", name, "--no-cache", "-f", "Dockerfile", ctx))
  5259  	if err == nil {
  5260  		t.Fatalf("Expected error. Out: %s", out)
  5261  	}
  5262  	deleteImages(name)
  5263  
  5264  	logDone("build - Dockerfile outside context")
  5265  }
  5266  
  5267  func TestBuildSpaces(t *testing.T) {
  5268  	// Test to make sure that leading/trailing spaces on a command
  5269  	// doesn't change the error msg we get
  5270  	var (
  5271  		err1 error
  5272  		err2 error
  5273  	)
  5274  
  5275  	name := "testspaces"
  5276  	defer deleteImages(name)
  5277  	ctx, err := fakeContext("FROM busybox\nCOPY\n",
  5278  		map[string]string{
  5279  			"Dockerfile": "FROM busybox\nCOPY\n",
  5280  		})
  5281  	if err != nil {
  5282  		t.Fatal(err)
  5283  	}
  5284  	defer ctx.Close()
  5285  
  5286  	if _, err1 = buildImageFromContext(name, ctx, false); err1 == nil {
  5287  		t.Fatal("Build 1 was supposed to fail, but didn't")
  5288  	}
  5289  
  5290  	ctx.Add("Dockerfile", "FROM busybox\nCOPY    ")
  5291  	if _, err2 = buildImageFromContext(name, ctx, false); err2 == nil {
  5292  		t.Fatal("Build 2 was supposed to fail, but didn't")
  5293  	}
  5294  
  5295  	removeLogTimestamps := func(s string) string {
  5296  		return regexp.MustCompile(`time="(.*?)"`).ReplaceAllString(s, `time=[TIMESTAMP]`)
  5297  	}
  5298  
  5299  	// Skip over the times
  5300  	e1 := removeLogTimestamps(err1.Error())
  5301  	e2 := removeLogTimestamps(err2.Error())
  5302  
  5303  	// Ignore whitespace since that's what were verifying doesn't change stuff
  5304  	if strings.Replace(e1, " ", "", -1) != strings.Replace(e2, " ", "", -1) {
  5305  		t.Fatalf("Build 2's error wasn't the same as build 1's\n1:%s\n2:%s", err1, err2)
  5306  	}
  5307  
  5308  	ctx.Add("Dockerfile", "FROM busybox\n   COPY")
  5309  	if _, err2 = buildImageFromContext(name, ctx, false); err2 == nil {
  5310  		t.Fatal("Build 3 was supposed to fail, but didn't")
  5311  	}
  5312  
  5313  	// Skip over the times
  5314  	e1 = removeLogTimestamps(err1.Error())
  5315  	e2 = removeLogTimestamps(err2.Error())
  5316  
  5317  	// Ignore whitespace since that's what were verifying doesn't change stuff
  5318  	if strings.Replace(e1, " ", "", -1) != strings.Replace(e2, " ", "", -1) {
  5319  		t.Fatalf("Build 3's error wasn't the same as build 1's\n1:%s\n3:%s", err1, err2)
  5320  	}
  5321  
  5322  	ctx.Add("Dockerfile", "FROM busybox\n   COPY    ")
  5323  	if _, err2 = buildImageFromContext(name, ctx, false); err2 == nil {
  5324  		t.Fatal("Build 4 was supposed to fail, but didn't")
  5325  	}
  5326  
  5327  	// Skip over the times
  5328  	e1 = removeLogTimestamps(err1.Error())
  5329  	e2 = removeLogTimestamps(err2.Error())
  5330  
  5331  	// Ignore whitespace since that's what were verifying doesn't change stuff
  5332  	if strings.Replace(e1, " ", "", -1) != strings.Replace(e2, " ", "", -1) {
  5333  		t.Fatalf("Build 4's error wasn't the same as build 1's\n1:%s\n4:%s", err1, err2)
  5334  	}
  5335  
  5336  	logDone("build - test spaces")
  5337  }
  5338  
  5339  func TestBuildSpacesWithQuotes(t *testing.T) {
  5340  	// Test to make sure that spaces in quotes aren't lost
  5341  	name := "testspacesquotes"
  5342  	defer deleteImages(name)
  5343  
  5344  	dockerfile := `FROM busybox
  5345  RUN echo "  \
  5346    foo  "`
  5347  
  5348  	_, out, err := buildImageWithOut(name, dockerfile, false)
  5349  	if err != nil {
  5350  		t.Fatal("Build failed:", err)
  5351  	}
  5352  
  5353  	expecting := "\n    foo  \n"
  5354  	if !strings.Contains(out, expecting) {
  5355  		t.Fatalf("Bad output: %q expecting to contian %q", out, expecting)
  5356  	}
  5357  
  5358  	logDone("build - test spaces with quotes")
  5359  }
  5360  
  5361  // #4393
  5362  func TestBuildVolumeFileExistsinContainer(t *testing.T) {
  5363  	buildCmd := exec.Command(dockerBinary, "build", "-t", "docker-test-errcreatevolumewithfile", "-")
  5364  	buildCmd.Stdin = strings.NewReader(`
  5365  	FROM busybox
  5366  	RUN touch /foo
  5367  	VOLUME /foo
  5368  	`)
  5369  
  5370  	out, _, err := runCommandWithOutput(buildCmd)
  5371  	if err == nil || !strings.Contains(out, "file exists") {
  5372  		t.Fatalf("expected build to fail when file exists in container at requested volume path")
  5373  	}
  5374  
  5375  	logDone("build - errors when volume is specified where a file exists")
  5376  }
  5377  
  5378  func TestBuildMissingArgs(t *testing.T) {
  5379  	// Test to make sure that all Dockerfile commands (except the ones listed
  5380  	// in skipCmds) will generate an error if no args are provided.
  5381  	// Note: INSERT is deprecated so we exclude it because of that.
  5382  	skipCmds := map[string]struct{}{
  5383  		"CMD":        {},
  5384  		"RUN":        {},
  5385  		"ENTRYPOINT": {},
  5386  		"INSERT":     {},
  5387  	}
  5388  
  5389  	defer deleteAllContainers()
  5390  
  5391  	for cmd := range command.Commands {
  5392  		cmd = strings.ToUpper(cmd)
  5393  		if _, ok := skipCmds[cmd]; ok {
  5394  			continue
  5395  		}
  5396  
  5397  		var dockerfile string
  5398  		if cmd == "FROM" {
  5399  			dockerfile = cmd
  5400  		} else {
  5401  			// Add FROM to make sure we don't complain about it missing
  5402  			dockerfile = "FROM busybox\n" + cmd
  5403  		}
  5404  
  5405  		ctx, err := fakeContext(dockerfile, map[string]string{})
  5406  		if err != nil {
  5407  			t.Fatal(err)
  5408  		}
  5409  		defer ctx.Close()
  5410  		var out string
  5411  		if out, err = buildImageFromContext("args", ctx, true); err == nil {
  5412  			t.Fatalf("%s was supposed to fail. Out:%s", cmd, out)
  5413  		}
  5414  		if !strings.Contains(err.Error(), cmd+" requires") {
  5415  			t.Fatalf("%s returned the wrong type of error:%s", cmd, err)
  5416  		}
  5417  	}
  5418  
  5419  	logDone("build - verify missing args")
  5420  }
  5421  
  5422  func TestBuildEmptyScratch(t *testing.T) {
  5423  	defer deleteImages("sc")
  5424  	_, out, err := buildImageWithOut("sc", "FROM scratch", true)
  5425  	if err == nil {
  5426  		t.Fatalf("Build was supposed to fail")
  5427  	}
  5428  	if !strings.Contains(out, "No image was generated") {
  5429  		t.Fatalf("Wrong error message: %v", out)
  5430  	}
  5431  	logDone("build - empty scratch Dockerfile")
  5432  }
  5433  
  5434  func TestBuildDotDotFile(t *testing.T) {
  5435  	defer deleteImages("sc")
  5436  	ctx, err := fakeContext("FROM busybox\n",
  5437  		map[string]string{
  5438  			"..gitme": "",
  5439  		})
  5440  	if err != nil {
  5441  		t.Fatal(err)
  5442  	}
  5443  	defer ctx.Close()
  5444  
  5445  	if _, err = buildImageFromContext("sc", ctx, false); err != nil {
  5446  		t.Fatalf("Build was supposed to work: %s", err)
  5447  	}
  5448  	logDone("build - ..file")
  5449  }
  5450  
  5451  func TestBuildNotVerbose(t *testing.T) {
  5452  	defer deleteAllContainers()
  5453  	defer deleteImages("verbose")
  5454  
  5455  	ctx, err := fakeContext("FROM busybox\nENV abc=hi\nRUN echo $abc there", map[string]string{})
  5456  	if err != nil {
  5457  		t.Fatal(err)
  5458  	}
  5459  	defer ctx.Close()
  5460  
  5461  	// First do it w/verbose - baseline
  5462  	buildCmd := exec.Command(dockerBinary, "build", "--no-cache", "-t", "verbose", ".")
  5463  	buildCmd.Dir = ctx.Dir
  5464  	out, _, err := runCommandWithOutput(buildCmd)
  5465  	if err != nil {
  5466  		t.Fatalf("failed to build the image w/o -q: %s, %v", out, err)
  5467  	}
  5468  	if !strings.Contains(out, "hi there") {
  5469  		t.Fatalf("missing output:%s\n", out)
  5470  	}
  5471  
  5472  	// Now do it w/o verbose
  5473  	buildCmd = exec.Command(dockerBinary, "build", "--no-cache", "-q", "-t", "verbose", ".")
  5474  	buildCmd.Dir = ctx.Dir
  5475  	out, _, err = runCommandWithOutput(buildCmd)
  5476  	if err != nil {
  5477  		t.Fatalf("failed to build the image w/ -q: %s, %v", out, err)
  5478  	}
  5479  	if strings.Contains(out, "hi there") {
  5480  		t.Fatalf("Bad output, should not contain 'hi there':%s", out)
  5481  	}
  5482  
  5483  	logDone("build - not verbose")
  5484  }
  5485  
  5486  func TestBuildRUNoneJSON(t *testing.T) {
  5487  	name := "testbuildrunonejson"
  5488  
  5489  	defer deleteAllContainers()
  5490  	defer deleteImages(name)
  5491  
  5492  	ctx, err := fakeContext(`FROM hello-world:frozen
  5493  RUN [ "/hello" ]`, map[string]string{})
  5494  	if err != nil {
  5495  		t.Fatal(err)
  5496  	}
  5497  	defer ctx.Close()
  5498  
  5499  	buildCmd := exec.Command(dockerBinary, "build", "--no-cache", "-t", name, ".")
  5500  	buildCmd.Dir = ctx.Dir
  5501  	out, _, err := runCommandWithOutput(buildCmd)
  5502  	if err != nil {
  5503  		t.Fatalf("failed to build the image: %s, %v", out, err)
  5504  	}
  5505  
  5506  	if !strings.Contains(out, "Hello from Docker") {
  5507  		t.Fatalf("bad output: %s", out)
  5508  	}
  5509  
  5510  	logDone("build - RUN with one JSON arg")
  5511  }
  5512  
  5513  func TestBuildResourceConstraintsAreUsed(t *testing.T) {
  5514  	name := "testbuildresourceconstraints"
  5515  	defer deleteAllContainers()
  5516  	defer deleteImages(name)
  5517  
  5518  	ctx, err := fakeContext(`
  5519  	FROM hello-world:frozen
  5520  	RUN ["/hello"]
  5521  	`, map[string]string{})
  5522  	if err != nil {
  5523  		t.Fatal(err)
  5524  	}
  5525  
  5526  	cmd := exec.Command(dockerBinary, "build", "--rm=false", "--memory=64m", "--memory-swap=-1", "--cpuset-cpus=1", "--cpu-shares=100", "-t", name, ".")
  5527  	cmd.Dir = ctx.Dir
  5528  
  5529  	out, _, err := runCommandWithOutput(cmd)
  5530  	if err != nil {
  5531  		t.Fatal(err, out)
  5532  	}
  5533  	out, _, err = dockerCmd(t, "ps", "-lq")
  5534  	if err != nil {
  5535  		t.Fatal(err, out)
  5536  	}
  5537  
  5538  	cID := stripTrailingCharacters(out)
  5539  
  5540  	type hostConfig struct {
  5541  		Memory     float64 // Use float64 here since the json decoder sees it that way
  5542  		MemorySwap int
  5543  		CpusetCpus string
  5544  		CpuShares  int
  5545  	}
  5546  
  5547  	cfg, err := inspectFieldJSON(cID, "HostConfig")
  5548  	if err != nil {
  5549  		t.Fatal(err)
  5550  	}
  5551  
  5552  	var c1 hostConfig
  5553  	if err := json.Unmarshal([]byte(cfg), &c1); err != nil {
  5554  		t.Fatal(err, cfg)
  5555  	}
  5556  	mem := int64(c1.Memory)
  5557  	if mem != 67108864 || c1.MemorySwap != -1 || c1.CpusetCpus != "1" || c1.CpuShares != 100 {
  5558  		t.Fatalf("resource constraints not set properly:\nMemory: %d, MemSwap: %d, CpusetCpus: %s, CpuShares: %d",
  5559  			mem, c1.MemorySwap, c1.CpusetCpus, c1.CpuShares)
  5560  	}
  5561  
  5562  	// Make sure constraints aren't saved to image
  5563  	_, _, err = dockerCmd(t, "run", "--name=test", name)
  5564  	if err != nil {
  5565  		t.Fatal(err)
  5566  	}
  5567  	cfg, err = inspectFieldJSON("test", "HostConfig")
  5568  	if err != nil {
  5569  		t.Fatal(err)
  5570  	}
  5571  	var c2 hostConfig
  5572  	if err := json.Unmarshal([]byte(cfg), &c2); err != nil {
  5573  		t.Fatal(err, cfg)
  5574  	}
  5575  	mem = int64(c2.Memory)
  5576  	if mem == 67108864 || c2.MemorySwap == -1 || c2.CpusetCpus == "1" || c2.CpuShares == 100 {
  5577  		t.Fatalf("resource constraints leaked from build:\nMemory: %d, MemSwap: %d, CpusetCpus: %s, CpuShares: %d",
  5578  			mem, c2.MemorySwap, c2.CpusetCpus, c2.CpuShares)
  5579  	}
  5580  
  5581  	logDone("build - resource constraints applied")
  5582  }
  5583  
  5584  func TestBuildEmptyStringVolume(t *testing.T) {
  5585  	name := "testbuildemptystringvolume"
  5586  	defer deleteImages(name)
  5587  
  5588  	_, err := buildImage(name, `
  5589    FROM busybox
  5590    ENV foo=""
  5591    VOLUME $foo
  5592    `, false)
  5593  	if err == nil {
  5594  		t.Fatal("Should have failed to build")
  5595  	}
  5596  
  5597  	logDone("build - empty string volume")
  5598  }