github.com/tilt-dev/tilt@v0.33.15-0.20240515162809-0a22ed45d8a0/internal/tiltfile/os/os_test.go (about)

     1  package os
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"path/filepath"
     7  	"runtime"
     8  	"strings"
     9  	"testing"
    10  
    11  	"github.com/stretchr/testify/assert"
    12  	"github.com/stretchr/testify/require"
    13  
    14  	"github.com/tilt-dev/tilt/internal/tiltfile/io"
    15  	"github.com/tilt-dev/tilt/internal/tiltfile/starkit"
    16  )
    17  
    18  func TestEnviron(t *testing.T) {
    19  	f := NewFixture(t)
    20  	t.Setenv("FAKE_ENV_VARIABLE", "fakeValue")
    21  
    22  	f.File("Tiltfile", `
    23  print(os.environ['FAKE_ENV_VARIABLE'])
    24  print(os.environ.get('FAKE_ENV_VARIABLE'))
    25  `)
    26  
    27  	_, err := f.ExecFile("Tiltfile")
    28  	assert.NoError(t, err)
    29  	assert.Equal(t, "fakeValue\nfakeValue\n", f.PrintOutput())
    30  }
    31  
    32  func TestGetenv(t *testing.T) {
    33  	f := NewFixture(t)
    34  	t.Setenv("FAKE_ENV_VARIABLE", "fakeValue")
    35  
    36  	f.File("Tiltfile", `
    37  print(os.getenv('FAKE_ENV_VARIABLE'))
    38  print(os.getenv('FAKE_ENV_VARIABLE', 'foo'))
    39  print(os.getenv('FAKE_ENV_VARIABLE_UNSET', 'bar'))
    40  `)
    41  
    42  	_, err := f.ExecFile("Tiltfile")
    43  	assert.NoError(t, err)
    44  	assert.Equal(t, "fakeValue\nfakeValue\nbar\n", f.PrintOutput())
    45  }
    46  
    47  func TestPutenv(t *testing.T) {
    48  	f := NewFixture(t)
    49  	t.Setenv("FAKE_ENV_VARIABLE", "fakeValue")
    50  
    51  	f.File("Tiltfile", `
    52  os.putenv('FAKE_ENV_VARIABLE', 'fakeValue2')
    53  print(os.getenv('FAKE_ENV_VARIABLE'))
    54  `)
    55  
    56  	_, err := f.ExecFile("Tiltfile")
    57  	assert.NoError(t, err)
    58  	assert.Equal(t, "fakeValue2\n", f.PrintOutput())
    59  	assert.Equal(t, "fakeValue2", os.Getenv("FAKE_ENV_VARIABLE"))
    60  }
    61  
    62  func TestPutenvByDict(t *testing.T) {
    63  	f := NewFixture(t)
    64  	t.Setenv("FAKE_ENV_VARIABLE", "fakeValue")
    65  
    66  	f.File("Tiltfile", `
    67  os.environ['FAKE_ENV_VARIABLE'] = 'fakeValueByDict'
    68  print(os.getenv('FAKE_ENV_VARIABLE'))
    69  `)
    70  
    71  	_, err := f.ExecFile("Tiltfile")
    72  	assert.NoError(t, err)
    73  	assert.Equal(t, "fakeValueByDict\n", f.PrintOutput())
    74  	assert.Equal(t, "fakeValueByDict", os.Getenv("FAKE_ENV_VARIABLE"))
    75  }
    76  
    77  func TestUnsetenv(t *testing.T) {
    78  	f := NewFixture(t)
    79  	t.Setenv("FAKE_ENV_VARIABLE", "fakeValue")
    80  
    81  	f.File("Tiltfile", `
    82  os.unsetenv('FAKE_ENV_VARIABLE')
    83  print(os.getenv('FAKE_ENV_VARIABLE', 'unused'))
    84  `)
    85  
    86  	_, err := f.ExecFile("Tiltfile")
    87  	assert.NoError(t, err)
    88  	assert.Equal(t, "unused\n", f.PrintOutput())
    89  
    90  	_, found := os.LookupEnv("FAKE_ENV_VARIABLE")
    91  	assert.False(t, found)
    92  }
    93  
    94  func TestUnsetenvAsDict(t *testing.T) {
    95  	f := NewFixture(t)
    96  	t.Setenv("FAKE_ENV_VARIABLE", "fakeValue")
    97  
    98  	f.File("Tiltfile", `
    99  os.environ.pop('FAKE_ENV_VARIABLE')
   100  print(os.getenv('FAKE_ENV_VARIABLE', 'unused'))
   101  `)
   102  
   103  	_, err := f.ExecFile("Tiltfile")
   104  	assert.NoError(t, err)
   105  	assert.Equal(t, "unused\n", f.PrintOutput())
   106  
   107  	_, found := os.LookupEnv("FAKE_ENV_VARIABLE")
   108  	assert.False(t, found)
   109  }
   110  
   111  func TestGetCwd(t *testing.T) {
   112  	f := NewFixture(t)
   113  
   114  	f.File("Tiltfile", `
   115  print(os.getcwd())
   116  `)
   117  
   118  	_, err := f.ExecFile("Tiltfile")
   119  	assert.NoError(t, err)
   120  	assert.Equal(t, fmt.Sprintf("%s\n", f.Path()), f.PrintOutput())
   121  }
   122  
   123  func TestGetCwdLoad(t *testing.T) {
   124  	f := NewFixture(t)
   125  
   126  	f.File("foo/Tiltfile", `
   127  cwd = os.getcwd()
   128  `)
   129  	f.File("Tiltfile", `
   130  load('./foo/Tiltfile', 'cwd')
   131  print(cwd)
   132  `)
   133  
   134  	_, err := f.ExecFile("Tiltfile")
   135  	assert.NoError(t, err)
   136  	assert.Equal(t, fmt.Sprintf("%s\n", f.JoinPath("foo")), f.PrintOutput())
   137  }
   138  
   139  func TestGetCwdLoadFunction(t *testing.T) {
   140  	f := NewFixture(t)
   141  
   142  	f.File("foo/Tiltfile", `
   143  def get_cwd_wrapper():
   144    return os.getcwd()
   145  `)
   146  	f.File("Tiltfile", `
   147  load('./foo/Tiltfile', 'get_cwd_wrapper')
   148  print(get_cwd_wrapper())
   149  `)
   150  
   151  	_, err := f.ExecFile("Tiltfile")
   152  	assert.NoError(t, err)
   153  	assert.Equal(t, fmt.Sprintf("%s\n", f.Path()), f.PrintOutput())
   154  }
   155  
   156  func TestAbspath(t *testing.T) {
   157  	f := NewFixture(t)
   158  	f.UseRealFS()
   159  
   160  	f.File("foo/Tiltfile", `
   161  path = os.path.abspath('.')
   162  `)
   163  	f.File("Tiltfile", `
   164  load('./foo/Tiltfile', 'path')
   165  print(path)
   166  `)
   167  
   168  	_, err := f.ExecFile("Tiltfile")
   169  	require.NoError(t, err)
   170  	assert.Equal(t, fmt.Sprintf("%s\n", f.JoinPath("foo")), f.PrintOutput())
   171  }
   172  
   173  func TestAbspathSymlinks(t *testing.T) {
   174  	if runtime.GOOS == "windows" {
   175  		t.Skip("no user-land symlink support on windows")
   176  	}
   177  
   178  	f := NewFixture(t)
   179  	f.UseRealFS()
   180  
   181  	f.File("foo/Tiltfile", `
   182  path = os.path.abspath('.')
   183  `)
   184  	f.Symlink("foo", "bar")
   185  	f.File("Tiltfile", `
   186  load('./bar/Tiltfile', 'path')
   187  print(path)
   188  `)
   189  
   190  	_, err := f.ExecFile("Tiltfile")
   191  	require.NoError(t, err)
   192  	assert.Equal(t, fmt.Sprintf("%s\n", f.JoinPath("bar")), f.PrintOutput())
   193  }
   194  
   195  // NOTE(maia): `relpath` tests use raw strings (`r'stuff'`) so that Windows tests pass
   196  // (otherwise Starlark sees invalid escape sequences in Windows filespaths and gets mad)
   197  // Also, we use filepath.Rel to get expected path so it works on all OS's.
   198  func TestRelpathDefaultCWD(t *testing.T) {
   199  	f := NewFixture(t)
   200  	f.UseRealFS()
   201  
   202  	targpath := f.JoinPath("beep/boop")
   203  	expected, err := filepath.Rel(f.Path(), targpath)
   204  	assert.NoError(t, err)
   205  
   206  	f.File("Tiltfile", fmt.Sprintf(`
   207  print(os.path.relpath(r'%s'))
   208  `, targpath))
   209  
   210  	_, err = f.ExecFile("Tiltfile")
   211  	require.NoError(t, err)
   212  	assert.Equal(t, expected, strings.TrimSpace(f.PrintOutput()))
   213  }
   214  
   215  func TestRelpathToDifferentDir(t *testing.T) {
   216  	f := NewFixture(t)
   217  	f.UseRealFS()
   218  
   219  	targpath := f.JoinPath("beep/boop")
   220  	basepath := f.JoinPath("beep/")
   221  	expected, err := filepath.Rel(basepath, targpath)
   222  	assert.NoError(t, err)
   223  
   224  	f.File("Tiltfile", fmt.Sprintf(`
   225  print(os.path.relpath(r'%s', r'%s'))
   226  `, targpath, basepath))
   227  
   228  	_, err = f.ExecFile("Tiltfile")
   229  	require.NoError(t, err)
   230  	assert.Equal(t, expected, strings.TrimSpace(f.PrintOutput()))
   231  }
   232  
   233  func TestRelpathImpossible(t *testing.T) {
   234  	f := NewFixture(t)
   235  	f.UseRealFS()
   236  
   237  	f.File("Tiltfile", `
   238  print(os.path.relpath('some/nonsense/path'))
   239  `)
   240  	_, err := f.ExecFile("Tiltfile")
   241  	require.Error(t, err)
   242  	assert.Contains(t, err.Error(), "can't make some/nonsense/path relative to")
   243  }
   244  
   245  func TestRelpathUpADir(t *testing.T) {
   246  	f := NewFixture(t)
   247  	f.UseRealFS()
   248  
   249  	targpath := f.JoinPath("beep/boop")
   250  	basepath := f.JoinPath("foo")
   251  	expected, err := filepath.Rel(basepath, targpath)
   252  	assert.NoError(t, err)
   253  
   254  	f.File("foo/Tiltfile", fmt.Sprintf(`
   255  print(os.path.relpath(r'%s'))
   256  `, f.JoinPath("beep/boop")))
   257  
   258  	_, err = f.ExecFile("foo/Tiltfile")
   259  	require.NoError(t, err)
   260  	assert.Equal(t, expected, strings.TrimSpace(f.PrintOutput()))
   261  }
   262  
   263  func TestRelpathLoad(t *testing.T) {
   264  	f := NewFixture(t)
   265  	f.UseRealFS()
   266  
   267  	targpath := f.JoinPath("foo/beep/boop")
   268  	basepath := f.JoinPath("foo")
   269  	expected, err := filepath.Rel(basepath, targpath)
   270  	assert.NoError(t, err)
   271  
   272  	f.File("foo/Tiltfile", fmt.Sprintf(`
   273  path = os.path.relpath(r'%s')
   274  `, f.JoinPath("foo/beep/boop")))
   275  
   276  	f.File("Tiltfile", `
   277  load('./foo/Tiltfile', 'path')
   278  print(path)
   279  `)
   280  	_, err = f.ExecFile("Tiltfile")
   281  	require.NoError(t, err)
   282  	assert.Equal(t, expected, strings.TrimSpace(f.PrintOutput()))
   283  }
   284  
   285  func TestBasename(t *testing.T) {
   286  	f := NewFixture(t)
   287  	f.UseRealFS()
   288  
   289  	f.File("foo/Tiltfile", `
   290  path = os.path.basename(os.path.abspath('.'))
   291  `)
   292  	f.File("Tiltfile", `
   293  load('./foo/Tiltfile', 'path')
   294  print(path)
   295  `)
   296  
   297  	_, err := f.ExecFile("Tiltfile")
   298  	require.NoError(t, err)
   299  	assert.Equal(t, "foo\n", f.PrintOutput())
   300  }
   301  
   302  func TestDirname(t *testing.T) {
   303  	f := NewFixture(t)
   304  	f.UseRealFS()
   305  
   306  	f.File("foo/Tiltfile", `
   307  path = os.path.dirname(os.path.abspath('.'))
   308  `)
   309  	f.File("Tiltfile", `
   310  load('./foo/Tiltfile', 'path')
   311  print(path)
   312  `)
   313  
   314  	_, err := f.ExecFile("Tiltfile")
   315  	require.NoError(t, err)
   316  	assert.Equal(t, f.Path()+"\n", f.PrintOutput())
   317  }
   318  
   319  func TestExists(t *testing.T) {
   320  	f := NewFixture(t)
   321  	f.UseRealFS()
   322  
   323  	f.File("foo/Tiltfile", `
   324  result1 = os.path.exists('foo/Tiltfile')
   325  result2 = os.path.exists('./Tiltfile')
   326  result3 = os.path.exists('../Tiltfile')
   327  result4 = os.path.exists('../foo')
   328  result5 = os.path.exists('../bar')
   329  `)
   330  	f.File("Tiltfile", `
   331  load('./foo/Tiltfile', 'result1', 'result2', 'result3', 'result4', 'result5')
   332  print(result1)
   333  print(result2)
   334  print(result3)
   335  print(result4)
   336  print(result5)
   337  `)
   338  
   339  	_, err := f.ExecFile("Tiltfile")
   340  	require.NoError(t, err)
   341  	assert.Equal(t, "False\nTrue\nTrue\nTrue\nFalse\n", f.PrintOutput())
   342  }
   343  
   344  func TestPermissionDenied(t *testing.T) {
   345  	if runtime.GOOS != "linux" {
   346  		t.Skip("Test relies on Unix /root permissions")
   347  	}
   348  	f := NewFixture(t)
   349  	f.UseRealFS()
   350  
   351  	f.File("Tiltfile", `
   352  print(os.path.exists('/root/x'))
   353  `)
   354  
   355  	model, err := f.ExecFile("Tiltfile")
   356  	require.NoError(t, err)
   357  	assert.Equal(t, "False\n", f.PrintOutput())
   358  
   359  	readState := io.MustState(model)
   360  	assert.Equal(t, []string{f.JoinPath("Tiltfile")}, readState.Paths)
   361  }
   362  
   363  func TestPathExistsDir(t *testing.T) {
   364  	if runtime.GOOS != "linux" {
   365  		t.Skip("Test relies on Unix /root permissions")
   366  	}
   367  	f := NewFixture(t)
   368  	f.UseRealFS()
   369  
   370  	f.File(f.JoinPath("subdir", "inner", "a.txt"), "hello")
   371  	f.File("Tiltfile", `
   372  print(os.path.exists('subdir'))
   373  `)
   374  
   375  	model, err := f.ExecFile("Tiltfile")
   376  	require.NoError(t, err)
   377  	assert.Equal(t, "True\n", f.PrintOutput())
   378  
   379  	// Verify that we're not watching the subdir recursively.
   380  	readState := io.MustState(model)
   381  	assert.Equal(t, []string{f.JoinPath("Tiltfile")}, readState.Paths)
   382  }
   383  
   384  func TestRealpath(t *testing.T) {
   385  	f := NewFixture(t)
   386  
   387  	f.File("Tiltfile", `
   388  print(os.path.realpath('.'))
   389  `)
   390  
   391  	_, err := f.ExecFile("Tiltfile")
   392  	require.NoError(t, err)
   393  	assert.Equal(t, fmt.Sprintf("%s\n", f.Path()), f.PrintOutput())
   394  }
   395  
   396  func TestRealpathSymlink(t *testing.T) {
   397  	if runtime.GOOS == "windows" {
   398  		t.Skip("no user-land symlink support on windows")
   399  	}
   400  	f := NewFixture(t)
   401  	f.UseRealFS()
   402  
   403  	f.File("foo/Tiltfile", `
   404  path = os.path.realpath('.')
   405  `)
   406  	f.Symlink("foo", "bar")
   407  	f.File("Tiltfile", `
   408  load('./bar/Tiltfile', 'path')
   409  print(path)
   410  `)
   411  
   412  	_, err := f.ExecFile("Tiltfile")
   413  	require.NoError(t, err)
   414  
   415  	// on MacOS, /tmp is a symlink to /private/tmp. If we don't eval the expected path,
   416  	// we get an error because /tmp != /private/tmp
   417  	expected, err := filepath.EvalSymlinks(f.JoinPath("foo"))
   418  	require.NoError(t, err)
   419  	assert.Equal(t, fmt.Sprintf("%s\n", expected), f.PrintOutput())
   420  }
   421  
   422  func TestName(t *testing.T) {
   423  	f := NewFixture(t)
   424  	f.File("Tiltfile", `
   425  print(os.name)
   426  `)
   427  
   428  	_, err := f.ExecFile("Tiltfile")
   429  	require.NoError(t, err)
   430  
   431  	assert.Equal(t, fmt.Sprintf("%s\n", osName()), f.PrintOutput())
   432  }
   433  
   434  func TestJoin(t *testing.T) {
   435  	f := NewFixture(t)
   436  	f.File("Tiltfile", `
   437  print(os.path.join("foo", "bar", "baz"))
   438  `)
   439  
   440  	_, err := f.ExecFile("Tiltfile")
   441  	require.NoError(t, err)
   442  
   443  	assert.Equal(t, fmt.Sprintf("%s\n", filepath.Join("foo", "bar", "baz")), f.PrintOutput())
   444  }
   445  
   446  func NewFixture(tb testing.TB) *starkit.Fixture {
   447  	return starkit.NewFixture(tb, NewPlugin(), io.NewPlugin())
   448  }