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  }