373 lines
11 KiB
JavaScript
373 lines
11 KiB
JavaScript
import { wait, initArrays, compareUsers, Y, flushAll, 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 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)
|
|
})
|
|
*/
|