github.com/goplus/gop@v1.2.6/env/path_test.go (about)

     1  /*
     2   * Copyright (c) 2021 The GoPlus Authors (goplus.org). All rights reserved.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package env
    18  
    19  import (
    20  	"os"
    21  	"path/filepath"
    22  	"testing"
    23  
    24  	"github.com/goplus/mod"
    25  )
    26  
    27  func findGoModFile(dir string) (modfile string, noCacheFile bool, err error) {
    28  	modfile, err = mod.GOMOD(dir)
    29  	if err != nil {
    30  		gopRoot, err := findGopRoot()
    31  		if err == nil {
    32  			modfile = filepath.Join(gopRoot, "go.mod")
    33  			return modfile, true, nil
    34  		}
    35  	}
    36  	return
    37  }
    38  
    39  // Common testing directory structure:
    40  // testing_root/
    41  //
    42  //	  src/
    43  //		   subdir/
    44  //	  valid_goproot/
    45  //		   go.mod
    46  //		   go.sum
    47  //	    cmd/gop/
    48  func makeTestDir(t *testing.T) (root string, src string, gopRoot string) {
    49  	root, _ = filepath.EvalSymlinks(t.TempDir())
    50  	src = filepath.Join(root, "src")
    51  	gopRoot = filepath.Join(root, "valid_goproot")
    52  	makeValidGopRoot(gopRoot)
    53  	os.Mkdir(src, 0755)
    54  	return
    55  }
    56  
    57  func makeValidGopRoot(root string) {
    58  	os.Mkdir(root, 0755)
    59  	os.MkdirAll(filepath.Join(root, "cmd/gop"), 0755)
    60  	os.WriteFile(filepath.Join(root, "go.mod"), []byte(""), 0644)
    61  	os.WriteFile(filepath.Join(root, "go.sum"), []byte(""), 0644)
    62  }
    63  
    64  func writeDummyFile(path string) {
    65  	os.WriteFile(path, []byte(""), 0644)
    66  }
    67  
    68  func cleanup() {
    69  	os.Setenv("GOPROOT", "")
    70  	os.Setenv(envHOME, "")
    71  	defaultGopRoot = ""
    72  }
    73  
    74  func TestBasic(t *testing.T) {
    75  	defaultGopRoot = ".."
    76  	if GOPROOT() == "" {
    77  		t.Fatal("TestBasic failed")
    78  	}
    79  	defaultGopRoot = ""
    80  }
    81  
    82  func TestFindGoModFileInGoModDir(t *testing.T) {
    83  	cleanup()
    84  
    85  	t.Run("the src/ is a valid mod dir", func(tt *testing.T) {
    86  		tt.Cleanup(cleanup)
    87  		_, src, _ := makeTestDir(tt)
    88  		subdir := filepath.Join(src, "subdir")
    89  		writeDummyFile(filepath.Join(src, "go.mod"))
    90  		os.Mkdir(subdir, 0755)
    91  
    92  		{
    93  			modfile, noCacheFile, err := findGoModFile(src)
    94  
    95  			if err != nil || modfile != filepath.Join(src, "go.mod") || noCacheFile {
    96  				tt.Fatal("got:", modfile, noCacheFile, err)
    97  			}
    98  		}
    99  
   100  		{
   101  			// Should found go.mod in parent dir
   102  			modfile, noCacheFile, err := findGoModFile(subdir)
   103  
   104  			if err != nil || modfile != filepath.Join(src, "go.mod") || noCacheFile {
   105  				tt.Fatal("got:", modfile, noCacheFile, err)
   106  			}
   107  		}
   108  	})
   109  
   110  	t.Run("the src/ is not a valid mod dir", func(tt *testing.T) {
   111  		tt.Cleanup(cleanup)
   112  		_, src, _ := makeTestDir(tt)
   113  
   114  		modfile, noCacheFile, err := findGoModFile(src)
   115  
   116  		if err == nil {
   117  			tt.Fatal("should not found the mod file, but got:", modfile, noCacheFile)
   118  		}
   119  	})
   120  }
   121  
   122  func TestFindGoModFileInGopRoot(t *testing.T) {
   123  	originDir, _ := os.Getwd()
   124  	origiExecutable := executable
   125  	home := filepath.Join(os.TempDir(), "test_home")
   126  	os.Mkdir(home, 0755)
   127  	t.Cleanup(func() {
   128  		os.Chdir(originDir)
   129  		os.RemoveAll(home)
   130  		executable = origiExecutable
   131  	})
   132  
   133  	bin := filepath.Join(home, "bin")
   134  
   135  	// Don't find go.mod in gop source dir when testing
   136  	os.Chdir(home)
   137  
   138  	cleanupAll := func() {
   139  		cleanup()
   140  		executable = func() (string, error) {
   141  			return filepath.Join(bin, "run"), nil
   142  		}
   143  	}
   144  	cleanupAll()
   145  
   146  	t.Run("without gop root", func(tt *testing.T) {
   147  		tt.Cleanup(cleanupAll)
   148  		root, _, _ := makeTestDir(tt)
   149  
   150  		modfile, noCacheFile, err := findGoModFile(root)
   151  
   152  		if err == nil || noCacheFile || modfile != "" {
   153  			tt.Fatal("should not found go.mod without gop root, got:", modfile, noCacheFile, err)
   154  		}
   155  	})
   156  
   157  	t.Run("set GOPROOT to a valid goproot path", func(tt *testing.T) {
   158  		tt.Cleanup(cleanupAll)
   159  		_, src, gopRoot := makeTestDir(tt)
   160  
   161  		os.Setenv("GOPROOT", gopRoot)
   162  		modfile, noCacheFile, err := findGoModFile(src)
   163  
   164  		if err != nil || modfile != filepath.Join(gopRoot, "go.mod") || !noCacheFile {
   165  			tt.Fatal("should found mod file in GOPROOT, got:", modfile, noCacheFile, err)
   166  		}
   167  	})
   168  
   169  	t.Run("set GOPROOT to an invalid goproot path", func(tt *testing.T) {
   170  		tt.Cleanup(cleanupAll)
   171  		root, src, _ := makeTestDir(tt)
   172  		invalidGopRoot := filepath.Join(root, "invalid_goproot")
   173  
   174  		defer func() {
   175  			r := recover()
   176  			if r == nil {
   177  				tt.Fatal("should panic, but not")
   178  			}
   179  		}()
   180  
   181  		os.Setenv("GOPROOT", invalidGopRoot)
   182  		findGoModFile(src)
   183  	})
   184  
   185  	t.Run("set defaultGopRoot to a valid goproot path", func(tt *testing.T) {
   186  		tt.Cleanup(cleanupAll)
   187  		_, src, gopRoot := makeTestDir(tt)
   188  
   189  		defaultGopRoot = gopRoot
   190  		modfile, noCacheFile, err := findGoModFile(src)
   191  
   192  		if err != nil || modfile != filepath.Join(gopRoot, "go.mod") || !noCacheFile {
   193  			tt.Fatal("should found go.mod in the dir of defaultGopRoot, got:", modfile, noCacheFile, err)
   194  		}
   195  	})
   196  
   197  	t.Run("set defaultGopRoot to an invalid path", func(tt *testing.T) {
   198  		tt.Cleanup(cleanupAll)
   199  		root, src, _ := makeTestDir(tt)
   200  		invalidGopRoot := filepath.Join(root, "invalid_goproot")
   201  
   202  		defaultGopRoot = invalidGopRoot
   203  		{
   204  			modfile, noCacheFile, err := findGoModFile(src)
   205  
   206  			if err == nil || noCacheFile || modfile != "" {
   207  				tt.Fatal("should not found go.mod when defaultGopRoot isn't exists, got:", modfile, noCacheFile, err)
   208  			}
   209  		}
   210  
   211  		{
   212  			os.Mkdir(invalidGopRoot, 0755)
   213  			modfile, noCacheFile, err := findGoModFile(src)
   214  
   215  			if err == nil || noCacheFile || modfile != "" {
   216  				tt.Fatal("should not found go.mod when defaultGopRoot isn't an valid gop root dir, got:", modfile, noCacheFile, err)
   217  			}
   218  		}
   219  	})
   220  
   221  	t.Run("use $HOME/gop or $HOME/goplus", func(tt *testing.T) {
   222  		tt.Cleanup(cleanupAll)
   223  		root, src, _ := makeTestDir(tt)
   224  		home := filepath.Join(root, "home")
   225  		os.Mkdir(home, 0755)
   226  		os.Setenv(envHOME, home)
   227  
   228  		{
   229  			gopRoot := filepath.Join(home, "goplus")
   230  			makeValidGopRoot(gopRoot)
   231  
   232  			modfile, noCacheFile, err := findGoModFile(src)
   233  
   234  			if err != nil || !noCacheFile || modfile != filepath.Join(gopRoot, "go.mod") {
   235  				tt.Fatal("should found go.mod in $HOME/goplus, but got:", modfile, noCacheFile, err)
   236  			}
   237  		}
   238  
   239  		{
   240  			gopRoot := filepath.Join(home, "gop")
   241  			makeValidGopRoot(gopRoot)
   242  
   243  			modfile, noCacheFile, err := findGoModFile(src)
   244  
   245  			if err != nil || !noCacheFile || modfile != filepath.Join(gopRoot, "go.mod") {
   246  				tt.Fatal("should found go.mod in $HOME/gop, but got:", modfile, noCacheFile, err)
   247  			}
   248  		}
   249  	})
   250  
   251  	t.Run("check if parent dir of the executable is valid gop root", func(tt *testing.T) {
   252  		tt.Cleanup(cleanupAll)
   253  		_, src, gopRoot := makeTestDir(tt)
   254  		bin := filepath.Join(gopRoot, "bin")
   255  		exePath := filepath.Join(bin, "run")
   256  		os.Mkdir(bin, 0755)
   257  		writeDummyFile(exePath)
   258  
   259  		// Mock executable location
   260  		executable = func() (string, error) {
   261  			return exePath, nil
   262  		}
   263  
   264  		modfile, noCacheFile, err := findGoModFile(src)
   265  
   266  		if err != nil || !noCacheFile || modfile != filepath.Join(gopRoot, "go.mod") {
   267  			tt.Fatal("should found go.mod in gopRoot, but got:", modfile, noCacheFile, err)
   268  		}
   269  	})
   270  
   271  	t.Run("test gop root priority", func(tt *testing.T) {
   272  		tt.Cleanup(cleanupAll)
   273  		root, src, _ := makeTestDir(tt)
   274  
   275  		tt.Run("without gop root", func(tt *testing.T) {
   276  			modfile, noCacheFile, err := findGoModFile(src)
   277  
   278  			if err == nil || noCacheFile || modfile != "" {
   279  				tt.Fatal("should not found go.mod without gop root, got:", modfile, noCacheFile, err)
   280  			}
   281  		})
   282  
   283  		tt.Run("set HOME but hasn't $HOME/gop/ and $HOME/goplus/", func(tt *testing.T) {
   284  			os.Setenv(envHOME, root)
   285  
   286  			modfile, noCacheFile, err := findGoModFile(src)
   287  
   288  			if err == nil || noCacheFile || modfile != "" {
   289  				tt.Fatal("should not found go.mod without gop root, got:", modfile, noCacheFile, err)
   290  			}
   291  		})
   292  
   293  		tt.Run("set HOME, and has valid $HOME/goplus/", func(tt *testing.T) {
   294  			gopRoot := filepath.Join(root, "goplus")
   295  			makeValidGopRoot(gopRoot)
   296  
   297  			modfile, noCacheFile, err := findGoModFile(src)
   298  
   299  			if err != nil || !noCacheFile || modfile != filepath.Join(gopRoot, "go.mod") {
   300  				tt.Fatal("should found go.mod in $HOME/goplus, but got:", modfile, noCacheFile, err)
   301  			}
   302  		})
   303  
   304  		tt.Run("set HOME, and has valid $HOME/gop/", func(tt *testing.T) {
   305  			gopRoot := filepath.Join(root, "gop")
   306  			makeValidGopRoot(gopRoot)
   307  
   308  			modfile, noCacheFile, err := findGoModFile(src)
   309  
   310  			if err != nil || !noCacheFile || modfile != filepath.Join(gopRoot, "go.mod") {
   311  				tt.Fatal("should found go.mod in $HOME/gop, but got:", modfile, noCacheFile, err)
   312  			}
   313  		})
   314  
   315  		tt.Run("set defaultGopRoot to an invalid gop root dir", func(tt *testing.T) {
   316  			gopRoot := filepath.Join(root, "gop")
   317  
   318  			defaultGopRoot = filepath.Join(root, "invalid_goproot")
   319  			modfile, noCacheFile, err := findGoModFile(src)
   320  
   321  			if err != nil || !noCacheFile || modfile != filepath.Join(gopRoot, "go.mod") {
   322  				tt.Fatal("should found go.mod in $HOME/gop, but got:", modfile, noCacheFile, err)
   323  			}
   324  		})
   325  
   326  		tt.Run("set defaultGopRoot to a valid gop root dir", func(tt *testing.T) {
   327  			newGopRoot := filepath.Join(root, "new_gop_root")
   328  			makeValidGopRoot(newGopRoot)
   329  
   330  			defaultGopRoot = newGopRoot
   331  			modfile, noCacheFile, err := findGoModFile(src)
   332  
   333  			if err != nil || !noCacheFile || modfile != filepath.Join(newGopRoot, "go.mod") {
   334  				tt.Fatal("should found go.mod in new_gop_root/, but got:", modfile, noCacheFile, err)
   335  			}
   336  		})
   337  
   338  		tt.Run("the executable's parent dir is a valid gop root dir", func(tt *testing.T) {
   339  			newGopRoot2 := filepath.Join(root, "new_gop_root2")
   340  			makeValidGopRoot(newGopRoot2)
   341  			bin := filepath.Join(newGopRoot2, "bin")
   342  			exePath := filepath.Join(bin, "run")
   343  			os.Mkdir(bin, 0755)
   344  			writeDummyFile(exePath)
   345  			// Mock executable location
   346  			executable = func() (string, error) {
   347  				return exePath, nil
   348  			}
   349  
   350  			modfile, noCacheFile, err := findGoModFile(src)
   351  
   352  			if err != nil || !noCacheFile || modfile != filepath.Join(newGopRoot2, "go.mod") {
   353  				tt.Fatal("should found go.mod in new_gop_root2/, but got:", modfile, noCacheFile, err)
   354  			}
   355  		})
   356  
   357  		tt.Run("set GOPROOT to an invalid gop root dir", func(tt *testing.T) {
   358  			newGopRoot3 := filepath.Join(root, "new_gop_root3")
   359  
   360  			defer func() {
   361  				r := recover()
   362  				if r == nil {
   363  					tt.Fatal("should panic, but not")
   364  				}
   365  			}()
   366  
   367  			os.Setenv("GOPROOT", newGopRoot3)
   368  			findGoModFile(src)
   369  		})
   370  
   371  		tt.Run("set GOPROOT to a valid gop root dir", func(tt *testing.T) {
   372  			newGopRoot4 := filepath.Join(root, "new_gop_root4")
   373  			makeValidGopRoot(newGopRoot4)
   374  
   375  			os.Setenv("GOPROOT", newGopRoot4)
   376  			modfile, noCacheFile, err := findGoModFile(src)
   377  
   378  			if err != nil || !noCacheFile || modfile != filepath.Join(newGopRoot4, "go.mod") {
   379  				tt.Fatal("should found go.mod in new_gop_root3/, but got:", modfile, noCacheFile, err)
   380  			}
   381  		})
   382  	})
   383  }