github.com/matrixorigin/matrixone@v0.7.0/pkg/lockservice/slice_test.go (about) 1 // Copyright 2023 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 lockservice 16 17 import ( 18 "testing" 19 20 "github.com/stretchr/testify/assert" 21 ) 22 23 func TestNewFixedSlicePool(t *testing.T) { 24 assert.Equal(t, 1, len(newFixedSlicePool(1).slices)) 25 assert.Equal(t, 2, len(newFixedSlicePool(2).slices)) 26 assert.Equal(t, 3, len(newFixedSlicePool(3).slices)) 27 assert.Equal(t, 3, len(newFixedSlicePool(4).slices)) 28 assert.Equal(t, 4, len(newFixedSlicePool(5).slices)) 29 assert.Equal(t, 4, len(newFixedSlicePool(6).slices)) 30 assert.Equal(t, 4, len(newFixedSlicePool(7).slices)) 31 assert.Equal(t, 4, len(newFixedSlicePool(8).slices)) 32 } 33 34 func TestAcquire(t *testing.T) { 35 fsp := newFixedSlicePool(16) 36 fs := fsp.acquire(1) 37 assert.Equal(t, 1, fs.cap()) 38 fs.close() 39 40 fs = fsp.acquire(3) 41 assert.Equal(t, 4, fs.cap()) 42 fs.close() 43 44 fs = fsp.acquire(5) 45 assert.Equal(t, 8, fs.cap()) 46 fs.close() 47 48 defer func() { 49 if err := recover(); err != nil { 50 return 51 } 52 assert.Fail(t, "must panic") 53 }() 54 fsp.acquire(1024) 55 } 56 57 func TestRelease(t *testing.T) { 58 fsp := newFixedSlicePool(16) 59 fs := fsp.acquire(1) 60 fsp.release(fs) 61 assert.Equal(t, uint64(1), fsp.releaseV.Load()) 62 63 defer func() { 64 if err := recover(); err != nil { 65 return 66 } 67 assert.Fail(t, "must panic") 68 }() 69 fs = fsp.acquire(1) 70 fs.values = make([][]byte, 1024) 71 fsp.release(fs) 72 } 73 74 func TestFixedSliceAppend(t *testing.T) { 75 fsp := newFixedSlicePool(16) 76 fs := fsp.acquire(4) 77 defer fs.close() 78 79 for i := byte(0); i < 4; i++ { 80 fs.append([][]byte{{i}}) 81 assert.Equal(t, int(i+1), fs.len()) 82 } 83 } 84 85 func TestFixedSliceJoin(t *testing.T) { 86 fsp := newFixedSlicePool(16) 87 fs1 := fsp.acquire(4) 88 defer fs1.close() 89 90 fs2 := fsp.acquire(1) 91 defer fs2.close() 92 fs2.append([][]byte{{1}}) 93 94 fs1.join(fs2, [][]byte{{2}}) 95 assert.Equal(t, 2, fs1.len()) 96 assert.Equal(t, [][]byte{{1}, {2}}, fs1.values[:fs1.len()]) 97 } 98 99 func TestFxiedSliceRefAndUnRef(t *testing.T) { 100 fsp := newFixedSlicePool(16) 101 fs := fsp.acquire(1) 102 assert.Equal(t, int32(1), fs.atomic.ref.Load()) 103 fs.ref() 104 assert.Equal(t, int32(2), fs.atomic.ref.Load()) 105 fs.append([][]byte{{1}}) 106 107 fs.unref() 108 assert.Equal(t, int32(1), fs.atomic.ref.Load()) 109 assert.Equal(t, 1, fs.len()) 110 111 fs.unref() 112 assert.Equal(t, int32(0), fs.atomic.ref.Load()) 113 assert.Equal(t, 0, fs.len()) 114 115 defer func() { 116 if err := recover(); err != nil { 117 return 118 } 119 assert.Fail(t, "must panic") 120 }() 121 fs.unref() 122 } 123 124 func TestFxiedSliceIter(t *testing.T) { 125 fsp := newFixedSlicePool(16) 126 fs := fsp.acquire(4) 127 defer fs.close() 128 129 for i := byte(0); i < 4; i++ { 130 fs.append([][]byte{{i}}) 131 } 132 133 var values [][]byte 134 fs.iter(func(b []byte) bool { 135 values = append(values, b) 136 return true 137 }) 138 assert.Equal(t, fs.values[:fs.len()], values) 139 140 values = values[:0] 141 fs.iter(func(b []byte) bool { 142 values = append(values, b) 143 return false 144 }) 145 assert.Equal(t, fs.values[:1], values) 146 } 147 148 func TestCowSliceAppend(t *testing.T) { 149 fsp := newFixedSlicePool(16) 150 cs := newCowSlice(fsp, [][]byte{{1}, {2}, {3}}) 151 assert.Equal(t, 4, cs.fs.Load().(*fixedSlice).cap()) 152 assert.Equal(t, uint64(1), fsp.acquireV.Load()) 153 154 cs.append([][]byte{{4}}) 155 assert.Equal(t, 4, cs.fs.Load().(*fixedSlice).cap()) 156 assert.Equal(t, uint64(1), fsp.acquireV.Load()) 157 158 assert.Equal(t, [][]byte{{1}, {2}, {3}, {4}}, 159 cs.fs.Load().(*fixedSlice).values[:cs.fs.Load().(*fixedSlice).len()]) 160 } 161 162 func TestCowSliceAppendWithCow(t *testing.T) { 163 fsp := newFixedSlicePool(16) 164 cs := newCowSlice(fsp, [][]byte{{1}}) 165 assert.Equal(t, 1, cs.fs.Load().(*fixedSlice).cap()) 166 assert.Equal(t, uint64(1), fsp.acquireV.Load()) 167 168 cs.append([][]byte{{2}}) 169 assert.Equal(t, 2, cs.fs.Load().(*fixedSlice).cap()) 170 assert.Equal(t, uint64(2), fsp.acquireV.Load()) 171 172 assert.Equal(t, [][]byte{{1}, {2}}, 173 cs.fs.Load().(*fixedSlice).values[:cs.fs.Load().(*fixedSlice).len()]) 174 } 175 176 func TestCowSliceRead(t *testing.T) { 177 fsp := newFixedSlicePool(16) 178 cs := newCowSlice(fsp, [][]byte{{1}}) 179 180 s := cs.slice() 181 assert.Equal(t, [][]byte{{1}}, s.values[:s.len()]) 182 183 cs.append([][]byte{{2}}) 184 assert.Equal(t, uint64(0), fsp.releaseV.Load()) 185 186 assert.Equal(t, [][]byte{{1}}, s.values[:s.len()]) 187 s.unref() 188 assert.Equal(t, uint64(1), fsp.releaseV.Load()) 189 190 cs.close() 191 assert.Equal(t, uint64(2), fsp.releaseV.Load()) 192 } 193 194 func TestCowSliceAppendConcurrentWithSliceGetNew(t *testing.T) { 195 fsp := newFixedSlicePool(16) 196 cs := newCowSlice(fsp, [][]byte{{1}}) 197 var s *fixedSlice 198 n := 0 199 cs.hack.replace = func() { 200 if s == nil { 201 s = cs.slice() 202 } 203 n++ 204 } 205 cs.append([][]byte{{2}}) 206 assert.Equal(t, 2, n) 207 assert.Equal(t, uint64(1), fsp.releaseV.Load()) 208 } 209 210 func TestCowSliceAppendConcurrentWithSliceGetOld(t *testing.T) { 211 fsp := newFixedSlicePool(16) 212 cs := newCowSlice(fsp, [][]byte{{1}}) 213 old := cs.fs.Load().(*fixedSlice) 214 n := 0 215 cs.hack.replace = func() { 216 if n == 0 { 217 old.ref() 218 cs.v.Add(1) 219 } 220 n++ 221 } 222 cs.append([][]byte{{2}}) 223 assert.Equal(t, 2, n) 224 assert.Equal(t, uint64(0), fsp.releaseV.Load()) 225 226 old.unref() 227 assert.Equal(t, uint64(1), fsp.releaseV.Load()) 228 } 229 230 func TestCowSliceSliceReadConcurrentWithAppend(t *testing.T) { 231 fsp := newFixedSlicePool(16) 232 cs := newCowSlice(fsp, [][]byte{{1}}) 233 234 n := 0 235 cs.hack.slice = func() { 236 if n == 0 { 237 cs.append([][]byte{{2}}) 238 } 239 n++ 240 } 241 s := cs.slice() 242 assert.Equal(t, [][]byte{{1}, {2}}, s.values[:s.len()]) 243 s.unref() 244 assert.Equal(t, uint64(1), fsp.releaseV.Load()) 245 246 s.close() 247 assert.Equal(t, uint64(2), fsp.releaseV.Load()) 248 }