github.com/tilt-dev/tilt@v0.33.15-0.20240515162809-0a22ed45d8a0/internal/store/store_test.go (about) 1 package store 2 3 import ( 4 "context" 5 "testing" 6 7 "github.com/tilt-dev/tilt/pkg/logger" 8 9 "github.com/stretchr/testify/assert" 10 ) 11 12 func TestProcessActions(t *testing.T) { 13 f := newFixture(t) 14 f.Start() 15 16 f.store.Dispatch(CompletedBuildAction{}) 17 f.store.Dispatch(CompletedBuildAction{}) 18 f.store.Dispatch(DoneAction{}) 19 20 f.WaitUntilDone() 21 22 assert.Equal(t, 2, f.store.state.CompletedBuildCount) 23 } 24 25 func TestBroadcastActions(t *testing.T) { 26 f := newFixture(t) 27 28 s := newFakeSubscriber() 29 _ = f.store.AddSubscriber(f.ctx, s) 30 31 f.Start() 32 33 f.store.Dispatch(CompletedBuildAction{}) 34 35 s.assertOnChangeCount(t, 1) 36 37 f.store.Dispatch(DoneAction{}) 38 f.WaitUntilDone() 39 } 40 41 func TestLogOnly(t *testing.T) { 42 f := newFixture(t) 43 44 s := newFakeSubscriber() 45 _ = f.store.AddSubscriber(f.ctx, s) 46 47 f.Start() 48 49 f.store.Dispatch(CompletedBuildAction{}) 50 call := <-s.onChange 51 assert.False(t, call.summary.IsLogOnly()) 52 assert.True(t, call.summary.Legacy) 53 close(call.done) 54 55 f.store.Dispatch(LogAction{}) 56 call = <-s.onChange 57 assert.True(t, call.summary.IsLogOnly()) 58 close(call.done) 59 60 f.store.Dispatch(DoneAction{}) 61 f.WaitUntilDone() 62 } 63 64 func TestBroadcastActionsBatching(t *testing.T) { 65 f := newFixture(t) 66 67 s := newFakeSubscriber() 68 _ = f.store.AddSubscriber(f.ctx, s) 69 70 f.Start() 71 72 f.store.mu.Lock() 73 f.store.Dispatch(CompletedBuildAction{}) 74 f.store.Dispatch(CompletedBuildAction{}) 75 f.store.mu.Unlock() 76 77 s.assertOnChangeCount(t, 1) 78 79 f.store.Dispatch(DoneAction{}) 80 f.WaitUntilDone() 81 } 82 83 // if the logstore checkpoint changes, the summary should say there's a log change 84 // even if the action summarizer doesn't 85 func TestInferredSummaryLog(t *testing.T) { 86 f := newFixture(t) 87 88 s := newFakeSubscriber() 89 _ = f.store.AddSubscriber(f.ctx, s) 90 91 f.Start() 92 93 f.store.Dispatch(CompletedBuildAction{}) 94 call := <-s.onChange 95 assert.False(t, call.summary.IsLogOnly()) 96 assert.True(t, call.summary.Legacy) 97 close(call.done) 98 99 f.store.Dispatch(SneakyLoggingAction{}) 100 call = <-s.onChange 101 assert.True(t, call.summary.Log) 102 assert.True(t, call.summary.Legacy) 103 close(call.done) 104 105 f.store.Dispatch(DoneAction{}) 106 f.WaitUntilDone() 107 } 108 109 type fixture struct { 110 t *testing.T 111 store *Store 112 ctx context.Context 113 cancel func() 114 done chan error 115 } 116 117 func newFixture(t *testing.T) fixture { 118 ctx, cancel := context.WithCancel(context.Background()) 119 st := NewStore(TestReducer, LogActionsFlag(false)) 120 return fixture{ 121 t: t, 122 store: st, 123 ctx: ctx, 124 cancel: cancel, 125 done: make(chan error), 126 } 127 } 128 129 func (f fixture) Start() { 130 go func() { 131 err := f.store.Loop(f.ctx) 132 f.done <- err 133 }() 134 } 135 136 func (f fixture) WaitUntilDone() { 137 err := <-f.done 138 if err != nil && err != context.Canceled { 139 f.t.Fatalf("Loop failed unexpectedly: %v", err) 140 } 141 } 142 143 func (f fixture) TearDown() { 144 f.cancel() 145 f.WaitUntilDone() 146 } 147 148 type CompletedBuildAction struct { 149 } 150 151 func (CompletedBuildAction) Action() {} 152 153 // An action that writes to the log but doesn't report it via 154 // Summarize (or even implement Summarizer!) 155 type SneakyLoggingAction struct { 156 } 157 158 func (SneakyLoggingAction) Action() {} 159 160 type DoneAction struct { 161 } 162 163 func (DoneAction) Action() {} 164 165 var TestReducer = Reducer(func(ctx context.Context, s *EngineState, action Action) { 166 switch action.(type) { 167 case CompletedBuildAction: 168 s.CompletedBuildCount++ 169 case SneakyLoggingAction: 170 s.LogStore.Append(NewLogAction("foo", "foo", logger.ErrorLvl, nil, []byte("hi")), s.Secrets) 171 case DoneAction: 172 s.FatalError = context.Canceled 173 } 174 })