github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/cdc/processor/memquota/mem_quota_test.go (about) 1 // Copyright 2022 PingCAP, Inc. 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 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package memquota 15 16 import ( 17 "context" 18 "sync" 19 "testing" 20 21 "github.com/pingcap/tiflow/cdc/model" 22 "github.com/pingcap/tiflow/pkg/spanz" 23 "github.com/stretchr/testify/require" 24 ) 25 26 func TestMemQuotaTryAcquire(t *testing.T) { 27 t.Parallel() 28 29 m := NewMemQuota(model.DefaultChangeFeedID("1"), 100, "") 30 defer m.Close() 31 32 require.True(t, m.TryAcquire(50)) 33 require.True(t, m.TryAcquire(50)) 34 require.False(t, m.TryAcquire(1)) 35 } 36 37 func TestMemQuotaForceAcquire(t *testing.T) { 38 t.Parallel() 39 40 m := NewMemQuota(model.DefaultChangeFeedID("1"), 100, "") 41 defer m.Close() 42 43 require.True(t, m.TryAcquire(100)) 44 require.False(t, m.TryAcquire(1)) 45 m.ForceAcquire(1) 46 require.Equal(t, uint64(101), m.GetUsedBytes()) 47 } 48 49 func TestMemQuotaBlockAcquire(t *testing.T) { 50 t.Parallel() 51 52 m := NewMemQuota(model.DefaultChangeFeedID("1"), 100, "") 53 defer m.Close() 54 err := m.BlockAcquire(100) 55 require.NoError(t, err) 56 57 span := spanz.TableIDToComparableSpan(1) 58 m.Record(span, model.NewResolvedTs(1), 50) 59 m.Record(span, model.NewResolvedTs(2), 50) 60 61 var wg sync.WaitGroup 62 wg.Add(1) 63 go func() { 64 defer wg.Done() 65 err := m.BlockAcquire(50) 66 require.NoError(t, err) 67 }() 68 wg.Add(1) 69 go func() { 70 defer wg.Done() 71 err := m.BlockAcquire(50) 72 require.NoError(t, err) 73 }() 74 m.Release(span, model.NewResolvedTs(1)) 75 m.Release(span, model.NewResolvedTs(2)) 76 wg.Wait() 77 } 78 79 func TestMemQuotaClose(t *testing.T) { 80 t.Parallel() 81 82 m := NewMemQuota(model.DefaultChangeFeedID("1"), 100, "") 83 84 err := m.BlockAcquire(100) 85 require.NoError(t, err) 86 span := spanz.TableIDToComparableSpan(1) 87 m.Record(span, model.NewResolvedTs(2), 100) 88 89 var wg sync.WaitGroup 90 wg.Add(1) 91 go func() { 92 defer wg.Done() 93 err := m.BlockAcquire(50) 94 if err != nil { 95 require.ErrorIs(t, err, context.Canceled) 96 } 97 }() 98 wg.Add(1) 99 go func() { 100 defer wg.Done() 101 err := m.BlockAcquire(50) 102 if err != nil { 103 require.ErrorIs(t, err, context.Canceled) 104 } 105 }() 106 wg.Add(1) 107 go func() { 108 defer wg.Done() 109 err := m.BlockAcquire(50) 110 if err != nil { 111 require.ErrorIs(t, err, context.Canceled) 112 } 113 }() 114 115 // Randomly release some memory. 116 wg.Add(1) 117 go func() { 118 defer wg.Done() 119 m.Release(span, model.NewResolvedTs(2)) 120 }() 121 m.Close() 122 wg.Wait() 123 } 124 125 func TestMemQuotaRefund(t *testing.T) { 126 t.Parallel() 127 128 m := NewMemQuota(model.DefaultChangeFeedID("1"), 100, "") 129 defer m.Close() 130 131 require.True(t, m.TryAcquire(50)) 132 require.True(t, m.TryAcquire(50)) 133 m.Refund(50) 134 require.True(t, m.TryAcquire(1)) 135 require.True(t, m.TryAcquire(49)) 136 137 // Test notify the blocked acquire. 138 var wg sync.WaitGroup 139 wg.Add(1) 140 go func() { 141 defer wg.Done() 142 err := m.BlockAcquire(50) 143 require.NoError(t, err) 144 }() 145 m.Refund(50) 146 wg.Wait() 147 } 148 149 func TestMemQuotaHasAvailable(t *testing.T) { 150 t.Parallel() 151 152 m := NewMemQuota(model.DefaultChangeFeedID("1"), 100, "") 153 defer m.Close() 154 155 require.True(t, m.hasAvailable(100)) 156 require.True(t, m.TryAcquire(100)) 157 require.False(t, m.hasAvailable(1)) 158 } 159 160 func TestMemQuotaRecordAndRelease(t *testing.T) { 161 t.Parallel() 162 163 m := NewMemQuota(model.DefaultChangeFeedID("1"), 300, "") 164 defer m.Close() 165 span := spanz.TableIDToComparableSpan(1) 166 m.AddTable(span) 167 168 require.True(t, m.TryAcquire(100)) 169 m.Record(span, model.NewResolvedTs(100), 100) 170 require.True(t, m.TryAcquire(100)) 171 m.Record(span, model.NewResolvedTs(200), 100) 172 require.True(t, m.TryAcquire(100)) 173 m.Record(span, model.NewResolvedTs(300), 100) 174 require.False(t, m.TryAcquire(1)) 175 require.False(t, m.hasAvailable(1)) 176 // release the memory of resolvedTs 100 177 m.Release(span, model.NewResolvedTs(101)) 178 require.True(t, m.hasAvailable(100)) 179 // release the memory of resolvedTs 200 180 m.Release(span, model.NewResolvedTs(201)) 181 require.True(t, m.hasAvailable(200)) 182 // release the memory of resolvedTs 300 183 m.Release(span, model.NewResolvedTs(301)) 184 require.True(t, m.hasAvailable(300)) 185 // release the memory of resolvedTs 300 again 186 m.Release(span, model.NewResolvedTs(301)) 187 require.True(t, m.hasAvailable(300)) 188 } 189 190 func TestMemQuotaRecordAndReleaseWithBatchID(t *testing.T) { 191 t.Parallel() 192 193 m := NewMemQuota(model.DefaultChangeFeedID("1"), 300, "") 194 defer m.Close() 195 span := spanz.TableIDToComparableSpan(1) 196 m.AddTable(span) 197 198 require.True(t, m.TryAcquire(100)) 199 resolvedTs := model.ResolvedTs{ 200 Mode: model.BatchResolvedMode, 201 Ts: 100, 202 BatchID: 1, 203 } 204 m.Record(span, resolvedTs, 100) 205 resolvedTs = model.ResolvedTs{ 206 Mode: model.BatchResolvedMode, 207 Ts: 100, 208 BatchID: 2, 209 } 210 require.True(t, m.TryAcquire(100)) 211 m.Record(span, resolvedTs, 100) 212 resolvedTs = model.ResolvedTs{ 213 Mode: model.BatchResolvedMode, 214 Ts: 100, 215 BatchID: 3, 216 } 217 require.True(t, m.TryAcquire(100)) 218 m.Record(span, resolvedTs, 100) 219 require.False(t, m.TryAcquire(1)) 220 require.False(t, m.hasAvailable(1)) 221 222 // release the memory of resolvedTs 100 batchID 2 223 resolvedTs = model.ResolvedTs{ 224 Mode: model.BatchResolvedMode, 225 Ts: 100, 226 BatchID: 2, 227 } 228 m.Release(span, resolvedTs) 229 require.True(t, m.hasAvailable(200)) 230 // release the memory of resolvedTs 101 231 m.Release(span, model.NewResolvedTs(101)) 232 require.True(t, m.hasAvailable(300)) 233 } 234 235 func TestMemQuotaRecordAndClean(t *testing.T) { 236 t.Parallel() 237 238 m := NewMemQuota(model.DefaultChangeFeedID("1"), 300, "") 239 defer m.Close() 240 span := spanz.TableIDToComparableSpan(1) 241 m.AddTable(span) 242 243 require.True(t, m.TryAcquire(100)) 244 m.Record(span, model.NewResolvedTs(100), 100) 245 require.True(t, m.TryAcquire(100)) 246 m.Record(span, model.NewResolvedTs(200), 100) 247 require.True(t, m.TryAcquire(100)) 248 m.Record(span, model.NewResolvedTs(300), 100) 249 require.False(t, m.TryAcquire(1)) 250 require.False(t, m.hasAvailable(1)) 251 252 // clean the all memory. 253 cleanedBytes := m.ClearTable(span) 254 require.Equal(t, uint64(300), cleanedBytes) 255 require.True(t, m.hasAvailable(100)) 256 257 cleanedBytes = m.RemoveTable(span) 258 require.Equal(t, uint64(0), cleanedBytes) 259 }