Merge pull request #1030 from kalman/followup

Add tests for modifying chunked sets/maps/lists read from a chunkstore.
This commit is contained in:
Ben Kalman
2016-02-25 15:54:54 -08:00
6 changed files with 141 additions and 95 deletions

View File

@@ -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())
}

View File

@@ -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))
}

View File

@@ -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
}

View File

@@ -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))
}

View File

@@ -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)

View File

@@ -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
}