github.com/matrixorigin/matrixone@v0.7.0/pkg/taskservice/task_storage_test.go (about) 1 // Copyright 2022 Matrix Origin 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package taskservice 16 17 import ( 18 "context" 19 "testing" 20 "time" 21 22 "github.com/matrixorigin/matrixone/pkg/common/runtime" 23 "github.com/matrixorigin/matrixone/pkg/pb/task" 24 "github.com/stretchr/testify/assert" 25 "github.com/stretchr/testify/require" 26 ) 27 28 var ( 29 storages = map[string]func(*testing.T) TaskStorage{ 30 "mem": createMem, 31 "refresh": createRefresh, 32 } 33 ) 34 35 func createMem(t *testing.T) TaskStorage { 36 return NewMemTaskStorage() 37 } 38 39 func createRefresh(t *testing.T) TaskStorage { 40 return newRefreshableTaskStorage( 41 runtime.DefaultRuntime(), 42 func(context.Context) (string, error) { return "", nil }, 43 NewFixedTaskStorageFactory(NewMemTaskStorage())) 44 } 45 46 // TODO: move to cluster testing. 47 // func createMysql(t *testing.T) TaskStorage { 48 // storage, err := NewMysqlTaskStorage("root:root@tcp(127.0.0.1:12345)/", "mo_task") 49 // require.NoError(t, err) 50 // return storage 51 // } 52 53 func TestAddTask(t *testing.T) { 54 for name, factory := range storages { 55 t.Run(name, func(t *testing.T) { 56 s := factory(t) 57 defer func() { 58 assert.NoError(t, s.Close()) 59 }() 60 61 v := newTestTask("t1") 62 mustAddTestTask(t, s, 1, v) 63 mustAddTestTask(t, s, 0, v) 64 assert.Equal(t, 1, len(mustGetTestTask(t, s, 1))) 65 }) 66 } 67 } 68 69 func TestUpdateTask(t *testing.T) { 70 for name, factory := range storages { 71 t.Run(name, func(t *testing.T) { 72 s := factory(t) 73 defer func() { 74 assert.NoError(t, s.Close()) 75 }() 76 77 v := newTestTask("t1") 78 mustAddTestTask(t, s, 1, v) 79 80 tasks := mustGetTestTask(t, s, 1) 81 tasks[0].Metadata.Executor = 1 82 mustUpdateTestTask(t, s, 1, tasks) 83 }) 84 } 85 } 86 87 func TestUpdateTaskWithConditions(t *testing.T) { 88 for name, factory := range storages { 89 t.Run(name, func(t *testing.T) { 90 s := factory(t) 91 defer func() { 92 assert.NoError(t, s.Close()) 93 }() 94 95 mustAddTestTask(t, s, 1, newTestTask("t1")) 96 tasks := mustGetTestTask(t, s, 1) 97 98 mustUpdateTestTask(t, s, 0, tasks, WithTaskRunnerCond(EQ, "t2")) 99 mustUpdateTestTask(t, s, 1, tasks, WithTaskRunnerCond(EQ, "t1")) 100 101 tasks[0].Metadata.Context = []byte{1} 102 mustUpdateTestTask(t, s, 0, tasks, WithTaskIDCond(EQ, tasks[0].ID+1)) 103 mustUpdateTestTask(t, s, 1, tasks, WithTaskIDCond(EQ, tasks[0].ID)) 104 tasks[0].Metadata.Context = []byte{1, 2} 105 mustUpdateTestTask(t, s, 1, tasks, WithTaskIDCond(GT, 0)) 106 }) 107 } 108 } 109 110 func TestDeleteTaskWithConditions(t *testing.T) { 111 for name, factory := range storages { 112 t.Run(name, func(t *testing.T) { 113 s := factory(t) 114 defer func() { 115 assert.NoError(t, s.Close()) 116 }() 117 118 mustAddTestTask(t, s, 1, newTestTask("t1")) 119 mustAddTestTask(t, s, 1, newTestTask("t2")) 120 mustAddTestTask(t, s, 1, newTestTask("t3")) 121 tasks := mustGetTestTask(t, s, 3) 122 123 mustDeleteTestTask(t, s, 0, WithTaskRunnerCond(EQ, "t4")) 124 mustDeleteTestTask(t, s, 1, WithTaskRunnerCond(EQ, "t1")) 125 126 mustDeleteTestTask(t, s, 0, WithTaskIDCond(EQ, tasks[len(tasks)-1].ID+1)) 127 mustDeleteTestTask(t, s, 2, WithTaskIDCond(GT, tasks[0].ID)) 128 129 mustGetTestTask(t, s, 0) 130 }) 131 } 132 } 133 134 func TestQueryTaskWithConditions(t *testing.T) { 135 for name, factory := range storages { 136 t.Run(name, func(t *testing.T) { 137 s := factory(t) 138 defer func() { 139 assert.NoError(t, s.Close()) 140 }() 141 142 mustAddTestTask(t, s, 1, newTestTask("t1")) 143 mustAddTestTask(t, s, 1, newTestTask("t2")) 144 mustAddTestTask(t, s, 1, newTestTask("t3")) 145 tasks := mustGetTestTask(t, s, 3) 146 147 mustGetTestTask(t, s, 1, WithLimitCond(1)) 148 mustGetTestTask(t, s, 1, WithTaskRunnerCond(EQ, "t1")) 149 mustGetTestTask(t, s, 2, WithTaskIDCond(GT, tasks[0].ID)) 150 mustGetTestTask(t, s, 3, WithTaskIDCond(GE, tasks[0].ID)) 151 mustGetTestTask(t, s, 3, WithTaskIDCond(LE, tasks[2].ID)) 152 mustGetTestTask(t, s, 2, WithTaskIDCond(LT, tasks[2].ID)) 153 mustGetTestTask(t, s, 1, WithLimitCond(1), WithTaskIDCond(GT, tasks[0].ID)) 154 mustGetTestTask(t, s, 1, WithTaskIDCond(EQ, tasks[0].ID)) 155 }) 156 } 157 } 158 159 func TestAddAndQueryCronTask(t *testing.T) { 160 for name, factory := range storages { 161 t.Run(name, func(t *testing.T) { 162 s := factory(t) 163 defer func() { 164 assert.NoError(t, s.Close()) 165 }() 166 167 mustQueryTestCronTask(t, s, 0) 168 169 v1 := newTestCronTask("t1", "cron1") 170 v2 := newTestCronTask("t2", "cron2") 171 mustAddTestCronTask(t, s, 2, v1, v2) 172 mustQueryTestCronTask(t, s, 2) 173 174 mustAddTestCronTask(t, s, 0, v1, v2) 175 mustQueryTestCronTask(t, s, 2) 176 }) 177 } 178 } 179 180 func TestUpdateCronTask(t *testing.T) { 181 for name, factory := range storages { 182 t.Run(name, func(t *testing.T) { 183 s := factory(t) 184 defer func() { 185 assert.NoError(t, s.Close()) 186 }() 187 188 v1 := newTestCronTask("t1", "cron1") 189 v2 := newTestTask("t1-cron-1") 190 v3 := newTestTask("t1-cron-2") 191 192 ctx, cancel := context.WithTimeout(context.TODO(), time.Second*10) 193 defer cancel() 194 195 n, err := s.UpdateCronTask(ctx, v1, v2) 196 assert.NoError(t, err) 197 assert.Equal(t, 0, n) 198 199 mustAddTestCronTask(t, s, 1, v1) 200 mustAddTestTask(t, s, 1, v2) 201 202 v1 = mustQueryTestCronTask(t, s, 1)[0] 203 204 n, err = s.UpdateCronTask(ctx, v1, v2) 205 assert.NoError(t, err) 206 assert.Equal(t, 0, n) 207 208 n, err = s.UpdateCronTask(ctx, v1, v3) 209 assert.NoError(t, err) 210 assert.Equal(t, 0, n) 211 212 v1.TriggerTimes++ 213 n, err = s.UpdateCronTask(ctx, v1, v3) 214 assert.NoError(t, err) 215 assert.Equal(t, 2, n) 216 }) 217 } 218 } 219 220 func mustGetTestTask(t *testing.T, s TaskStorage, expectCount int, conds ...Condition) []task.Task { 221 ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) 222 defer cancel() 223 tasks, err := s.Query(ctx, conds...) 224 require.NoError(t, err) 225 require.Equal(t, expectCount, len(tasks)) 226 return tasks 227 } 228 229 func mustAddTestTask(t *testing.T, s TaskStorage, expectAdded int, tasks ...task.Task) { 230 ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) 231 defer cancel() 232 233 n, err := s.Add(ctx, tasks...) 234 require.NoError(t, err) 235 require.Equal(t, expectAdded, n) 236 } 237 238 func mustUpdateTestTask(t *testing.T, s TaskStorage, expectUpdated int, tasks []task.Task, conds ...Condition) { 239 ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) 240 defer cancel() 241 242 n, err := s.Update(ctx, tasks, conds...) 243 require.NoError(t, err) 244 require.Equal(t, expectUpdated, n) 245 } 246 247 func mustDeleteTestTask(t *testing.T, s TaskStorage, expectUpdated int, conds ...Condition) { 248 ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) 249 defer cancel() 250 251 n, err := s.Delete(ctx, conds...) 252 require.NoError(t, err) 253 require.Equal(t, expectUpdated, n) 254 } 255 256 func mustAddTestCronTask(t *testing.T, s TaskStorage, expectAdded int, tasks ...task.CronTask) { 257 ctx, cancel := context.WithTimeout(context.Background(), time.Second*1000) 258 defer cancel() 259 260 n, err := s.AddCronTask(ctx, tasks...) 261 require.NoError(t, err) 262 require.Equal(t, expectAdded, n) 263 } 264 265 func mustQueryTestCronTask(t *testing.T, s TaskStorage, expectQueryCount int) []task.CronTask { 266 ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) 267 defer cancel() 268 269 tasks, err := s.QueryCronTask(ctx) 270 require.NoError(t, err) 271 require.Equal(t, expectQueryCount, len(tasks)) 272 return tasks 273 } 274 275 func newTestTask(id string) task.Task { 276 v := task.Task{} 277 v.Metadata.ID = id 278 v.TaskRunner = id 279 return v 280 } 281 282 func newTestCronTask(id, cron string) task.CronTask { 283 v := task.CronTask{} 284 v.Metadata.ID = id 285 v.CronExpr = cron 286 return v 287 }