github.com/tilt-dev/tilt@v0.36.0/internal/tiltfile/starkit/fixture.go (about) 1 package starkit 2 3 import ( 4 "bytes" 5 "context" 6 "fmt" 7 "os" 8 "path/filepath" 9 "testing" 10 11 "github.com/stretchr/testify/assert" 12 "github.com/stretchr/testify/require" 13 "go.starlark.net/starlark" 14 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 15 16 "github.com/tilt-dev/tilt/internal/testutils/tempdir" 17 "github.com/tilt-dev/tilt/pkg/apis/core/v1alpha1" 18 "github.com/tilt-dev/tilt/pkg/logger" 19 ) 20 21 // A fixture for test setup/teardown 22 type Fixture struct { 23 tb testing.TB 24 plugins []Plugin 25 path string 26 temp *tempdir.TempDirFixture 27 fs map[string]string 28 out *bytes.Buffer 29 useRealFS bool // Use a real filesystem 30 loadInterceptors []LoadInterceptor 31 ctx context.Context 32 tf *v1alpha1.Tiltfile 33 } 34 35 func NewFixture(tb testing.TB, plugins ...Plugin) *Fixture { 36 out := bytes.NewBuffer(nil) 37 ctx := logger.WithLogger(context.Background(), logger.NewTestLogger(out)) 38 temp := tempdir.NewTempDirFixture(tb) 39 temp.Chdir() 40 41 ret := &Fixture{ 42 tb: tb, 43 plugins: plugins, 44 path: temp.Path(), 45 temp: temp, 46 fs: make(map[string]string), 47 out: out, 48 ctx: ctx, 49 tf: &v1alpha1.Tiltfile{ 50 ObjectMeta: metav1.ObjectMeta{ 51 Name: "(Tiltfile)", 52 }, 53 }, 54 } 55 56 return ret 57 } 58 59 func (f *Fixture) SetContext(ctx context.Context) { 60 f.ctx = ctx 61 } 62 63 func (f *Fixture) SetOutput(out *bytes.Buffer) { 64 f.out = out 65 } 66 67 func (f *Fixture) OnStart(e *Environment) error { 68 if !f.useRealFS { 69 e.SetFakeFileSystem(f.fs) 70 } 71 72 e.SetPrint(func(t *starlark.Thread, msg string) { 73 _, _ = fmt.Fprintf(f.out, "%s\n", msg) 74 }) 75 e.SetContext(f.ctx) 76 return nil 77 } 78 79 func (f *Fixture) ExecFile(name string) (Model, error) { 80 plugins := append([]Plugin{f}, f.plugins...) 81 env := newEnvironment(plugins...) 82 for _, i := range f.loadInterceptors { 83 env.AddLoadInterceptor(i) 84 } 85 f.tf.Spec.Path = filepath.Join(f.path, name) 86 return env.start(f.tf) 87 } 88 89 func (f *Fixture) SetLoadInterceptor(i LoadInterceptor) { 90 f.loadInterceptors = append(f.loadInterceptors, i) 91 } 92 93 func (f *Fixture) PrintOutput() string { 94 return f.out.String() 95 } 96 97 func (f *Fixture) Path() string { 98 return f.path 99 } 100 101 func (f *Fixture) Tiltfile() *v1alpha1.Tiltfile { 102 return f.tf 103 } 104 105 func (f *Fixture) JoinPath(elem ...string) string { 106 return filepath.Join(append([]string{f.path}, elem...)...) 107 } 108 109 func (f *Fixture) File(name, contents string) { 110 fullPath := name 111 if !filepath.IsAbs(fullPath) { 112 fullPath = filepath.Join(f.path, name) 113 } 114 115 if f.useRealFS { 116 dir := filepath.Dir(fullPath) 117 err := os.MkdirAll(dir, os.FileMode(0755)) 118 assert.NoError(f.tb, err) 119 120 err = os.WriteFile(fullPath, []byte(contents), os.FileMode(0644)) 121 assert.NoError(f.tb, err) 122 return 123 } 124 f.fs[fullPath] = contents 125 } 126 127 func (f *Fixture) Symlink(old, new string) { 128 if !f.useRealFS { 129 panic("Can only use symlinks with a real FS") 130 } 131 err := os.Symlink(f.JoinPath(old), f.JoinPath(new)) 132 assert.NoError(f.tb, err) 133 } 134 135 func (f *Fixture) UseRealFS() { 136 path, err := os.MkdirTemp("", tempdir.SanitizeFileName(f.tb.Name())) 137 require.NoError(f.tb, err) 138 f.path = path 139 f.useRealFS = true 140 f.tf.Spec.Path = path 141 }