Add tests for type after mutations (#1753)

Also, remove invariant for set intersection. We can handle different
types now.

Fixes #1749
This commit is contained in:
Erik Arvidsson
2016-06-08 11:39:12 -07:00
parent 335a28026c
commit bc896efcc5
7 changed files with 214 additions and 14 deletions
+26
View File
@@ -795,3 +795,29 @@ func TestListDiffString3(t *testing.T) {
}
assert.Equal(diff2Expected, diff2, "expected diff is wrong")
}
func TestListTypeAfterMutations(t *testing.T) {
assert := assert.New(t)
test := func(n int, c interface{}) {
values := generateNumbersAsValues(n)
l := NewList(values...)
assert.Equal(l.Len(), uint64(n))
assert.IsType(c, l.sequence())
assert.True(l.Type().Equals(MakeListType(NumberType)))
l = l.Append(NewString("a"))
assert.Equal(l.Len(), uint64(n+1))
assert.IsType(c, l.sequence())
assert.True(l.Type().Equals(MakeListType(MakeUnionType(NumberType, StringType))))
l = l.Splice(l.Len()-1, 1)
assert.Equal(l.Len(), uint64(n))
assert.IsType(c, l.sequence())
assert.True(l.Type().Equals(MakeListType(NumberType)))
}
test(10, listLeafSequence{})
test(100, indexedMetaSequence{})
}
+30
View File
@@ -947,3 +947,33 @@ func TestMapModifyAfterRead(t *testing.T) {
m = m.Set(fst, fstval)
assert.True(m.Has(fst))
}
func TestMapTypeAfterMutations(t *testing.T) {
assert := assert.New(t)
test := func(n int, c interface{}) {
values := make([]Value, 2*n)
for i := 0; i < n; i++ {
values[2*i] = Number(i)
values[2*i+1] = Number(i)
}
m := NewMap(values...)
assert.Equal(m.Len(), uint64(n))
assert.IsType(c, m.sequence())
assert.True(m.Type().Equals(MakeMapType(NumberType, NumberType)))
m = m.Set(NewString("a"), NewString("a"))
assert.Equal(m.Len(), uint64(n+1))
assert.IsType(c, m.sequence())
assert.True(m.Type().Equals(MakeMapType(MakeUnionType(NumberType, StringType), MakeUnionType(NumberType, StringType))))
m = m.Remove(NewString("a"))
assert.Equal(m.Len(), uint64(n))
assert.IsType(c, m.sequence())
assert.True(m.Type().Equals(MakeMapType(NumberType, NumberType)))
}
test(10, mapLeafSequence{})
test(100, orderedMetaSequence{})
}
+26
View File
@@ -804,3 +804,29 @@ func TestSetModifyAfterRead(t *testing.T) {
set = set.Insert(fst)
assert.True(set.Has(fst))
}
func TestSetTypeAfterMutations(t *testing.T) {
assert := assert.New(t)
test := func(n int, c interface{}) {
values := generateNumbersAsValues(n)
s := NewSet(values...)
assert.Equal(s.Len(), uint64(n))
assert.IsType(c, s.sequence())
assert.True(s.Type().Equals(MakeSetType(NumberType)))
s = s.Insert(NewString("a"))
assert.Equal(s.Len(), uint64(n+1))
assert.IsType(c, s.sequence())
assert.True(s.Type().Equals(MakeSetType(MakeUnionType(NumberType, StringType))))
s = s.Remove(NewString("a"))
assert.Equal(s.Len(), uint64(n))
assert.IsType(c, s.sequence())
assert.True(s.Type().Equals(MakeSetType(NumberType)))
}
test(10, setLeafSequence{})
test(100, orderedMetaSequence{})
}
+28 -3
View File
@@ -7,18 +7,19 @@
import {assert} from 'chai';
import {suite, setup, teardown, test} from 'mocha';
import List, {ListWriter} from './list.js';
import List, {ListWriter, ListLeafSequence} from './list.js';
import Ref from './ref.js';
import {MetaTuple, newListMetaSequence} from './meta-sequence.js';
import {calcSplices} from './edit-distance.js';
import {equals} from './compare.js';
import {invariant, notNull} from './assert.js';
import {newStruct} from './struct.js';
import {
makeRefType,
makeListType,
makeRefType,
makeUnionType,
numberType,
stringType,
} from './type.js';
import {
assertChunkCountAndType,
@@ -32,6 +33,7 @@ import {
testRoundTripAndValidate,
} from './test-util.js';
import TestDatabase from './test-database.js';
import {IndexedMetaSequence} from './meta-sequence.js';
const testListSize = 5000;
const listOfNRef = 'sha1-241e54086d50c131db3c2f3f5f17e68f42fd98ac';
@@ -591,4 +593,27 @@ suite('ListWriter', () => {
assert.strictEqual(l2, l3);
});
test('Type after mutations', async () => {
async function t(n, c) {
const values: any = intSequence(n);
let l = new List(values);
assert.equal(l.length, n);
assert.instanceOf(l.sequence, c);
assert.isTrue(equals(l.type, makeListType(numberType)));
l = await l.append('a');
assert.equal(l.length, n + 1);
assert.instanceOf(l.sequence, c);
assert.isTrue(equals(l.type, makeListType(makeUnionType([numberType, stringType]))));
l = await l.splice(l.length - 1, 1);
assert.equal(l.length, n);
assert.instanceOf(l.sequence, c);
assert.isTrue(equals(l.type, makeListType(numberType)));
}
await t(10, ListLeafSequence);
await t(100, IndexedMetaSequence);
});
});
+36 -1
View File
@@ -16,11 +16,18 @@ import Struct, {newStruct} from './struct.js';
import {flatten, flattenParallel, deriveCollectionHeight} from './test-util.js';
import {invariant, notNull} from './assert.js';
import Chunk from './chunk.js';
import Map from './map.js';
import Map, {MapLeafSequence} from './map.js';
import {MetaTuple, newMapMetaSequence} from './meta-sequence.js';
import Hash from './hash.js';
import type {ValueReadWriter} from './value-store.js';
import {compare, equals} from './compare.js';
import {OrderedMetaSequence} from './meta-sequence.js';
import {
makeMapType,
makeUnionType,
numberType,
stringType,
} from './type.js';
const testMapSize = 1000;
const mapOfNRef = 'sha1-9fce950ce2606ced8681a695b608384c642ffb53';
@@ -658,4 +665,32 @@ suite('CompoundMap', () => {
assert.deepEqual(sequence.items[0].ref, chunks[0]);
assert.deepEqual(sequence.items[1].ref, chunks[1]);
});
test('Type after mutations', async () => {
async function t(n, c) {
const values: any = new Array(n);
for (let i = 0; i < n; i++) {
values[i] = [i, i];
}
let m = new Map(values);
assert.equal(m.size, n);
assert.instanceOf(m.sequence, c);
assert.isTrue(equals(m.type, makeMapType(numberType, numberType)));
m = await m.set('a', 'a');
assert.equal(m.size, n + 1);
assert.instanceOf(m.sequence, c);
assert.isTrue(equals(m.type, makeMapType(makeUnionType([numberType, stringType]),
makeUnionType([numberType, stringType]))));
m = await m.remove('a');
assert.equal(m.size, n);
assert.instanceOf(m.sequence, c);
assert.isTrue(equals(m.type, makeMapType(numberType, numberType)));
}
await t(10, MapLeafSequence);
await t(100, OrderedMetaSequence);
});
});
+68 -5
View File
@@ -13,7 +13,7 @@ import Database from './database.js';
import Hash from './hash.js';
import MemoryStore from './memory-store.js';
import Ref from './ref.js';
import Set from './set.js';
import Set, {SetLeafSequence} from './set.js';
import type {ValueReadWriter} from './value-store.js';
import {BatchStoreAdaptorDelegate, makeTestingBatchStore} from './batch-store-adaptor.js';
import {MetaTuple, newSetMetaSequence} from './meta-sequence.js';
@@ -22,6 +22,13 @@ import {compare, equals} from './compare.js';
import {flatten, flattenParallel, intSequence, deriveCollectionHeight} from './test-util.js';
import {invariant, notNull} from './assert.js';
import {newStruct} from './struct.js';
import {OrderedMetaSequence} from './meta-sequence.js';
import {
makeSetType,
makeUnionType,
numberType,
stringType,
} from './type.js';
const testSetSize = 5000;
const setOfNRef = 'sha1-1fc97c4e369770b643e013569c68687765601514';
@@ -309,8 +316,8 @@ suite('SetLeaf', () => {
test('chunks', () => {
const refs = ['x', 'a', 'b'].map(c => db.writeValue(c));
refs.sort(compare);
const l = new Set(['z', ...refs]);
assert.deepEqual(refs, l.chunks);
const s = new Set(['z', ...refs]);
assert.deepEqual(refs, s.chunks);
});
});
@@ -328,8 +335,8 @@ suite('CompoundSet', () => {
let tuples = [];
for (let i = 0; i < values.length; i += 2) {
const l = new Set([values[i], values[i + 1]]);
const r = vwr.writeValue(l);
const s = new Set([values[i], values[i + 1]]);
const r = vwr.writeValue(s);
tuples.push(new MetaTuple(r, values[i + 1], 2, null));
}
@@ -663,4 +670,60 @@ suite('CompoundSet', () => {
assert.deepEqual(sequence.items[0].ref, chunks[0]);
assert.deepEqual(sequence.items[1].ref, chunks[1]);
});
test('Type after mutations', async () => {
async function t(n, c) {
const values: any = intSequence(n);
let s = new Set(values);
assert.equal(s.size, n);
assert.instanceOf(s.sequence, c);
assert.isTrue(equals(s.type, makeSetType(numberType)));
s = await s.insert('a');
assert.equal(s.size, n + 1);
assert.instanceOf(s.sequence, c);
assert.isTrue(equals(s.type, makeSetType(makeUnionType([numberType, stringType]))));
s = await s.remove('a');
assert.equal(s.size, n);
assert.instanceOf(s.sequence, c);
assert.isTrue(equals(s.type, makeSetType(numberType)));
}
await t(10, SetLeafSequence);
await t(100, OrderedMetaSequence);
});
test('Type after mutations - interesect', async () => {
async function t(n, c) {
const nums: any = intSequence(n);
const strings = nums.map(n => String.fromCodePoint(n));
const combined = nums.concat(strings);
const numSet = new Set(nums);
assert.equal(numSet.size, n);
assert.instanceOf(numSet.sequence, c);
assert.isTrue(equals(numSet.type, makeSetType(numberType)));
const stringSet = new Set(strings);
assert.equal(stringSet.size, n);
assert.instanceOf(stringSet.sequence, c);
assert.isTrue(equals(stringSet.type, makeSetType(stringType)));
const combinedSet = new Set(combined);
assert.equal(combinedSet.size, 2 * n);
assert.instanceOf(combinedSet.sequence, c);
assert.isTrue(equals(combinedSet.type, makeSetType(makeUnionType([numberType, stringType]))));
const s = await combinedSet.intersect(numSet);
assert.isTrue(equals(s, numSet));
const s2 = await combinedSet.intersect(stringSet);
assert.isTrue(equals(s2, stringSet));
}
await t(10, SetLeafSequence);
await t(100, OrderedMetaSequence);
});
});
-5
View File
@@ -159,11 +159,6 @@ export default class Set<T: Value> extends Collection<OrderedSequence> {
return this;
}
// Can't intersect sets of different element type.
for (let i = 0; i < sets.length; i++) {
invariant(equals(sets[i].type, this.type));
}
let cursor = await this.sequence.newCursorAt(null);
if (!cursor.valid) {
return this;