move array tests and map tests to yjs
This commit is contained in:
parent
3ca260e0da
commit
7e12ea2db5
374
test/y-array.tests.js
Normal file
374
test/y-array.tests.js
Normal file
@ -0,0 +1,374 @@
|
||||
import { wait, initArrays, compareUsers, Y, flushAll, garbageCollectUsers, applyRandomTests } from '../tests-lib/helper.js'
|
||||
import { test, proxyConsole } from 'cutest'
|
||||
|
||||
proxyConsole()
|
||||
|
||||
test('basic spec', async function array0 (t) {
|
||||
let { users, array0 } = await initArrays(t, { users: 2 })
|
||||
|
||||
array0.delete(0, 0)
|
||||
t.assert(true, 'Does not throw when deleting zero elements with position 0')
|
||||
|
||||
let throwInvalidPosition = false
|
||||
try {
|
||||
array0.delete(1, 0)
|
||||
} catch (e) {
|
||||
throwInvalidPosition = true
|
||||
}
|
||||
t.assert(throwInvalidPosition, 'Throws when deleting zero elements with an invalid position')
|
||||
|
||||
array0.insert(0, ['A'])
|
||||
array0.delete(1, 0)
|
||||
t.assert(true, 'Does not throw when deleting zero elements with valid position 1')
|
||||
|
||||
await compareUsers(t, users)
|
||||
})
|
||||
|
||||
test('insert three elements, try re-get property', async function array1 (t) {
|
||||
var { users, array0, array1 } = await initArrays(t, { users: 2 })
|
||||
array0.insert(0, [1, 2, 3])
|
||||
t.compare(array0.toArray(), [1, 2, 3], '.toArray() works')
|
||||
await flushAll(t, users)
|
||||
t.compare(array1.toArray(), [1, 2, 3], '.toArray() works after sync')
|
||||
await compareUsers(t, users)
|
||||
})
|
||||
|
||||
test('concurrent insert (handle three conflicts)', async function array2 (t) {
|
||||
var { users, array0, array1, array2 } = await initArrays(t, { users: 3 })
|
||||
array0.insert(0, [0])
|
||||
array1.insert(0, [1])
|
||||
array2.insert(0, [2])
|
||||
|
||||
await compareUsers(t, users)
|
||||
})
|
||||
|
||||
test('concurrent insert&delete (handle three conflicts)', async function array3 (t) {
|
||||
var { users, array0, array1, array2 } = await initArrays(t, { users: 3 })
|
||||
array0.insert(0, ['x', 'y', 'z'])
|
||||
await flushAll(t, users)
|
||||
array0.insert(1, [0])
|
||||
array1.delete(0)
|
||||
array1.delete(1, 1)
|
||||
array2.insert(1, [2])
|
||||
|
||||
await compareUsers(t, users)
|
||||
})
|
||||
|
||||
test('insertions work in late sync', async function array4 (t) {
|
||||
var { users, array0, array1, array2 } = await initArrays(t, { users: 3 })
|
||||
array0.insert(0, ['x', 'y'])
|
||||
await flushAll(t, users)
|
||||
users[1].disconnect()
|
||||
users[2].disconnect()
|
||||
array0.insert(1, ['user0'])
|
||||
array1.insert(1, ['user1'])
|
||||
array2.insert(1, ['user2'])
|
||||
await users[1].reconnect()
|
||||
await users[2].reconnect()
|
||||
await compareUsers(t, users)
|
||||
})
|
||||
|
||||
test('disconnect really prevents sending messages', async function array5 (t) {
|
||||
var { users, array0, array1 } = await initArrays(t, { users: 3 })
|
||||
array0.insert(0, ['x', 'y'])
|
||||
await flushAll(t, users)
|
||||
users[1].disconnect()
|
||||
users[2].disconnect()
|
||||
array0.insert(1, ['user0'])
|
||||
array1.insert(1, ['user1'])
|
||||
await wait(1000)
|
||||
t.compare(array0.toArray(), ['x', 'user0', 'y'])
|
||||
t.compare(array1.toArray(), ['x', 'user1', 'y'])
|
||||
await users[1].reconnect()
|
||||
await users[2].reconnect()
|
||||
await compareUsers(t, users)
|
||||
})
|
||||
|
||||
test('deletions in late sync', async function array6 (t) {
|
||||
var { users, array0, array1 } = await initArrays(t, { users: 2 })
|
||||
array0.insert(0, ['x', 'y'])
|
||||
await flushAll(t, users)
|
||||
await users[1].disconnect()
|
||||
array1.delete(1, 1)
|
||||
array0.delete(0, 2)
|
||||
await wait()
|
||||
await users[1].reconnect()
|
||||
await compareUsers(t, users)
|
||||
})
|
||||
|
||||
test('insert, then marge delete on sync', async function array7 (t) {
|
||||
var { users, array0, array1 } = await initArrays(t, { users: 2 })
|
||||
array0.insert(0, ['x', 'y', 'z'])
|
||||
await flushAll(t, users)
|
||||
await wait()
|
||||
await users[0].disconnect()
|
||||
array1.delete(0, 3)
|
||||
await wait()
|
||||
await users[0].reconnect()
|
||||
await compareUsers(t, users)
|
||||
})
|
||||
|
||||
function compareEvent (t, is, should) {
|
||||
for (var key in should) {
|
||||
t.assert(
|
||||
should[key] === is[key] ||
|
||||
JSON.stringify(should[key]) === JSON.stringify(is[key])
|
||||
, 'event works as expected'
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
test('insert & delete events', async function array8 (t) {
|
||||
var { array0, users } = await initArrays(t, { users: 2 })
|
||||
var event
|
||||
array0.observe(function (e) {
|
||||
event = e
|
||||
})
|
||||
array0.insert(0, [0, 1, 2])
|
||||
compareEvent(t, event, {
|
||||
type: 'insert',
|
||||
index: 0,
|
||||
values: [0, 1, 2],
|
||||
length: 3
|
||||
})
|
||||
array0.delete(0)
|
||||
compareEvent(t, event, {
|
||||
type: 'delete',
|
||||
index: 0,
|
||||
length: 1,
|
||||
values: [0]
|
||||
})
|
||||
array0.delete(0, 2)
|
||||
compareEvent(t, event, {
|
||||
type: 'delete',
|
||||
index: 0,
|
||||
length: 2,
|
||||
values: [1, 2]
|
||||
})
|
||||
await compareUsers(t, users)
|
||||
})
|
||||
|
||||
test('insert & delete events for types', async function array9 (t) {
|
||||
var { array0, users } = await initArrays(t, { users: 2 })
|
||||
var event
|
||||
array0.observe(function (e) {
|
||||
event = e
|
||||
})
|
||||
array0.insert(0, [Y.Array])
|
||||
compareEvent(t, event, {
|
||||
type: 'insert',
|
||||
object: array0,
|
||||
index: 0,
|
||||
length: 1
|
||||
})
|
||||
var type = array0.get(0)
|
||||
t.assert(type._model != null, 'Model of type is defined')
|
||||
array0.delete(0)
|
||||
compareEvent(t, event, {
|
||||
type: 'delete',
|
||||
object: array0,
|
||||
index: 0,
|
||||
length: 1
|
||||
})
|
||||
await compareUsers(t, users)
|
||||
})
|
||||
|
||||
test('insert & delete events for types (2)', async function array10 (t) {
|
||||
var { array0, users } = await initArrays(t, { users: 2 })
|
||||
var events = []
|
||||
array0.observe(function (e) {
|
||||
events.push(e)
|
||||
})
|
||||
array0.insert(0, ['hi', Y.Map])
|
||||
compareEvent(t, events[0], {
|
||||
type: 'insert',
|
||||
object: array0,
|
||||
index: 0,
|
||||
length: 1,
|
||||
values: ['hi']
|
||||
})
|
||||
compareEvent(t, events[1], {
|
||||
type: 'insert',
|
||||
object: array0,
|
||||
index: 1,
|
||||
length: 1
|
||||
})
|
||||
array0.delete(1)
|
||||
compareEvent(t, events[2], {
|
||||
type: 'delete',
|
||||
object: array0,
|
||||
index: 1,
|
||||
length: 1
|
||||
})
|
||||
await compareUsers(t, users)
|
||||
})
|
||||
|
||||
test('garbage collector', async function gc1 (t) {
|
||||
var { users, array0 } = await initArrays(t, { users: 3 })
|
||||
|
||||
array0.insert(0, ['x', 'y', 'z'])
|
||||
await flushAll(t, users)
|
||||
users[0].disconnect()
|
||||
array0.delete(0, 3)
|
||||
await wait()
|
||||
await users[0].reconnect()
|
||||
await flushAll(t, users)
|
||||
await garbageCollectUsers(t, users)
|
||||
await compareUsers(t, users)
|
||||
})
|
||||
|
||||
test('event has correct value when setting a primitive on a YArray (same user)', async function array11 (t) {
|
||||
var { array0, users } = await initArrays(t, { users: 3 })
|
||||
|
||||
var event
|
||||
array0.observe(function (e) {
|
||||
event = e
|
||||
})
|
||||
array0.insert(0, ['stuff'])
|
||||
t.assert(event.values[0] === event.object.get(0), 'compare value with get method')
|
||||
t.assert(event.values[0] === 'stuff', 'check that value is actually present')
|
||||
t.assert(event.values[0] === array0.toArray()[0], '.toArray works as expected')
|
||||
await compareUsers(t, users)
|
||||
})
|
||||
|
||||
test('event has correct value when setting a primitive on a YArray (received from another user)', async function array12 (t) {
|
||||
var { users, array0, array1 } = await initArrays(t, { users: 3 })
|
||||
|
||||
var event
|
||||
array0.observe(function (e) {
|
||||
event = e
|
||||
})
|
||||
array1.insert(0, ['stuff'])
|
||||
await flushAll(t, users)
|
||||
t.assert(event.values[0] === event.object.get(0), 'compare value with get method')
|
||||
t.assert(event.values[0] === 'stuff', 'check that value is actually present')
|
||||
t.assert(event.values[0] === array0.toArray()[0], '.toArray works as expected')
|
||||
await compareUsers(t, users)
|
||||
})
|
||||
|
||||
test('event has correct value when setting a type on a YArray (same user)', async function array13 (t) {
|
||||
var { array0, users } = await initArrays(t, { users: 3 })
|
||||
|
||||
var event
|
||||
array0.observe(function (e) {
|
||||
event = e
|
||||
})
|
||||
array0.insert(0, [Y.Array])
|
||||
t.assert(event.values[0] === event.object.get(0), 'compare value with get method')
|
||||
t.assert(event.values[0] != null, 'event.value exists')
|
||||
t.assert(event.values[0] === array0.toArray()[0], '.toArray works as expected')
|
||||
await compareUsers(t, users)
|
||||
})
|
||||
test('event has correct value when setting a type on a YArray (ops received from another user)', async function array14 (t) {
|
||||
var { users, array0, array1 } = await initArrays(t, { users: 3 })
|
||||
|
||||
var event
|
||||
array0.observe(function (e) {
|
||||
event = e
|
||||
})
|
||||
array1.insert(0, [Y.Array])
|
||||
await flushAll(t, users)
|
||||
t.assert(event.values[0] === event.object.get(0), 'compare value with get method')
|
||||
t.assert(event.values[0] != null, 'event.value exists')
|
||||
t.assert(event.values[0] === array0.toArray()[0], '.toArray works as expected')
|
||||
await compareUsers(t, users)
|
||||
})
|
||||
|
||||
var _uniqueNumber = 0
|
||||
function getUniqueNumber () {
|
||||
return _uniqueNumber++
|
||||
}
|
||||
|
||||
var arrayTransactions = [
|
||||
function insert (t, user, chance) {
|
||||
var uniqueNumber = getUniqueNumber()
|
||||
var content = []
|
||||
var len = chance.integer({ min: 1, max: 4 })
|
||||
for (var i = 0; i < len; i++) {
|
||||
content.push(uniqueNumber)
|
||||
}
|
||||
var pos = chance.integer({ min: 0, max: user.share.array.length })
|
||||
user.share.array.insert(pos, content)
|
||||
},
|
||||
function insertTypeArray (t, user, chance) {
|
||||
var pos = chance.integer({ min: 0, max: user.share.array.length })
|
||||
user.share.array.insert(pos, [Y.Array])
|
||||
var array2 = user.share.array.get(pos)
|
||||
array2.insert(0, [1, 2, 3, 4])
|
||||
},
|
||||
function insertTypeMap (t, user, chance) {
|
||||
var pos = chance.integer({ min: 0, max: user.share.array.length })
|
||||
user.share.array.insert(pos, [Y.Map])
|
||||
var map = user.share.array.get(pos)
|
||||
map.set('someprop', 42)
|
||||
map.set('someprop', 43)
|
||||
map.set('someprop', 44)
|
||||
},
|
||||
function _delete (t, user, chance) {
|
||||
var length = user.share.array._content.length
|
||||
if (length > 0) {
|
||||
var pos = chance.integer({ min: 0, max: length - 1 })
|
||||
var delLength = chance.integer({ min: 1, max: Math.min(2, length - pos) })
|
||||
if (user.share.array._content[pos].type != null) {
|
||||
if (chance.bool()) {
|
||||
var type = user.share.array.get(pos)
|
||||
if (type instanceof Y.Array.typeDefinition.class) {
|
||||
if (type._content.length > 0) {
|
||||
pos = chance.integer({ min: 0, max: type._content.length - 1 })
|
||||
delLength = chance.integer({ min: 0, max: Math.min(2, type._content.length - pos) })
|
||||
type.delete(pos, delLength)
|
||||
}
|
||||
} else {
|
||||
type.delete('someprop')
|
||||
}
|
||||
} else {
|
||||
user.share.array.delete(pos, delLength)
|
||||
}
|
||||
} else {
|
||||
user.share.array.delete(pos, delLength)
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
test('y-array: Random tests (42)', async function randomArray42 (t) {
|
||||
await applyRandomTests(t, arrayTransactions, 42)
|
||||
})
|
||||
|
||||
test('y-array: Random tests (43)', async function randomArray43 (t) {
|
||||
await applyRandomTests(t, arrayTransactions, 43)
|
||||
})
|
||||
|
||||
test('y-array: Random tests (44)', async function randomArray44 (t) {
|
||||
await applyRandomTests(t, arrayTransactions, 44)
|
||||
})
|
||||
|
||||
test('y-array: Random tests (45)', async function randomArray45 (t) {
|
||||
await applyRandomTests(t, arrayTransactions, 45)
|
||||
})
|
||||
|
||||
test('y-array: Random tests (46)', async function randomArray46 (t) {
|
||||
await applyRandomTests(t, arrayTransactions, 46)
|
||||
})
|
||||
|
||||
test('y-array: Random tests (47)', async function randomArray47 (t) {
|
||||
await applyRandomTests(t, arrayTransactions, 47)
|
||||
})
|
||||
|
||||
/*
|
||||
test('y-array: Random tests (200)', async function randomArray200 (t) {
|
||||
await applyRandomTests(t, arrayTransactions, 200)
|
||||
})
|
||||
|
||||
test('y-array: Random tests (300)', async function randomArray300 (t) {
|
||||
await applyRandomTests(t, arrayTransactions, 300)
|
||||
})
|
||||
|
||||
test('y-array: Random tests (400)', async function randomArray400 (t) {
|
||||
await applyRandomTests(t, arrayTransactions, 400)
|
||||
})
|
||||
|
||||
test('y-array: Random tests (500)', async function randomArray500 (t) {
|
||||
await applyRandomTests(t, arrayTransactions, 500)
|
||||
})
|
||||
*/
|
371
test/y-map.tests.js
Normal file
371
test/y-map.tests.js
Normal file
@ -0,0 +1,371 @@
|
||||
import { initArrays, compareUsers, Y, flushAll, applyRandomTests } from '../tests-lib/helper.js'
|
||||
import { test, proxyConsole } from 'cutest'
|
||||
|
||||
proxyConsole()
|
||||
|
||||
test('basic map tests', async function map0 (t) {
|
||||
let { users, map0, map1, map2 } = await initArrays(t, { users: 3 })
|
||||
users[2].disconnect()
|
||||
|
||||
map0.set('number', 1)
|
||||
map0.set('string', 'hello Y')
|
||||
map0.set('object', { key: { key2: 'value' } })
|
||||
map0.set('y-map', Y.Map)
|
||||
let map = map0.get('y-map')
|
||||
map.set('y-array', Y.Array)
|
||||
let array = map.get('y-array')
|
||||
array.insert(0, [0])
|
||||
array.insert(0, [-1])
|
||||
|
||||
t.assert(map0.get('number') === 1, 'client 0 computed the change (number)')
|
||||
t.assert(map0.get('string') === 'hello Y', 'client 0 computed the change (string)')
|
||||
t.compare(map0.get('object'), { key: { key2: 'value' } }, 'client 0 computed the change (object)')
|
||||
t.assert(map0.get('y-map').get('y-array').get(0) === -1, 'client 0 computed the change (type)')
|
||||
|
||||
await users[2].reconnect()
|
||||
await flushAll(t, users)
|
||||
|
||||
t.assert(map1.get('number') === 1, 'client 1 received the update (number)')
|
||||
t.assert(map1.get('string') === 'hello Y', 'client 1 received the update (string)')
|
||||
t.compare(map1.get('object'), { key: { key2: 'value' } }, 'client 1 received the update (object)')
|
||||
t.assert(map1.get('y-map').get('y-array').get(0) === -1, 'client 1 received the update (type)')
|
||||
|
||||
// compare disconnected user
|
||||
t.assert(map2.get('number') === 1, 'client 2 received the update (number) - was disconnected')
|
||||
t.assert(map2.get('string') === 'hello Y', 'client 2 received the update (string) - was disconnected')
|
||||
t.compare(map2.get('object'), { key: { key2: 'value' } }, 'client 2 received the update (object) - was disconnected')
|
||||
t.assert(map2.get('y-map').get('y-array').get(0) === -1, 'client 2 received the update (type) - was disconnected')
|
||||
await compareUsers(t, users)
|
||||
})
|
||||
|
||||
test('Basic get&set of Map property (converge via sync)', async function map1 (t) {
|
||||
let { users, map0 } = await initArrays(t, { users: 2 })
|
||||
map0.set('stuff', 'stuffy')
|
||||
t.compare(map0.get('stuff'), 'stuffy')
|
||||
|
||||
await flushAll(t, users)
|
||||
|
||||
for (let user of users) {
|
||||
var u = user.share.map
|
||||
t.compare(u.get('stuff'), 'stuffy')
|
||||
}
|
||||
await compareUsers(t, users)
|
||||
})
|
||||
|
||||
test('Map can set custom types (Map)', async function map2 (t) {
|
||||
let { users, map0 } = await initArrays(t, { users: 2 })
|
||||
var map = map0.set('Map', Y.Map)
|
||||
map.set('one', 1)
|
||||
map = map0.get('Map')
|
||||
t.compare(map.get('one'), 1)
|
||||
await compareUsers(t, users)
|
||||
})
|
||||
|
||||
test('Map can set custom types (Map) - get also returns the type', async function map3 (t) {
|
||||
let { users, map0 } = await initArrays(t, { users: 2 })
|
||||
map0.set('Map', Y.Map)
|
||||
var map = map0.get('Map')
|
||||
map.set('one', 1)
|
||||
map = map0.get('Map')
|
||||
t.compare(map.get('one'), 1)
|
||||
await compareUsers(t, users)
|
||||
})
|
||||
|
||||
test('Map can set custom types (Array)', async function map4 (t) {
|
||||
let { users, map0 } = await initArrays(t, { users: 2 })
|
||||
var array = map0.set('Array', Y.Array)
|
||||
array.insert(0, [1, 2, 3])
|
||||
array = map0.get('Array')
|
||||
t.compare(array.toArray(), [1, 2, 3])
|
||||
await compareUsers(t, users)
|
||||
})
|
||||
|
||||
test('Basic get&set of Map property (converge via update)', async function map5 (t) {
|
||||
let { users, map0 } = await initArrays(t, { users: 2 })
|
||||
map0.set('stuff', 'stuffy')
|
||||
t.compare(map0.get('stuff'), 'stuffy')
|
||||
|
||||
await flushAll(t, users)
|
||||
|
||||
for (let user of users) {
|
||||
var u = user.share.map
|
||||
t.compare(u.get('stuff'), 'stuffy')
|
||||
}
|
||||
await compareUsers(t, users)
|
||||
})
|
||||
|
||||
test('Basic get&set of Map property (handle conflict)', async function map6 (t) {
|
||||
let { users, map0, map1 } = await initArrays(t, { users: 3 })
|
||||
map0.set('stuff', 'c0')
|
||||
map1.set('stuff', 'c1')
|
||||
|
||||
await flushAll(t, users)
|
||||
|
||||
for (let user of users) {
|
||||
var u = user.share.map
|
||||
t.compare(u.get('stuff'), 'c0')
|
||||
}
|
||||
await compareUsers(t, users)
|
||||
})
|
||||
|
||||
test('Basic get&set&delete of Map property (handle conflict)', async function map7 (t) {
|
||||
let { users, map0, map1 } = await initArrays(t, { users: 3 })
|
||||
map0.set('stuff', 'c0')
|
||||
map0.delete('stuff')
|
||||
map1.set('stuff', 'c1')
|
||||
await flushAll(t, users)
|
||||
for (let user of users) {
|
||||
var u = user.share.map
|
||||
t.assert(u.get('stuff') === undefined)
|
||||
}
|
||||
await compareUsers(t, users)
|
||||
})
|
||||
|
||||
test('Basic get&set of Map property (handle three conflicts)', async function map8 (t) {
|
||||
let { users, map0, map1, map2 } = await initArrays(t, { users: 3 })
|
||||
map0.set('stuff', 'c0')
|
||||
map1.set('stuff', 'c1')
|
||||
map1.set('stuff', 'c2')
|
||||
map2.set('stuff', 'c3')
|
||||
await flushAll(t, users)
|
||||
for (let user of users) {
|
||||
var u = user.share.map
|
||||
t.compare(u.get('stuff'), 'c0')
|
||||
}
|
||||
await compareUsers(t, users)
|
||||
})
|
||||
|
||||
test('Basic get&set&delete of Map property (handle three conflicts)', async function map9 (t) {
|
||||
let { users, map0, map1, map2, map3 } = await initArrays(t, { users: 4 })
|
||||
map0.set('stuff', 'c0')
|
||||
map1.set('stuff', 'c1')
|
||||
map1.set('stuff', 'c2')
|
||||
map2.set('stuff', 'c3')
|
||||
await flushAll(t, users)
|
||||
map0.set('stuff', 'deleteme')
|
||||
map0.delete('stuff')
|
||||
map1.set('stuff', 'c1')
|
||||
map2.set('stuff', 'c2')
|
||||
map3.set('stuff', 'c3')
|
||||
await flushAll(t, users)
|
||||
for (let user of users) {
|
||||
var u = user.share.map
|
||||
t.assert(u.get('stuff') === undefined)
|
||||
}
|
||||
await compareUsers(t, users)
|
||||
})
|
||||
|
||||
test('observePath properties', async function map10 (t) {
|
||||
let { users, map0, map1, map2 } = await initArrays(t, { users: 3 })
|
||||
let map
|
||||
map0.observePath(['map'], function (map) {
|
||||
if (map != null) {
|
||||
map.set('yay', 4)
|
||||
}
|
||||
})
|
||||
map1.set('map', Y.Map)
|
||||
await flushAll(t, users)
|
||||
map = map2.get('map')
|
||||
t.compare(map.get('yay'), 4)
|
||||
await compareUsers(t, users)
|
||||
})
|
||||
|
||||
test('observe deep properties', async function map11 (t) {
|
||||
let { users, map1, map2, map3 } = await initArrays(t, { users: 4 })
|
||||
var _map1 = map1.set('map', Y.Map)
|
||||
var calls = 0
|
||||
var dmapid
|
||||
_map1.observe(function (event) {
|
||||
calls++
|
||||
t.compare(event.name, 'deepmap')
|
||||
dmapid = event.object.opContents.deepmap
|
||||
})
|
||||
await flushAll(t, users)
|
||||
var _map3 = map3.get('map')
|
||||
_map3.set('deepmap', Y.Map)
|
||||
await flushAll(t, users)
|
||||
var _map2 = map2.get('map')
|
||||
_map2.set('deepmap', Y.Map)
|
||||
await flushAll(t, users)
|
||||
var dmap1 = _map1.get('deepmap')
|
||||
var dmap2 = _map2.get('deepmap')
|
||||
var dmap3 = _map3.get('deepmap')
|
||||
t.assert(calls > 0)
|
||||
t.compare(dmap1._model, dmap2._model)
|
||||
t.compare(dmap1._model, dmap3._model)
|
||||
t.compare(dmap1._model, dmapid)
|
||||
await compareUsers(t, users)
|
||||
})
|
||||
|
||||
test('observes using observePath', async function map12 (t) {
|
||||
let { users, map0 } = await initArrays(t, { users: 2 })
|
||||
var pathes = []
|
||||
var calls = 0
|
||||
map0.observeDeep(function (event) {
|
||||
pathes.push(event.path)
|
||||
calls++
|
||||
})
|
||||
map0.set('map', Y.Map)
|
||||
map0.get('map').set('array', Y.Array)
|
||||
map0.get('map').get('array').insert(0, ['content'])
|
||||
t.assert(calls === 3)
|
||||
t.compare(pathes, [[], ['map'], ['map', 'array']])
|
||||
await compareUsers(t, users)
|
||||
})
|
||||
|
||||
function compareEvent (t, is, should) {
|
||||
for (var key in should) {
|
||||
t.assert(should[key] === is[key])
|
||||
}
|
||||
}
|
||||
|
||||
test('throws add & update & delete events (with type and primitive content)', async function map13 (t) {
|
||||
let { users, map0 } = await initArrays(t, { users: 2 })
|
||||
var event
|
||||
await flushAll(t, users)
|
||||
map0.observe(function (e) {
|
||||
event = e // just put it on event, should be thrown synchronously anyway
|
||||
})
|
||||
map0.set('stuff', 4)
|
||||
compareEvent(t, event, {
|
||||
type: 'add',
|
||||
object: map0,
|
||||
name: 'stuff'
|
||||
})
|
||||
// update, oldValue is in contents
|
||||
map0.set('stuff', Y.Array)
|
||||
compareEvent(t, event, {
|
||||
type: 'update',
|
||||
object: map0,
|
||||
name: 'stuff',
|
||||
oldValue: 4
|
||||
})
|
||||
var replacedArray = map0.get('stuff')
|
||||
// update, oldValue is in opContents
|
||||
map0.set('stuff', 5)
|
||||
var array = event.oldValue
|
||||
t.compare(array._model, replacedArray._model)
|
||||
// delete
|
||||
map0.delete('stuff')
|
||||
compareEvent(t, event, {
|
||||
type: 'delete',
|
||||
name: 'stuff',
|
||||
object: map0,
|
||||
oldValue: 5
|
||||
})
|
||||
await compareUsers(t, users)
|
||||
})
|
||||
|
||||
test('event has correct value when setting a primitive on a YMap (same user)', async function map14 (t) {
|
||||
let { users, map0 } = await initArrays(t, { users: 3 })
|
||||
var event
|
||||
await flushAll(t, users)
|
||||
map0.observe(function (e) {
|
||||
event = e
|
||||
})
|
||||
map0.set('stuff', 2)
|
||||
t.compare(event.value, event.object.get(event.name))
|
||||
await compareUsers(t, users)
|
||||
})
|
||||
|
||||
test('event has correct value when setting a primitive on a YMap (received from another user)', async function map15 (t) {
|
||||
let { users, map0, map1 } = await initArrays(t, { users: 3 })
|
||||
var event
|
||||
await flushAll(t, users)
|
||||
map0.observe(function (e) {
|
||||
event = e
|
||||
})
|
||||
map1.set('stuff', 2)
|
||||
await flushAll(t, users)
|
||||
t.compare(event.value, event.object.get(event.name))
|
||||
await compareUsers(t, users)
|
||||
})
|
||||
|
||||
test('event has correct value when setting a type on a YMap (same user)', async function map16 (t) {
|
||||
let { users, map0 } = await initArrays(t, { users: 3 })
|
||||
var event
|
||||
await flushAll(t, users)
|
||||
map0.observe(function (e) {
|
||||
event = e
|
||||
})
|
||||
map0.set('stuff', Y.Map)
|
||||
t.compare(event.value._model, event.object.get(event.name)._model)
|
||||
await compareUsers(t, users)
|
||||
})
|
||||
|
||||
test('event has correct value when setting a type on a YMap (ops received from another user)', async function map17 (t) {
|
||||
let { users, map0, map1 } = await initArrays(t, { users: 3 })
|
||||
var event
|
||||
await flushAll(t, users)
|
||||
map0.observe(function (e) {
|
||||
event = e
|
||||
})
|
||||
map1.set('stuff', Y.Map)
|
||||
await flushAll(t, users)
|
||||
t.compare(event.value._model, event.object.get(event.name)._model)
|
||||
await compareUsers(t, users)
|
||||
})
|
||||
|
||||
var mapTransactions = [
|
||||
function set (t, user, chance) {
|
||||
let key = chance.pickone(['one', 'two'])
|
||||
var value = chance.string()
|
||||
user.share.map.set(key, value)
|
||||
},
|
||||
function setType (t, user, chance) {
|
||||
let key = chance.pickone(['one', 'two'])
|
||||
var value = chance.pickone([Y.Array, Y.Map])
|
||||
let type = user.share.map.set(key, value)
|
||||
if (value === Y.Array) {
|
||||
type.insert(0, [1, 2, 3, 4])
|
||||
} else {
|
||||
type.set('deepkey', 'deepvalue')
|
||||
}
|
||||
},
|
||||
function _delete (t, user, chance) {
|
||||
let key = chance.pickone(['one', 'two'])
|
||||
user.share.map.delete(key)
|
||||
}
|
||||
]
|
||||
|
||||
test('y-map: Random tests (42)', async function randomMap42 (t) {
|
||||
await applyRandomTests(t, mapTransactions, 42)
|
||||
})
|
||||
|
||||
test('y-map: Random tests (43)', async function randomMap43 (t) {
|
||||
await applyRandomTests(t, mapTransactions, 43)
|
||||
})
|
||||
|
||||
test('y-map: Random tests (44)', async function randomMap44 (t) {
|
||||
await applyRandomTests(t, mapTransactions, 44)
|
||||
})
|
||||
|
||||
test('y-map: Random tests (45)', async function randomMap45 (t) {
|
||||
await applyRandomTests(t, mapTransactions, 45)
|
||||
})
|
||||
|
||||
test('y-map: Random tests (46)', async function randomMap46 (t) {
|
||||
await applyRandomTests(t, mapTransactions, 46)
|
||||
})
|
||||
|
||||
test('y-map: Random tests (47)', async function randomMap47 (t) {
|
||||
await applyRandomTests(t, mapTransactions, 47)
|
||||
})
|
||||
|
||||
/*
|
||||
test('y-map: Random tests (200)', async function randomMap200 (t) {
|
||||
await applyRandomTests(t, mapTransactions, 200)
|
||||
})
|
||||
|
||||
test('y-map: Random tests (300)', async function randomMap300 (t) {
|
||||
await applyRandomTests(t, mapTransactions, 300)
|
||||
})
|
||||
|
||||
test('y-map: Random tests (400)', async function randomMap400 (t) {
|
||||
await applyRandomTests(t, mapTransactions, 400)
|
||||
})
|
||||
|
||||
test('y-map: Random tests (500)', async function randomMap500 (t) {
|
||||
await applyRandomTests(t, mapTransactions, 500)
|
||||
})
|
||||
*/
|
@ -12,6 +12,9 @@ export let Y = _Y
|
||||
|
||||
Y.extend(yMemory, yArray, yMap, yTest)
|
||||
|
||||
export var database = { name: 'memory' }
|
||||
export var connector = { name: 'test', url: 'http://localhost:1234' }
|
||||
|
||||
function * getStateSet () {
|
||||
var ss = {}
|
||||
yield * this.ss.iterate(this, null, null, function * (n) {
|
||||
@ -60,7 +63,16 @@ export async function compareUsers (t, users) {
|
||||
await wait()
|
||||
await flushAll(t, users)
|
||||
|
||||
var userTypeContents = users.map(u => u.share.array._content.map(c => c.val || JSON.stringify(c.type)))
|
||||
var userArrayValues = users.map(u => u.share.array._content.map(c => c.val || JSON.stringify(c.type)))
|
||||
function valueToComparable (v) {
|
||||
if (v != null && v._model != null) {
|
||||
return v._model
|
||||
} else {
|
||||
return v || null
|
||||
}
|
||||
}
|
||||
var userMapOneValues = users.map(u => u.share.map.get('one')).map(valueToComparable)
|
||||
var userMapTwoValues = users.map(u => u.share.map.get('two')).map(valueToComparable)
|
||||
|
||||
await users[0].db.garbageCollect()
|
||||
await users[0].db.garbageCollect()
|
||||
@ -118,7 +130,9 @@ export async function compareUsers (t, users) {
|
||||
}))
|
||||
for (var i = 0; i < data.length - 1; i++) {
|
||||
await t.asyncGroup(async () => {
|
||||
t.compare(userTypeContents[i], userTypeContents[i + 1], 'types')
|
||||
t.compare(userArrayValues[i], userArrayValues[i + 1], 'array types')
|
||||
t.compare(userMapOneValues[i], userMapOneValues[i + 1], 'map types (propery "one")')
|
||||
t.compare(userMapTwoValues[i], userMapTwoValues[i + 1], 'map types (propery "two")')
|
||||
t.compare(data[i].os, data[i + 1].os, 'os')
|
||||
t.compare(data[i].ds, data[i + 1].ds, 'ds')
|
||||
t.compare(data[i].ss, data[i + 1].ss, 'ss')
|
||||
@ -135,17 +149,17 @@ export async function initArrays (t, opts) {
|
||||
}
|
||||
var share = Object.assign({ flushHelper: 'Map', array: 'Array', map: 'Map' }, opts.share)
|
||||
var chance = opts.chance || new Chance(t.getSeed() * 1000000000)
|
||||
var connector = Object.assign({ room: 'debugging_' + t.name, generateUserId: false, testContext: t, chance }, opts.connector)
|
||||
var conn = Object.assign({ room: 'debugging_' + t.name, generateUserId: false, testContext: t, chance }, connector)
|
||||
for (let i = 0; i < opts.users; i++) {
|
||||
let dbOpts
|
||||
let connOpts
|
||||
if (i === 0) {
|
||||
// Only one instance can gc!
|
||||
dbOpts = Object.assign({ gc: false }, opts.db)
|
||||
connOpts = Object.assign({ role: 'master' }, connector)
|
||||
dbOpts = Object.assign({ gc: false }, database)
|
||||
connOpts = Object.assign({ role: 'master' }, conn)
|
||||
} else {
|
||||
dbOpts = Object.assign({ gc: false }, opts.db)
|
||||
connOpts = Object.assign({ role: 'slave' }, connector)
|
||||
dbOpts = Object.assign({ gc: false }, database)
|
||||
connOpts = Object.assign({ role: 'slave' }, conn)
|
||||
}
|
||||
let y = await Y({
|
||||
connector: connOpts,
|
||||
@ -220,3 +234,48 @@ export function wait (t) {
|
||||
setTimeout(resolve, t != null ? t : 100)
|
||||
})
|
||||
}
|
||||
|
||||
export async function applyRandomTests (t, mods, iterations) {
|
||||
const chance = new Chance(t.getSeed() * 1000000000)
|
||||
var initInformation = await initArrays(t, { users: 5, chance: chance })
|
||||
let { users } = initInformation
|
||||
for (var i = 0; i < iterations; i++) {
|
||||
if (chance.bool({likelihood: 10})) {
|
||||
// 10% chance to disconnect/reconnect a user
|
||||
// we make sure that the first users always is connected
|
||||
let user = chance.pickone(users.slice(1))
|
||||
if (user.connector.isSynced) {
|
||||
if (users.filter(u => u.connector.isSynced).length > 1) {
|
||||
// make sure that at least one user remains in the room
|
||||
await user.disconnect()
|
||||
if (users[0].connector.testRoom == null) {
|
||||
await wait(100)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
await user.reconnect()
|
||||
if (users[0].connector.testRoom == null) {
|
||||
await wait(100)
|
||||
}
|
||||
await new Promise(function (resolve) {
|
||||
user.connector.whenSynced(resolve)
|
||||
})
|
||||
}
|
||||
} else if (chance.bool({likelihood: 5})) {
|
||||
// 20%*!prev chance to flush all & garbagecollect
|
||||
// TODO: We do not gc all users as this does not work yet
|
||||
// await garbageCollectUsers(t, users)
|
||||
await flushAll(t, users)
|
||||
await users[0].db.emptyGarbageCollector()
|
||||
await flushAll(t, users)
|
||||
} else if (chance.bool({likelihood: 10})) {
|
||||
// 20%*!prev chance to flush some operations
|
||||
await flushSome(t, users)
|
||||
}
|
||||
let user = chance.pickone(users)
|
||||
var test = chance.pickone(mods)
|
||||
test(t, user, chance)
|
||||
}
|
||||
await compareUsers(t, users)
|
||||
return initInformation
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user