github.com/insolar/vanilla@v0.0.0-20201023172447-248fdf805322/keyset/keyset_test.go (about) 1 // Copyright 2020 Insolar Network Ltd. 2 // All rights reserved. 3 // This material is licensed under the Insolar License version 1.0, 4 // available at https://github.com/insolar/assured-ledger/blob/master/LICENSE.md. 5 6 package keyset 7 8 import ( 9 "math" 10 "math/bits" 11 "reflect" 12 "runtime" 13 "strings" 14 "testing" 15 16 "github.com/stretchr/testify/assert" 17 "github.com/stretchr/testify/require" 18 19 "github.com/insolar/vanilla/longbits" 20 ) 21 22 func TestInstrument(t *testing.T) { 23 for i := uint(0); i <= math.MaxUint8; i++ { 24 ks := bitsToKeySet(i) 25 require.NotNil(t, ks) 26 require.Equal(t, i, keySetToBits(ks)) 27 } 28 } 29 30 func TestImmutable(t *testing.T) { 31 for name, factoryFn := range map[string]func() keySetGeneratorFunc{"KeySet": newKeySetGen, "Overlay": newOverlayGen} { 32 t.Run(name, func(t *testing.T) { 33 runSomeTest(t, factoryFn(), testInverse) 34 runSomeTest(t, factoryFn(), testContains) 35 runSomeTest(t, factoryFn(), testKeyCount) 36 37 runBoolTest(t, factoryFn(), KeySet.SupersetOf, func(i, j uint) bool { return i&j == j }) 38 runBoolTest(t, factoryFn(), KeySet.SubsetOf, func(i, j uint) bool { return i&j == i }) 39 runBoolTest(t, factoryFn(), KeySet.ContainsAny, func(i, j uint) bool { return i&j != 0 }) 40 runBoolTest(t, factoryFn(), KeySet.Equal, func(i, j uint) bool { return i == j }) 41 runBoolTest(t, factoryFn(), KeySet.EqualInverse, func(i, j uint) bool { return ^i == j }) 42 43 runKSetTest(t, factoryFn(), KeySet.Union, func(i, j uint) uint { return i | j }) 44 runKSetTest(t, factoryFn(), KeySet.Intersect, func(i, j uint) uint { return i & j }) 45 runKSetTest(t, factoryFn(), KeySet.Subtract, func(i, j uint) uint { return i &^ j }) 46 }) 47 } 48 } 49 50 func TestMutable(t *testing.T) { 51 for name, factoryFn := range map[string]func() mutableGeneratorFunc{"KeySet": newMutableGen, "Overlay": newMutableOverlayGen} { 52 t.Run(name, func(t *testing.T) { 53 runMSomeTest(t, factoryFn(), testInverseCopy) 54 runMSomeTest(t, factoryFn(), testAddKeys) 55 runMSomeTest(t, factoryFn(), testRemoveKeys) 56 runMSomeTest(t, factoryFn(), testCopyInverse) 57 58 runMSetTest(t, factoryFn, (*MutableKeySet).RetainAll, func(i, j uint) uint { return i & j }) 59 runMSetTest(t, factoryFn, (*MutableKeySet).RemoveAll, func(i, j uint) uint { return i &^ j }) 60 runMSetTest(t, factoryFn, (*MutableKeySet).AddAll, func(i, j uint) uint { return i | j }) 61 }) 62 } 63 } 64 65 func runKSetTest(t *testing.T, genFn keySetGeneratorFunc, testFn func(KeySet, KeySet) KeySet, checkFn func(i, j uint) uint) { 66 t.Run(methodName(testFn), func(t *testing.T) { 67 testKeySetOp(t, genFn, testFn, checkFn) 68 }) 69 } 70 71 func runBoolTest(t *testing.T, genFn keySetGeneratorFunc, testFn func(KeySet, KeySet) bool, checkFn func(i, j uint) bool) { 72 t.Run(methodName(testFn), func(t *testing.T) { 73 testKeySetBoolOp(t, genFn, testFn, checkFn) 74 }) 75 } 76 77 func runSomeTest(t *testing.T, genFn keySetGeneratorFunc, testFn func(*testing.T, KeySet, uint)) { 78 name := methodName(testFn) 79 if strings.HasPrefix(name, "test") { 80 name = name[4:] 81 } 82 t.Run(name, func(t *testing.T) { 83 for ksi, ti := genFn(); ksi != nil; ksi, ti = genFn() { 84 testFn(t, ksi, ti) 85 } 86 }) 87 } 88 89 func runMSetTest(t *testing.T, genFactoryFn func() mutableGeneratorFunc, testFn func(*MutableKeySet, KeySet), checkFn func(i, j uint) uint) { 90 t.Run(methodName(testFn), func(t *testing.T) { 91 testMutableOp(t, genFactoryFn, testFn, checkFn) 92 }) 93 } 94 95 func runMSomeTest(t *testing.T, genFn mutableGeneratorFunc, testFn func(*testing.T, *MutableKeySet, uint)) { 96 name := methodName(testFn) 97 if strings.HasPrefix(name, "test") { 98 name = name[4:] 99 } 100 t.Run(name, func(t *testing.T) { 101 for ksi, ti := genFn(); ksi != nil; ksi, ti = genFn() { 102 testFn(t, ksi, ti) 103 } 104 }) 105 } 106 107 func testInverse(t *testing.T, ksi KeySet, bits uint) { 108 require.Equal(t, bits, keySetToBits(ksi)) 109 require.Equal(t, ^bits, keySetToBits(ksi.Inverse())) 110 require.True(t, CopySet(ksi).EqualInverse(ksi.Inverse())) 111 require.True(t, CopySet(ksi).Inverse().Equal(ksi.Inverse())) 112 require.True(t, CopySet(ksi).Inverse().EqualInverse(ksi)) 113 114 require.False(t, ksi.EqualInverse(ksi)) 115 require.False(t, CopySet(ksi).EqualInverse(ksi)) 116 require.False(t, CopySet(ksi).Inverse().Equal(ksi)) 117 require.False(t, CopySet(ksi).Equal(ksi.Inverse())) 118 } 119 120 func testInverseCopy(t *testing.T, ksi *MutableKeySet, bits uint) { 121 require.Equal(t, bits, keySetToBits(ksi)) 122 require.Equal(t, ^bits, keySetToBits(ksi.InverseCopy())) 123 require.True(t, CopySet(ksi).EqualInverse(ksi.InverseCopy())) 124 require.True(t, CopySet(ksi.InverseCopy()).Equal(ksi.InverseCopy())) 125 require.True(t, CopySet(ksi.InverseCopy()).EqualInverse(ksi)) 126 127 require.False(t, ksi.EqualInverse(ksi)) 128 require.False(t, CopySet(ksi).EqualInverse(ksi)) 129 require.False(t, CopySet(ksi.InverseCopy()).Equal(ksi)) 130 require.False(t, CopySet(ksi).Equal(ksi.InverseCopy())) 131 } 132 133 func testAddKeys(t *testing.T, ksi *MutableKeySet, bitMask uint) { 134 k := bitToKey(0x2) 135 ksi.Add(k) 136 bitMask |= 1 << 0x2 137 require.True(t, ksi.Contains(k)) 138 139 bitMask |= 0x5 140 ksi.AddKeys(bitsToKeys(0x5)) 141 142 require.Equal(t, keySetToBits(ksi), bitMask) 143 } 144 145 func testRemoveKeys(t *testing.T, ksi *MutableKeySet, bitMask uint) { 146 k := bitToKey(2) 147 ksi.Remove(k) 148 bitMask &^= 1 << 2 149 require.False(t, ksi.Contains(k)) 150 151 bitMask &^= 0x5 152 ksi.RemoveKeys(bitsToKeys(0x5)) 153 154 require.Equal(t, keySetToBits(ksi), bitMask) 155 } 156 157 func testCopyInverse(t *testing.T, ksi *MutableKeySet, bitMask uint) { 158 copy := ksi.Copy() 159 inversed := ksi.InverseCopy() 160 161 require.True(t, inversed.Inverse().Equal(copy)) 162 163 k := bitToKey(2) 164 copy.Remove(k) 165 copyMask := bitMask 166 copyMask &^= 1 << 2 167 require.False(t, copy.Contains(k)) 168 169 require.Equal(t, keySetToBits(copy), copyMask) 170 require.Equal(t, keySetToBits(inversed), ^bitMask) 171 } 172 173 func testContains(t *testing.T, ksi KeySet, bitMask uint) { 174 for i := uint(1 << 16); i != 0; i >>= 1 { 175 k := bitToKey(bits.Len(i) - 1) 176 if bitMask&i != 0 { 177 // t.Log("In:", i, bits.Len(i)-1) 178 assert.True(t, ksi.Contains(k), "f(%x, %x)=true", bitMask, i) 179 } else { 180 // t.Log("Not: ", i, bits.Len(i)-1) 181 assert.False(t, ksi.Contains(k), "f(%x, %x)=false", bitMask, i) 182 } 183 } 184 } 185 186 func testKeyCount(t *testing.T, ksi KeySet, bitMask uint) { 187 bitCount := 0 188 if ksi.IsOpenSet() { 189 bitCount = bits.OnesCount(^bitMask) 190 } else { 191 bitCount = bits.OnesCount(bitMask) 192 } 193 require.Equal(t, bitCount, ksi.RawKeyCount()) 194 } 195 196 type keySetGeneratorFunc func() (KeySet, uint) 197 type mutableGeneratorFunc func() (*MutableKeySet, uint) 198 199 func testKeySetOp(t *testing.T, nextFn keySetGeneratorFunc, testFn func(KeySet, KeySet) KeySet, checkFn func(i, j uint) uint) { 200 nextFnJ := newKeySetGen() 201 202 for ksi, ti := nextFn(); ksi != nil; ksi, ti = nextFn() { 203 for ksj, tj := nextFnJ(); ksj != nil; ksj, tj = nextFnJ() { 204 ksr := testFn(ksi, ksj) 205 206 r := checkFn(ti, tj) 207 // t.Logf("f(%x, %x)=%x", ti, tj, r) 208 require.Equal(t, r, keySetToBits(ksr), "f(%x, %x)=%x", ti, tj, r) 209 } 210 } 211 } 212 213 func testKeySetBoolOp(t *testing.T, nextFn keySetGeneratorFunc, testFn func(KeySet, KeySet) bool, checkFn func(i, j uint) bool) { 214 nextFnJ := newKeySetGen() 215 216 for ksi, ti := nextFn(); ksi != nil; ksi, ti = nextFn() { 217 for ksj, tj := nextFnJ(); ksj != nil; ksj, tj = nextFnJ() { 218 if checkFn(ti, tj) { 219 require.True(t, testFn(ksi, ksj), "f(%x, %x)=true", ti, tj) 220 } else { 221 require.False(t, testFn(ksi, ksj), "f(%x, %x)=false", ti, tj) 222 } 223 } 224 } 225 } 226 227 func testMutableOp(t *testing.T, genFactoryFn func() mutableGeneratorFunc, testFn func(*MutableKeySet, KeySet), checkFn func(i, j uint) uint) { 228 nextFnJ := newKeySetGen() 229 230 for ksj, tj := nextFnJ(); ksj != nil; ksj, tj = nextFnJ() { 231 nextFn := genFactoryFn() 232 for ksi, ti := nextFn(); ksi != nil; ksi, ti = nextFn() { 233 testFn(ksi, ksj) 234 235 r := checkFn(ti, tj) 236 // t.Logf("f(%x, %x)=%x", ti, tj, r) 237 require.Equal(t, r, keySetToBits(ksi), "f(%x, %x)=%x", ti, tj, r) 238 } 239 } 240 } 241 242 const testKeyLen = 16 243 244 func bitToKey(index int) Key { 245 return longbits.Fill(testKeyLen, byte(index+'0')) 246 } 247 248 func bitsToKeySet(v uint) KeySet { 249 if v == 1 { 250 return SoloKeySet(bitToKey(0)) 251 } 252 return bitsToMutableKeySet(v).Freeze() 253 } 254 255 func bitsToKeys(v uint) (r []Key) { 256 index := 0 257 for v != 0 { 258 shift := bits.TrailingZeros(v) + 1 259 index += shift 260 r = append(r, bitToKey(index-1)) 261 v >>= uint8(shift) 262 } 263 return r 264 } 265 266 func bitsToMutableKeySet(v uint) *MutableKeySet { 267 r := NewMutable() 268 index := 0 269 for v != 0 { 270 shift := bits.TrailingZeros(v) + 1 271 index += shift 272 r.Add(bitToKey(index - 1)) 273 v >>= uint8(shift) 274 } 275 return &r 276 } 277 278 func keySetToBits(ks KeySet) uint { 279 r := uint(0) 280 ks.EnumRawKeys(func(k Key, _ bool) bool { 281 if k.FixedByteSize() != testKeyLen { 282 panic("illegal value") 283 } 284 if k[0] < '0' || k[0] >= '0'+32 { 285 panic("illegal value") 286 } 287 i := uint(1) << uint8(k[0]-'0') 288 if r&i != 0 { 289 panic("illegal value") 290 } 291 r |= i 292 return false 293 }) 294 if ks.IsOpenSet() { 295 r = ^r 296 } 297 return r 298 } 299 300 func newKeySetGen() keySetGeneratorFunc { 301 ni := uint(0) 302 return func() (KeySet, uint) { 303 if ni >= 32 { 304 return nil, 0 305 } 306 i := ni & 0xF 307 ksi := bitsToKeySet(i) 308 ti := i 309 if ni > 0xF { 310 ti = ^i 311 ksi = ksi.Inverse() 312 } 313 ni++ 314 return ksi, ti 315 } 316 } 317 318 func newMutableGen() mutableGeneratorFunc { 319 ni := uint(0) 320 return func() (*MutableKeySet, uint) { 321 if ni >= 32 { 322 return nil, 0 323 } 324 i := ni & 0xF 325 ksi := bitsToMutableKeySet(i) 326 ti := i 327 if ni > 0xF { 328 ti = ^i 329 ksi = ksi.InverseCopy() 330 } 331 ni++ 332 return ksi, ti 333 } 334 } 335 336 func newOverlayGen() keySetGeneratorFunc { 337 mutableGen := newMutableOverlayGen() 338 return func() (KeySet, uint) { 339 o, m := mutableGen() 340 if o == nil { 341 return nil, 0 342 } 343 return o.Freeze(), m 344 } 345 } 346 347 func newMutableOverlayGen() mutableGeneratorFunc { 348 baseGenFn := newKeySetGen() 349 baseKs, baseMask := baseGenFn() 350 351 deltaN := uint(0) 352 353 return func() (*MutableKeySet, uint) { 354 var deltaKeys []Key 355 if deltaN >= 32 { 356 baseKs, baseMask = baseGenFn() 357 if baseKs == nil || baseKs.IsOpenSet() { 358 return nil, 0 359 } 360 deltaN = 0 361 } else { 362 deltaKeys = bitsToKeys(deltaN & 0xF) 363 } 364 365 overlayMask := baseMask 366 overlay := WrapAsMutable(baseKs.(KeyList)) 367 if deltaN > 0xF { 368 overlay.RemoveKeys(deltaKeys) 369 overlayMask &^= deltaN 370 } else { 371 overlay.AddKeys(deltaKeys) 372 overlayMask |= deltaN 373 } 374 375 deltaN++ 376 return &overlay, overlayMask 377 } 378 } 379 380 func methodName(testFn interface{}) string { 381 fullName := runtime.FuncForPC(reflect.ValueOf(testFn).Pointer()).Name() 382 if lastIndex := strings.LastIndex(fullName, "."); lastIndex >= 0 { 383 fullName = fullName[lastIndex+1:] 384 } 385 if lastIndex := strings.LastIndex(fullName, "-"); lastIndex >= 0 { 386 fullName = fullName[:lastIndex] 387 } 388 return fullName 389 }