github.com/ktr0731/dept@v0.1.4-0.20191208040738-06ee3ca97c03/deptfile/workspace_test.go (about)

     1  package deptfile_test
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"os"
     7  	"path/filepath"
     8  	"testing"
     9  
    10  	"github.com/google/go-cmp/cmp"
    11  	"github.com/ktr0731/dept/deptfile"
    12  	"github.com/ktr0731/modfile"
    13  	"github.com/pkg/errors"
    14  )
    15  
    16  var _ deptfile.Workspacer = (*deptfile.Workspace)(nil)
    17  
    18  // TestDo runs tests against to testdata/gotool.mod.
    19  func TestDo(t *testing.T) {
    20  	testRequires := func(t *testing.T, r []*deptfile.Require, cond map[string]func(r *deptfile.Require) error) {
    21  		passed := map[string]bool{}
    22  		for _, r := range r {
    23  			for modName, cond := range cond {
    24  				if _, ok := passed[modName]; !ok {
    25  					passed[modName] = false
    26  				}
    27  				if r.Path != modName {
    28  					continue
    29  				}
    30  				if len(r.ToolPaths) == 0 {
    31  					t.Fatalf("%s: length of ToolPaths is 0", r.Path)
    32  				}
    33  				if err := cond(r); err != nil {
    34  					t.Errorf("%s: %s", r.Path, err)
    35  				} else {
    36  					passed[modName] = true
    37  				}
    38  			}
    39  		}
    40  		for modName, passed := range passed {
    41  			if !passed {
    42  				t.Errorf("tests for %s are not passed. invalid condition?", modName)
    43  			}
    44  		}
    45  	}
    46  
    47  	t.Run("workspace changes directory to a temp dir and copies gotool.mod to there", func(t *testing.T) {
    48  		cases := map[string]struct {
    49  			dir        string
    50  			numRequire int
    51  			testcases  map[string]func(r *deptfile.Require) error
    52  		}{
    53  			"some required tools": {
    54  				dir:        "normal",
    55  				numRequire: 4,
    56  				testcases: map[string]func(r *deptfile.Require) error{
    57  					"github.com/ktr0731/evans": func(r *deptfile.Require) error {
    58  						expectedToolPath := &deptfile.Tool{Path: "/"}
    59  						if diff := cmp.Diff(expectedToolPath, r.ToolPaths[0]); diff != "" {
    60  							return errors.Errorf("ToolPaths[0] is wrong:\n%s", diff)
    61  						}
    62  						return nil
    63  					},
    64  					"honnef.co/go/tools": func(r *deptfile.Require) error {
    65  						if n := len(r.ToolPaths); n != 2 {
    66  							return errors.Errorf("expected 2 tools in this module, but got %d", n)
    67  						}
    68  						if r.ToolPaths[0].Path != "/cmd/staticcheck" {
    69  							return errors.Errorf("expected r.ToolPaths[0].Path is '/cmd/staticcheck', but %s", r.ToolPaths[0].Path)
    70  						}
    71  						if r.ToolPaths[1].Path != "/cmd/unused" {
    72  							return errors.Errorf("expected r.ToolPaths[0].Path is '/cmd/unused', but %s", r.ToolPaths[0].Path)
    73  						}
    74  						return nil
    75  					},
    76  				},
    77  			},
    78  			"only one require tool": {
    79  				dir:        "oneline",
    80  				numRequire: 1,
    81  				testcases: map[string]func(r *deptfile.Require) error{
    82  					"github.com/ktr0731/evans": func(r *deptfile.Require) error {
    83  						expectedToolPath := &deptfile.Tool{Path: "/"}
    84  						if diff := cmp.Diff(expectedToolPath, r.ToolPaths[0]); diff != "" {
    85  							return errors.Errorf("ToolPaths[0] is wrong:\n%s", diff)
    86  						}
    87  						return nil
    88  					},
    89  				},
    90  			},
    91  			"renamed tools": {
    92  				dir:        "rename",
    93  				numRequire: 3,
    94  				testcases: map[string]func(r *deptfile.Require) error{
    95  					"github.com/ktr0731/itunes-cli": func(r *deptfile.Require) error {
    96  						if n := len(r.ToolPaths); n != 1 {
    97  							return errors.Errorf("expected 1 tool in this module, but got %d", n)
    98  						}
    99  						expectedToolPath := &deptfile.Tool{Path: "/itunes", Name: "it"}
   100  						if diff := cmp.Diff(expectedToolPath, r.ToolPaths[0]); diff != "" {
   101  							return errors.Errorf("ToolPaths[0] is wrong:\n%s", diff)
   102  						}
   103  						return nil
   104  					},
   105  					"github.com/ktr0731/evans": func(r *deptfile.Require) error {
   106  						if n := len(r.ToolPaths); n != 1 {
   107  							return errors.Errorf("expected 1 tool in this module, but got %d", n)
   108  						}
   109  						expectedToolPath := &deptfile.Tool{Path: "/", Name: "ev"}
   110  						if diff := cmp.Diff(expectedToolPath, r.ToolPaths[0]); diff != "" {
   111  							return errors.Errorf("ToolPaths[0] is wrong:\n%s", diff)
   112  						}
   113  						return nil
   114  					},
   115  					"honnef.co/go/tools": func(r *deptfile.Require) error {
   116  						if n := len(r.ToolPaths); n != 2 {
   117  							return errors.Errorf("expected 2 tools in this module, but got %d", n)
   118  						}
   119  						expectedToolPath0 := &deptfile.Tool{Path: "/cmd/staticcheck", Name: "sc"}
   120  						if diff := cmp.Diff(expectedToolPath0, r.ToolPaths[0]); diff != "" {
   121  							return errors.Errorf("ToolPaths[0] is wrong:\n%s", diff)
   122  						}
   123  						expectedToolPath1 := &deptfile.Tool{Path: "/cmd/unused"}
   124  						if diff := cmp.Diff(expectedToolPath1, r.ToolPaths[1]); diff != "" {
   125  							return errors.Errorf("ToolPaths[1] is wrong:\n%s", diff)
   126  						}
   127  						return nil
   128  					},
   129  				},
   130  			},
   131  		}
   132  
   133  		for name, c := range cases {
   134  			t.Run(name, func(t *testing.T) {
   135  				testDataDir, err := filepath.Abs(filepath.Join("testdata", c.dir))
   136  				if err != nil {
   137  					t.Fatalf("failed to get abs path: %s", err)
   138  				}
   139  				cleanup := setupEnv(t, testDataDir)
   140  				defer cleanup()
   141  
   142  				cwd, err := os.Getwd()
   143  				if err != nil {
   144  					t.Fatalf("failed to get cwd: %s", err)
   145  				}
   146  
   147  				w := &deptfile.Workspace{
   148  					SourcePath: cwd,
   149  				}
   150  				err = w.Do(func(proj string, gomod *deptfile.File) error {
   151  					if gomod == nil {
   152  						t.Fatalf("deptfile must not be nil, but nil")
   153  					}
   154  
   155  					if n := len(gomod.Require); n != c.numRequire {
   156  						t.Errorf("deptfile must have %d required modules (managed tools), but %d", c.numRequire, n)
   157  					}
   158  
   159  					testRequires(t, gomod.Require, c.testcases)
   160  
   161  					newcwd, err := os.Getwd()
   162  					if err != nil {
   163  						t.Fatalf("failed to get current working dir: %s", err)
   164  					}
   165  					if cwd == newcwd {
   166  						t.Errorf("current dir in Do must not be equal to dir outside of Do")
   167  					}
   168  					return nil
   169  				})
   170  				if err != nil {
   171  					t.Errorf("Do must not return errors, but got an error: %s", err)
   172  				}
   173  
   174  				cwd2, err := os.Getwd()
   175  				if err != nil {
   176  					t.Errorf("failed to get current working dir: %s", err)
   177  				}
   178  				if cwd != cwd2 {
   179  					t.Errorf("current working dir which called before Do and after one must be equal, but %s and %s", cwd, cwd2)
   180  				}
   181  
   182  				if _, err := os.Stat(deptfile.FileName); os.IsNotExist(err) {
   183  					t.Errorf("gotool.mod must be in the current dir, but not found")
   184  				}
   185  
   186  				checkGoModSyntax(t)
   187  
   188  				assertEqualDeptfile(t, filepath.Join(testDataDir, deptfile.FileName))
   189  			})
   190  		}
   191  	})
   192  
   193  	t.Run("workspace returns ErrNotFound", func(t *testing.T) {
   194  		dir, err := ioutil.TempDir("", "")
   195  		if err != nil {
   196  			t.Fatalf("failed to create a temp dir: %s", err)
   197  		}
   198  		w := &deptfile.Workspace{SourcePath: dir}
   199  		err = w.Do(func(proj string, gomod *deptfile.File) error {
   200  			return nil
   201  		})
   202  		if err != deptfile.ErrNotFound {
   203  			t.Errorf("workspace must return ErrNotFound because gotool.mod is not found in current working dir, but '%s'", err)
   204  		}
   205  	})
   206  }
   207  
   208  func checkGoModSyntax(t *testing.T) {
   209  	b, err := ioutil.ReadFile(deptfile.FileName)
   210  	if err != nil {
   211  		t.Fatalf("failed to read %s", deptfile.FileName)
   212  	}
   213  	_, err = modfile.Parse(deptfile.FileName, b, nil)
   214  	if err != nil {
   215  		fmt.Println(string(b))
   216  		t.Fatalf("failed to parse %s: %s", deptfile.FileName, err)
   217  	}
   218  }
   219  
   220  func assertEqualDeptfile(t *testing.T, fname string) {
   221  	f1, err := ioutil.ReadFile(deptfile.FileName)
   222  	if err != nil {
   223  		t.Fatalf("failed to read %s: %s", deptfile.FileName, err)
   224  	}
   225  	f2, err := ioutil.ReadFile(fname)
   226  	if err != nil {
   227  		t.Fatalf("failed to read %s: %s", fname, err)
   228  	}
   229  	if diff := cmp.Diff(string(f1), string(f2)); diff != "" {
   230  		t.Errorf("f1 is not equal to f2:\n%s", diff)
   231  	}
   232  }