github.com/tilt-dev/tilt@v0.33.15-0.20240515162809-0a22ed45d8a0/internal/controllers/apis/restarton/restarton_test.go (about) 1 package restarton 2 3 import ( 4 "context" 5 "errors" 6 "strings" 7 "testing" 8 "time" 9 10 "github.com/davecgh/go-spew/spew" 11 "github.com/stretchr/testify/assert" 12 "github.com/stretchr/testify/require" 13 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 14 "k8s.io/apimachinery/pkg/runtime/schema" 15 "k8s.io/apimachinery/pkg/types" 16 ctrl "sigs.k8s.io/controller-runtime" 17 "sigs.k8s.io/controller-runtime/pkg/builder" 18 ctrlclient "sigs.k8s.io/controller-runtime/pkg/client" 19 "sigs.k8s.io/controller-runtime/pkg/reconcile" 20 21 "github.com/tilt-dev/tilt/internal/controllers/fake" 22 "github.com/tilt-dev/tilt/internal/controllers/indexer" 23 "github.com/tilt-dev/tilt/pkg/apis/core/v1alpha1" 24 ) 25 26 func TestExtractKeysForIndexer(t *testing.T) { 27 const ns = "fake-ns" 28 29 key := func(name string, kind string) indexer.Key { 30 return indexer.Key{ 31 Name: types.NamespacedName{Namespace: ns, Name: name}, 32 GVK: schema.GroupVersionKind{ 33 Group: "tilt.dev", 34 Version: "v1alpha1", 35 Kind: kind, 36 }, 37 } 38 } 39 40 fwKey := func(name string) indexer.Key { 41 return key(name, "FileWatch") 42 } 43 44 btnKey := func(name string) indexer.Key { 45 return key(name, "UIButton") 46 } 47 48 type tc struct { 49 restartOn *v1alpha1.RestartOnSpec 50 startOn *v1alpha1.StartOnSpec 51 expected []indexer.Key 52 } 53 54 tcs := []tc{ 55 {nil, nil, []indexer.Key(nil)}, 56 { 57 &v1alpha1.RestartOnSpec{FileWatches: []string{"foo"}}, 58 nil, 59 []indexer.Key{fwKey("foo")}, 60 }, 61 { 62 nil, 63 &v1alpha1.StartOnSpec{UIButtons: []string{"btn"}}, 64 []indexer.Key{btnKey("btn")}, 65 }, 66 { 67 &v1alpha1.RestartOnSpec{FileWatches: []string{"foo"}, UIButtons: []string{"bar"}}, 68 &v1alpha1.StartOnSpec{UIButtons: []string{"baz"}}, 69 []indexer.Key{fwKey("foo"), btnKey("bar"), btnKey("baz")}, 70 }, 71 } 72 73 for _, tc := range tcs { 74 keys := extractKeysForIndexer(ns, tc.restartOn, tc.startOn) 75 assert.ElementsMatchf(t, tc.expected, keys, 76 "Indexer keys did not match\nRestartOnSpec: %s\nStartOnSpec: %s", 77 strings.TrimSpace(spew.Sdump(tc.restartOn)), 78 spew.Sdump(tc.startOn)) 79 } 80 } 81 82 func TestFetchObjects(t *testing.T) { 83 f := fake.NewControllerFixtureBuilder(t).Build(noopController{}) 84 85 f.Create(&v1alpha1.FileWatch{ObjectMeta: metav1.ObjectMeta{Name: "fw1"}}) 86 f.Create(&v1alpha1.FileWatch{ObjectMeta: metav1.ObjectMeta{Name: "fw2"}}) 87 f.Create(&v1alpha1.UIButton{ObjectMeta: metav1.ObjectMeta{Name: "btn1"}}) 88 f.Create(&v1alpha1.UIButton{ObjectMeta: metav1.ObjectMeta{Name: "btn2"}}) 89 90 triggerObjs, err := FetchObjects(f.Context(), f.Client, 91 &v1alpha1.RestartOnSpec{ 92 FileWatches: []string{"fw1", "fw2", "fw3"}, 93 UIButtons: []string{"btn1"}, 94 }, 95 &v1alpha1.StartOnSpec{ 96 UIButtons: []string{"btn2", "btn3"}, 97 }) 98 require.NoError(t, err) 99 assert.NotNil(t, triggerObjs.FileWatches["fw1"]) 100 assert.NotNil(t, triggerObjs.FileWatches["fw2"]) 101 // fw3 doesn't exist but should have been silently ignored 102 assert.Nil(t, triggerObjs.FileWatches["fw3"]) 103 104 assert.NotNil(t, triggerObjs.UIButtons["btn1"]) 105 assert.NotNil(t, triggerObjs.UIButtons["btn2"]) 106 // btn3 doesn't exist but should have been silently ignored 107 assert.Nil(t, triggerObjs.UIButtons["btn3"]) 108 } 109 110 func TestFetchObjects_Error(t *testing.T) { 111 cli := &explodingReader{err: errors.New("oh no")} 112 ctx, cancel := context.WithTimeout(context.Background(), time.Second) 113 defer cancel() 114 triggerObjs, err := FetchObjects(ctx, cli, &v1alpha1.RestartOnSpec{FileWatches: []string{"fw"}}, nil) 115 require.Error(t, err, "FetchObjects should have failed with an error") 116 require.Empty(t, triggerObjs.FileWatches) 117 require.Empty(t, triggerObjs.UIButtons) 118 } 119 120 type noopController struct{} 121 122 func (n noopController) CreateBuilder(_ ctrl.Manager) (*builder.Builder, error) { 123 return nil, nil 124 } 125 126 func (n noopController) Reconcile(_ context.Context, _ reconcile.Request) (reconcile.Result, error) { 127 return reconcile.Result{}, nil 128 } 129 130 type explodingReader struct { 131 err error 132 } 133 134 func (e explodingReader) Get(_ context.Context, _ ctrlclient.ObjectKey, _ ctrlclient.Object, _ ...ctrlclient.GetOption) error { 135 return e.err 136 } 137 138 func (e explodingReader) List(_ context.Context, _ ctrlclient.ObjectList, _ ...ctrlclient.ListOption) error { 139 return e.err 140 }