github.com/golang/dep@v0.5.4/cmd/dep/integration_test.go (about)

     1  // Copyright 2017 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package main
     6  
     7  import (
     8  	"fmt"
     9  	"io"
    10  	"io/ioutil"
    11  	"os"
    12  	"os/exec"
    13  	"path/filepath"
    14  	"runtime"
    15  	"strings"
    16  	"testing"
    17  
    18  	"github.com/golang/dep"
    19  	"github.com/golang/dep/internal/test"
    20  	"github.com/golang/dep/internal/test/integration"
    21  )
    22  
    23  func TestIntegration(t *testing.T) {
    24  	t.Parallel()
    25  
    26  	test.NeedsExternalNetwork(t)
    27  	test.NeedsGit(t)
    28  
    29  	wd, err := os.Getwd()
    30  	if err != nil {
    31  		t.Fatal(err)
    32  	}
    33  
    34  	relPath := filepath.Join("testdata", "harness_tests")
    35  	filepath.Walk(relPath, func(path string, info os.FileInfo, err error) error {
    36  		if err != nil {
    37  			t.Fatal("error walking filepath")
    38  		}
    39  
    40  		if filepath.Base(path) != "testcase.json" {
    41  			return nil
    42  		}
    43  
    44  		parse := strings.Split(path, string(filepath.Separator))
    45  		testName := strings.Join(parse[2:len(parse)-1], "/")
    46  		t.Run(testName, func(t *testing.T) {
    47  			t.Parallel()
    48  
    49  			t.Run("external", testIntegration(testName, relPath, wd, execCmd))
    50  			t.Run("internal", testIntegration(testName, relPath, wd, runMain))
    51  		})
    52  
    53  		return nil
    54  	})
    55  }
    56  
    57  func TestDepCachedir(t *testing.T) {
    58  	if runtime.GOOS == "windows" {
    59  		// This test is unreliable on Windows and fails at random which makes it very
    60  		// difficult to debug. It might have something to do with parallel execution.
    61  		// Since the test doesn't test any specific behavior of Windows, it should be okay
    62  		// to skip.
    63  		t.Skip("skipping on windows")
    64  	}
    65  	t.Parallel()
    66  
    67  	test.NeedsExternalNetwork(t)
    68  	test.NeedsGit(t)
    69  
    70  	wd, err := os.Getwd()
    71  	if err != nil {
    72  		t.Fatal(err)
    73  	}
    74  
    75  	initPath := filepath.Join("testdata", "cachedir")
    76  
    77  	t.Run("env-invalid-cachedir", func(t *testing.T) {
    78  		t.Parallel()
    79  		testProj := integration.NewTestProject(t, initPath, wd, runMain)
    80  		defer testProj.Cleanup()
    81  
    82  		var d []byte
    83  		tmpFp := testProj.Path("tmp-file")
    84  		ioutil.WriteFile(tmpFp, d, 0644)
    85  		cases := []string{
    86  			// invalid path
    87  			"\000",
    88  			// parent directory does not exist
    89  			testProj.Path("non-existent-fldr", "cachedir"),
    90  			// path is a regular file
    91  			tmpFp,
    92  			// invalid path, tmp-file is a regular file
    93  			testProj.Path("tmp-file", "cachedir"),
    94  		}
    95  
    96  		wantErr := "dep: $DEPCACHEDIR set to an invalid or inaccessible path"
    97  		for _, c := range cases {
    98  			testProj.Setenv("DEPCACHEDIR", c)
    99  
   100  			err = testProj.DoRun([]string{"ensure"})
   101  
   102  			if err == nil {
   103  				// Log the output from running `dep ensure`, could be useful.
   104  				t.Logf("test run output: \n%s\n%s", testProj.GetStdout(), testProj.GetStderr())
   105  				t.Error("unexpected result: \n\t(GOT) nil\n\t(WNT) exit status 1")
   106  			} else if stderr := testProj.GetStderr(); !strings.Contains(stderr, wantErr) {
   107  				t.Errorf(
   108  					"unexpected error output: \n\t(GOT) %s\n\t(WNT) %s",
   109  					strings.TrimSpace(stderr), wantErr,
   110  				)
   111  			}
   112  		}
   113  	})
   114  
   115  }
   116  
   117  // execCmd is a test.RunFunc which runs the program in another process.
   118  func execCmd(prog string, args []string, stdout, stderr io.Writer, dir string, env []string) error {
   119  	cmd := exec.Command(prog, args...)
   120  	cmd.Stdout = stdout
   121  	cmd.Stderr = stderr
   122  	cmd.Env = env
   123  	cmd.Dir = dir
   124  	return cmd.Run()
   125  }
   126  
   127  // runMain is a test.RunFunc which runs the program in-process.
   128  func runMain(prog string, args []string, stdout, stderr io.Writer, dir string, env []string) (err error) {
   129  	defer func() {
   130  		if r := recover(); r != nil {
   131  			switch r := r.(type) {
   132  			case error:
   133  				err = r
   134  			default:
   135  				err = fmt.Errorf("%v", r)
   136  			}
   137  		}
   138  	}()
   139  	m := &Config{
   140  		Args:       append([]string{prog}, args...),
   141  		Stdout:     stdout,
   142  		Stderr:     stderr,
   143  		WorkingDir: dir,
   144  		Env:        env,
   145  	}
   146  	if exitCode := m.Run(); exitCode != 0 {
   147  		err = fmt.Errorf("exit status %d", exitCode)
   148  	}
   149  	return
   150  }
   151  
   152  // testIntegration runs the test specified by <wd>/<relPath>/<name>/testcase.json
   153  func testIntegration(name, relPath, wd string, run integration.RunFunc) func(t *testing.T) {
   154  	return func(t *testing.T) {
   155  		t.Parallel()
   156  
   157  		testCase := integration.NewTestCase(t, filepath.Join(wd, relPath), name)
   158  
   159  		// Skip tests for disabled features
   160  		if testCase.RequiredFeatureFlag != "" {
   161  			featureEnabled, err := readFeatureFlag(testCase.RequiredFeatureFlag)
   162  			if err != nil {
   163  				t.Fatal(err)
   164  			}
   165  
   166  			if !featureEnabled {
   167  				t.Skipf("skipping %s, %s feature flag not enabled", name, testCase.RequiredFeatureFlag)
   168  			}
   169  		}
   170  
   171  		// Set up environment
   172  		testProj := integration.NewTestProject(t, testCase.InitialPath(), wd, run)
   173  		defer testProj.Cleanup()
   174  
   175  		// Create and checkout the vendor revisions
   176  		for ip, rev := range testCase.VendorInitial {
   177  			testProj.GetVendorGit(ip)
   178  			testProj.RunGit(testProj.VendorPath(ip), "checkout", rev)
   179  		}
   180  
   181  		// Create and checkout the import revisions
   182  		for ip, rev := range testCase.GopathInitial {
   183  			testProj.RunGo("get", ip)
   184  			testProj.RunGit(testProj.Path("src", ip), "checkout", rev)
   185  		}
   186  
   187  		// Run commands
   188  		testProj.RecordImportPaths()
   189  
   190  		var err error
   191  		for i, args := range testCase.Commands {
   192  			err = testProj.DoRun(args)
   193  			if err != nil && i < len(testCase.Commands)-1 {
   194  				t.Fatalf("cmd %s raised an unexpected error: %s", args[0], err.Error())
   195  			}
   196  		}
   197  
   198  		if err != nil {
   199  			t.Log(err)
   200  		}
   201  
   202  		// Check error raised in final command
   203  		testCase.CompareCmdFailure(err != nil)
   204  		testCase.CompareError(err, testProj.GetStderr())
   205  
   206  		if *test.UpdateGolden {
   207  			testCase.UpdateOutput(testProj.GetStdout())
   208  		} else {
   209  			// Check output
   210  			testCase.CompareOutput(testProj.GetStdout())
   211  		}
   212  
   213  		// Check vendor paths
   214  		testProj.CompareImportPaths()
   215  		testCase.CompareVendorPaths(testProj.GetVendorPaths())
   216  
   217  		if *test.UpdateGolden {
   218  			// Update manifest and lock
   219  			testCase.UpdateFile(dep.ManifestName, testProj.ProjPath(dep.ManifestName))
   220  			testCase.UpdateFile(dep.LockName, testProj.ProjPath(dep.LockName))
   221  		} else {
   222  			// Check final manifest and lock
   223  			testCase.CompareFile(dep.ManifestName, testProj.ProjPath(dep.ManifestName))
   224  			testCase.CompareFile(dep.LockName, testProj.ProjPath(dep.LockName))
   225  		}
   226  	}
   227  }