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  }