github.com/weaviate/weaviate@v1.24.6/entities/cyclemanager/cyclecallbackctrl_test.go (about) 1 // _ _ 2 // __ _____ __ ___ ___ __ _| |_ ___ 3 // \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \ 4 // \ V V / __/ (_| |\ V /| | (_| | || __/ 5 // \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___| 6 // 7 // Copyright © 2016 - 2024 Weaviate B.V. All rights reserved. 8 // 9 // CONTACT: hello@weaviate.io 10 // 11 12 package cyclemanager 13 14 import ( 15 "context" 16 "testing" 17 "time" 18 19 "github.com/sirupsen/logrus/hooks/test" 20 "github.com/stretchr/testify/assert" 21 "github.com/stretchr/testify/require" 22 ) 23 24 func TestCycleCombineCallbackCtrl_Unregister(t *testing.T) { 25 logger, _ := test.NewNullLogger() 26 ctx := context.Background() 27 28 t.Run("unregisters both", func(t *testing.T) { 29 callback1 := func(shouldAbort ShouldAbortCallback) bool { 30 time.Sleep(100 * time.Millisecond) 31 return true 32 } 33 callback2 := func(shouldAbort ShouldAbortCallback) bool { 34 time.Sleep(100 * time.Millisecond) 35 return true 36 } 37 38 callbacks := NewCallbackGroup("id", logger, 2) 39 ctrl1 := callbacks.Register("c1", callback1) 40 ctrl2 := callbacks.Register("c2", callback2) 41 combinedCtrl := NewCombinedCallbackCtrl(2, logger, ctrl1, ctrl2) 42 43 cycle := NewManager(NewFixedTicker(100*time.Millisecond), callbacks.CycleCallback, logger) 44 cycle.Start() 45 defer cycle.StopAndWait(ctx) 46 47 err := combinedCtrl.Unregister(ctx) 48 require.Nil(t, err) 49 50 assert.False(t, combinedCtrl.IsActive()) 51 assert.False(t, ctrl1.IsActive()) 52 assert.False(t, ctrl2.IsActive()) 53 }) 54 55 t.Run("does not unregister on expired context", func(t *testing.T) { 56 expiredCtx, cancel := context.WithDeadline(ctx, time.Now()) 57 defer cancel() 58 59 callback1 := func(shouldAbort ShouldAbortCallback) bool { 60 time.Sleep(100 * time.Millisecond) 61 return true 62 } 63 callback2 := func(shouldAbort ShouldAbortCallback) bool { 64 time.Sleep(100 * time.Millisecond) 65 return true 66 } 67 68 callbacks := NewCallbackGroup("id", logger, 2) 69 ctrl1 := callbacks.Register("c1", callback1) 70 ctrl2 := callbacks.Register("c2", callback2) 71 combinedCtrl := NewCombinedCallbackCtrl(2, logger, ctrl1, ctrl2) 72 73 cycle := NewManager(NewFixedTicker(100*time.Millisecond), callbacks.CycleCallback, logger) 74 cycle.Start() 75 defer cycle.StopAndWait(ctx) 76 77 err := combinedCtrl.Unregister(expiredCtx) 78 require.NotNil(t, err) 79 assert.Contains(t, err.Error(), "unregistering callback 'c1' of 'id' failed: context deadline exceeded") 80 assert.Contains(t, err.Error(), "unregistering callback 'c2' of 'id' failed: context deadline exceeded") 81 82 assert.True(t, combinedCtrl.IsActive()) 83 assert.True(t, ctrl1.IsActive()) 84 assert.True(t, ctrl2.IsActive()) 85 }) 86 87 t.Run("fails unregistering one", func(t *testing.T) { 88 callbackShort := func(shouldAbort ShouldAbortCallback) bool { 89 time.Sleep(100 * time.Millisecond) 90 return true 91 } 92 callbackLong := func(shouldAbort ShouldAbortCallback) bool { 93 time.Sleep(500 * time.Millisecond) 94 return true 95 } 96 97 callbacks := NewCallbackGroup("id", logger, 2) 98 ctrlShort := callbacks.Register("short", callbackShort) 99 ctrlLong := callbacks.Register("long", callbackLong) 100 combinedCtrl := NewCombinedCallbackCtrl(2, logger, ctrlShort, ctrlLong) 101 102 cycle := NewManager(NewFixedTicker(100*time.Millisecond), callbacks.CycleCallback, logger) 103 cycle.Start() 104 defer cycle.StopAndWait(ctx) 105 106 // wait long enough to call Unregister while 2nd callback is still processed. 107 // set timeout short enough to expire before 2nd callback finishes 108 time.Sleep(300 * time.Millisecond) 109 expirableCtx, cancel := context.WithTimeout(ctx, 100*time.Millisecond) 110 defer cancel() 111 112 err := combinedCtrl.Unregister(expirableCtx) 113 require.NotNil(t, err) 114 assert.EqualError(t, err, "unregistering callback 'long' of 'id' failed: context deadline exceeded") 115 116 assert.False(t, combinedCtrl.IsActive()) 117 assert.False(t, ctrlShort.IsActive()) 118 assert.True(t, ctrlLong.IsActive()) 119 }) 120 } 121 122 func TestCycleCombineCallbackCtrl_Deactivate(t *testing.T) { 123 logger, _ := test.NewNullLogger() 124 ctx := context.Background() 125 126 t.Run("deactivates both", func(t *testing.T) { 127 callback1 := func(shouldAbort ShouldAbortCallback) bool { 128 time.Sleep(100 * time.Millisecond) 129 return true 130 } 131 callback2 := func(shouldAbort ShouldAbortCallback) bool { 132 time.Sleep(100 * time.Millisecond) 133 return true 134 } 135 136 callbacks := NewCallbackGroup("id", logger, 2) 137 ctrl1 := callbacks.Register("c1", callback1) 138 ctrl2 := callbacks.Register("c2", callback2) 139 combinedCtrl := NewCombinedCallbackCtrl(2, logger, ctrl1, ctrl2) 140 141 cycle := NewManager(NewFixedTicker(100*time.Millisecond), callbacks.CycleCallback, logger) 142 cycle.Start() 143 defer cycle.StopAndWait(ctx) 144 145 err := combinedCtrl.Deactivate(ctx) 146 require.Nil(t, err) 147 148 assert.False(t, combinedCtrl.IsActive()) 149 assert.False(t, ctrl1.IsActive()) 150 assert.False(t, ctrl2.IsActive()) 151 }) 152 153 t.Run("does not deactivate on expired context", func(t *testing.T) { 154 expiredCtx, cancel := context.WithDeadline(ctx, time.Now()) 155 defer cancel() 156 157 callback1 := func(shouldAbort ShouldAbortCallback) bool { 158 time.Sleep(100 * time.Millisecond) 159 return true 160 } 161 callback2 := func(shouldAbort ShouldAbortCallback) bool { 162 time.Sleep(100 * time.Millisecond) 163 return true 164 } 165 166 callbacks := NewCallbackGroup("id", logger, 2) 167 ctrl1 := callbacks.Register("c1", callback1) 168 ctrl2 := callbacks.Register("c2", callback2) 169 combinedCtrl := NewCombinedCallbackCtrl(2, logger, ctrl1, ctrl2) 170 171 cycle := NewManager(NewFixedTicker(100*time.Millisecond), callbacks.CycleCallback, logger) 172 cycle.Start() 173 defer cycle.StopAndWait(ctx) 174 175 err := combinedCtrl.Deactivate(expiredCtx) 176 require.NotNil(t, err) 177 assert.Contains(t, err.Error(), "deactivating callback 'c1' of 'id' failed: context deadline exceeded") 178 assert.Contains(t, err.Error(), "deactivating callback 'c1' of 'id' failed: context deadline exceeded") 179 180 assert.True(t, combinedCtrl.IsActive()) 181 assert.True(t, ctrl1.IsActive()) 182 assert.True(t, ctrl2.IsActive()) 183 }) 184 185 t.Run("fails deactivating one, activates other again", func(t *testing.T) { 186 callbackShort := func(shouldAbort ShouldAbortCallback) bool { 187 time.Sleep(100 * time.Millisecond) 188 return true 189 } 190 callbackLong := func(shouldAbort ShouldAbortCallback) bool { 191 time.Sleep(500 * time.Millisecond) 192 return true 193 } 194 195 callbacks := NewCallbackGroup("id", logger, 2) 196 ctrlShort := callbacks.Register("short", callbackShort) 197 ctrlLong := callbacks.Register("long", callbackLong) 198 combinedCtrl := NewCombinedCallbackCtrl(2, logger, ctrlShort, ctrlLong) 199 200 cycle := NewManager(NewFixedTicker(100*time.Millisecond), callbacks.CycleCallback, logger) 201 cycle.Start() 202 defer cycle.StopAndWait(ctx) 203 204 // wait long enough to call Deactivate while 2nd callback is still processed. 205 // set timeout short enough to expire before 2nd callback finishes 206 time.Sleep(300 * time.Millisecond) 207 expirableCtx, cancel := context.WithTimeout(ctx, 100*time.Millisecond) 208 defer cancel() 209 210 err := combinedCtrl.Deactivate(expirableCtx) 211 require.NotNil(t, err) 212 assert.EqualError(t, err, "deactivating callback 'long' of 'id' failed: context deadline exceeded") 213 214 assert.True(t, combinedCtrl.IsActive()) 215 assert.True(t, ctrlShort.IsActive()) 216 assert.True(t, ctrlLong.IsActive()) 217 }) 218 } 219 220 func TestCycleCombineCallbackCtrl_Activate(t *testing.T) { 221 logger, _ := test.NewNullLogger() 222 ctx := context.Background() 223 224 t.Run("activates both", func(t *testing.T) { 225 callback1 := func(shouldAbort ShouldAbortCallback) bool { 226 time.Sleep(100 * time.Millisecond) 227 return true 228 } 229 callback2 := func(shouldAbort ShouldAbortCallback) bool { 230 time.Sleep(100 * time.Millisecond) 231 return true 232 } 233 234 callbacks := NewCallbackGroup("id", logger, 2) 235 ctrl1 := callbacks.Register("c1", callback1, AsInactive()) 236 ctrl2 := callbacks.Register("c2", callback2, AsInactive()) 237 combinedCtrl := NewCombinedCallbackCtrl(2, logger, ctrl1, ctrl2) 238 239 cycle := NewManager(NewFixedTicker(100*time.Millisecond), callbacks.CycleCallback, logger) 240 cycle.Start() 241 defer cycle.StopAndWait(ctx) 242 243 assert.False(t, combinedCtrl.IsActive()) 244 assert.False(t, ctrl1.IsActive()) 245 assert.False(t, ctrl2.IsActive()) 246 247 err := combinedCtrl.Activate() 248 require.Nil(t, err) 249 250 assert.True(t, combinedCtrl.IsActive()) 251 assert.True(t, ctrl1.IsActive()) 252 assert.True(t, ctrl2.IsActive()) 253 }) 254 }