mirror of
https://github.com/dolthub/dolt.git
synced 2026-02-11 10:33:08 -06:00
Merge pull request #1030 from kalman/followup
Add tests for modifying chunked sets/maps/lists read from a chunkstore.
This commit is contained in:
@@ -35,8 +35,8 @@ func (tsl testSimpleList) RemoveAt(idx int) testSimpleList {
|
||||
return tsl.Remove(idx, idx+1)
|
||||
}
|
||||
|
||||
func (tsl testSimpleList) ToNomsList() List {
|
||||
return NewList(tsl...)
|
||||
func (tsl testSimpleList) toCompoundList() compoundList {
|
||||
return NewList(tsl...).(compoundList)
|
||||
}
|
||||
|
||||
func getTestSimpleListLen() uint64 {
|
||||
@@ -306,7 +306,7 @@ func TestCompoundListAppend(t *testing.T) {
|
||||
func TestCompoundListInsertNothing(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
cl := getTestSimpleList().ToNomsList()
|
||||
cl := getTestSimpleList().toCompoundList()
|
||||
|
||||
assert.True(cl.Equals(cl.Insert(0)))
|
||||
for i := uint64(1); i < getTestSimpleListLen(); i *= 2 {
|
||||
@@ -319,7 +319,7 @@ func TestCompoundListInsertNothing(t *testing.T) {
|
||||
func TestCompoundListInsertStart(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
cl := getTestSimpleList().ToNomsList()
|
||||
cl := getTestSimpleList().toCompoundList()
|
||||
cl2 := cl.Insert(0, Int64(42))
|
||||
cl3 := cl2.Insert(0, Int64(43))
|
||||
cl4 := cl3.Insert(0, getTestSimpleList()...)
|
||||
@@ -329,38 +329,38 @@ func TestCompoundListInsertStart(t *testing.T) {
|
||||
expected := getTestSimpleList()
|
||||
assert.Equal(expected, testSimpleListFromNomsList(cl))
|
||||
assert.Equal(getTestSimpleListLen(), cl.Len())
|
||||
assert.True(expected.ToNomsList().Equals(cl))
|
||||
assert.True(expected.toCompoundList().Equals(cl))
|
||||
|
||||
expected = expected.Insert(0, Int64(42))
|
||||
assert.Equal(expected, testSimpleListFromNomsList(cl2))
|
||||
assert.Equal(getTestSimpleListLen()+1, cl2.Len())
|
||||
assert.True(expected.ToNomsList().Equals(cl2))
|
||||
assert.True(expected.toCompoundList().Equals(cl2))
|
||||
|
||||
expected = expected.Insert(0, Int64(43))
|
||||
assert.Equal(expected, testSimpleListFromNomsList(cl3))
|
||||
assert.Equal(getTestSimpleListLen()+2, cl3.Len())
|
||||
assert.True(expected.ToNomsList().Equals(cl3))
|
||||
assert.True(expected.toCompoundList().Equals(cl3))
|
||||
|
||||
expected = expected.Insert(0, getTestSimpleList()...)
|
||||
assert.Equal(expected, testSimpleListFromNomsList(cl4))
|
||||
assert.Equal(2*getTestSimpleListLen()+2, cl4.Len())
|
||||
assert.True(expected.ToNomsList().Equals(cl4))
|
||||
assert.True(expected.toCompoundList().Equals(cl4))
|
||||
|
||||
expected = expected.Insert(0, Int64(44), Int64(45))
|
||||
assert.Equal(expected, testSimpleListFromNomsList(cl5))
|
||||
assert.Equal(2*getTestSimpleListLen()+4, cl5.Len())
|
||||
assert.True(expected.ToNomsList().Equals(cl5))
|
||||
assert.True(expected.toCompoundList().Equals(cl5))
|
||||
|
||||
expected = expected.Insert(0, getTestSimpleList()...)
|
||||
assert.Equal(expected, testSimpleListFromNomsList(cl6))
|
||||
assert.Equal(3*getTestSimpleListLen()+4, cl6.Len())
|
||||
assert.True(expected.ToNomsList().Equals(cl6))
|
||||
assert.True(expected.toCompoundList().Equals(cl6))
|
||||
}
|
||||
|
||||
func TestCompoundListInsertMiddle(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
cl := getTestSimpleList().ToNomsList()
|
||||
cl := getTestSimpleList().toCompoundList()
|
||||
cl2 := cl.Insert(100, Int64(42))
|
||||
cl3 := cl2.Insert(200, Int64(43))
|
||||
cl4 := cl3.Insert(300, getTestSimpleList()...)
|
||||
@@ -371,50 +371,50 @@ func TestCompoundListInsertMiddle(t *testing.T) {
|
||||
expected := getTestSimpleList()
|
||||
assert.Equal(expected, testSimpleListFromNomsList(cl))
|
||||
assert.Equal(getTestSimpleListLen(), cl.Len())
|
||||
assert.True(expected.ToNomsList().Equals(cl))
|
||||
assert.True(expected.toCompoundList().Equals(cl))
|
||||
|
||||
expected = expected.Insert(100, Int64(42))
|
||||
assert.Equal(expected, testSimpleListFromNomsList(cl2))
|
||||
assert.Equal(getTestSimpleListLen()+1, cl2.Len())
|
||||
assert.True(expected.ToNomsList().Equals(cl2))
|
||||
assert.True(expected.toCompoundList().Equals(cl2))
|
||||
|
||||
expected = expected.Insert(200, Int64(43))
|
||||
assert.Equal(expected, testSimpleListFromNomsList(cl3))
|
||||
assert.Equal(getTestSimpleListLen()+2, cl3.Len())
|
||||
assert.True(expected.ToNomsList().Equals(cl3))
|
||||
assert.True(expected.toCompoundList().Equals(cl3))
|
||||
|
||||
expected = expected.Insert(300, getTestSimpleList()...)
|
||||
assert.Equal(expected, testSimpleListFromNomsList(cl4))
|
||||
assert.Equal(2*getTestSimpleListLen()+2, cl4.Len())
|
||||
assert.True(expected.ToNomsList().Equals(cl4))
|
||||
assert.True(expected.toCompoundList().Equals(cl4))
|
||||
|
||||
expected = expected.Insert(400, Int64(44), Int64(45))
|
||||
assert.Equal(expected, testSimpleListFromNomsList(cl5))
|
||||
assert.Equal(2*getTestSimpleListLen()+4, cl5.Len())
|
||||
assert.True(expected.ToNomsList().Equals(cl5))
|
||||
assert.True(expected.toCompoundList().Equals(cl5))
|
||||
|
||||
expected = expected.Insert(500, getTestSimpleList()...)
|
||||
assert.Equal(expected, testSimpleListFromNomsList(cl6))
|
||||
assert.Equal(3*getTestSimpleListLen()+4, cl6.Len())
|
||||
assert.True(expected.ToNomsList().Equals(cl6))
|
||||
assert.True(expected.toCompoundList().Equals(cl6))
|
||||
|
||||
expected = expected.Insert(600, Int64(100))
|
||||
assert.Equal(expected, testSimpleListFromNomsList(cl7))
|
||||
assert.Equal(3*getTestSimpleListLen()+5, cl7.Len())
|
||||
assert.True(expected.ToNomsList().Equals(cl7))
|
||||
assert.True(expected.toCompoundList().Equals(cl7))
|
||||
}
|
||||
|
||||
func TestCompoundListInsertRanges(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
testList := getTestSimpleList()
|
||||
whole := testList.ToNomsList()
|
||||
whole := testList.toCompoundList()
|
||||
|
||||
// Compare list equality. Increment by 256 (16^2) because each iteration requires building a new list, which is slow.
|
||||
for incr, i := 256, 0; i < len(testList)-incr; i += incr {
|
||||
for window := 1; window <= incr; window *= 16 {
|
||||
testListPart := testList.Remove(i, i+window)
|
||||
actual := testListPart.ToNomsList().Insert(uint64(i), testList[i:i+window]...)
|
||||
actual := testListPart.toCompoundList().Insert(uint64(i), testList[i:i+window]...)
|
||||
assert.Equal(whole.Len(), actual.Len())
|
||||
assert.True(whole.Equals(actual))
|
||||
}
|
||||
@@ -440,7 +440,7 @@ func TestCompoundListInsertTypeError(t *testing.T) {
|
||||
func TestCompoundListRemoveNothing(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
cl := getTestSimpleList().ToNomsList()
|
||||
cl := getTestSimpleList().toCompoundList()
|
||||
|
||||
assert.True(cl.Equals(cl.Remove(0, 0)))
|
||||
for i := uint64(1); i < getTestSimpleListLen(); i *= 2 {
|
||||
@@ -453,7 +453,7 @@ func TestCompoundListRemoveNothing(t *testing.T) {
|
||||
func TestCompoundListRemoveEverything(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
cl := getTestSimpleList().ToNomsList().Remove(0, getTestSimpleListLen())
|
||||
cl := getTestSimpleList().toCompoundList().Remove(0, getTestSimpleListLen())
|
||||
|
||||
assert.True(NewList().Equals(cl))
|
||||
assert.Equal(0, int(cl.Len()))
|
||||
@@ -462,37 +462,37 @@ func TestCompoundListRemoveEverything(t *testing.T) {
|
||||
func TestCompoundListRemoveAtMiddle(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
cl := getTestSimpleList().ToNomsList()
|
||||
cl := getTestSimpleList().toCompoundList()
|
||||
cl2 := cl.RemoveAt(100)
|
||||
cl3 := cl2.RemoveAt(200)
|
||||
|
||||
expected := getTestSimpleList()
|
||||
assert.Equal(expected, testSimpleListFromNomsList(cl))
|
||||
assert.Equal(getTestSimpleListLen(), cl.Len())
|
||||
assert.True(expected.ToNomsList().Equals(cl))
|
||||
assert.True(expected.toCompoundList().Equals(cl))
|
||||
|
||||
expected = expected.RemoveAt(100)
|
||||
assert.Equal(expected, testSimpleListFromNomsList(cl2))
|
||||
assert.Equal(getTestSimpleListLen()-1, cl2.Len())
|
||||
assert.True(expected.ToNomsList().Equals(cl2))
|
||||
assert.True(expected.toCompoundList().Equals(cl2))
|
||||
|
||||
expected = expected.RemoveAt(200)
|
||||
assert.Equal(expected, testSimpleListFromNomsList(cl3))
|
||||
assert.Equal(getTestSimpleListLen()-2, cl3.Len())
|
||||
assert.True(expected.ToNomsList().Equals(cl3))
|
||||
assert.True(expected.toCompoundList().Equals(cl3))
|
||||
}
|
||||
|
||||
func TestCompoundListRemoveRanges(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
testList := getTestSimpleList()
|
||||
whole := testList.ToNomsList()
|
||||
whole := testList.toCompoundList()
|
||||
|
||||
// Compare list equality. Increment by 256 (16^2) because each iteration requires building a new list, which is slow.
|
||||
for incr, i := 256, 0; i < len(testList)-incr; i += incr {
|
||||
for window := 1; window <= incr; window *= 16 {
|
||||
testListPart := testList.Remove(i, i+window)
|
||||
expected := testListPart.ToNomsList()
|
||||
expected := testListPart.toCompoundList()
|
||||
actual := whole.Remove(uint64(i), uint64(i+window))
|
||||
assert.Equal(expected.Len(), actual.Len())
|
||||
assert.True(expected.Equals(actual))
|
||||
@@ -509,14 +509,14 @@ func TestCompoundListSet(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
testList := getTestSimpleList()
|
||||
cl := testList.ToNomsList()
|
||||
cl := testList.toCompoundList()
|
||||
|
||||
testIdx := func(idx int, testEquality bool) {
|
||||
newVal := Int64(-1) // Test values are never < 0
|
||||
cl2 := cl.Set(uint64(idx), newVal)
|
||||
assert.False(cl.Equals(cl2))
|
||||
if testEquality {
|
||||
assert.True(testList.Set(idx, newVal).ToNomsList().Equals(cl2))
|
||||
assert.True(testList.Set(idx, newVal).toCompoundList().Equals(cl2))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -597,25 +597,14 @@ func TestCompoundListFilter(t *testing.T) {
|
||||
}
|
||||
|
||||
}
|
||||
cl := simple.ToNomsList()
|
||||
cl := simple.toCompoundList()
|
||||
|
||||
res := cl.Filter(filterCb)
|
||||
assert.Equal(len(expected), int(res.Len()))
|
||||
res.IterAll(func(v Value, idx uint64) {
|
||||
assert.Equal(expected[idx], v)
|
||||
})
|
||||
assert.True(expected.ToNomsList().Equals(res))
|
||||
}
|
||||
|
||||
func TestCompoundListFilterEmpty(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
empty := testSimpleList{}.ToNomsList()
|
||||
filterCb := func(v Value, idx uint64) bool {
|
||||
return v.(Int64)%5 != 0
|
||||
}
|
||||
res1 := empty.Filter(filterCb)
|
||||
assert.True(res1.Empty())
|
||||
assert.True(expected.toCompoundList().Equals(res))
|
||||
}
|
||||
|
||||
func TestCompoundListFirstNNumbers(t *testing.T) {
|
||||
@@ -636,3 +625,18 @@ func TestCompoundListFirstNNumbers(t *testing.T) {
|
||||
s := NewTypedList(listType, nums...)
|
||||
assert.Equal(s.Ref().String(), "sha1-11e947e8aacfda8e9052bb57e661da442b26c625")
|
||||
}
|
||||
|
||||
func TestCompoundListModifyAfterRead(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
ms := chunks.NewMemoryStore()
|
||||
list := getTestSimpleList().toCompoundList()
|
||||
// Drop chunk values.
|
||||
list = ReadValue(WriteValue(list, ms), ms).(compoundList)
|
||||
// Modify/query. Once upon a time this would crash.
|
||||
llen := list.Len()
|
||||
z := list.Get(0)
|
||||
list = list.RemoveAt(0).(compoundList)
|
||||
assert.Equal(llen-1, list.Len())
|
||||
list = list.Append(z).(compoundList)
|
||||
assert.Equal(llen, list.Len())
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ func (tm testMap) Flatten(from, to int) []Value {
|
||||
return flat
|
||||
}
|
||||
|
||||
func (tm testMap) toCompoundMap(cs chunks.ChunkStore) compoundMap {
|
||||
func (tm testMap) toCompoundMap() compoundMap {
|
||||
keyvals := []Value{}
|
||||
for _, entry := range tm.entries {
|
||||
keyvals = append(keyvals, entry.key, entry.value)
|
||||
@@ -122,7 +122,7 @@ func TestCompoundMapHas(t *testing.T) {
|
||||
|
||||
doTest := func(tm testMap) {
|
||||
cs := chunks.NewMemoryStore()
|
||||
m := tm.toCompoundMap(cs)
|
||||
m := tm.toCompoundMap()
|
||||
m2 := ReadValue(WriteValue(m, cs), cs).(compoundMap)
|
||||
for _, entry := range tm.entries {
|
||||
k, v := entry.key, entry.value
|
||||
@@ -143,7 +143,7 @@ func TestCompoundMapFirst(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
doTest := func(tm testMap) {
|
||||
m := tm.toCompoundMap(chunks.NewMemoryStore())
|
||||
m := tm.toCompoundMap()
|
||||
sort.Stable(tm)
|
||||
actualKey, actualValue := m.First()
|
||||
assert.True(tm.entries[0].key.Equals(actualKey))
|
||||
@@ -160,7 +160,7 @@ func TestCompoundMapMaybeGet(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
doTest := func(tm testMap) {
|
||||
m := tm.toCompoundMap(chunks.NewMemoryStore())
|
||||
m := tm.toCompoundMap()
|
||||
for _, entry := range tm.entries {
|
||||
v, ok := m.MaybeGet(entry.key)
|
||||
if assert.True(ok, "%v should have been in the map!", entry.key) {
|
||||
@@ -181,7 +181,7 @@ func TestCompoundMapIter(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
doTest := func(tm testMap) {
|
||||
m := tm.toCompoundMap(chunks.NewMemoryStore())
|
||||
m := tm.toCompoundMap()
|
||||
sort.Sort(tm)
|
||||
idx := uint64(0)
|
||||
endAt := uint64(mapPattern)
|
||||
@@ -209,7 +209,7 @@ func TestCompoundMapIterAll(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
doTest := func(tm testMap) {
|
||||
m := tm.toCompoundMap(chunks.NewMemoryStore())
|
||||
m := tm.toCompoundMap()
|
||||
sort.Sort(tm)
|
||||
idx := uint64(0)
|
||||
|
||||
@@ -230,10 +230,9 @@ func TestCompoundMapSet(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
doTest := func(incr, offset int, tm testMap) {
|
||||
cs := chunks.NewMemoryStore()
|
||||
expected := tm.toCompoundMap(cs)
|
||||
expected := tm.toCompoundMap()
|
||||
run := func(from, to int) {
|
||||
actual := tm.Remove(from, to).toCompoundMap(cs).SetM(tm.Flatten(from, to)...)
|
||||
actual := tm.Remove(from, to).toCompoundMap().SetM(tm.Flatten(from, to)...)
|
||||
assert.Equal(expected.Len(), actual.Len())
|
||||
assert.True(expected.Equals(actual))
|
||||
}
|
||||
@@ -256,9 +255,8 @@ func TestCompoundMapSet(t *testing.T) {
|
||||
func TestCompoundMapSetExistingKeyToExistingValue(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
cs := chunks.NewMemoryStore()
|
||||
tm := getTestNativeOrderMap(2)
|
||||
original := tm.toCompoundMap(cs)
|
||||
original := tm.toCompoundMap()
|
||||
|
||||
actual := original
|
||||
for _, entry := range tm.entries {
|
||||
@@ -272,9 +270,8 @@ func TestCompoundMapSetExistingKeyToExistingValue(t *testing.T) {
|
||||
func TestCompoundMapSetExistingKeyToNewValue(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
cs := chunks.NewMemoryStore()
|
||||
tm := getTestNativeOrderMap(2)
|
||||
original := tm.toCompoundMap(cs)
|
||||
original := tm.toCompoundMap()
|
||||
|
||||
expectedWorking := tm
|
||||
actual := original
|
||||
@@ -284,7 +281,7 @@ func TestCompoundMapSetExistingKeyToNewValue(t *testing.T) {
|
||||
actual = actual.Set(entry.key, newValue).(compoundMap)
|
||||
}
|
||||
|
||||
expected := expectedWorking.toCompoundMap(cs)
|
||||
expected := expectedWorking.toCompoundMap()
|
||||
assert.Equal(expected.Len(), actual.Len())
|
||||
assert.True(expected.Equals(actual))
|
||||
assert.False(original.Equals(actual))
|
||||
@@ -294,10 +291,9 @@ func TestCompoundMapRemove(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
doTest := func(incr int, tm testMap) {
|
||||
cs := chunks.NewMemoryStore()
|
||||
whole := tm.toCompoundMap(cs)
|
||||
whole := tm.toCompoundMap()
|
||||
run := func(i int) {
|
||||
expected := tm.Remove(i, i+1).toCompoundMap(cs)
|
||||
expected := tm.Remove(i, i+1).toCompoundMap()
|
||||
actual := whole.Remove(tm.entries[i].key)
|
||||
assert.Equal(expected.Len(), actual.Len())
|
||||
assert.True(expected.Equals(actual))
|
||||
@@ -317,9 +313,8 @@ func TestCompoundMapRemove(t *testing.T) {
|
||||
func TestCompoundMapRemoveNonexistentKey(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
cs := chunks.NewMemoryStore()
|
||||
tm := getTestNativeOrderMap(2)
|
||||
original := tm.toCompoundMap(cs)
|
||||
original := tm.toCompoundMap()
|
||||
actual := original.Remove(Int64(-1)) // rand.Int63 returns non-negative numbers.
|
||||
|
||||
assert.Equal(original.Len(), actual.Len())
|
||||
@@ -330,8 +325,7 @@ func TestCompoundMapFilter(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
doTest := func(tm testMap) {
|
||||
cs := chunks.NewMemoryStore()
|
||||
m := tm.toCompoundMap(cs)
|
||||
m := tm.toCompoundMap()
|
||||
sort.Sort(tm)
|
||||
pivotPoint := 10
|
||||
pivot := tm.entries[pivotPoint].key
|
||||
@@ -368,3 +362,21 @@ func TestCompoundMapFirstNNumbers(t *testing.T) {
|
||||
m := NewTypedMap(mapType, kvs...)
|
||||
assert.Equal(m.Ref().String(), "sha1-1b9664e55091370996f3af428ffee78f1ad36426")
|
||||
}
|
||||
|
||||
func TestCompoundMapModifyAfterRead(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
ms := chunks.NewMemoryStore()
|
||||
m := getTestNativeOrderMap(2).toCompoundMap()
|
||||
// Drop chunk values.
|
||||
m = ReadValue(WriteValue(m, ms), ms).(compoundMap)
|
||||
// Modify/query. Once upon a time this would crash.
|
||||
fst, fstval := m.First()
|
||||
m = m.Remove(fst).(compoundMap)
|
||||
assert.False(m.Has(fst))
|
||||
{
|
||||
fst, _ := m.First()
|
||||
assert.True(m.Has(fst))
|
||||
}
|
||||
m = m.Set(fst, fstval).(compoundMap)
|
||||
assert.True(m.Has(fst))
|
||||
}
|
||||
|
||||
@@ -113,17 +113,8 @@ func (cs compoundSet) sequenceChunkerAtValue(v Value) (*sequenceChunker, bool) {
|
||||
return seq, found
|
||||
}
|
||||
|
||||
func (cs compoundSet) elemType() Type {
|
||||
return cs.t.Desc.(CompoundDesc).ElemTypes[0]
|
||||
}
|
||||
|
||||
func (cs compoundSet) sequenceCursorAtFirst() *sequenceCursor {
|
||||
metaCur, leaf := newMetaSequenceCursor(cs, cs.cs)
|
||||
return newSetSequenceCursorAtPosition(metaCur, leaf.(setLeaf), 0, cs.cs)
|
||||
}
|
||||
|
||||
func (cs compoundSet) Union(others ...Set) Set {
|
||||
return setUnion(cs.cs, cs, others)
|
||||
return setUnion(cs, others)
|
||||
}
|
||||
|
||||
func (cs compoundSet) Subtract(others ...Set) Set {
|
||||
@@ -179,3 +170,16 @@ func (cs compoundSet) IterAllP(concurrency int, f setIterAllCallback) {
|
||||
return false
|
||||
})
|
||||
}
|
||||
|
||||
func (cs compoundSet) elemType() Type {
|
||||
return cs.t.Desc.(CompoundDesc).ElemTypes[0]
|
||||
}
|
||||
|
||||
func (cs compoundSet) sequenceCursorAtFirst() *sequenceCursor {
|
||||
metaCur, leaf := newMetaSequenceCursor(cs, cs.cs)
|
||||
return newSetSequenceCursorAtPosition(metaCur, leaf.(setLeaf), 0, cs.cs)
|
||||
}
|
||||
|
||||
func (cs compoundSet) chunkSource() chunks.ChunkSource {
|
||||
return cs.cs
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ func (ts testSet) Remove(from, to int) testSet {
|
||||
return testSet{values, ts.less, ts.tr}
|
||||
}
|
||||
|
||||
func (ts testSet) toCompoundSet(cs chunks.ChunkStore) Set {
|
||||
func (ts testSet) toCompoundSet() compoundSet {
|
||||
return NewTypedSet(ts.tr, ts.values...).(compoundSet)
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ func TestCompoundSetHas(t *testing.T) {
|
||||
|
||||
doTest := func(ts testSet) {
|
||||
cs := chunks.NewMemoryStore()
|
||||
set := ts.toCompoundSet(cs)
|
||||
set := ts.toCompoundSet()
|
||||
set2 := ReadValue(WriteValue(set, cs), cs).(compoundSet)
|
||||
for _, v := range ts.values {
|
||||
assert.True(set.Has(v))
|
||||
@@ -117,7 +117,7 @@ func TestCompoundSetFirst(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
doTest := func(ts testSet) {
|
||||
s := ts.toCompoundSet(chunks.NewMemoryStore())
|
||||
s := ts.toCompoundSet()
|
||||
sort.Stable(ts)
|
||||
actual := s.First()
|
||||
assert.True(ts.values[0].Equals(actual), "%v != %v", ts.values[0], actual)
|
||||
@@ -133,7 +133,7 @@ func TestCompoundSetIter(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
doTest := func(ts testSet) {
|
||||
set := ts.toCompoundSet(chunks.NewMemoryStore())
|
||||
set := ts.toCompoundSet()
|
||||
sort.Sort(ts)
|
||||
idx := uint64(0)
|
||||
endAt := uint64(setPattern)
|
||||
@@ -160,7 +160,7 @@ func TestCompoundSetIterAll(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
doTest := func(ts testSet) {
|
||||
set := ts.toCompoundSet(chunks.NewMemoryStore())
|
||||
set := ts.toCompoundSet()
|
||||
sort.Sort(ts)
|
||||
idx := uint64(0)
|
||||
|
||||
@@ -180,10 +180,9 @@ func TestCompoundSetInsert(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
doTest := func(incr, offset int, ts testSet) {
|
||||
cs := chunks.NewMemoryStore()
|
||||
expected := ts.toCompoundSet(cs)
|
||||
expected := ts.toCompoundSet()
|
||||
run := func(from, to int) {
|
||||
actual := ts.Remove(from, to).toCompoundSet(cs).Insert(ts.values[from:to]...)
|
||||
actual := ts.Remove(from, to).toCompoundSet().Insert(ts.values[from:to]...)
|
||||
assert.Equal(expected.Len(), actual.Len())
|
||||
assert.True(expected.Equals(actual))
|
||||
}
|
||||
@@ -206,9 +205,8 @@ func TestCompoundSetInsert(t *testing.T) {
|
||||
func TestCompoundSetInsertExistingValue(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
cs := chunks.NewMemoryStore()
|
||||
ts := getTestNativeOrderSet(2)
|
||||
original := ts.toCompoundSet(cs)
|
||||
original := ts.toCompoundSet()
|
||||
actual := original.Insert(ts.values[0])
|
||||
|
||||
assert.Equal(original.Len(), actual.Len())
|
||||
@@ -219,10 +217,9 @@ func TestCompoundSetRemove(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
doTest := func(incr, offset int, ts testSet) {
|
||||
cs := chunks.NewMemoryStore()
|
||||
whole := ts.toCompoundSet(cs)
|
||||
whole := ts.toCompoundSet()
|
||||
run := func(from, to int) {
|
||||
expected := ts.Remove(from, to).toCompoundSet(cs)
|
||||
expected := ts.Remove(from, to).toCompoundSet()
|
||||
actual := whole.Remove(ts.values[from:to]...)
|
||||
assert.Equal(expected.Len(), actual.Len())
|
||||
assert.True(expected.Equals(actual))
|
||||
@@ -243,9 +240,8 @@ func TestCompoundSetRemove(t *testing.T) {
|
||||
func TestCompoundSetRemoveNonexistentValue(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
cs := chunks.NewMemoryStore()
|
||||
ts := getTestNativeOrderSet(2)
|
||||
original := ts.toCompoundSet(cs)
|
||||
original := ts.toCompoundSet()
|
||||
actual := original.Remove(Int64(-1)) // rand.Int63 returns non-negative values.
|
||||
|
||||
assert.Equal(original.Len(), actual.Len())
|
||||
@@ -256,8 +252,7 @@ func TestCompoundSetFilter(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
doTest := func(ts testSet) {
|
||||
cs := chunks.NewMemoryStore()
|
||||
set := ts.toCompoundSet(cs)
|
||||
set := ts.toCompoundSet()
|
||||
sort.Sort(ts)
|
||||
pivotPoint := 10
|
||||
pivot := ts.values[pivotPoint]
|
||||
@@ -281,10 +276,9 @@ func TestCompoundSetFilter(t *testing.T) {
|
||||
|
||||
func TestCompoundSetUnion(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
ms := chunks.NewMemoryStore()
|
||||
|
||||
doTest := func(ts testSet) {
|
||||
cs := ts.toCompoundSet(ms)
|
||||
cs := ts.toCompoundSet()
|
||||
cs2 := cs.Union()
|
||||
assert.True(cs.Equals(cs2))
|
||||
cs3 := cs.Union(cs2)
|
||||
@@ -347,3 +341,18 @@ func TestCompoundSetFirstNNumbers(t *testing.T) {
|
||||
s := newTypedSet(setType, nums...)
|
||||
assert.Equal(s.Ref().String(), "sha1-54ff8f84b5f39fe2171572922d067257a57c539c")
|
||||
}
|
||||
|
||||
func TestCompoundSetModifyAfterRead(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
ms := chunks.NewMemoryStore()
|
||||
set := getTestNativeOrderSet(2).toCompoundSet()
|
||||
// Drop chunk values.
|
||||
set = ReadValue(WriteValue(set, ms), ms).(compoundSet)
|
||||
// Modify/query. Once upon a time this would crash.
|
||||
fst := set.First()
|
||||
set = set.Remove(fst).(compoundSet)
|
||||
assert.False(set.Has(fst))
|
||||
assert.True(set.Has(set.First()))
|
||||
set = set.Insert(fst).(compoundSet)
|
||||
assert.True(set.Has(fst))
|
||||
}
|
||||
|
||||
15
types/set.go
15
types/set.go
@@ -20,6 +20,7 @@ type Set interface {
|
||||
Filter(cb setFilterCallback) Set
|
||||
elemType() Type
|
||||
sequenceCursorAtFirst() *sequenceCursor
|
||||
chunkSource() chunks.ChunkSource
|
||||
}
|
||||
|
||||
type indexOfSetFn func(m setData, v Value) int
|
||||
@@ -47,13 +48,25 @@ func newTypedSet(t Type, data ...Value) Set {
|
||||
return seq.Done().(Set)
|
||||
}
|
||||
|
||||
func setUnion(cs chunks.ChunkSource, set Set, others []Set) Set {
|
||||
func setUnion(set Set, others []Set) Set {
|
||||
// TODO: This can be done more efficiently by realizing that if two sets have the same meta tuple we only have to traverse one of the subtrees. Bug 794
|
||||
if len(others) == 0 {
|
||||
return set
|
||||
}
|
||||
assertSetsSameType(set, others...)
|
||||
|
||||
cs := set.chunkSource()
|
||||
for _, s := range others {
|
||||
// This both tries to find a ChunkSource to use for the new Set, and asserts that if it does,
|
||||
// it's the same (or nil) for all Sets. I.e. it should be possible to take the union of a Set
|
||||
// without a ChunkSource (constructed in memory but not written yet) and one with a ChunkSource
|
||||
// (from that source) but not with a *different* ChunkSource because this would get complicated.
|
||||
if cs == nil {
|
||||
cs = s.chunkSource()
|
||||
}
|
||||
d.Chk.True(cs == nil || cs == s.chunkSource())
|
||||
}
|
||||
|
||||
tr := set.Type()
|
||||
seq := newEmptySequenceChunker(makeSetLeafChunkFn(tr, cs), newOrderedMetaSequenceChunkFn(tr, cs), newSetLeafBoundaryChecker(), newOrderedMetaSequenceBoundaryChecker)
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ func (s setLeaf) Remove(values ...Value) Set {
|
||||
}
|
||||
|
||||
func (s setLeaf) Union(others ...Set) Set {
|
||||
return setUnion(s.cs, s, others)
|
||||
return setUnion(s, others)
|
||||
}
|
||||
|
||||
func (s setLeaf) Iter(cb setIterCallback) {
|
||||
@@ -236,3 +236,7 @@ func (s setLeaf) sequenceCursorAtFirst() *sequenceCursor {
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s setLeaf) chunkSource() chunks.ChunkSource {
|
||||
return s.cs
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user