github.com/matrixorigin/matrixone@v1.2.0/pkg/txn/client/client_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 client 16 17 import ( 18 "context" 19 "sync" 20 "testing" 21 "time" 22 23 "github.com/lni/goutils/leaktest" 24 "github.com/matrixorigin/matrixone/pkg/common/runtime" 25 "github.com/matrixorigin/matrixone/pkg/logutil" 26 "github.com/matrixorigin/matrixone/pkg/pb/metadata" 27 "github.com/matrixorigin/matrixone/pkg/pb/timestamp" 28 "github.com/matrixorigin/matrixone/pkg/pb/txn" 29 "github.com/matrixorigin/matrixone/pkg/txn/clock" 30 "github.com/matrixorigin/matrixone/pkg/txn/rpc" 31 "github.com/stretchr/testify/assert" 32 "github.com/stretchr/testify/require" 33 ) 34 35 func TestAdjustClient(t *testing.T) { 36 runtime.SetupProcessLevelRuntime(runtime.DefaultRuntime()) 37 c := &txnClient{} 38 c.adjust() 39 assert.NotNil(t, c.generator) 40 assert.NotNil(t, c.generator) 41 } 42 43 func TestNewTxn(t *testing.T) { 44 rt := runtime.NewRuntime(metadata.ServiceType_CN, "", 45 logutil.GetPanicLogger(), 46 runtime.WithClock(clock.NewHLCClock(func() int64 { 47 return 1 48 }, 0))) 49 runtime.SetupProcessLevelRuntime(rt) 50 c := NewTxnClient(newTestTxnSender()) 51 c.Resume() 52 ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond) 53 defer cancel() 54 tx, err := c.New(ctx, newTestTimestamp(0)) 55 assert.Nil(t, err) 56 txnMeta := tx.(*txnOperator).mu.txn 57 assert.Equal(t, timestamp.Timestamp{PhysicalTime: 0}, txnMeta.SnapshotTS) 58 assert.NotEmpty(t, txnMeta.ID) 59 assert.Equal(t, txn.TxnStatus_Active, txnMeta.Status) 60 } 61 62 func TestNewTxnWithNormalStateWait(t *testing.T) { 63 defer leaktest.AfterTest(t)() 64 rt := runtime.NewRuntime(metadata.ServiceType_CN, "", 65 logutil.GetPanicLogger(), 66 runtime.WithClock(clock.NewHLCClock(func() int64 { 67 return 1 68 }, 0))) 69 runtime.SetupProcessLevelRuntime(rt) 70 c := NewTxnClient(newTestTxnSender()) 71 // Do not resume the txn client for now. 72 // c.Resume() 73 var wg sync.WaitGroup 74 for i := 0; i < 20; i++ { 75 wg.Add(1) 76 go func() { 77 defer wg.Done() 78 ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond) 79 defer cancel() 80 tx, err := c.New(ctx, newTestTimestamp(0)) 81 assert.Nil(t, err) 82 txnMeta := tx.(*txnOperator).mu.txn 83 assert.Equal(t, int64(0), txnMeta.SnapshotTS.PhysicalTime) 84 assert.NotEmpty(t, txnMeta.ID) 85 assert.Equal(t, txn.TxnStatus_Active, txnMeta.Status) 86 }() 87 } 88 // Resume it now. 89 c.Resume() 90 wg.Wait() 91 } 92 93 func TestNewTxnWithNormalStateNoWait(t *testing.T) { 94 defer leaktest.AfterTest(t)() 95 rt := runtime.NewRuntime(metadata.ServiceType_CN, "", 96 logutil.GetPanicLogger(), 97 runtime.WithClock(clock.NewHLCClock(func() int64 { 98 return 1 99 }, 0))) 100 runtime.SetupProcessLevelRuntime(rt) 101 c := NewTxnClient(newTestTxnSender(), WithNormalStateNoWait(true)) 102 // Do not resume the txn client. 103 // c.Resume() 104 var wg sync.WaitGroup 105 for i := 0; i < 20; i++ { 106 wg.Add(1) 107 go func() { 108 defer wg.Done() 109 ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond) 110 defer cancel() 111 tx, err := c.New(ctx, newTestTimestamp(0)) 112 assert.Error(t, err) 113 assert.Nil(t, tx) 114 }() 115 } 116 wg.Wait() 117 } 118 119 func TestNewTxnWithSnapshotTS(t *testing.T) { 120 rt := runtime.NewRuntime(metadata.ServiceType_CN, "", 121 logutil.GetPanicLogger(), 122 runtime.WithClock(clock.NewHLCClock(func() int64 { 123 return 1 124 }, 0))) 125 runtime.SetupProcessLevelRuntime(rt) 126 c := NewTxnClient(newTestTxnSender()) 127 c.Resume() 128 ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond) 129 defer cancel() 130 tx, err := c.New(ctx, newTestTimestamp(0), WithSnapshotTS(timestamp.Timestamp{PhysicalTime: 10})) 131 assert.Nil(t, err) 132 txnMeta := tx.(*txnOperator).mu.txn 133 assert.Equal(t, timestamp.Timestamp{PhysicalTime: 10}, txnMeta.SnapshotTS) 134 assert.NotEmpty(t, txnMeta.ID) 135 assert.Equal(t, txn.TxnStatus_Active, txnMeta.Status) 136 } 137 138 func TestTxnClientAbortAllRunningTxn(t *testing.T) { 139 rt := runtime.NewRuntime(metadata.ServiceType_CN, "", 140 logutil.GetPanicLogger(), 141 runtime.WithClock(clock.NewHLCClock(func() int64 { 142 return 1 143 }, 0))) 144 runtime.SetupProcessLevelRuntime(rt) 145 146 c := NewTxnClient(newTestTxnSender()) 147 c.Resume() 148 149 ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond) 150 defer cancel() 151 var ops []TxnOperator 152 for i := 0; i < 10; i++ { 153 op, err := c.New(ctx, newTestTimestamp(0)) 154 assert.Nil(t, err) 155 ops = append(ops, op) 156 } 157 require.Equal(t, 10, len(c.(*txnClient).mu.activeTxns)) 158 159 c.AbortAllRunningTxn() 160 require.Equal(t, 0, len(c.(*txnClient).mu.activeTxns)) 161 for _, op := range ops { 162 assert.Equal(t, txn.TxnStatus_Aborted, op.(*txnOperator).mu.txn.Status) 163 } 164 } 165 166 func TestTxnClientPauseAndResume(t *testing.T) { 167 rt := runtime.NewRuntime(metadata.ServiceType_CN, "", 168 logutil.GetPanicLogger(), 169 runtime.WithClock(clock.NewHLCClock(func() int64 { 170 return 1 171 }, 0))) 172 runtime.SetupProcessLevelRuntime(rt) 173 c := NewTxnClient(newTestTxnSender()) 174 175 c.Pause() 176 require.Equal(t, paused, c.(*txnClient).mu.state) 177 c.Resume() 178 require.Equal(t, normal, c.(*txnClient).mu.state) 179 } 180 181 func TestLimit(t *testing.T) { 182 RunTxnTests( 183 func(tc TxnClient, ts rpc.TxnSender) { 184 ctx := context.Background() 185 186 c := make(chan struct{}) 187 c2 := make(chan struct{}) 188 n := 0 189 go func() { 190 defer close(c2) 191 for { 192 select { 193 case <-c: 194 return 195 default: 196 op, err := tc.New(ctx, newTestTimestamp(0)) 197 require.NoError(t, err) 198 require.NoError(t, op.Rollback(ctx)) 199 n++ 200 } 201 } 202 }() 203 time.Sleep(time.Millisecond * 200) 204 close(c) 205 <-c2 206 require.True(t, n < 5) 207 }, 208 WithTxnLimit(1)) 209 } 210 211 func TestMaxActiveTxnWithWaitPrevClosed(t *testing.T) { 212 RunTxnTests( 213 func(tc TxnClient, ts rpc.TxnSender) { 214 ctx := context.Background() 215 op1, err := tc.New(ctx, newTestTimestamp(0), WithUserTxn()) 216 require.NoError(t, err) 217 218 c := make(chan struct{}) 219 go func() { 220 defer close(c) 221 _, err = tc.New(ctx, newTestTimestamp(0), WithUserTxn()) 222 require.NoError(t, err) 223 }() 224 225 require.NoError(t, op1.Rollback(ctx)) 226 <-c 227 }, 228 WithMaxActiveTxn(1)) 229 } 230 231 func TestMaxActiveTxnWithWaitTimeout(t *testing.T) { 232 RunTxnTests( 233 func(tc TxnClient, ts rpc.TxnSender) { 234 ctx := context.Background() 235 op1, err := tc.New(ctx, newTestTimestamp(0), WithUserTxn()) 236 require.NoError(t, err) 237 defer func() { 238 require.NoError(t, op1.Rollback(ctx)) 239 }() 240 241 ctx2, cancel := context.WithTimeout(context.Background(), time.Second) 242 defer cancel() 243 _, err = tc.New(ctx2, newTestTimestamp(0), WithUserTxn()) 244 require.Error(t, err) 245 }, 246 WithMaxActiveTxn(1)) 247 }