github.com/jdhenke/godel@v0.0.0-20161213181855-abeb3861bf0d/integration_test/integration_test.go (about)

     1  // Copyright 2016 Palantir Technologies, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package integration_test
    16  
    17  import (
    18  	"fmt"
    19  	"io/ioutil"
    20  	"os"
    21  	"os/exec"
    22  	"path"
    23  	"path/filepath"
    24  	"regexp"
    25  	"strings"
    26  	"testing"
    27  
    28  	"github.com/nmiyake/pkg/dirs"
    29  	"github.com/nmiyake/pkg/gofiles"
    30  	"github.com/stretchr/testify/assert"
    31  	"github.com/stretchr/testify/require"
    32  
    33  	"github.com/palantir/godel/apps/distgo/pkg/git"
    34  	"github.com/palantir/godel/apps/distgo/pkg/git/gittest"
    35  	"github.com/palantir/godel/pkg/products"
    36  )
    37  
    38  var (
    39  	gödelTGZ    string
    40  	testRootDir string
    41  	version     string
    42  )
    43  
    44  func TestMain(m *testing.M) {
    45  	os.Exit(runTestMain(m))
    46  }
    47  
    48  func runTestMain(m *testing.M) int {
    49  	wd, err := os.Getwd()
    50  	if err != nil {
    51  		panic(err)
    52  	}
    53  	gödelProjectDir := path.Join(wd, "..")
    54  	version, err = git.ProjectVersion(gödelProjectDir)
    55  	if err != nil {
    56  		panic(fmt.Sprintf("Failed to get version from directory %s: %v", gödelProjectDir, err))
    57  	}
    58  
    59  	gödelTGZ, err = products.Dist("godel")
    60  	if err != nil {
    61  		panic(fmt.Sprintf("Failed create distribution: %v", err))
    62  	}
    63  
    64  	var cleanup func()
    65  	testRootDir, cleanup, err = dirs.TempDir(wd, "")
    66  	defer cleanup()
    67  	if err != nil {
    68  		panic(fmt.Sprintf("Failed to create temporary directory in %s: %v", wd, err))
    69  	}
    70  
    71  	return m.Run()
    72  }
    73  
    74  func TestVersion(t *testing.T) {
    75  	testProjectDir := setUpGödelTestAndDownload(t, testRootDir, gödelTGZ, version)
    76  
    77  	cmd := exec.Command("./godelw", "--version")
    78  	cmd.Dir = testProjectDir
    79  	output, err := cmd.CombinedOutput()
    80  	require.NoError(t, err, "Command %v failed. Output:\n%v", cmd.Args, string(output))
    81  
    82  	assert.Equal(t, fmt.Sprintf("godel version %v\n", version), string(output))
    83  }
    84  
    85  func TestFormat(t *testing.T) {
    86  	testProjectDir := setUpGödelTestAndDownload(t, testRootDir, gödelTGZ, version)
    87  
    88  	src := `package main
    89  		import "fmt"
    90  
    91  	func main() {
    92  	fmt.Println("hello, world!")
    93  	}`
    94  
    95  	formattedSrc := `package main
    96  
    97  import (
    98  	"fmt"
    99  )
   100  
   101  func main() {
   102  	fmt.Println("hello, world!")
   103  }
   104  `
   105  	err := ioutil.WriteFile(path.Join(testProjectDir, "main.go"), []byte(src), 0644)
   106  	require.NoError(t, err)
   107  
   108  	cmd := exec.Command("./godelw", "format")
   109  	cmd.Dir = testProjectDir
   110  	output, err := cmd.CombinedOutput()
   111  	require.NoError(t, err, "Command %v failed. Output:\n%v", cmd.Args, string(output))
   112  
   113  	content, err := ioutil.ReadFile(path.Join(testProjectDir, "main.go"))
   114  	require.NoError(t, err)
   115  	assert.Equal(t, formattedSrc, string(content))
   116  }
   117  
   118  func TestImports(t *testing.T) {
   119  	testProjectDir := setUpGödelTestAndDownload(t, testRootDir, gödelTGZ, version)
   120  
   121  	const importsYML = `root-dirs:
   122    - pkg`
   123  	err := ioutil.WriteFile(path.Join(testProjectDir, "godel", "config", "imports.yml"), []byte(importsYML), 0644)
   124  	require.NoError(t, err)
   125  
   126  	specs := []gofiles.GoFileSpec{
   127  		{
   128  			RelPath: "pkg/foo/foo.go",
   129  			Src:     `package foo; import _ "{{index . "bar.go"}}";`,
   130  		},
   131  		{
   132  			RelPath: "bar.go",
   133  			Src:     "package bar",
   134  		},
   135  	}
   136  
   137  	files, err := gofiles.Write(testProjectDir, specs)
   138  	require.NoError(t, err)
   139  
   140  	want := fmt.Sprintf(`{
   141      "imports": [
   142          {
   143              "path": "%s",
   144              "numGoFiles": 1,
   145              "numImportedGoFiles": 0,
   146              "importedFrom": [
   147                  "%s"
   148              ]
   149          }
   150      ],
   151      "mainOnlyImports": [],
   152      "testOnlyImports": []
   153  }`, files["bar.go"].ImportPath, files["pkg/foo/foo.go"].ImportPath)
   154  
   155  	cmd := exec.Command("./godelw", "imports")
   156  	cmd.Dir = testProjectDir
   157  	output, err := cmd.CombinedOutput()
   158  	require.NoError(t, err, "Command %v failed. Output:\n%v", cmd.Args, string(output))
   159  
   160  	content, err := ioutil.ReadFile(path.Join(testProjectDir, "pkg", "gocd_imports.json"))
   161  	require.NoError(t, err)
   162  	assert.Equal(t, want, string(content))
   163  }
   164  
   165  func TestImportsVerify(t *testing.T) {
   166  	testProjectDir := setUpGödelTestAndDownload(t, testRootDir, gödelTGZ, version)
   167  
   168  	const importsYML = `root-dirs:
   169    - pkg`
   170  	err := ioutil.WriteFile(path.Join(testProjectDir, "godel", "config", "imports.yml"), []byte(importsYML), 0644)
   171  	require.NoError(t, err)
   172  
   173  	specs := []gofiles.GoFileSpec{
   174  		{
   175  			RelPath: "pkg/foo/foo.go",
   176  			Src:     `package foo; import _ "{{index . "bar.go"}}";`,
   177  		},
   178  		{
   179  			RelPath: "bar.go",
   180  			Src:     "package bar",
   181  		},
   182  	}
   183  
   184  	_, err = gofiles.Write(testProjectDir, specs)
   185  	require.NoError(t, err)
   186  
   187  	cmd := exec.Command("./godelw", "imports", "--verify")
   188  	cmd.Dir = testProjectDir
   189  	output, err := cmd.CombinedOutput()
   190  	require.Error(t, err)
   191  	assert.Equal(t, "gocd_imports.json out of date for 1 directory:\n\tpkg: gocd_imports.json does not exist\n", string(output))
   192  }
   193  
   194  func TestLicense(t *testing.T) {
   195  	testProjectDir := setUpGödelTestAndDownload(t, testRootDir, gödelTGZ, version)
   196  
   197  	const licenseYML = `header: |
   198    /*
   199    Copyright 2016 Palantir Technologies, Inc.
   200  
   201    Licensed under the Apache License, Version 2.0 (the "License");
   202    you may not use this file except in compliance with the License.
   203    You may obtain a copy of the License at
   204  
   205    http://www.apache.org/licenses/LICENSE-2.0
   206  
   207    Unless required by applicable law or agreed to in writing, software
   208    distributed under the License is distributed on an "AS IS" BASIS,
   209    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   210    See the License for the specific language governing permissions and
   211    limitations under the License.
   212    */
   213  `
   214  	err := ioutil.WriteFile(path.Join(testProjectDir, "godel", "config", "license.yml"), []byte(licenseYML), 0644)
   215  	require.NoError(t, err)
   216  
   217  	specs := []gofiles.GoFileSpec{
   218  		{
   219  			RelPath: "foo.go",
   220  			Src:     "package foo",
   221  		},
   222  		{
   223  			RelPath: "vendor/github.com/bar.go",
   224  			Src:     "package bar",
   225  		},
   226  	}
   227  
   228  	files, err := gofiles.Write(testProjectDir, specs)
   229  	require.NoError(t, err)
   230  
   231  	want := `/*
   232  Copyright 2016 Palantir Technologies, Inc.
   233  
   234  Licensed under the Apache License, Version 2.0 (the "License");
   235  you may not use this file except in compliance with the License.
   236  You may obtain a copy of the License at
   237  
   238  http://www.apache.org/licenses/LICENSE-2.0
   239  
   240  Unless required by applicable law or agreed to in writing, software
   241  distributed under the License is distributed on an "AS IS" BASIS,
   242  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   243  See the License for the specific language governing permissions and
   244  limitations under the License.
   245  */
   246  
   247  package foo`
   248  
   249  	cmd := exec.Command("./godelw", "license")
   250  	cmd.Dir = testProjectDir
   251  	output, err := cmd.CombinedOutput()
   252  	require.NoError(t, err, "Command %v failed. Output:\n%v", cmd.Args, string(output))
   253  
   254  	content, err := ioutil.ReadFile(files["foo.go"].Path)
   255  	require.NoError(t, err)
   256  	assert.Equal(t, want, string(content))
   257  
   258  	want = `package bar`
   259  	content, err = ioutil.ReadFile(files["vendor/github.com/bar.go"].Path)
   260  	require.NoError(t, err)
   261  	assert.Equal(t, want, string(content))
   262  }
   263  
   264  func TestLicenseVerify(t *testing.T) {
   265  	testProjectDir := setUpGödelTestAndDownload(t, testRootDir, gödelTGZ, version)
   266  
   267  	const licenseYML = `header: |
   268    /*
   269    Copyright 2016 Palantir Technologies, Inc.
   270  
   271    Licensed under the Apache License, Version 2.0 (the "License");
   272    you may not use this file except in compliance with the License.
   273    You may obtain a copy of the License at
   274  
   275    http://www.apache.org/licenses/LICENSE-2.0
   276  
   277    Unless required by applicable law or agreed to in writing, software
   278    distributed under the License is distributed on an "AS IS" BASIS,
   279    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   280    See the License for the specific language governing permissions and
   281    limitations under the License.
   282    */
   283  `
   284  	err := ioutil.WriteFile(path.Join(testProjectDir, "godel", "config", "license.yml"), []byte(licenseYML), 0644)
   285  	require.NoError(t, err)
   286  
   287  	specs := []gofiles.GoFileSpec{
   288  		{
   289  			RelPath: "foo.go",
   290  			Src:     "package foo",
   291  		},
   292  		{
   293  			RelPath: "bar/bar.go",
   294  			Src: `/*
   295  Copyright 2016 Palantir Technologies, Inc.
   296  
   297  Licensed under the Apache License, Version 2.0 (the "License");
   298  you may not use this file except in compliance with the License.
   299  You may obtain a copy of the License at
   300  
   301  http://www.apache.org/licenses/LICENSE-2.0
   302  
   303  Unless required by applicable law or agreed to in writing, software
   304  distributed under the License is distributed on an "AS IS" BASIS,
   305  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   306  See the License for the specific language governing permissions and
   307  limitations under the License.
   308  */
   309  
   310  package bar`,
   311  		},
   312  		{
   313  			RelPath: "vendor/github.com/baz.go",
   314  			Src:     "package baz",
   315  		},
   316  	}
   317  
   318  	_, err = gofiles.Write(testProjectDir, specs)
   319  	require.NoError(t, err)
   320  
   321  	cmd := exec.Command("./godelw", "license", "--verify")
   322  	cmd.Dir = testProjectDir
   323  	output, err := cmd.CombinedOutput()
   324  	require.Error(t, err)
   325  	assert.Equal(t, "1 file does not have the correct license header:\n\tfoo.go\n", string(output))
   326  }
   327  
   328  func TestCheck(t *testing.T) {
   329  	testProjectDir := setUpGödelTestAndDownload(t, testRootDir, gödelTGZ, version)
   330  	src := `package main
   331  	import "fmt"
   332  
   333  	func main() {
   334  		fmt.Println("hello, world!")
   335  	}`
   336  	err := ioutil.WriteFile(path.Join(testProjectDir, "main.go"), []byte(src), 0644)
   337  	require.NoError(t, err)
   338  
   339  	cmd := exec.Command("./godelw", "check")
   340  	cmd.Dir = testProjectDir
   341  	output, err := cmd.CombinedOutput()
   342  	require.NoError(t, err, "Command %v failed. Output:\n%v", cmd.Args, string(output))
   343  }
   344  
   345  func TestProducts(t *testing.T) {
   346  	testProjectDir := setUpGödelTestAndDownload(t, testRootDir, gödelTGZ, version)
   347  
   348  	distYml := `
   349  products:
   350    foo:
   351      build:
   352        main-pkg: ./foo
   353    bar:
   354      build:
   355        main-pkg: ./bar
   356  `
   357  	err := ioutil.WriteFile(path.Join(testProjectDir, "godel", "config", "dist.yml"), []byte(distYml), 0644)
   358  	require.NoError(t, err)
   359  
   360  	src := `package main
   361  	import "fmt"
   362  
   363  	func main() {
   364  		fmt.Println("hello, world!")
   365  	}`
   366  	err = os.MkdirAll(path.Join(testProjectDir, "foo"), 0755)
   367  	require.NoError(t, err)
   368  	err = ioutil.WriteFile(path.Join(testProjectDir, "foo", "foo.go"), []byte(src), 0644)
   369  	require.NoError(t, err)
   370  
   371  	err = os.MkdirAll(path.Join(testProjectDir, "bar"), 0755)
   372  	require.NoError(t, err)
   373  	err = ioutil.WriteFile(path.Join(testProjectDir, "bar", "bar.go"), []byte(src), 0644)
   374  	require.NoError(t, err)
   375  
   376  	cmd := exec.Command("./godelw", "products")
   377  	cmd.Dir = testProjectDir
   378  	output, err := cmd.CombinedOutput()
   379  	require.NoError(t, err, "Command %v failed. Output:\n%v", cmd.Args, string(output))
   380  	assert.Equal(t, "bar\nfoo\n", string(output))
   381  }
   382  
   383  func TestArtifactsBuild(t *testing.T) {
   384  	testProjectDir := setUpGödelTestAndDownload(t, testRootDir, gödelTGZ, version)
   385  	gittest.InitGitDir(t, testProjectDir)
   386  
   387  	distYml := `
   388  products:
   389    foo:
   390      build:
   391        main-pkg: ./foo
   392        os-archs:
   393          - os: darwin
   394            arch: amd64
   395          - os: linux
   396            arch: amd64
   397    bar:
   398      build:
   399        main-pkg: ./bar
   400        os-archs:
   401          - os: windows
   402            arch: amd64
   403  `
   404  	err := ioutil.WriteFile(path.Join(testProjectDir, "godel", "config", "dist.yml"), []byte(distYml), 0644)
   405  	require.NoError(t, err)
   406  
   407  	src := `package main
   408  	import "fmt"
   409  
   410  	func main() {
   411  		fmt.Println("hello, world!")
   412  	}`
   413  	err = os.MkdirAll(path.Join(testProjectDir, "foo"), 0755)
   414  	require.NoError(t, err)
   415  	err = ioutil.WriteFile(path.Join(testProjectDir, "foo", "foo.go"), []byte(src), 0644)
   416  	require.NoError(t, err)
   417  
   418  	err = os.MkdirAll(path.Join(testProjectDir, "bar"), 0755)
   419  	require.NoError(t, err)
   420  	err = ioutil.WriteFile(path.Join(testProjectDir, "bar", "bar.go"), []byte(src), 0644)
   421  	require.NoError(t, err)
   422  
   423  	gittest.CommitAllFiles(t, testProjectDir, "Commit files")
   424  	gittest.CreateGitTag(t, testProjectDir, "0.1.0")
   425  
   426  	cmd := exec.Command("./godelw", "artifacts", "build")
   427  	cmd.Dir = testProjectDir
   428  	output, err := cmd.CombinedOutput()
   429  	require.NoError(t, err, "Command %v failed. Output:\n%v", cmd.Args, string(output))
   430  
   431  	want := `build/0.1.0/windows-amd64/bar.exe
   432  build/0.1.0/darwin-amd64/foo
   433  build/0.1.0/linux-amd64/foo
   434  `
   435  	assert.Equal(t, want, string(output))
   436  }
   437  
   438  func TestArtifactsDist(t *testing.T) {
   439  	testProjectDir := setUpGödelTestAndDownload(t, testRootDir, gödelTGZ, version)
   440  	gittest.InitGitDir(t, testProjectDir)
   441  
   442  	distYml := `
   443  products:
   444    foo:
   445      build:
   446        main-pkg: ./foo
   447    bar:
   448      build:
   449        main-pkg: ./bar
   450  `
   451  	err := ioutil.WriteFile(path.Join(testProjectDir, "godel", "config", "dist.yml"), []byte(distYml), 0644)
   452  	require.NoError(t, err)
   453  
   454  	src := `package main
   455  	import "fmt"
   456  
   457  	func main() {
   458  		fmt.Println("hello, world!")
   459  	}`
   460  	err = os.MkdirAll(path.Join(testProjectDir, "foo"), 0755)
   461  	require.NoError(t, err)
   462  	err = ioutil.WriteFile(path.Join(testProjectDir, "foo", "foo.go"), []byte(src), 0644)
   463  	require.NoError(t, err)
   464  
   465  	err = os.MkdirAll(path.Join(testProjectDir, "bar"), 0755)
   466  	require.NoError(t, err)
   467  	err = ioutil.WriteFile(path.Join(testProjectDir, "bar", "bar.go"), []byte(src), 0644)
   468  	require.NoError(t, err)
   469  
   470  	gittest.CommitAllFiles(t, testProjectDir, "Commit files")
   471  	gittest.CreateGitTag(t, testProjectDir, "0.1.0")
   472  
   473  	cmd := exec.Command("./godelw", "artifacts", "dist")
   474  	cmd.Dir = testProjectDir
   475  	output, err := cmd.CombinedOutput()
   476  	require.NoError(t, err, "Command %v failed. Output:\n%v", cmd.Args, string(output))
   477  	assert.Equal(t, "dist/bar-0.1.0.sls.tgz\ndist/foo-0.1.0.sls.tgz\n", string(output))
   478  }
   479  
   480  func TestTest(t *testing.T) {
   481  	testProjectDir := setUpGödelTestAndDownload(t, testRootDir, gödelTGZ, version)
   482  	src := `package foo_test
   483  	import "testing"
   484  
   485  	func TestFoo(t *testing.T) {}`
   486  	err := ioutil.WriteFile(path.Join(testProjectDir, "foo_test.go"), []byte(src), 0644)
   487  	require.NoError(t, err)
   488  
   489  	cmd := exec.Command("./godelw", "test")
   490  	cmd.Dir = testProjectDir
   491  	output, err := cmd.CombinedOutput()
   492  	require.NoError(t, err, "Command %v failed. Output:\n%v", cmd.Args, string(output))
   493  }
   494  
   495  // Run "../godelw check" and ensure that it works (command supports being invoked from subdirectory). The action should
   496  // execute with the subdirectory as the working directory.
   497  func TestCheckFromNestedDirectory(t *testing.T) {
   498  	testProjectDir := setUpGödelTestAndDownload(t, testRootDir, gödelTGZ, version)
   499  
   500  	// write invalid Go file to root directory of project
   501  	badSrc := `badContentForGoFile`
   502  	err := ioutil.WriteFile(path.Join(testProjectDir, "main.go"), []byte(badSrc), 0644)
   503  	require.NoError(t, err)
   504  
   505  	// write valid Go file to child directory
   506  	childDir := path.Join(testProjectDir, "childDir")
   507  	err = os.MkdirAll(childDir, 0755)
   508  	require.NoError(t, err)
   509  	src := `package main
   510  	import "fmt"
   511  
   512  	func main() {
   513  		fmt.Println("hello, world!")
   514  	}`
   515  	err = ioutil.WriteFile(path.Join(childDir, "main.go"), []byte(src), 0644)
   516  	require.NoError(t, err)
   517  
   518  	cmd := exec.Command("../godelw", "check")
   519  	cmd.Dir = childDir
   520  	output, err := cmd.CombinedOutput()
   521  	require.NoError(t, err, "Command %v failed. Output:\n%v", cmd.Args, string(output))
   522  }
   523  
   524  // Run "../godelw build" and ensure that it works (command supports being invoked from sub-directory). The build action
   525  // should execute with the root project directory as the working directory. Verifies #235.
   526  func TestBuildFromNestedDirectory(t *testing.T) {
   527  	testProjectDir := setUpGödelTestAndDownload(t, testRootDir, gödelTGZ, version)
   528  	src := `package main
   529  	import "fmt"
   530  
   531  	func main() {
   532  		fmt.Println("hello, world!")
   533  	}`
   534  	err := ioutil.WriteFile(path.Join(testProjectDir, "main.go"), []byte(src), 0644)
   535  	require.NoError(t, err)
   536  
   537  	childDir := path.Join(testProjectDir, "childDir")
   538  	err = os.MkdirAll(childDir, 0755)
   539  	require.NoError(t, err)
   540  
   541  	cmd := exec.Command("../godelw", "build")
   542  	cmd.Dir = childDir
   543  	output, err := cmd.CombinedOutput()
   544  	require.NoError(t, err, "Command %v failed. Output:\n%v", cmd.Args, string(output))
   545  
   546  	info, err := os.Stat(path.Join(testProjectDir, "build"))
   547  	require.NoError(t, err)
   548  	assert.True(t, info.IsDir())
   549  }
   550  
   551  // Run "./godelw publish" and verify that it prints a help message and exits with a non-0 exit code. Verifies #243.
   552  func TestPublishWithNoAction(t *testing.T) {
   553  	testProjectDir := setUpGödelTestAndDownload(t, testRootDir, gödelTGZ, version)
   554  	src := `package main
   555  	import "fmt"
   556  
   557  	func main() {
   558  		fmt.Println("hello, world!")
   559  	}`
   560  	err := ioutil.WriteFile(path.Join(testProjectDir, "main.go"), []byte(src), 0644)
   561  	require.NoError(t, err)
   562  
   563  	cmd := exec.Command("./godelw", "publish")
   564  	cmd.Dir = testProjectDir
   565  	output, err := cmd.CombinedOutput()
   566  	require.Error(t, err)
   567  	assert.Regexp(t, regexp.MustCompile(`(?s)NAME:.+publish - Publish product distributions.+USAGE:.+godel publish.+SUBCOMMANDS:.+FLAGS:.+`), string(output))
   568  }
   569  
   570  func TestVerify(t *testing.T) {
   571  	testProjectDir := setUpGödelTestAndDownload(t, testRootDir, gödelTGZ, version)
   572  	const (
   573  		src = `package main
   574  	import "fmt"
   575  
   576  	func main() {
   577  		fmt.Println("hello, world!")
   578  	}`
   579  		testSrc = `package main_test
   580  	import "testing"
   581  
   582  	func TestFoo(t *testing.T) {
   583  		t=t
   584  		t.Fail()
   585  	}`
   586  		importsYML = `root-dirs:
   587    - .`
   588  		licenseYML = `header: |
   589    /*
   590    Copyright 2016 Palantir Technologies, Inc.
   591  
   592    Licensed under the Apache License, Version 2.0 (the "License");
   593    you may not use this file except in compliance with the License.
   594    You may obtain a copy of the License at
   595  
   596    http://www.apache.org/licenses/LICENSE-2.0
   597  
   598    Unless required by applicable law or agreed to in writing, software
   599    distributed under the License is distributed on an "AS IS" BASIS,
   600    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   601    See the License for the specific language governing permissions and
   602    limitations under the License.
   603    */
   604  `
   605  	)
   606  	err := ioutil.WriteFile(path.Join(testProjectDir, "main.go"), []byte(src), 0644)
   607  	require.NoError(t, err)
   608  	err = ioutil.WriteFile(path.Join(testProjectDir, "main_test.go"), []byte(testSrc), 0644)
   609  	require.NoError(t, err)
   610  	err = ioutil.WriteFile(path.Join(testProjectDir, "godel", "config", "imports.yml"), []byte(importsYML), 0644)
   611  	require.NoError(t, err)
   612  	err = ioutil.WriteFile(path.Join(testProjectDir, "godel", "config", "license.yml"), []byte(licenseYML), 0644)
   613  	require.NoError(t, err)
   614  
   615  	for i, currCase := range []struct {
   616  		args []string
   617  		want string
   618  	}{
   619  		{want: `(?s).+Failed tasks:\n\tformat -v -l\n\timports --verify\n\tlicense --verify\n\tcheck\n\ttest`},
   620  		{args: []string{"--skip-format"}, want: `(?s).+Failed tasks:\n\timports --verify\n\tlicense --verify\n\tcheck\n\ttest`},
   621  		{args: []string{"--skip-check"}, want: `(?s).+Failed tasks:\n\tformat -v -l\n\timports --verify\n\tlicense --verify\n\ttest`},
   622  		{args: []string{"--skip-imports"}, want: `(?s).+Failed tasks:\n\tformat -v -l\n\tlicense --verify\n\tcheck\n\ttest`},
   623  		{args: []string{"--skip-license"}, want: `(?s).+Failed tasks:\n\tformat -v -l\n\timports --verify\n\tcheck\n\ttest`},
   624  		{args: []string{"--skip-test"}, want: `(?s).+Failed tasks:\n\tformat -v -l\n\timports --verify\n\tlicense --verify\n\tcheck`},
   625  	} {
   626  		cmd := exec.Command("./godelw", append([]string{"verify", "--apply=false"}, currCase.args...)...)
   627  		cmd.Dir = testProjectDir
   628  		output, err := cmd.CombinedOutput()
   629  		require.Error(t, err)
   630  		assert.Regexp(t, regexp.MustCompile(currCase.want), string(output), "Case %d", i)
   631  	}
   632  }
   633  
   634  func TestVerifyApply(t *testing.T) {
   635  	testProjectDir := setUpGödelTestAndDownload(t, testRootDir, gödelTGZ, version)
   636  	const (
   637  		src = `package main
   638  	import "fmt"
   639  
   640  	func main() {
   641  		fmt.Println("hello, world!")
   642  	}`
   643  		testSrc = `package main_test
   644  	import "testing"
   645  
   646  	func TestFoo(t *testing.T) {
   647  		t=t
   648  		t.Fail()
   649  	}`
   650  		formattedTestSrc = `package main_test
   651  
   652  import (
   653  	"testing"
   654  )
   655  
   656  func TestFoo(t *testing.T) {
   657  	t = t
   658  	t.Fail()
   659  }
   660  `
   661  		licensedTestSrc = `/*
   662  Copyright 2016 Palantir Technologies, Inc.
   663  
   664  Licensed under the Apache License, Version 2.0 (the "License");
   665  you may not use this file except in compliance with the License.
   666  You may obtain a copy of the License at
   667  
   668  http://www.apache.org/licenses/LICENSE-2.0
   669  
   670  Unless required by applicable law or agreed to in writing, software
   671  distributed under the License is distributed on an "AS IS" BASIS,
   672  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   673  See the License for the specific language governing permissions and
   674  limitations under the License.
   675  */
   676  
   677  package main_test
   678  	import "testing"
   679  
   680  	func TestFoo(t *testing.T) {
   681  		t=t
   682  		t.Fail()
   683  	}`
   684  		licensedAndFormattedTestSrc = `/*
   685  Copyright 2016 Palantir Technologies, Inc.
   686  
   687  Licensed under the Apache License, Version 2.0 (the "License");
   688  you may not use this file except in compliance with the License.
   689  You may obtain a copy of the License at
   690  
   691  http://www.apache.org/licenses/LICENSE-2.0
   692  
   693  Unless required by applicable law or agreed to in writing, software
   694  distributed under the License is distributed on an "AS IS" BASIS,
   695  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   696  See the License for the specific language governing permissions and
   697  limitations under the License.
   698  */
   699  
   700  package main_test
   701  
   702  import (
   703  	"testing"
   704  )
   705  
   706  func TestFoo(t *testing.T) {
   707  	t = t
   708  	t.Fail()
   709  }
   710  `
   711  		importsYML = `root-dirs:
   712    - .`
   713  		importsJSON = `{
   714      "imports": [],
   715      "mainOnlyImports": [],
   716      "testOnlyImports": []
   717  }`
   718  
   719  		licenseYML = `header: |
   720    /*
   721    Copyright 2016 Palantir Technologies, Inc.
   722  
   723    Licensed under the Apache License, Version 2.0 (the "License");
   724    you may not use this file except in compliance with the License.
   725    You may obtain a copy of the License at
   726  
   727    http://www.apache.org/licenses/LICENSE-2.0
   728  
   729    Unless required by applicable law or agreed to in writing, software
   730    distributed under the License is distributed on an "AS IS" BASIS,
   731    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   732    See the License for the specific language governing permissions and
   733    limitations under the License.
   734    */
   735  `
   736  	)
   737  	err := ioutil.WriteFile(path.Join(testProjectDir, "main.go"), []byte(src), 0644)
   738  	require.NoError(t, err)
   739  	err = ioutil.WriteFile(path.Join(testProjectDir, "godel", "config", "imports.yml"), []byte(importsYML), 0644)
   740  	require.NoError(t, err)
   741  	err = ioutil.WriteFile(path.Join(testProjectDir, "godel", "config", "license.yml"), []byte(licenseYML), 0644)
   742  	require.NoError(t, err)
   743  
   744  	for i, currCase := range []struct {
   745  		args            []string
   746  		want            string
   747  		wantTestSrc     string
   748  		wantImportsJSON string
   749  	}{
   750  		{want: `(?s).+Failed tasks:\n\tcheck\n\ttest`, wantTestSrc: licensedAndFormattedTestSrc, wantImportsJSON: importsJSON},
   751  		{args: []string{"--skip-format"}, want: `(?s).+Failed tasks:\n\tcheck\n\ttest`, wantTestSrc: licensedTestSrc, wantImportsJSON: importsJSON},
   752  		{args: []string{"--skip-imports"}, want: `(?s).+Failed tasks:\n\tcheck\n\ttest`, wantTestSrc: licensedAndFormattedTestSrc},
   753  		{args: []string{"--skip-license"}, want: `(?s).+Failed tasks:\n\tcheck\n\ttest`, wantTestSrc: formattedTestSrc, wantImportsJSON: importsJSON},
   754  		{args: []string{"--skip-check"}, want: `(?s).+Failed tasks:\n\ttest`, wantTestSrc: licensedAndFormattedTestSrc, wantImportsJSON: importsJSON},
   755  		{args: []string{"--skip-test"}, want: `(?s).+Failed tasks:\n\tcheck`, wantTestSrc: licensedAndFormattedTestSrc, wantImportsJSON: importsJSON},
   756  	} {
   757  		err = ioutil.WriteFile(path.Join(testProjectDir, "main_test.go"), []byte(testSrc), 0644)
   758  		require.NoError(t, err, "Case %d", i)
   759  
   760  		cmd := exec.Command("./godelw", append([]string{"verify"}, currCase.args...)...)
   761  		cmd.Dir = testProjectDir
   762  		output, err := cmd.CombinedOutput()
   763  		require.Error(t, err, fmt.Sprintf("Case %d", i))
   764  		assert.Regexp(t, regexp.MustCompile(currCase.want), string(output), "Case %d", i)
   765  
   766  		bytes, err := ioutil.ReadFile(path.Join(testProjectDir, "main_test.go"))
   767  		require.NoError(t, err, "Case %d", i)
   768  		assert.Equal(t, currCase.wantTestSrc, string(bytes), "Case %d", i)
   769  
   770  		importsJSONPath := path.Join(testProjectDir, "gocd_imports.json")
   771  		if currCase.wantImportsJSON == "" {
   772  			_, err = os.Stat(importsJSONPath)
   773  			assert.True(t, os.IsNotExist(err), "Case %d: gocd_imports.json should not exist", i)
   774  		} else {
   775  			bytes, err = ioutil.ReadFile(importsJSONPath)
   776  			require.NoError(t, err, "Case %d", i)
   777  			assert.Equal(t, currCase.wantImportsJSON, string(bytes), "Case %d", i)
   778  			err = os.Remove(importsJSONPath)
   779  			require.NoError(t, err, "Case %d", i)
   780  		}
   781  	}
   782  }
   783  
   784  func TestVerifyWithJUnitOutput(t *testing.T) {
   785  	testProjectDir := setUpGödelTestAndDownload(t, testRootDir, gödelTGZ, version)
   786  	src := `package main
   787  	import "fmt"
   788  	func main() {
   789  		fmt.Println("hello, world!")
   790  	}`
   791  	err := ioutil.WriteFile(path.Join(testProjectDir, "main.go"), []byte(src), 0644)
   792  	require.NoError(t, err)
   793  	testSrc := `package main_test
   794  	import "testing"
   795  	func TestFoo(t *testing.T) {
   796  	}`
   797  	err = ioutil.WriteFile(path.Join(testProjectDir, "main_test.go"), []byte(testSrc), 0644)
   798  	require.NoError(t, err)
   799  
   800  	junitOutputFile := "test-output.xml"
   801  	cmd := exec.Command("./godelw", "verify", "--apply=false", "--junit-output", junitOutputFile)
   802  	cmd.Dir = testProjectDir
   803  	err = cmd.Run()
   804  	require.Error(t, err)
   805  
   806  	fi, err := os.Stat(path.Join(testProjectDir, junitOutputFile))
   807  	require.NoError(t, err)
   808  
   809  	assert.False(t, fi.IsDir())
   810  }
   811  
   812  func TestDebugFlagPrintsStackTrace(t *testing.T) {
   813  	testProjectDir := setUpGödelTestAndDownload(t, testRootDir, gödelTGZ, version)
   814  
   815  	cmd := exec.Command("./godelw", "install", "foo")
   816  	cmd.Dir = testProjectDir
   817  	output, err := cmd.CombinedOutput()
   818  	require.Error(t, err)
   819  	assert.Regexp(t, `^Failed to install from foo into .+: foo does not exist\n$`, string(output))
   820  
   821  	cmd = exec.Command("./godelw", "--debug", "install", "foo")
   822  	cmd.Dir = testProjectDir
   823  	output, err = cmd.CombinedOutput()
   824  	require.Error(t, err)
   825  	assert.Regexp(t, `(?s)^foo does not exist.+cmd/godel.localPkg.getPkg.+Failed to install from foo into .+`, string(output))
   826  }
   827  
   828  // * Symlink "test-go" -> $GOPATH
   829  // * Set current directory to test project inside the symlink
   830  // * Verify that "./godelw check" works in sym-linked path
   831  func TestCheckInGoPathSymLink(t *testing.T) {
   832  	testProjectDir := setUpGödelTestAndDownload(t, testRootDir, gödelTGZ, version)
   833  	src := `package foo_test
   834  	import "testing"
   835  
   836  	func TestFoo(t *testing.T) {}`
   837  	err := ioutil.WriteFile(path.Join(testProjectDir, "foo_test.go"), []byte(src), 0644)
   838  	require.NoError(t, err)
   839  
   840  	symLinkParentDir, cleanup, err := dirs.TempDir("", "")
   841  	defer cleanup()
   842  	require.NoError(t, err)
   843  	symLinkPath := path.Join(symLinkParentDir, "test-go")
   844  
   845  	originalGoPath := os.Getenv("GOPATH")
   846  	err = os.Symlink(originalGoPath, symLinkPath)
   847  	require.NoError(t, err)
   848  
   849  	testProjectRelPath, err := filepath.Rel(originalGoPath, testProjectDir)
   850  	require.NoError(t, err)
   851  
   852  	// use script to set cd because setting wd on exec.Command does not work for symlinks
   853  	projectPathInSymLink := path.Join(symLinkPath, testProjectRelPath)
   854  	scriptTemplate := `#!/bin/bash
   855  cd %v
   856  pwd
   857  `
   858  	scriptFilePath := path.Join(symLinkParentDir, "script.sh")
   859  	err = ioutil.WriteFile(scriptFilePath, []byte(fmt.Sprintf(scriptTemplate, projectPathInSymLink)), 0755)
   860  	require.NoError(t, err)
   861  
   862  	cmd := exec.Command(scriptFilePath)
   863  	output, err := cmd.CombinedOutput()
   864  	require.NoError(t, err, "Command %v failed. Output:\n%v", cmd.Args, string(output))
   865  	assert.Equal(t, projectPathInSymLink, strings.TrimSpace(string(output)))
   866  
   867  	scriptTemplate = `#!/bin/bash
   868  cd %v
   869  ./godelw check
   870  `
   871  	err = ioutil.WriteFile(scriptFilePath, []byte(fmt.Sprintf(scriptTemplate, projectPathInSymLink)), 0755)
   872  	require.NoError(t, err)
   873  
   874  	cmd = exec.Command(scriptFilePath)
   875  	output, err = cmd.CombinedOutput()
   876  	require.NoError(t, err, "Command %v failed. Output:\n%v", cmd.Args, string(output))
   877  }
   878  
   879  // * Symlink "test-go" -> $GOPATH
   880  // * Set $GOPATH to be the symlink ("test-go")
   881  // * Set current directory to test project inside the symlink
   882  // * Verify that "./godelw check" works in sym-linked path
   883  // * Restore $GOPATH to original value
   884  func TestCheckInGoPathSymLinkGoPathSymLink(t *testing.T) {
   885  	testProjectDir := setUpGödelTestAndDownload(t, testRootDir, gödelTGZ, version)
   886  	src := `package foo_test
   887  	import "testing"
   888  
   889  	func TestFoo(t *testing.T) {}`
   890  	err := ioutil.WriteFile(path.Join(testProjectDir, "foo_test.go"), []byte(src), 0644)
   891  	require.NoError(t, err)
   892  
   893  	symLinkParentDir, cleanup, err := dirs.TempDir("", "")
   894  	defer cleanup()
   895  	require.NoError(t, err)
   896  	symLinkPath := path.Join(symLinkParentDir, "test-go")
   897  
   898  	originalGoPath := os.Getenv("GOPATH")
   899  	err = os.Symlink(originalGoPath, symLinkPath)
   900  	require.NoError(t, err)
   901  
   902  	err = os.Setenv("GOPATH", symLinkPath)
   903  	require.NoError(t, err)
   904  	defer func() {
   905  		if err := os.Setenv("GOPATH", originalGoPath); err != nil {
   906  			require.NoError(t, err, "failed to restore GOPATH environment variable in defer")
   907  		}
   908  	}()
   909  
   910  	testProjectRelPath, err := filepath.Rel(originalGoPath, testProjectDir)
   911  	require.NoError(t, err)
   912  
   913  	// use script to set cd because setting wd on exec.Command does not work for symlinks
   914  	projectPathInSymLink := path.Join(symLinkPath, testProjectRelPath)
   915  	scriptTemplate := `#!/bin/bash
   916  cd %v
   917  pwd
   918  `
   919  	scriptFilePath := path.Join(symLinkParentDir, "script.sh")
   920  	err = ioutil.WriteFile(scriptFilePath, []byte(fmt.Sprintf(scriptTemplate, projectPathInSymLink)), 0755)
   921  	require.NoError(t, err)
   922  
   923  	cmd := exec.Command(scriptFilePath)
   924  	output, err := cmd.CombinedOutput()
   925  	require.NoError(t, err, "Command %v failed. Output:\n%v", cmd.Args, string(output))
   926  	assert.Equal(t, projectPathInSymLink, strings.TrimSpace(string(output)))
   927  
   928  	scriptTemplate = `#!/bin/bash
   929  cd %v
   930  ./godelw check
   931  `
   932  	err = ioutil.WriteFile(scriptFilePath, []byte(fmt.Sprintf(scriptTemplate, projectPathInSymLink)), 0755)
   933  	require.NoError(t, err)
   934  
   935  	cmd = exec.Command(scriptFilePath)
   936  	output, err = cmd.CombinedOutput()
   937  	require.NoError(t, err, "Command %v failed. Output:\n%v", cmd.Args, string(output))
   938  }
   939  
   940  // * Symlink "test-go" -> $GOPATH
   941  // * Set $GOPATH to be the symlink ("test-go")
   942  // * Set current directory to real project (not inside symlink)
   943  // * Verify that "./godelw check" works in real path
   944  // * Restore $GOPATH to original value
   945  func TestCheckInGoPathNonSymLinkWhenGoPathIsSymLink(t *testing.T) {
   946  	testProjectDir := setUpGödelTestAndDownload(t, testRootDir, gödelTGZ, version)
   947  	src := `package foo_test
   948  	import "testing"
   949  
   950  	func TestFoo(t *testing.T) {}`
   951  	err := ioutil.WriteFile(path.Join(testProjectDir, "foo_test.go"), []byte(src), 0644)
   952  	require.NoError(t, err)
   953  
   954  	symLinkParentDir, cleanup, err := dirs.TempDir("", "")
   955  	defer cleanup()
   956  	require.NoError(t, err)
   957  	symLinkPath := path.Join(symLinkParentDir, "test-go")
   958  
   959  	originalGoPath := os.Getenv("GOPATH")
   960  	err = os.Symlink(originalGoPath, symLinkPath)
   961  	require.NoError(t, err)
   962  
   963  	err = os.Setenv("GOPATH", symLinkPath)
   964  	require.NoError(t, err)
   965  	defer func() {
   966  		if err := os.Setenv("GOPATH", originalGoPath); err != nil {
   967  			require.NoError(t, err, "failed to restore GOPATH environment variable in defer")
   968  		}
   969  	}()
   970  
   971  	cmd := exec.Command("./godelw", "check")
   972  	cmd.Dir = testProjectDir
   973  	output, err := cmd.CombinedOutput()
   974  	require.NoError(t, err, "Command %v failed. Output:\n%v", cmd.Args, string(output))
   975  }