implemented indexedDB database :shipit:
This commit is contained in:
parent
45814c4e00
commit
04139d3b7e
@ -65,6 +65,8 @@ class AbstractDatabase {
|
||||
if (this.gcTimeout > 0) {
|
||||
garbageCollect()
|
||||
}
|
||||
this.waitingTransactions = []
|
||||
this.transactionInProgress = false
|
||||
}
|
||||
addToDebug () {
|
||||
if (typeof YConcurrency_TestingMode !== 'undefined') {
|
||||
@ -252,8 +254,8 @@ class AbstractDatabase {
|
||||
yield* Y.Struct.Delete.execute.call(this, op)
|
||||
} else if ((yield* this.getOperation(op.id)) == null && !(yield* this.isGarbageCollected(op.id))) {
|
||||
yield* Y.Struct[op.struct].execute.call(this, op)
|
||||
var next = yield* this.addOperation(op)
|
||||
yield* this.store.operationAdded(this, op, next)
|
||||
yield* this.addOperation(op)
|
||||
yield* this.store.operationAdded(this, op)
|
||||
|
||||
// Delete if DS says this is actually deleted
|
||||
if (yield* this.isDeleted(op.id)) {
|
||||
@ -262,7 +264,7 @@ class AbstractDatabase {
|
||||
}
|
||||
}
|
||||
// called by a transaction when an operation is added
|
||||
* operationAdded (transaction, op, next) {
|
||||
* operationAdded (transaction, op) {
|
||||
// increase SS
|
||||
var o = op
|
||||
var state = yield* transaction.getState(op.id[0])
|
||||
@ -270,7 +272,7 @@ class AbstractDatabase {
|
||||
// either its a new operation (1. case), or it is an operation that was deleted, but is not yet in the OS
|
||||
state.clock++
|
||||
yield* transaction.checkDeleteStoreForState(state)
|
||||
o = next()
|
||||
o = yield* transaction.os.findNext(o.id)
|
||||
}
|
||||
yield* transaction.setState(state)
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* global Y, async */
|
||||
/* global Y, async, databases */
|
||||
/* eslint-env browser,jasmine,console */
|
||||
var databases = ['Memory']
|
||||
|
||||
for (var database of databases) {
|
||||
describe(`Database (${database})`, function () {
|
||||
var store
|
||||
@ -8,7 +8,14 @@ for (var database of databases) {
|
||||
describe('Basic', function () {
|
||||
beforeEach(function () {
|
||||
store = new Y[database](null, {
|
||||
gcTimeout: -1
|
||||
gcTimeout: -1,
|
||||
namespace: 'testing'
|
||||
})
|
||||
})
|
||||
afterEach(function (done) {
|
||||
store.requestTransaction(function * () {
|
||||
yield* this.store.destroy()
|
||||
done()
|
||||
})
|
||||
})
|
||||
it('Deleted operation is deleted', async(function * (done) {
|
||||
@ -151,7 +158,14 @@ for (var database of databases) {
|
||||
describe('Basic Tests', function () {
|
||||
beforeEach(function () {
|
||||
store = new Y[database](null, {
|
||||
gcTimeout: -1
|
||||
gcTimeout: -1,
|
||||
namespace: 'testing'
|
||||
})
|
||||
})
|
||||
afterEach(function (done) {
|
||||
store.requestTransaction(function * () {
|
||||
yield* this.store.destroy()
|
||||
done()
|
||||
})
|
||||
})
|
||||
it('debug #1', function (done) {
|
||||
@ -160,9 +174,9 @@ for (var database of databases) {
|
||||
yield* this.os.put({id: [0]})
|
||||
yield* this.os.delete([2])
|
||||
yield* this.os.put({id: [1]})
|
||||
expect(yield* this.os.find([0])).not.toBeNull()
|
||||
expect(yield* this.os.find([1])).not.toBeNull()
|
||||
expect(yield* this.os.find([2])).toBeNull()
|
||||
expect(yield* this.os.find([0])).toBeTruthy()
|
||||
expect(yield* this.os.find([1])).toBeTruthy()
|
||||
expect(yield* this.os.find([2])).toBeFalsy()
|
||||
done()
|
||||
})
|
||||
})
|
||||
@ -207,14 +221,15 @@ for (var database of databases) {
|
||||
var elements = []
|
||||
beforeAll(function (done) {
|
||||
store = new Y[database](null, {
|
||||
gcTimeout: -1
|
||||
gcTimeout: -1,
|
||||
namespace: 'testing'
|
||||
})
|
||||
store.requestTransaction(function * () {
|
||||
for (var i = 0; i < numberOfOSTests; i++) {
|
||||
var r = Math.random()
|
||||
if (r < 0.8) {
|
||||
var obj = [Math.floor(Math.random() * numberOfOSTests * 10000)]
|
||||
if (!(this.os.findNode(obj))) {
|
||||
if (!(yield* this.os.find(obj))) {
|
||||
elements.push(obj)
|
||||
yield* this.os.put({id: obj})
|
||||
}
|
||||
@ -230,6 +245,12 @@ for (var database of databases) {
|
||||
done()
|
||||
})
|
||||
})
|
||||
afterAll(function (done) {
|
||||
store.requestTransaction(function * () {
|
||||
yield* this.store.destroy()
|
||||
done()
|
||||
})
|
||||
})
|
||||
it('can find every object', function (done) {
|
||||
store.requestTransaction(function * () {
|
||||
for (var id of elements) {
|
||||
@ -242,8 +263,8 @@ for (var database of databases) {
|
||||
it('can find every object with lower bound search', function (done) {
|
||||
store.requestTransaction(function * () {
|
||||
for (var id of elements) {
|
||||
var e = yield* this.os.findNodeWithLowerBound(id)
|
||||
expect(e.val.id).toEqual(id)
|
||||
var e = yield* this.os.findWithLowerBound(id)
|
||||
expect(e.id).toEqual(id)
|
||||
}
|
||||
done()
|
||||
})
|
||||
|
@ -7,22 +7,26 @@ Y.IndexedDB = (function () {
|
||||
constructor (transaction, name) {
|
||||
this.store = transaction.objectStore(name)
|
||||
}
|
||||
find (id) {
|
||||
return this.store.get(id)
|
||||
* find (id) {
|
||||
return yield this.store.get(id)
|
||||
}
|
||||
put (v) {
|
||||
return this.store.put(v)
|
||||
* put (v) {
|
||||
yield this.store.put(v)
|
||||
}
|
||||
delete (id) {
|
||||
return this.store.delete(id)
|
||||
* delete (id) {
|
||||
yield this.store.delete(id)
|
||||
}
|
||||
* findNodeWithLowerBound (start) {
|
||||
var cursorResult = this.store.openCursor(window.IDBKeyRange.lowerBound(start))
|
||||
var cursor
|
||||
while ((cursor = yield cursorResult) != null) {
|
||||
// yield* gen.call(t, cursor.value)
|
||||
cursor.continue()
|
||||
}
|
||||
* findWithLowerBound (start) {
|
||||
return yield this.store.openCursor(window.IDBKeyRange.lowerBound(start))
|
||||
}
|
||||
* findWithUpperBound (end) {
|
||||
return yield this.store.openCursor(window.IDBKeyRange.upperBound(end), 'prev')
|
||||
}
|
||||
* findNext (id) {
|
||||
return yield* this.findWithLowerBound([id[0], id[1] + 1])
|
||||
}
|
||||
* findPrev (id) {
|
||||
return yield* this.findWithUpperBound([id[0], id[1] - 1])
|
||||
}
|
||||
* iterate (t, start, end, gen) {
|
||||
var range = null
|
||||
@ -34,61 +38,22 @@ Y.IndexedDB = (function () {
|
||||
range = window.IDBKeyRange.upperBound(end)
|
||||
}
|
||||
var cursorResult = this.store.openCursor(range)
|
||||
var cursor
|
||||
while ((cursor = yield cursorResult) != null) {
|
||||
yield* gen.call(t, cursor.value)
|
||||
cursor.continue()
|
||||
while ((yield cursorResult) != null) {
|
||||
yield* gen.call(t, cursorResult.result.value)
|
||||
cursorResult.result.continue()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
class Transaction {
|
||||
class Transaction extends Y.Transaction {
|
||||
constructor (store) {
|
||||
super(store)
|
||||
var transaction = store.db.transaction(['OperationStore', 'StateStore', 'DeleteStore'], 'readwrite')
|
||||
this.store = store
|
||||
this.ss = new Store(transaction, 'StateStore')
|
||||
this.os = new Store(transaction, 'OperationStore')
|
||||
this.ds = new Store(transaction, 'DeleteStore')
|
||||
}
|
||||
* getStateVector () {
|
||||
var stateVector = []
|
||||
var cursorResult = this.sv.openCursor()
|
||||
var cursor
|
||||
while ((cursor = yield cursorResult) != null) {
|
||||
stateVector.push(cursor.value)
|
||||
cursor.continue()
|
||||
}
|
||||
return stateVector
|
||||
}
|
||||
* getStateSet () {
|
||||
var sv = yield* this.getStateVector()
|
||||
var ss = {}
|
||||
for (var state of sv) {
|
||||
ss[state.user] = state.clock
|
||||
}
|
||||
return ss
|
||||
}
|
||||
|
||||
* getOperations (startSS) {
|
||||
if (startSS == null) {
|
||||
startSS = {}
|
||||
}
|
||||
var ops = []
|
||||
|
||||
var endSV = yield* this.getStateVector()
|
||||
for (var endState of endSV) {
|
||||
var user = endState.user
|
||||
var startPos = startSS[user] || 0
|
||||
var endPos = endState.clock
|
||||
var range = window.IDBKeyRange.bound([user, startPos], [user, endPos])
|
||||
var cursorResult = this.os.openCursor(range)
|
||||
var cursor
|
||||
while ((cursor = yield cursorResult) != null) {
|
||||
ops.push(cursor.value)
|
||||
cursor.continue()
|
||||
}
|
||||
}
|
||||
return ops
|
||||
}
|
||||
}
|
||||
class OperationStore extends Y.AbstractDatabase {
|
||||
constructor (y, opts) {
|
||||
@ -106,58 +71,64 @@ Y.IndexedDB = (function () {
|
||||
} else {
|
||||
this.idbVersion = 5
|
||||
}
|
||||
|
||||
this.transactionQueue = {
|
||||
queue: [],
|
||||
onRequest: null
|
||||
var store = this
|
||||
// initialize database!
|
||||
this.requestTransaction(function * () {
|
||||
store.db = yield window.indexedDB.open(opts.namespace, store.idbVersion)
|
||||
})
|
||||
if (opts.cleanStart) {
|
||||
this.requestTransaction(function * () {
|
||||
yield this.os.store.clear()
|
||||
yield this.ds.store.clear()
|
||||
yield this.ss.store.clear()
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
transact (makeGen) {
|
||||
var transaction = this.db != null ? new Transaction(this) : null
|
||||
var store = this
|
||||
|
||||
var tGen = (function * transactionGen () {
|
||||
store.db = yield window.indexedDB.open(opts.namespace, store.idbVersion)
|
||||
var transactionQueue = store.transactionQueue
|
||||
var gen = makeGen.call(transaction)
|
||||
handleTransactions(gen.next())
|
||||
|
||||
var transaction = null
|
||||
var cont = true
|
||||
while (cont) {
|
||||
var request = yield transactionQueue
|
||||
transaction = new Transaction(store)
|
||||
|
||||
yield* request.call(transaction, request) /*
|
||||
while (transactionQueue.queue.length > 0) {
|
||||
yield* transactionQueue.queue.shift().call(transaction)
|
||||
}*/
|
||||
}
|
||||
})()
|
||||
|
||||
function handleTransactions (t) {
|
||||
var request = t.value
|
||||
if (t.done) {
|
||||
function handleTransactions (result) {
|
||||
var request = result.value
|
||||
if (result.done) {
|
||||
makeGen = store.getNextRequest()
|
||||
if (makeGen != null) {
|
||||
if (transaction == null && store.db != null) {
|
||||
transaction = new Transaction(store)
|
||||
}
|
||||
gen = makeGen.call(transaction)
|
||||
handleTransactions(gen.next())
|
||||
} // else no transaction in progress!
|
||||
return
|
||||
} else if (request.constructor === window.IDBRequest || request.constructor === window.IDBCursor) {
|
||||
}
|
||||
if (request.constructor === window.IDBRequest) {
|
||||
request.onsuccess = function () {
|
||||
handleTransactions(tGen.next(request.result))
|
||||
var res = request.result
|
||||
if (res != null && res.constructor === window.IDBCursorWithValue) {
|
||||
res = res.value
|
||||
}
|
||||
handleTransactions(gen.next(res))
|
||||
}
|
||||
request.onerror = function (err) {
|
||||
tGen.throw(err)
|
||||
gen.throw(err)
|
||||
}
|
||||
} else if (request === store.transactionQueue) {
|
||||
if (request.queue.length > 0) {
|
||||
handleTransactions(tGen.next(request.queue.shift()))
|
||||
} else {
|
||||
request.onRequest = function () {
|
||||
request.onRequest = null
|
||||
handleTransactions(tGen.next(request.queue.shift()))
|
||||
}
|
||||
} else if (request.constructor === window.IDBCursor) {
|
||||
request.onsuccess = function () {
|
||||
handleTransactions(gen.next(request.result != null ? request.result.value : null))
|
||||
}
|
||||
request.onerror = function (err) {
|
||||
gen.throw(err)
|
||||
}
|
||||
} else if (request.constructor === window.IDBOpenDBRequest) {
|
||||
request.onsuccess = function (event) {
|
||||
var db = event.target.result
|
||||
handleTransactions(tGen.next(db))
|
||||
handleTransactions(gen.next(db))
|
||||
}
|
||||
request.onerror = function () {
|
||||
tGen.throw("Couldn't open IndexedDB database!")
|
||||
gen.throw("Couldn't open IndexedDB database!")
|
||||
}
|
||||
request.onupgradeneeded = function (event) {
|
||||
var db = event.target.result
|
||||
@ -166,31 +137,13 @@ Y.IndexedDB = (function () {
|
||||
db.createObjectStore('DeleteStore', {keyPath: 'id'})
|
||||
db.createObjectStore('StateStore', {keyPath: 'id'})
|
||||
} catch (e) {
|
||||
// console.log("Store already exists!")
|
||||
console.log('Store already exists!')
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tGen.throw('You can not yield this type!')
|
||||
gen.throw('You must not yield this type!')
|
||||
}
|
||||
}
|
||||
handleTransactions(tGen.next())
|
||||
}
|
||||
requestTransaction (makeGen) {
|
||||
this.transactionQueue.queue.push(makeGen)
|
||||
if (this.transactionQueue.onRequest != null) {
|
||||
this.transactionQueue.onRequest()
|
||||
}
|
||||
}
|
||||
transact (makeGen) {
|
||||
var t = new Y.Transaction(this)
|
||||
while (makeGen !== null) {
|
||||
var gen = makeGen.call(t)
|
||||
var res = gen.next()
|
||||
while (!res.done) {
|
||||
res = gen.next(res.value)
|
||||
}
|
||||
makeGen = this.getNextRequest()
|
||||
}
|
||||
}
|
||||
// TODO: implement "free"..
|
||||
* destroy () {
|
||||
|
@ -17,8 +17,6 @@ Y.Memory = (function () {
|
||||
this.os = new Y.utils.RBTree()
|
||||
this.ds = new Y.utils.RBTree()
|
||||
this.ss = new Y.utils.RBTree()
|
||||
this.waitingTransactions = []
|
||||
this.transactionInProgress = false
|
||||
}
|
||||
logTable () {
|
||||
var self = this
|
||||
|
@ -131,14 +131,12 @@ class RBTree {
|
||||
this.length = 0
|
||||
}
|
||||
* findNext (id) {
|
||||
var n = yield* this.findNodeWithLowerBound([id[0], id[1] + 1])
|
||||
return n == null ? null : n.val
|
||||
return yield* this.findWithLowerBound([id[0], id[1] + 1])
|
||||
}
|
||||
* findPrev (id) {
|
||||
var n = yield* this.findNodeWithUpperBound([id[0], id[1] - 1])
|
||||
return n == null ? null : n.val
|
||||
return yield* this.findWithUpperBound([id[0], id[1] - 1])
|
||||
}
|
||||
* findNodeWithLowerBound (from) {
|
||||
findNodeWithLowerBound (from) {
|
||||
if (from === void 0) {
|
||||
throw new Error('You must define from!')
|
||||
}
|
||||
@ -166,7 +164,7 @@ class RBTree {
|
||||
}
|
||||
}
|
||||
}
|
||||
* findNodeWithUpperBound (to) {
|
||||
findNodeWithUpperBound (to) {
|
||||
if (to === void 0) {
|
||||
throw new Error('You must define from!')
|
||||
}
|
||||
@ -194,8 +192,16 @@ class RBTree {
|
||||
}
|
||||
}
|
||||
}
|
||||
* findWithLowerBound (from) {
|
||||
var n = this.findNodeWithLowerBound(from)
|
||||
return n == null ? null : n.val
|
||||
}
|
||||
* findWithUpperBound (to) {
|
||||
var n = this.findNodeWithUpperBound(to)
|
||||
return n == null ? null : n.val
|
||||
}
|
||||
* iterate (t, from, to, f) {
|
||||
var o = yield* this.findNodeWithLowerBound(from)
|
||||
var o = this.findNodeWithLowerBound(from)
|
||||
while (o !== null && (to === null || Y.utils.smaller(o.val.id, to) || Y.utils.compareIds(o.val.id, to))) {
|
||||
yield* f.call(t, o.val)
|
||||
o = o.next()
|
||||
|
@ -124,7 +124,7 @@ describe('RedBlack Tree', function () {
|
||||
it('can find every object with lower bound search', function (done) {
|
||||
this.memory.requestTransaction(function * () {
|
||||
for (var id of elements) {
|
||||
expect((yield* tree.findNodeWithLowerBound(id)).val.id).toEqual(id)
|
||||
expect((yield* tree.findWithLowerBound(id)).id).toEqual(id)
|
||||
}
|
||||
done()
|
||||
})
|
||||
|
@ -31,7 +31,7 @@ g.describeManyTimes = function describeManyTimes (times, name, f) {
|
||||
*/
|
||||
function wait (t) {
|
||||
if (t == null) {
|
||||
t = 10
|
||||
t = 80
|
||||
}
|
||||
return new Promise(function (resolve) {
|
||||
setTimeout(function () {
|
||||
@ -41,6 +41,11 @@ function wait (t) {
|
||||
}
|
||||
g.wait = wait
|
||||
|
||||
g.databases = ['Memory']
|
||||
if (typeof window !== 'undefined') {
|
||||
g.databases.push('IndexedDB')
|
||||
}
|
||||
|
||||
/*
|
||||
returns a random element of o.
|
||||
works on Object, and Array
|
||||
@ -177,7 +182,7 @@ g.compareAllUsers = async(function * compareAllUsers (users) {
|
||||
var o = yield* this.getOperation([d.id[0], d.id[1] + i])
|
||||
// gc'd or deleted
|
||||
if (d.gc) {
|
||||
expect(o).toBeNull()
|
||||
expect(o).toBeFalsy()
|
||||
} else {
|
||||
expect(o.deleted).toBeTruthy()
|
||||
}
|
||||
@ -215,7 +220,7 @@ g.compareAllUsers = async(function * compareAllUsers (users) {
|
||||
}
|
||||
})
|
||||
|
||||
g.createUsers = async(function * createUsers (self, numberOfUsers) {
|
||||
g.createUsers = async(function * createUsers (self, numberOfUsers, database) {
|
||||
if (Y.utils.globalRoom.users[0] != null) {
|
||||
yield Y.utils.globalRoom.users[0].flushAll()
|
||||
}
|
||||
@ -229,7 +234,9 @@ g.createUsers = async(function * createUsers (self, numberOfUsers) {
|
||||
for (var i = 0; i < numberOfUsers; i++) {
|
||||
promises.push(Y({
|
||||
db: {
|
||||
name: 'Memory',
|
||||
name: database,
|
||||
namespace: 'User ' + i,
|
||||
cleanStart: true,
|
||||
gcTimeout: -1
|
||||
},
|
||||
connector: {
|
||||
|
@ -278,7 +278,7 @@ var Struct = {
|
||||
map: function * (o, f) {
|
||||
o = o.start
|
||||
var res = []
|
||||
while (o !== null) { // TODO: change to != (at least some convention)
|
||||
while (o != null) { // TODO: change to != (at least some convention)
|
||||
var operation = yield* this.getOperation(o)
|
||||
if (!operation.deleted) {
|
||||
res.push(f(operation))
|
||||
|
@ -201,8 +201,8 @@ class Transaction {
|
||||
var newlen = n.len - (id[1] - n.id[1])
|
||||
n.len -= newlen
|
||||
yield* this.ds.put(n)
|
||||
n = yield* this.ds.put({id: id, len: newlen, gc: false})
|
||||
n = n.val
|
||||
n = {id: id, len: newlen, gc: false}
|
||||
yield* this.ds.put(n)
|
||||
}
|
||||
// get prev&next before adding a new operation
|
||||
var prev = yield* this.ds.findPrev(id)
|
||||
@ -245,8 +245,7 @@ class Transaction {
|
||||
*/
|
||||
* markDeleted (id) {
|
||||
// this.mem.push(["del", id]);
|
||||
var n = yield* this.ds.findNodeWithUpperBound(id)
|
||||
n = n == null ? n : n.val
|
||||
var n = yield* this.ds.findWithUpperBound(id)
|
||||
if (n != null && n.id[0] === id[0]) {
|
||||
if (n.id[1] <= id[1] && id[1] < n.id[1] + n.len) {
|
||||
// already deleted
|
||||
@ -256,13 +255,13 @@ class Transaction {
|
||||
n.len++
|
||||
} else {
|
||||
// cannot extend left
|
||||
n = yield* this.ds.put({id: id, len: 1, gc: false})
|
||||
n = n.val
|
||||
n = {id: id, len: 1, gc: false}
|
||||
yield* this.ds.put(n)
|
||||
}
|
||||
} else {
|
||||
// cannot extend left
|
||||
n = yield* this.ds.put({id: id, len: 1, gc: false})
|
||||
n = n.val
|
||||
n = {id: id, len: 1, gc: false}
|
||||
yield* this.ds.put(n)
|
||||
}
|
||||
// can extend right?
|
||||
var next = yield* this.ds.findNext(n.id)
|
||||
@ -398,9 +397,9 @@ class Transaction {
|
||||
}
|
||||
}
|
||||
* checkDeleteStoreForState (state) {
|
||||
var n = yield* this.ds.findNodeWithUpperBound([state.user, state.clock])
|
||||
if (n !== null && n.val.id[0] === state.user && n.val.gc) {
|
||||
state.clock = Math.max(state.clock, n.val.id[1] + n.val.len)
|
||||
var n = yield* this.ds.findWithUpperBound([state.user, state.clock])
|
||||
if (n != null && n.id[0] === state.user && n.gc) {
|
||||
state.clock = Math.max(state.clock, n.id[1] + n.len)
|
||||
}
|
||||
}
|
||||
/*
|
||||
@ -477,8 +476,8 @@ class Transaction {
|
||||
}
|
||||
}
|
||||
* isGarbageCollected (id) {
|
||||
var n = yield* this.ds.findNodeWithUpperBound(id)
|
||||
return n !== null && n.val.id[0] === id[0] && id[1] < n.val.id[1] + n.val.len && n.val.gc
|
||||
var n = yield* this.ds.findWithUpperBound(id)
|
||||
return n != null && n.id[0] === id[0] && id[1] < n.id[1] + n.len && n.gc
|
||||
}
|
||||
/*
|
||||
A DeleteSet (ds) describes all the deleted ops in the OS
|
||||
@ -500,23 +499,15 @@ class Transaction {
|
||||
return ds
|
||||
}
|
||||
* isDeleted (id) {
|
||||
var n = yield* this.ds.findNodeWithUpperBound(id)
|
||||
return n !== null && n.val.id[0] === id[0] && id[1] < n.val.id[1] + n.val.len
|
||||
var n = yield* this.ds.findWithUpperBound(id)
|
||||
return n != null && n.id[0] === id[0] && id[1] < n.id[1] + n.len
|
||||
}
|
||||
* setOperation (op) {
|
||||
yield* this.os.put(op)
|
||||
return op
|
||||
}
|
||||
* addOperation (op) {
|
||||
var n = yield* this.os.put(op)
|
||||
return function () {
|
||||
if (n != null) {
|
||||
n = n.next()
|
||||
return n != null ? n.val : null
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
}
|
||||
yield* this.os.put(op)
|
||||
}
|
||||
* getOperation (id) {
|
||||
return yield* this.os.find(id)
|
||||
|
@ -1,308 +1,310 @@
|
||||
/* global createUsers, wait, Y, compareAllUsers, getRandomNumber, applyRandomTransactionsAllRejoinNoGC, applyRandomTransactionsWithGC, async, garbageCollectAllUsers, describeManyTimes */
|
||||
/* global createUsers, databases, wait, Y, compareAllUsers, getRandomNumber, applyRandomTransactionsAllRejoinNoGC, applyRandomTransactionsWithGC, async, garbageCollectAllUsers, describeManyTimes */
|
||||
/* eslint-env browser,jasmine */
|
||||
|
||||
var numberOfYArrayTests = 50
|
||||
var repeatArrayTests = 2
|
||||
|
||||
describe('Array Type', function () {
|
||||
var y1, y2, y3, yconfig1, yconfig2, yconfig3, flushAll
|
||||
for (var database of databases) {
|
||||
describe(`Array Type (DB: ${database})`, function () {
|
||||
var y1, y2, y3, yconfig1, yconfig2, yconfig3, flushAll
|
||||
|
||||
beforeEach(async(function * (done) {
|
||||
yield createUsers(this, 3)
|
||||
y1 = (yconfig1 = this.users[0]).root
|
||||
y2 = (yconfig2 = this.users[1]).root
|
||||
y3 = (yconfig3 = this.users[2]).root
|
||||
flushAll = this.users[0].connector.flushAll
|
||||
yield wait(10)
|
||||
done()
|
||||
}))
|
||||
afterEach(async(function * (done) {
|
||||
yield compareAllUsers(this.users)
|
||||
done()
|
||||
}))
|
||||
|
||||
describe('Basic tests', function () {
|
||||
it('insert three elements, try re-get property', async(function * (done) {
|
||||
var array = yield y1.set('Array', Y.Array)
|
||||
array.insert(0, [1, 2, 3])
|
||||
array = yield y1.get('Array') // re-get property
|
||||
expect(array.toArray()).toEqual([1, 2, 3])
|
||||
done()
|
||||
}))
|
||||
it('Basic insert in array (handle three conflicts)', async(function * (done) {
|
||||
yield y1.set('Array', Y.Array)
|
||||
yield flushAll()
|
||||
var l1 = yield y1.get('Array')
|
||||
l1.insert(0, [0])
|
||||
var l2 = yield y2.get('Array')
|
||||
l2.insert(0, [1])
|
||||
var l3 = yield y3.get('Array')
|
||||
l3.insert(0, [2])
|
||||
yield flushAll()
|
||||
expect(l1.toArray()).toEqual(l2.toArray())
|
||||
expect(l2.toArray()).toEqual(l3.toArray())
|
||||
done()
|
||||
}))
|
||||
it('Basic insert&delete in array (handle three conflicts)', async(function * (done) {
|
||||
var l1, l2, l3
|
||||
l1 = yield y1.set('Array', Y.Array)
|
||||
l1.insert(0, ['x', 'y', 'z'])
|
||||
yield flushAll()
|
||||
l1.insert(1, [0])
|
||||
l2 = yield y2.get('Array')
|
||||
l2.delete(0)
|
||||
l2.delete(1)
|
||||
l3 = yield y3.get('Array')
|
||||
l3.insert(1, [2])
|
||||
yield flushAll()
|
||||
expect(l1.toArray()).toEqual(l2.toArray())
|
||||
expect(l2.toArray()).toEqual(l3.toArray())
|
||||
expect(l2.toArray()).toEqual([0, 2, 'y'])
|
||||
done()
|
||||
}))
|
||||
it('Handles getOperations ascending ids bug in late sync', async(function * (done) {
|
||||
var l1, l2
|
||||
l1 = yield y1.set('Array', Y.Array)
|
||||
l1.insert(0, ['x', 'y'])
|
||||
yield flushAll()
|
||||
yconfig3.disconnect()
|
||||
yconfig2.disconnect()
|
||||
yield wait()
|
||||
l2 = yield y2.get('Array')
|
||||
l2.insert(1, [2])
|
||||
l2.insert(1, [3])
|
||||
yield yconfig2.reconnect()
|
||||
yield yconfig3.reconnect()
|
||||
expect(l1.toArray()).toEqual(l2.toArray())
|
||||
done()
|
||||
}))
|
||||
it('Handles deletions in late sync', async(function * (done) {
|
||||
var l1, l2
|
||||
l1 = yield y1.set('Array', Y.Array)
|
||||
l1.insert(0, ['x', 'y'])
|
||||
yield flushAll()
|
||||
yield yconfig2.disconnect()
|
||||
yield wait()
|
||||
l2 = yield y2.get('Array')
|
||||
l2.delete(1, 1)
|
||||
l1.delete(0, 2)
|
||||
yield yconfig2.reconnect()
|
||||
expect(l1.toArray()).toEqual(l2.toArray())
|
||||
done()
|
||||
}))
|
||||
it('Handles deletions in late sync (2)', async(function * (done) {
|
||||
var l1, l2
|
||||
l1 = yield y1.set('Array', Y.Array)
|
||||
yield flushAll()
|
||||
l2 = yield y2.get('Array')
|
||||
l1.insert(0, ['x', 'y'])
|
||||
l1.delete(0, 2)
|
||||
yield flushAll()
|
||||
expect(l1.toArray()).toEqual(l2.toArray())
|
||||
done()
|
||||
}))
|
||||
it('Basic insert. Then delete the whole array', async(function * (done) {
|
||||
var l1, l2, l3
|
||||
l1 = yield y1.set('Array', Y.Array)
|
||||
l1.insert(0, ['x', 'y', 'z'])
|
||||
yield flushAll()
|
||||
l1.delete(0, 3)
|
||||
l2 = yield y2.get('Array')
|
||||
l3 = yield y3.get('Array')
|
||||
yield flushAll()
|
||||
expect(l1.toArray()).toEqual(l2.toArray())
|
||||
expect(l2.toArray()).toEqual(l3.toArray())
|
||||
expect(l2.toArray()).toEqual([])
|
||||
done()
|
||||
}))
|
||||
it('Basic insert. Then delete the whole array (merge listeners on late sync)', async(function * (done) {
|
||||
var l1, l2, l3
|
||||
l1 = yield y1.set('Array', Y.Array)
|
||||
l1.insert(0, ['x', 'y', 'z'])
|
||||
yield flushAll()
|
||||
yconfig2.disconnect()
|
||||
l1.delete(0, 3)
|
||||
l2 = yield y2.get('Array')
|
||||
yield wait()
|
||||
yield yconfig2.reconnect()
|
||||
yield wait()
|
||||
l3 = yield y3.get('Array')
|
||||
yield flushAll()
|
||||
expect(l1.toArray()).toEqual(l2.toArray())
|
||||
expect(l2.toArray()).toEqual(l3.toArray())
|
||||
expect(l2.toArray()).toEqual([])
|
||||
done()
|
||||
}))
|
||||
// TODO?
|
||||
/* it('Basic insert. Then delete the whole array (merge deleter on late sync)', async(function * (done) {
|
||||
var l1, l2, l3
|
||||
l1 = yield y1.set('Array', Y.Array)
|
||||
l1.insert(0, ['x', 'y', 'z'])
|
||||
yield flushAll()
|
||||
yconfig1.disconnect()
|
||||
l1.delete(0, 3)
|
||||
l2 = yield y2.get('Array')
|
||||
yield yconfig1.reconnect()
|
||||
l3 = yield y3.get('Array')
|
||||
yield flushAll()
|
||||
expect(l1.toArray()).toEqual(l2.toArray())
|
||||
expect(l2.toArray()).toEqual(l3.toArray())
|
||||
expect(l2.toArray()).toEqual([])
|
||||
done()
|
||||
})) */
|
||||
it('throw insert & delete events', async(function * (done) {
|
||||
var array = yield this.users[0].root.set('array', Y.Array)
|
||||
var event
|
||||
array.observe(function (e) {
|
||||
event = e
|
||||
})
|
||||
array.insert(0, [0])
|
||||
expect(event).toEqual([{
|
||||
type: 'insert',
|
||||
object: array,
|
||||
index: 0,
|
||||
length: 1
|
||||
}])
|
||||
array.delete(0)
|
||||
expect(event).toEqual([{
|
||||
type: 'delete',
|
||||
object: array,
|
||||
index: 0,
|
||||
length: 1
|
||||
}])
|
||||
yield wait(50)
|
||||
done()
|
||||
}))
|
||||
it('garbage collects', async(function * (done) {
|
||||
var l1, l2, l3
|
||||
l1 = yield y1.set('Array', Y.Array)
|
||||
l1.insert(0, ['x', 'y', 'z'])
|
||||
yield flushAll()
|
||||
yconfig1.disconnect()
|
||||
l1.delete(0, 3)
|
||||
l2 = yield y2.get('Array')
|
||||
yield wait()
|
||||
yield yconfig1.reconnect()
|
||||
yield wait()
|
||||
l3 = yield y3.get('Array')
|
||||
yield flushAll()
|
||||
yield garbageCollectAllUsers(this.users)
|
||||
expect(l1.toArray()).toEqual(l2.toArray())
|
||||
expect(l2.toArray()).toEqual(l3.toArray())
|
||||
expect(l2.toArray()).toEqual([])
|
||||
done()
|
||||
}))
|
||||
it('debug right not existend in Insert.execute', async(function * (done) {
|
||||
yconfig1.db.requestTransaction(function * () {
|
||||
var ops = [{'struct':'Map','type':'Map','id':['130',0],'map':{}},{'id':['130',1],'left':null,'right':null,'origin':null,'parent':['_',0],'struct':'Insert','parentSub':'Map','opContent':['130',0]},{'struct':'Map','type':'Map','id':['130',0],'map':{}},{'id':['130',1],'left':null,'right':null,'origin':null,'parent':['_',0],'struct':'Insert','parentSub':'Map','opContent':['130',0]},{'struct':'Map','type':'Map','id':['130',0],'map':{}},{'id':['130',1],'left':null,'right':null,'origin':null,'parent':['_',0],'struct':'Insert','parentSub':'Map','opContent':['130',0]},{'left':null,'right':null,'origin':null,'parent':['130',0],'parentSub':'somekey','struct':'Insert','content':512,'id':['133',0]},{'id':['130',2],'left':null,'right':null,'origin':null,'parent':['130',0],'struct':'Insert','parentSub':'somekey','content':1131},{'id':['130',3],'left':null,'right':['130',2],'origin':null,'parent':['130',0],'struct':'Insert','parentSub':'somekey','content':4196},{'id':['131',3],'left':null,'right':null,'origin':null,'parent':['130',0],'struct':'Insert','parentSub':'somekey','content':5022}]//eslint-disable-line
|
||||
|
||||
for (var o of ops) {
|
||||
yield* this.store.tryExecute.call(this, o)
|
||||
}
|
||||
})
|
||||
yield wait()
|
||||
yield yconfig3.disconnect()
|
||||
yield yconfig2.disconnect()
|
||||
yield flushAll()
|
||||
wait()
|
||||
yield yconfig3.reconnect()
|
||||
yield yconfig2.reconnect()
|
||||
yield wait()
|
||||
yield flushAll()
|
||||
done()
|
||||
}))
|
||||
it('debug right not existend in Insert.execute (2)', async(function * (done) {
|
||||
yconfig1.db.requestTransaction(function * () {
|
||||
yield* this.store.tryExecute.call(this, {'struct': 'Map', 'type': 'Map', 'id': ['153', 0], 'map': {}})
|
||||
yield* this.store.tryExecute.call(this, {'id': ['153', 1], 'left': null, 'right': null, 'origin': null, 'parent': ['_', 0], 'struct': 'Insert', 'parentSub': 'Map', 'opContent': ['153', 0]})
|
||||
yield* this.store.tryExecute.call(this, {'struct': 'Map', 'type': 'Map', 'id': ['153', 0], 'map': {}})
|
||||
yield* this.store.tryExecute.call(this, {'id': ['153', 1], 'left': null, 'right': null, 'origin': null, 'parent': ['_', 0], 'struct': 'Insert', 'parentSub': 'Map', 'opContent': ['153', 0]})
|
||||
yield* this.store.tryExecute.call(this, {'struct': 'Map', 'type': 'Map', 'id': ['153', 0], 'map': {}})
|
||||
yield* this.store.tryExecute.call(this, {'id': ['153', 1], 'left': null, 'right': null, 'origin': null, 'parent': ['_', 0], 'struct': 'Insert', 'parentSub': 'Map', 'opContent': ['153', 0]})
|
||||
yield* this.store.tryExecute.call(this, {'left': null, 'right': null, 'origin': null, 'parent': ['153', 0], 'parentSub': 'somekey', 'struct': 'Insert', 'content': 3784, 'id': ['154', 0]})
|
||||
yield* this.store.tryExecute.call(this, {'left': null, 'right': ['154', 0], 'origin': null, 'parent': ['153', 0], 'parentSub': 'somekey', 'struct': 'Insert', 'content': 8217, 'id': ['154', 1]})
|
||||
yield* this.store.tryExecute.call(this, {'left': null, 'right': ['154', 1], 'origin': null, 'parent': ['153', 0], 'parentSub': 'somekey', 'struct': 'Insert', 'content': 5036, 'id': ['154', 2]})
|
||||
yield* this.store.tryExecute.call(this, {'id': ['153', 2], 'left': null, 'right': null, 'origin': null, 'parent': ['153', 0], 'struct': 'Insert', 'parentSub': 'somekey', 'content': 417})
|
||||
yield* this.store.tryExecute.call(this, {'id': ['155', 0], 'left': null, 'right': null, 'origin': null, 'parent': ['153', 0], 'struct': 'Insert', 'parentSub': 'somekey', 'content': 2202})
|
||||
yield* this.garbageCollectOperation(['153', 2])
|
||||
yield* this.garbageCollectOperation(['154', 0])
|
||||
yield* this.garbageCollectOperation(['154', 1])
|
||||
yield* this.garbageCollectOperation(['154', 2])
|
||||
yield* this.garbageCollectOperation(['155', 0])
|
||||
yield* this.garbageCollectOperation(['156', 0])
|
||||
yield* this.garbageCollectOperation(['157', 0])
|
||||
yield* this.garbageCollectOperation(['157', 1])
|
||||
yield* this.store.tryExecute.call(this, {'id': ['153', 3], 'left': null, 'right': null, 'origin': null, 'parent': ['153', 0], 'struct': 'Insert', 'parentSub': 'somekey', 'content': 4372})
|
||||
})
|
||||
yield wait()
|
||||
yield yconfig3.disconnect()
|
||||
yield yconfig2.disconnect()
|
||||
yield flushAll()
|
||||
wait()
|
||||
yield yconfig3.reconnect()
|
||||
yield yconfig2.reconnect()
|
||||
yield wait()
|
||||
yield flushAll()
|
||||
done()
|
||||
}))
|
||||
})
|
||||
describeManyTimes(repeatArrayTests, `Random tests`, function () {
|
||||
var randomArrayTransactions = [
|
||||
function insert (array) {
|
||||
array.insert(getRandomNumber(array.toArray().length), [getRandomNumber()])
|
||||
},
|
||||
function _delete (array) {
|
||||
var length = array.toArray().length
|
||||
if (length > 0) {
|
||||
array.delete(getRandomNumber(length - 1))
|
||||
}
|
||||
}
|
||||
]
|
||||
function compareArrayValues (arrays) {
|
||||
var firstArray
|
||||
for (var l of arrays) {
|
||||
var val = l.toArray()
|
||||
if (firstArray == null) {
|
||||
firstArray = val
|
||||
} else {
|
||||
expect(val).toEqual(firstArray)
|
||||
}
|
||||
}
|
||||
}
|
||||
beforeEach(async(function * (done) {
|
||||
yield this.users[0].root.set('Array', Y.Array)
|
||||
yield flushAll()
|
||||
yield createUsers(this, 3, database)
|
||||
y1 = (yconfig1 = this.users[0]).root
|
||||
y2 = (yconfig2 = this.users[1]).root
|
||||
y3 = (yconfig3 = this.users[2]).root
|
||||
flushAll = this.users[0].connector.flushAll
|
||||
yield wait(10)
|
||||
done()
|
||||
}))
|
||||
afterEach(async(function * (done) {
|
||||
yield compareAllUsers(this.users)
|
||||
done()
|
||||
}))
|
||||
|
||||
var promises = []
|
||||
for (var u = 0; u < this.users.length; u++) {
|
||||
promises.push(this.users[u].root.get('Array'))
|
||||
describe('Basic tests', function () {
|
||||
it('insert three elements, try re-get property', async(function * (done) {
|
||||
var array = yield y1.set('Array', Y.Array)
|
||||
array.insert(0, [1, 2, 3])
|
||||
array = yield y1.get('Array') // re-get property
|
||||
expect(array.toArray()).toEqual([1, 2, 3])
|
||||
done()
|
||||
}))
|
||||
it('Basic insert in array (handle three conflicts)', async(function * (done) {
|
||||
yield y1.set('Array', Y.Array)
|
||||
yield flushAll()
|
||||
var l1 = yield y1.get('Array')
|
||||
l1.insert(0, [0])
|
||||
var l2 = yield y2.get('Array')
|
||||
l2.insert(0, [1])
|
||||
var l3 = yield y3.get('Array')
|
||||
l3.insert(0, [2])
|
||||
yield flushAll()
|
||||
expect(l1.toArray()).toEqual(l2.toArray())
|
||||
expect(l2.toArray()).toEqual(l3.toArray())
|
||||
done()
|
||||
}))
|
||||
it('Basic insert&delete in array (handle three conflicts)', async(function * (done) {
|
||||
var l1, l2, l3
|
||||
l1 = yield y1.set('Array', Y.Array)
|
||||
l1.insert(0, ['x', 'y', 'z'])
|
||||
yield flushAll()
|
||||
l1.insert(1, [0])
|
||||
l2 = yield y2.get('Array')
|
||||
l2.delete(0)
|
||||
l2.delete(1)
|
||||
l3 = yield y3.get('Array')
|
||||
l3.insert(1, [2])
|
||||
yield flushAll()
|
||||
expect(l1.toArray()).toEqual(l2.toArray())
|
||||
expect(l2.toArray()).toEqual(l3.toArray())
|
||||
expect(l2.toArray()).toEqual([0, 2, 'y'])
|
||||
done()
|
||||
}))
|
||||
it('Handles getOperations ascending ids bug in late sync', async(function * (done) {
|
||||
var l1, l2
|
||||
l1 = yield y1.set('Array', Y.Array)
|
||||
l1.insert(0, ['x', 'y'])
|
||||
yield flushAll()
|
||||
yconfig3.disconnect()
|
||||
yconfig2.disconnect()
|
||||
yield wait()
|
||||
l2 = yield y2.get('Array')
|
||||
l2.insert(1, [2])
|
||||
l2.insert(1, [3])
|
||||
yield yconfig2.reconnect()
|
||||
yield yconfig3.reconnect()
|
||||
expect(l1.toArray()).toEqual(l2.toArray())
|
||||
done()
|
||||
}))
|
||||
it('Handles deletions in late sync', async(function * (done) {
|
||||
var l1, l2
|
||||
l1 = yield y1.set('Array', Y.Array)
|
||||
l1.insert(0, ['x', 'y'])
|
||||
yield flushAll()
|
||||
yield yconfig2.disconnect()
|
||||
yield wait()
|
||||
l2 = yield y2.get('Array')
|
||||
l2.delete(1, 1)
|
||||
l1.delete(0, 2)
|
||||
yield yconfig2.reconnect()
|
||||
expect(l1.toArray()).toEqual(l2.toArray())
|
||||
done()
|
||||
}))
|
||||
it('Handles deletions in late sync (2)', async(function * (done) {
|
||||
var l1, l2
|
||||
l1 = yield y1.set('Array', Y.Array)
|
||||
yield flushAll()
|
||||
l2 = yield y2.get('Array')
|
||||
l1.insert(0, ['x', 'y'])
|
||||
l1.delete(0, 2)
|
||||
yield flushAll()
|
||||
expect(l1.toArray()).toEqual(l2.toArray())
|
||||
done()
|
||||
}))
|
||||
it('Basic insert. Then delete the whole array', async(function * (done) {
|
||||
var l1, l2, l3
|
||||
l1 = yield y1.set('Array', Y.Array)
|
||||
l1.insert(0, ['x', 'y', 'z'])
|
||||
yield flushAll()
|
||||
l1.delete(0, 3)
|
||||
l2 = yield y2.get('Array')
|
||||
l3 = yield y3.get('Array')
|
||||
yield flushAll()
|
||||
expect(l1.toArray()).toEqual(l2.toArray())
|
||||
expect(l2.toArray()).toEqual(l3.toArray())
|
||||
expect(l2.toArray()).toEqual([])
|
||||
done()
|
||||
}))
|
||||
it('Basic insert. Then delete the whole array (merge listeners on late sync)', async(function * (done) {
|
||||
var l1, l2, l3
|
||||
l1 = yield y1.set('Array', Y.Array)
|
||||
l1.insert(0, ['x', 'y', 'z'])
|
||||
yield flushAll()
|
||||
yconfig2.disconnect()
|
||||
l1.delete(0, 3)
|
||||
l2 = yield y2.get('Array')
|
||||
yield wait()
|
||||
yield yconfig2.reconnect()
|
||||
yield wait()
|
||||
l3 = yield y3.get('Array')
|
||||
yield flushAll()
|
||||
expect(l1.toArray()).toEqual(l2.toArray())
|
||||
expect(l2.toArray()).toEqual(l3.toArray())
|
||||
expect(l2.toArray()).toEqual([])
|
||||
done()
|
||||
}))
|
||||
// TODO?
|
||||
/* it('Basic insert. Then delete the whole array (merge deleter on late sync)', async(function * (done) {
|
||||
var l1, l2, l3
|
||||
l1 = yield y1.set('Array', Y.Array)
|
||||
l1.insert(0, ['x', 'y', 'z'])
|
||||
yield flushAll()
|
||||
yconfig1.disconnect()
|
||||
l1.delete(0, 3)
|
||||
l2 = yield y2.get('Array')
|
||||
yield yconfig1.reconnect()
|
||||
l3 = yield y3.get('Array')
|
||||
yield flushAll()
|
||||
expect(l1.toArray()).toEqual(l2.toArray())
|
||||
expect(l2.toArray()).toEqual(l3.toArray())
|
||||
expect(l2.toArray()).toEqual([])
|
||||
done()
|
||||
})) */
|
||||
it('throw insert & delete events', async(function * (done) {
|
||||
var array = yield this.users[0].root.set('array', Y.Array)
|
||||
var event
|
||||
array.observe(function (e) {
|
||||
event = e
|
||||
})
|
||||
array.insert(0, [0])
|
||||
expect(event).toEqual([{
|
||||
type: 'insert',
|
||||
object: array,
|
||||
index: 0,
|
||||
length: 1
|
||||
}])
|
||||
array.delete(0)
|
||||
expect(event).toEqual([{
|
||||
type: 'delete',
|
||||
object: array,
|
||||
index: 0,
|
||||
length: 1
|
||||
}])
|
||||
yield wait(50)
|
||||
done()
|
||||
}))
|
||||
it('garbage collects', async(function * (done) {
|
||||
var l1, l2, l3
|
||||
l1 = yield y1.set('Array', Y.Array)
|
||||
l1.insert(0, ['x', 'y', 'z'])
|
||||
yield flushAll()
|
||||
yconfig1.disconnect()
|
||||
l1.delete(0, 3)
|
||||
l2 = yield y2.get('Array')
|
||||
yield wait()
|
||||
yield yconfig1.reconnect()
|
||||
yield wait()
|
||||
l3 = yield y3.get('Array')
|
||||
yield flushAll()
|
||||
yield garbageCollectAllUsers(this.users)
|
||||
expect(l1.toArray()).toEqual(l2.toArray())
|
||||
expect(l2.toArray()).toEqual(l3.toArray())
|
||||
expect(l2.toArray()).toEqual([])
|
||||
done()
|
||||
}))
|
||||
it('debug right not existend in Insert.execute', async(function * (done) {
|
||||
yconfig1.db.requestTransaction(function * () {
|
||||
var ops = [{'struct':'Map','type':'Map','id':['130',0],'map':{}},{'id':['130',1],'left':null,'right':null,'origin':null,'parent':['_',0],'struct':'Insert','parentSub':'Map','opContent':['130',0]},{'struct':'Map','type':'Map','id':['130',0],'map':{}},{'id':['130',1],'left':null,'right':null,'origin':null,'parent':['_',0],'struct':'Insert','parentSub':'Map','opContent':['130',0]},{'struct':'Map','type':'Map','id':['130',0],'map':{}},{'id':['130',1],'left':null,'right':null,'origin':null,'parent':['_',0],'struct':'Insert','parentSub':'Map','opContent':['130',0]},{'left':null,'right':null,'origin':null,'parent':['130',0],'parentSub':'somekey','struct':'Insert','content':512,'id':['133',0]},{'id':['130',2],'left':null,'right':null,'origin':null,'parent':['130',0],'struct':'Insert','parentSub':'somekey','content':1131},{'id':['130',3],'left':null,'right':['130',2],'origin':null,'parent':['130',0],'struct':'Insert','parentSub':'somekey','content':4196},{'id':['131',3],'left':null,'right':null,'origin':null,'parent':['130',0],'struct':'Insert','parentSub':'somekey','content':5022}]//eslint-disable-line
|
||||
|
||||
for (var o of ops) {
|
||||
yield* this.store.tryExecute.call(this, o)
|
||||
}
|
||||
})
|
||||
yield wait()
|
||||
yield yconfig3.disconnect()
|
||||
yield yconfig2.disconnect()
|
||||
yield flushAll()
|
||||
wait()
|
||||
yield yconfig3.reconnect()
|
||||
yield yconfig2.reconnect()
|
||||
yield wait()
|
||||
yield flushAll()
|
||||
done()
|
||||
}))
|
||||
it('debug right not existend in Insert.execute (2)', async(function * (done) {
|
||||
yconfig1.db.requestTransaction(function * () {
|
||||
yield* this.store.tryExecute.call(this, {'struct': 'Map', 'type': 'Map', 'id': ['153', 0], 'map': {}})
|
||||
yield* this.store.tryExecute.call(this, {'id': ['153', 1], 'left': null, 'right': null, 'origin': null, 'parent': ['_', 0], 'struct': 'Insert', 'parentSub': 'Map', 'opContent': ['153', 0]})
|
||||
yield* this.store.tryExecute.call(this, {'struct': 'Map', 'type': 'Map', 'id': ['153', 0], 'map': {}})
|
||||
yield* this.store.tryExecute.call(this, {'id': ['153', 1], 'left': null, 'right': null, 'origin': null, 'parent': ['_', 0], 'struct': 'Insert', 'parentSub': 'Map', 'opContent': ['153', 0]})
|
||||
yield* this.store.tryExecute.call(this, {'struct': 'Map', 'type': 'Map', 'id': ['153', 0], 'map': {}})
|
||||
yield* this.store.tryExecute.call(this, {'id': ['153', 1], 'left': null, 'right': null, 'origin': null, 'parent': ['_', 0], 'struct': 'Insert', 'parentSub': 'Map', 'opContent': ['153', 0]})
|
||||
yield* this.store.tryExecute.call(this, {'left': null, 'right': null, 'origin': null, 'parent': ['153', 0], 'parentSub': 'somekey', 'struct': 'Insert', 'content': 3784, 'id': ['154', 0]})
|
||||
yield* this.store.tryExecute.call(this, {'left': null, 'right': ['154', 0], 'origin': null, 'parent': ['153', 0], 'parentSub': 'somekey', 'struct': 'Insert', 'content': 8217, 'id': ['154', 1]})
|
||||
yield* this.store.tryExecute.call(this, {'left': null, 'right': ['154', 1], 'origin': null, 'parent': ['153', 0], 'parentSub': 'somekey', 'struct': 'Insert', 'content': 5036, 'id': ['154', 2]})
|
||||
yield* this.store.tryExecute.call(this, {'id': ['153', 2], 'left': null, 'right': null, 'origin': null, 'parent': ['153', 0], 'struct': 'Insert', 'parentSub': 'somekey', 'content': 417})
|
||||
yield* this.store.tryExecute.call(this, {'id': ['155', 0], 'left': null, 'right': null, 'origin': null, 'parent': ['153', 0], 'struct': 'Insert', 'parentSub': 'somekey', 'content': 2202})
|
||||
yield* this.garbageCollectOperation(['153', 2])
|
||||
yield* this.garbageCollectOperation(['154', 0])
|
||||
yield* this.garbageCollectOperation(['154', 1])
|
||||
yield* this.garbageCollectOperation(['154', 2])
|
||||
yield* this.garbageCollectOperation(['155', 0])
|
||||
yield* this.garbageCollectOperation(['156', 0])
|
||||
yield* this.garbageCollectOperation(['157', 0])
|
||||
yield* this.garbageCollectOperation(['157', 1])
|
||||
yield* this.store.tryExecute.call(this, {'id': ['153', 3], 'left': null, 'right': null, 'origin': null, 'parent': ['153', 0], 'struct': 'Insert', 'parentSub': 'somekey', 'content': 4372})
|
||||
})
|
||||
yield wait()
|
||||
yield yconfig3.disconnect()
|
||||
yield yconfig2.disconnect()
|
||||
yield flushAll()
|
||||
wait()
|
||||
yield yconfig3.reconnect()
|
||||
yield yconfig2.reconnect()
|
||||
yield wait()
|
||||
yield flushAll()
|
||||
done()
|
||||
}))
|
||||
})
|
||||
describeManyTimes(repeatArrayTests, `Random tests`, function () {
|
||||
var randomArrayTransactions = [
|
||||
function insert (array) {
|
||||
array.insert(getRandomNumber(array.toArray().length), [getRandomNumber()])
|
||||
},
|
||||
function _delete (array) {
|
||||
var length = array.toArray().length
|
||||
if (length > 0) {
|
||||
array.delete(getRandomNumber(length - 1))
|
||||
}
|
||||
}
|
||||
]
|
||||
function compareArrayValues (arrays) {
|
||||
var firstArray
|
||||
for (var l of arrays) {
|
||||
var val = l.toArray()
|
||||
if (firstArray == null) {
|
||||
firstArray = val
|
||||
} else {
|
||||
expect(val).toEqual(firstArray)
|
||||
}
|
||||
}
|
||||
}
|
||||
this.arrays = yield Promise.all(promises)
|
||||
done()
|
||||
}))
|
||||
it('arrays.length equals users.length', async(function * (done) {
|
||||
expect(this.arrays.length).toEqual(this.users.length)
|
||||
done()
|
||||
}))
|
||||
it(`succeed after ${numberOfYArrayTests} actions, no GC, all users disconnecting/reconnecting`, async(function * (done) {
|
||||
for (var u of this.users) {
|
||||
u.connector.debug = true
|
||||
}
|
||||
yield applyRandomTransactionsAllRejoinNoGC(this.users, this.arrays, randomArrayTransactions, numberOfYArrayTests)
|
||||
yield flushAll()
|
||||
yield compareArrayValues(this.arrays)
|
||||
yield compareAllUsers(this.users)
|
||||
done()
|
||||
}))
|
||||
it(`succeed after ${numberOfYArrayTests} actions, GC, user[0] is not disconnecting`, async(function * (done) {
|
||||
for (var u of this.users) {
|
||||
u.connector.debug = true
|
||||
}
|
||||
yield applyRandomTransactionsWithGC(this.users, this.arrays, randomArrayTransactions, numberOfYArrayTests)
|
||||
yield flushAll()
|
||||
yield compareArrayValues(this.arrays)
|
||||
yield compareAllUsers(this.users)
|
||||
done()
|
||||
}))
|
||||
beforeEach(async(function * (done) {
|
||||
yield this.users[0].root.set('Array', Y.Array)
|
||||
yield flushAll()
|
||||
|
||||
var promises = []
|
||||
for (var u = 0; u < this.users.length; u++) {
|
||||
promises.push(this.users[u].root.get('Array'))
|
||||
}
|
||||
this.arrays = yield Promise.all(promises)
|
||||
done()
|
||||
}))
|
||||
it('arrays.length equals users.length', async(function * (done) {
|
||||
expect(this.arrays.length).toEqual(this.users.length)
|
||||
done()
|
||||
}))
|
||||
it(`succeed after ${numberOfYArrayTests} actions, no GC, all users disconnecting/reconnecting`, async(function * (done) {
|
||||
for (var u of this.users) {
|
||||
u.connector.debug = true
|
||||
}
|
||||
yield applyRandomTransactionsAllRejoinNoGC(this.users, this.arrays, randomArrayTransactions, numberOfYArrayTests)
|
||||
yield flushAll()
|
||||
yield compareArrayValues(this.arrays)
|
||||
yield compareAllUsers(this.users)
|
||||
done()
|
||||
}))
|
||||
it(`succeed after ${numberOfYArrayTests} actions, GC, user[0] is not disconnecting`, async(function * (done) {
|
||||
for (var u of this.users) {
|
||||
u.connector.debug = true
|
||||
}
|
||||
yield applyRandomTransactionsWithGC(this.users, this.arrays, randomArrayTransactions, numberOfYArrayTests)
|
||||
yield flushAll()
|
||||
yield compareArrayValues(this.arrays)
|
||||
yield compareAllUsers(this.users)
|
||||
done()
|
||||
}))
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -1,217 +1,219 @@
|
||||
/* global createUsers, Y, compareAllUsers, getRandomNumber, applyRandomTransactionsAllRejoinNoGC, applyRandomTransactionsWithGC, async, describeManyTimes */
|
||||
/* global createUsers, Y, databases, compareAllUsers, getRandomNumber, applyRandomTransactionsAllRejoinNoGC, applyRandomTransactionsWithGC, async, describeManyTimes */
|
||||
/* eslint-env browser,jasmine */
|
||||
|
||||
var numberOfYMapTests = 40
|
||||
var repeatMapTeasts = 2
|
||||
|
||||
describe('Map Type', function () {
|
||||
var y1, y2, y3, y4, flushAll
|
||||
for (var database of databases) {
|
||||
describe(`Map Type (DB: ${database})`, function () {
|
||||
var y1, y2, y3, y4, flushAll
|
||||
|
||||
beforeEach(async(function * (done) {
|
||||
yield createUsers(this, 5)
|
||||
y1 = this.users[0].root
|
||||
y2 = this.users[1].root
|
||||
y3 = this.users[2].root
|
||||
y4 = this.users[3].root
|
||||
flushAll = this.users[0].connector.flushAll
|
||||
done()
|
||||
}))
|
||||
afterEach(async(function * (done) {
|
||||
yield compareAllUsers(this.users)
|
||||
done()
|
||||
}), 5000)
|
||||
|
||||
describe('Basic tests', function () {
|
||||
it('Basic get&set of Map property (converge via sync)', async(function * (done) {
|
||||
y1.set('stuff', 'stuffy')
|
||||
expect(y1.get('stuff')).toEqual('stuffy')
|
||||
yield flushAll()
|
||||
for (var key in this.users) {
|
||||
var u = this.users[key].root
|
||||
expect(u.get('stuff')).toEqual('stuffy')
|
||||
}
|
||||
done()
|
||||
}))
|
||||
it('Map can set custom types (Map)', async(function * (done) {
|
||||
var map = yield y1.set('Map', Y.Map)
|
||||
map.set('one', 1)
|
||||
map = yield y1.get('Map')
|
||||
expect(map.get('one')).toEqual(1)
|
||||
done()
|
||||
}))
|
||||
it('Map can set custom types (Array)', async(function * (done) {
|
||||
var array = yield y1.set('Array', Y.Array)
|
||||
array.insert(0, [1, 2, 3])
|
||||
array = yield y1.get('Array')
|
||||
expect(array.toArray()).toEqual([1, 2, 3])
|
||||
done()
|
||||
}))
|
||||
it('Basic get&set of Map property (converge via update)', async(function * (done) {
|
||||
yield flushAll()
|
||||
y1.set('stuff', 'stuffy')
|
||||
expect(y1.get('stuff')).toEqual('stuffy')
|
||||
|
||||
yield flushAll()
|
||||
for (var key in this.users) {
|
||||
var r = this.users[key].root
|
||||
expect(r.get('stuff')).toEqual('stuffy')
|
||||
}
|
||||
done()
|
||||
}))
|
||||
it('Basic get&set of Map property (handle conflict)', async(function * (done) {
|
||||
yield flushAll()
|
||||
y1.set('stuff', 'c0')
|
||||
y2.set('stuff', 'c1')
|
||||
|
||||
yield flushAll()
|
||||
for (var key in this.users) {
|
||||
var u = this.users[key]
|
||||
expect(u.root.get('stuff')).toEqual('c0')
|
||||
}
|
||||
done()
|
||||
}))
|
||||
it('Basic get&set&delete of Map property (handle conflict)', async(function * (done) {
|
||||
yield flushAll()
|
||||
y1.set('stuff', 'c0')
|
||||
y1.delete('stuff')
|
||||
y2.set('stuff', 'c1')
|
||||
yield flushAll()
|
||||
|
||||
for (var key in this.users) {
|
||||
var u = this.users[key]
|
||||
expect(u.root.get('stuff')).toBeUndefined()
|
||||
}
|
||||
done()
|
||||
}))
|
||||
it('Basic get&set of Map property (handle three conflicts)', async(function * (done) {
|
||||
yield flushAll()
|
||||
y1.set('stuff', 'c0')
|
||||
y2.set('stuff', 'c1')
|
||||
y2.set('stuff', 'c2')
|
||||
y3.set('stuff', 'c3')
|
||||
yield flushAll()
|
||||
|
||||
for (var key in this.users) {
|
||||
var u = this.users[key]
|
||||
expect(u.root.get('stuff')).toEqual('c0')
|
||||
}
|
||||
done()
|
||||
}))
|
||||
it('Basic get&set&delete of Map property (handle three conflicts)', async(function * (done) {
|
||||
yield flushAll()
|
||||
y1.set('stuff', 'c0')
|
||||
y2.set('stuff', 'c1')
|
||||
y2.set('stuff', 'c2')
|
||||
y3.set('stuff', 'c3')
|
||||
yield flushAll()
|
||||
y1.set('stuff', 'deleteme')
|
||||
y1.delete('stuff')
|
||||
y2.set('stuff', 'c1')
|
||||
y3.set('stuff', 'c2')
|
||||
y4.set('stuff', 'c3')
|
||||
yield flushAll()
|
||||
|
||||
for (var key in this.users) {
|
||||
var u = this.users[key]
|
||||
expect(u.root.get('stuff')).toBeUndefined()
|
||||
}
|
||||
done()
|
||||
}))
|
||||
it('observePath properties', async(function * (done) {
|
||||
y1.observePath(['map'], function (map) {
|
||||
if (map != null) {
|
||||
map.set('yay', 4)
|
||||
}
|
||||
})
|
||||
yield y2.set('map', Y.Map)
|
||||
yield flushAll()
|
||||
var map = yield y3.get('map')
|
||||
expect(map.get('yay')).toEqual(4)
|
||||
done()
|
||||
}))
|
||||
it('throws add & update & delete events (with type and primitive content)', async(function * (done) {
|
||||
var event
|
||||
yield flushAll()
|
||||
y1.observe(function (e) {
|
||||
event = e // just put it on event, should be thrown synchronously anyway
|
||||
})
|
||||
y1.set('stuff', 4)
|
||||
expect(event).toEqual([{
|
||||
type: 'add',
|
||||
object: y1,
|
||||
name: 'stuff'
|
||||
}])
|
||||
// update, oldValue is in contents
|
||||
yield y1.set('stuff', Y.Array)
|
||||
expect(event).toEqual([{
|
||||
type: 'update',
|
||||
object: y1,
|
||||
name: 'stuff',
|
||||
oldValue: 4
|
||||
}])
|
||||
y1.get('stuff').then(function (replacedArray) {
|
||||
// update, oldValue is in opContents
|
||||
y1.set('stuff', 5)
|
||||
var getYArray = event[0].oldValue
|
||||
expect(typeof getYArray.constructor === 'function').toBeTruthy()
|
||||
getYArray().then(function (array) {
|
||||
expect(array).toEqual(replacedArray)
|
||||
|
||||
// delete
|
||||
y1.delete('stuff')
|
||||
expect(event).toEqual([{
|
||||
type: 'delete',
|
||||
name: 'stuff',
|
||||
object: y1,
|
||||
oldValue: 5
|
||||
}])
|
||||
done()
|
||||
})
|
||||
})
|
||||
}))
|
||||
})
|
||||
describeManyTimes(repeatMapTeasts, `${numberOfYMapTests} Random tests`, function () {
|
||||
var randomMapTransactions = [
|
||||
function set (map) {
|
||||
map.set('somekey', getRandomNumber())
|
||||
},
|
||||
function delete_ (map) {
|
||||
map.delete('somekey')
|
||||
}
|
||||
]
|
||||
function compareMapValues (maps) {
|
||||
var firstMap
|
||||
for (var map of maps) {
|
||||
var val = map.getPrimitive()
|
||||
if (firstMap == null) {
|
||||
firstMap = val
|
||||
} else {
|
||||
expect(val).toEqual(firstMap)
|
||||
}
|
||||
}
|
||||
}
|
||||
beforeEach(async(function * (done) {
|
||||
yield y1.set('Map', Y.Map)
|
||||
yield flushAll()
|
||||
yield createUsers(this, 5, database)
|
||||
y1 = this.users[0].root
|
||||
y2 = this.users[1].root
|
||||
y3 = this.users[2].root
|
||||
y4 = this.users[3].root
|
||||
flushAll = this.users[0].connector.flushAll
|
||||
done()
|
||||
}))
|
||||
afterEach(async(function * (done) {
|
||||
yield compareAllUsers(this.users)
|
||||
done()
|
||||
}), 5000)
|
||||
|
||||
var promises = []
|
||||
for (var u = 0; u < this.users.length; u++) {
|
||||
promises.push(this.users[u].root.get('Map'))
|
||||
describe('Basic tests', function () {
|
||||
it('Basic get&set of Map property (converge via sync)', async(function * (done) {
|
||||
y1.set('stuff', 'stuffy')
|
||||
expect(y1.get('stuff')).toEqual('stuffy')
|
||||
yield flushAll()
|
||||
for (var key in this.users) {
|
||||
var u = this.users[key].root
|
||||
expect(u.get('stuff')).toEqual('stuffy')
|
||||
}
|
||||
done()
|
||||
}))
|
||||
it('Map can set custom types (Map)', async(function * (done) {
|
||||
var map = yield y1.set('Map', Y.Map)
|
||||
map.set('one', 1)
|
||||
map = yield y1.get('Map')
|
||||
expect(map.get('one')).toEqual(1)
|
||||
done()
|
||||
}))
|
||||
it('Map can set custom types (Array)', async(function * (done) {
|
||||
var array = yield y1.set('Array', Y.Array)
|
||||
array.insert(0, [1, 2, 3])
|
||||
array = yield y1.get('Array')
|
||||
expect(array.toArray()).toEqual([1, 2, 3])
|
||||
done()
|
||||
}))
|
||||
it('Basic get&set of Map property (converge via update)', async(function * (done) {
|
||||
yield flushAll()
|
||||
y1.set('stuff', 'stuffy')
|
||||
expect(y1.get('stuff')).toEqual('stuffy')
|
||||
|
||||
yield flushAll()
|
||||
for (var key in this.users) {
|
||||
var r = this.users[key].root
|
||||
expect(r.get('stuff')).toEqual('stuffy')
|
||||
}
|
||||
done()
|
||||
}))
|
||||
it('Basic get&set of Map property (handle conflict)', async(function * (done) {
|
||||
yield flushAll()
|
||||
y1.set('stuff', 'c0')
|
||||
y2.set('stuff', 'c1')
|
||||
|
||||
yield flushAll()
|
||||
for (var key in this.users) {
|
||||
var u = this.users[key]
|
||||
expect(u.root.get('stuff')).toEqual('c0')
|
||||
}
|
||||
done()
|
||||
}))
|
||||
it('Basic get&set&delete of Map property (handle conflict)', async(function * (done) {
|
||||
yield flushAll()
|
||||
y1.set('stuff', 'c0')
|
||||
y1.delete('stuff')
|
||||
y2.set('stuff', 'c1')
|
||||
yield flushAll()
|
||||
|
||||
for (var key in this.users) {
|
||||
var u = this.users[key]
|
||||
expect(u.root.get('stuff')).toBeUndefined()
|
||||
}
|
||||
done()
|
||||
}))
|
||||
it('Basic get&set of Map property (handle three conflicts)', async(function * (done) {
|
||||
yield flushAll()
|
||||
y1.set('stuff', 'c0')
|
||||
y2.set('stuff', 'c1')
|
||||
y2.set('stuff', 'c2')
|
||||
y3.set('stuff', 'c3')
|
||||
yield flushAll()
|
||||
|
||||
for (var key in this.users) {
|
||||
var u = this.users[key]
|
||||
expect(u.root.get('stuff')).toEqual('c0')
|
||||
}
|
||||
done()
|
||||
}))
|
||||
it('Basic get&set&delete of Map property (handle three conflicts)', async(function * (done) {
|
||||
yield flushAll()
|
||||
y1.set('stuff', 'c0')
|
||||
y2.set('stuff', 'c1')
|
||||
y2.set('stuff', 'c2')
|
||||
y3.set('stuff', 'c3')
|
||||
yield flushAll()
|
||||
y1.set('stuff', 'deleteme')
|
||||
y1.delete('stuff')
|
||||
y2.set('stuff', 'c1')
|
||||
y3.set('stuff', 'c2')
|
||||
y4.set('stuff', 'c3')
|
||||
yield flushAll()
|
||||
|
||||
for (var key in this.users) {
|
||||
var u = this.users[key]
|
||||
expect(u.root.get('stuff')).toBeUndefined()
|
||||
}
|
||||
done()
|
||||
}))
|
||||
it('observePath properties', async(function * (done) {
|
||||
y1.observePath(['map'], function (map) {
|
||||
if (map != null) {
|
||||
map.set('yay', 4)
|
||||
}
|
||||
})
|
||||
yield y2.set('map', Y.Map)
|
||||
yield flushAll()
|
||||
var map = yield y3.get('map')
|
||||
expect(map.get('yay')).toEqual(4)
|
||||
done()
|
||||
}))
|
||||
it('throws add & update & delete events (with type and primitive content)', async(function * (done) {
|
||||
var event
|
||||
yield flushAll()
|
||||
y1.observe(function (e) {
|
||||
event = e // just put it on event, should be thrown synchronously anyway
|
||||
})
|
||||
y1.set('stuff', 4)
|
||||
expect(event).toEqual([{
|
||||
type: 'add',
|
||||
object: y1,
|
||||
name: 'stuff'
|
||||
}])
|
||||
// update, oldValue is in contents
|
||||
yield y1.set('stuff', Y.Array)
|
||||
expect(event).toEqual([{
|
||||
type: 'update',
|
||||
object: y1,
|
||||
name: 'stuff',
|
||||
oldValue: 4
|
||||
}])
|
||||
y1.get('stuff').then(function (replacedArray) {
|
||||
// update, oldValue is in opContents
|
||||
y1.set('stuff', 5)
|
||||
var getYArray = event[0].oldValue
|
||||
expect(typeof getYArray.constructor === 'function').toBeTruthy()
|
||||
getYArray().then(function (array) {
|
||||
expect(array).toEqual(replacedArray)
|
||||
|
||||
// delete
|
||||
y1.delete('stuff')
|
||||
expect(event).toEqual([{
|
||||
type: 'delete',
|
||||
name: 'stuff',
|
||||
object: y1,
|
||||
oldValue: 5
|
||||
}])
|
||||
done()
|
||||
})
|
||||
})
|
||||
}))
|
||||
})
|
||||
describeManyTimes(repeatMapTeasts, `${numberOfYMapTests} Random tests`, function () {
|
||||
var randomMapTransactions = [
|
||||
function set (map) {
|
||||
map.set('somekey', getRandomNumber())
|
||||
},
|
||||
function delete_ (map) {
|
||||
map.delete('somekey')
|
||||
}
|
||||
]
|
||||
function compareMapValues (maps) {
|
||||
var firstMap
|
||||
for (var map of maps) {
|
||||
var val = map.getPrimitive()
|
||||
if (firstMap == null) {
|
||||
firstMap = val
|
||||
} else {
|
||||
expect(val).toEqual(firstMap)
|
||||
}
|
||||
}
|
||||
}
|
||||
this.maps = yield Promise.all(promises)
|
||||
done()
|
||||
}))
|
||||
it(`succeed after ${numberOfYMapTests} actions, no GC, all users disconnecting/reconnecting`, async(function * (done) {
|
||||
yield applyRandomTransactionsAllRejoinNoGC(this.users, this.maps, randomMapTransactions, numberOfYMapTests)
|
||||
yield flushAll()
|
||||
yield compareMapValues(this.maps)
|
||||
done()
|
||||
}))
|
||||
it(`succeed after ${numberOfYMapTests} actions, GC, user[0] is not disconnecting`, async(function * (done) {
|
||||
yield applyRandomTransactionsWithGC(this.users, this.maps, randomMapTransactions, numberOfYMapTests)
|
||||
yield flushAll()
|
||||
yield compareMapValues(this.maps)
|
||||
done()
|
||||
}))
|
||||
beforeEach(async(function * (done) {
|
||||
yield y1.set('Map', Y.Map)
|
||||
yield flushAll()
|
||||
|
||||
var promises = []
|
||||
for (var u = 0; u < this.users.length; u++) {
|
||||
promises.push(this.users[u].root.get('Map'))
|
||||
}
|
||||
this.maps = yield Promise.all(promises)
|
||||
done()
|
||||
}))
|
||||
it(`succeed after ${numberOfYMapTests} actions, no GC, all users disconnecting/reconnecting`, async(function * (done) {
|
||||
yield applyRandomTransactionsAllRejoinNoGC(this.users, this.maps, randomMapTransactions, numberOfYMapTests)
|
||||
yield flushAll()
|
||||
yield compareMapValues(this.maps)
|
||||
done()
|
||||
}))
|
||||
it(`succeed after ${numberOfYMapTests} actions, GC, user[0] is not disconnecting`, async(function * (done) {
|
||||
yield applyRandomTransactionsWithGC(this.users, this.maps, randomMapTransactions, numberOfYMapTests)
|
||||
yield flushAll()
|
||||
yield compareMapValues(this.maps)
|
||||
done()
|
||||
}))
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user