github.com/matrixorigin/matrixone@v1.2.0/pkg/tests/upgrade/upgrade_init_test.go (about) 1 // Copyright 2024 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 upgrade 16 17 import ( 18 "context" 19 "fmt" 20 "sync/atomic" 21 "testing" 22 "time" 23 24 "github.com/matrixorigin/matrixone/pkg/bootstrap" 25 "github.com/matrixorigin/matrixone/pkg/bootstrap/versions" 26 "github.com/matrixorigin/matrixone/pkg/bootstrap/versions/v1_2_0" 27 "github.com/matrixorigin/matrixone/pkg/catalog" 28 "github.com/matrixorigin/matrixone/pkg/cnservice" 29 "github.com/matrixorigin/matrixone/pkg/container/vector" 30 "github.com/matrixorigin/matrixone/pkg/tests/service" 31 "github.com/matrixorigin/matrixone/pkg/util/executor" 32 "github.com/stretchr/testify/require" 33 ) 34 35 func TestUpgradeFrameworkInit(t *testing.T) { 36 if testing.Short() { 37 t.Skip("skipping in short mode.") 38 return 39 } 40 41 runUpgradeTest( 42 t, 43 func(opts service.Options) service.Options { 44 return opts.WithCNOptionFunc(func(i int) []cnservice.Option { 45 return []cnservice.Option{ 46 cnservice.WithBootstrapOptions( 47 bootstrap.WithCheckUpgradeDuration(time.Millisecond*100), 48 bootstrap.WithCheckUpgradeTenantDuration(time.Millisecond*100), 49 bootstrap.WithCheckUpgradeTenantWorkers(1), 50 bootstrap.WithUpgradeTenantBatch(1), 51 bootstrap.WithUpgradeHandles([]bootstrap.VersionHandle{ 52 v1_2_0.Handler, 53 })), 54 } 55 }) 56 }, 57 func(c service.Cluster) { 58 waitVersionReady(t, "1.2.0", c) 59 checkVersionUpgrades(t, "1.2.0", c, func(upgrades []versions.VersionUpgrade) { 60 require.Equal(t, 0, len(upgrades)) 61 }) 62 }) 63 } 64 65 func TestUpgradeFrameworkInitWithHighVersion(t *testing.T) { 66 if testing.Short() { 67 t.Skip("skipping in short mode.") 68 return 69 } 70 71 h := newTestVersionHandler("1.3.0", "1.2.0", versions.Yes, versions.No) 72 73 runUpgradeTest( 74 t, 75 func(opts service.Options) service.Options { 76 return opts.WithCNOptionFunc(func(i int) []cnservice.Option { 77 return []cnservice.Option{ 78 cnservice.WithBootstrapOptions( 79 bootstrap.WithCheckUpgradeDuration(time.Millisecond*100), 80 bootstrap.WithCheckUpgradeTenantDuration(time.Millisecond*100), 81 bootstrap.WithCheckUpgradeTenantWorkers(1), 82 bootstrap.WithUpgradeTenantBatch(1), 83 bootstrap.WithUpgradeHandles([]bootstrap.VersionHandle{ 84 v1_2_0.Handler, 85 h, 86 })), 87 } 88 }) 89 }, 90 func(c service.Cluster) { 91 waitVersionReady(t, "1.3.0", c) 92 checkVersionUpgrades(t, "1.3.0", c, func(upgrades []versions.VersionUpgrade) { 93 require.Equal(t, 0, len(upgrades)) 94 }) 95 }) 96 } 97 98 func checkVersionUpgrades( 99 t *testing.T, 100 version string, 101 c service.Cluster, 102 ck func([]versions.VersionUpgrade)) { 103 svc, err := c.GetCNServiceIndexed(0) 104 require.NoError(t, err) 105 exec := svc.GetSQLExecutor() 106 ctx, cancel := context.WithTimeout(context.Background(), time.Second*60) 107 defer cancel() 108 109 now, _ := c.Clock().Now() 110 opts := executor.Options{}.WithDatabase(catalog.MO_CATALOG).WithMinCommittedTS(now) 111 err = exec.ExecTxn( 112 ctx, 113 func(txn executor.TxnExecutor) error { 114 upgrades, err := versions.GetUpgradeVersions(version, 0, txn, false, false) 115 require.NoError(t, err) 116 ck(upgrades) 117 return err 118 }, 119 opts) 120 require.NoError(t, err) 121 } 122 123 func waitVersionReady( 124 t *testing.T, 125 version string, 126 c service.Cluster) { 127 svc, err := c.GetCNServiceIndexed(0) 128 require.NoError(t, err) 129 exec := svc.GetSQLExecutor() 130 ctx, cancel := context.WithTimeout(context.Background(), time.Second*30) 131 defer cancel() 132 133 for { 134 ready := false 135 opts := executor.Options{}.WithDatabase(catalog.MO_CATALOG) 136 err := exec.ExecTxn( 137 ctx, 138 func(txn executor.TxnExecutor) error { 139 v, _, err := versions.GetVersionState(version, 0, txn, false) 140 if err != nil { 141 return err 142 } 143 ready = v == versions.StateReady 144 return nil 145 }, 146 opts) 147 require.NoError(t, err) 148 if ready { 149 return 150 } 151 time.Sleep(time.Second) 152 } 153 } 154 155 var ( 156 accountIndex atomic.Uint64 157 ) 158 159 func createTenants( 160 t *testing.T, 161 c service.Cluster, 162 n int, 163 version string) []int32 { 164 svc, err := c.GetCNServiceIndexed(0) 165 require.NoError(t, err) 166 exec := svc.GetSQLExecutor() 167 ctx, cancel := context.WithTimeout(context.Background(), time.Second*30) 168 defer cancel() 169 170 var ids []int32 171 opts := executor.Options{}.WithWaitCommittedLogApplied().WithDatabase(catalog.MO_CATALOG) 172 err = exec.ExecTxn( 173 ctx, 174 func(txn executor.TxnExecutor) error { 175 for i := 0; i < n; i++ { 176 sql := fmt.Sprintf(`insert into mo_catalog.mo_account( 177 account_name, 178 status, 179 created_time, 180 comments, 181 create_version) values ('test_%d','open',current_timestamp(),' ','%s');`, 182 accountIndex.Add(1), 183 version) 184 res, err := txn.Exec(sql, executor.StatementOption{}) 185 if err != nil { 186 return err 187 } 188 ids = append(ids, int32(res.LastInsertID)) 189 res.Close() 190 } 191 return nil 192 }, 193 opts) 194 require.NoError(t, err) 195 return ids 196 } 197 198 func checkTenantVersion( 199 t *testing.T, 200 c service.Cluster, 201 version string, 202 ids ...int32) { 203 svc, err := c.GetCNServiceIndexed(0) 204 require.NoError(t, err) 205 exec := svc.GetSQLExecutor() 206 ctx, cancel := context.WithTimeout(context.Background(), time.Second*30) 207 defer cancel() 208 209 opts := executor.Options{}.WithWaitCommittedLogApplied().WithDatabase(catalog.MO_CATALOG) 210 211 sql := "select account_id, create_version from mo_account" 212 if len(ids) > 0 { 213 sql += " where account_id in (" 214 for _, id := range ids { 215 sql += fmt.Sprintf("%d,", id) 216 } 217 sql = sql[:len(sql)-1] + ")" 218 } 219 220 res, err := exec.Exec(ctx, sql, opts) 221 require.NoError(t, err) 222 defer res.Close() 223 224 res.ReadRows(func(rows int, cols []*vector.Vector) bool { 225 for i := 0; i < rows; i++ { 226 require.Equal(t, version, cols[1].GetStringAt(i)) 227 } 228 return true 229 }) 230 } 231 232 func runUpgradeTest( 233 t *testing.T, 234 adjustOptions func(service.Options) service.Options, 235 fn func(c service.Cluster), 236 ) { 237 ctx := context.Background() 238 opts := service.DefaultOptions() 239 if adjustOptions != nil { 240 opts = adjustOptions(opts) 241 } 242 243 c, err := service.NewCluster( 244 ctx, 245 t, 246 opts) 247 require.NoError(t, err) 248 // close the cluster 249 defer func(c service.Cluster) { 250 require.NoError(t, c.Close()) 251 }(c) 252 // start the cluster 253 require.NoError(t, c.Start()) 254 255 fn(c) 256 } 257 258 func newTestVersionHandler( 259 version, minVersion string, 260 upgradeCluster, upgradeTenant int32) *testVersionHandle { 261 return &testVersionHandle{ 262 metadata: versions.Version{ 263 Version: version, 264 MinUpgradeVersion: minVersion, 265 UpgradeCluster: upgradeCluster, 266 UpgradeTenant: upgradeTenant, 267 }, 268 } 269 } 270 271 type testVersionHandle struct { 272 metadata versions.Version 273 callHandleClusterUpgrade atomic.Uint64 274 callHandleTenantUpgrade atomic.Uint64 275 } 276 277 func (h *testVersionHandle) Metadata() versions.Version { 278 return h.metadata 279 } 280 func (h *testVersionHandle) Prepare(ctx context.Context, txn executor.TxnExecutor, final bool) error { 281 return nil 282 } 283 func (h *testVersionHandle) HandleClusterUpgrade(ctx context.Context, txn executor.TxnExecutor) error { 284 h.callHandleClusterUpgrade.Add(1) 285 return nil 286 } 287 func (h *testVersionHandle) HandleTenantUpgrade(ctx context.Context, tenantID int32, txn executor.TxnExecutor) error { 288 h.callHandleTenantUpgrade.Add(1) 289 return nil 290 } 291 292 func (h *testVersionHandle) HandleCreateFrameworkDeps(txn executor.TxnExecutor) error { 293 return nil 294 }