re-implementing tests with async await. tests also check asynchronous behaviour now.

This commit is contained in:
Kevin Jahns 2015-07-18 23:15:20 +02:00
parent ebc628adfc
commit d4ef54358b
7 changed files with 183 additions and 164 deletions

View File

@ -37,6 +37,7 @@
"CustomType": true,
"window": true,
"document": true,
"smaller": true
"smaller": true,
"wait": true
}
}

View File

@ -95,7 +95,9 @@ gulp.task("build", function () {
.pipe(babel({
loose: "all",
modules: "ignore",
blacklist: ["regenerator"]
optional: ["es7.asyncFunctions"],
blacklist: ["regenerator"],
experimental: true
}))
.pipe(sourcemaps.write())
.pipe(gulp.dest("."));
@ -114,7 +116,9 @@ gulp.task("test", function () {
.pipe(concat("jasmine"))
.pipe(babel({
loose: "all",
modules: "ignore"
optional: ["es7.asyncFunctions"],
modules: "ignore",
experimental: true
}))
.pipe(uglify())
.pipe(sourcemaps.write())
@ -132,7 +136,9 @@ gulp.task("build_jasmine_browser", function(){
.pipe(babel({
loose: "all",
modules: "ignore",
blacklist: ["regenerator"]
optional: ["es7.asyncFunctions"],
blacklist: "regenerator",
experimental: true
}))
.pipe(sourcemaps.write())
.pipe(gulp.dest("build"));

View File

@ -81,22 +81,22 @@ class AbstractConnector { //eslint-disable-line no-unused-vars
// returns false, if there is no sync target
// true otherwise
findNextSyncTarget () {
if (this.currentSyncTarget != null && this.connections[this.currentSyncTarget].isSynced === false) {
throw new Error("The current sync has not finished!");
if (this.currentSyncTarget != null) {
return; // "The current sync has not finished!"
}
var syncUser = null;
for (var uid in this.connections) {
syncUser = this.connections[uid];
if (!syncUser.isSynced) {
if (!this.connections[uid].isSynced) {
syncUser = uid;
break;
}
}
if (syncUser != null){
var conn = this;
this.currentSyncTarget = syncUser;
this.y.db.requestTransaction(function*(){
conn.currentSyncTarget = uid;
conn.send(uid, {
conn.send(syncUser, {
type: "sync step 1",
stateVector: yield* this.getStateVector()
});
@ -110,7 +110,6 @@ class AbstractConnector { //eslint-disable-line no-unused-vars
}
this.whenSyncedListeners = null;
}
return false;
}
send (uid, message) {
if (this.debug) {
@ -149,24 +148,38 @@ class AbstractConnector { //eslint-disable-line no-unused-vars
type: "sync done"
});
}, conn.syncingClientDuration);
} else {
conn.send(sender, {
type: "sync done"
});
}
});
} else if (m.type === "sync step 2") {
this.y.db.apply(m.os);
let conn = this;
var broadcastHB = !this.broadcastedHB;
this.broadcastedHB = true;
this.y.db.requestTransaction(function*(){
var ops = yield* this.getOperations(m.stateVector);
conn.broadcastedHB = true;
if (ops.length > 0) {
conn.broadcast({
m = {
type: "update",
ops: ops
});
};
if (!broadcastHB) {
conn.send(sender, m);
} else {
// broadcast only once!
conn.broadcast(m);
}
}
});
} else if (m.type === "sync done") {
this.connections[sender].isSynced = true;
this.findNextSyncTarget();
if (sender === this.currentSyncTarget) {
this.currentSyncTarget = null;
this.findNextSyncTarget();
}
} else if (m.type === "update") {
if (this.forwardToSyncingClients) {
for (var client of this.syncingClients) {

View File

@ -73,10 +73,26 @@ class Test extends AbstractConnector {
}
}
flushAll () {
var c = true;
while (c) {
c = flushOne();
var def = Promise.defer();
// flushes may result in more created operations,
// flush until there is nothing more to flush
function nextFlush() {
var c = flushOne();
if (c) {
while(flushOne()) {
//nop
}
wait().then(nextFlush);
} else {
wait().then(function(){
def.resolve();
});
}
}
// in the case that there are
// still actions that want to be performed
wait(0).then(nextFlush);
return def.promise;
}
flushOne() {
flushOne();

View File

@ -5,6 +5,13 @@
This is "just" a compilation of functions that help to test this library!
***/
function wait(t = 0) {//eslint-disable-line
var def = Promise.defer();
setTimeout(function(){
def.resolve();
}, t);
return def.promise;
}
// returns a random element of o
// works on Object, and Array
@ -26,7 +33,7 @@ function getRandomNumber(n) {//eslint-disable-line
return Math.floor(Math.random() * n);
}
function applyRandomTransactions (users, objects, transactions, numberOfTransactions) {//eslint-disable-line
async function applyRandomTransactions (users, objects, transactions, numberOfTransactions) {//eslint-disable-line
function randomTransaction (root) {
var f = getRandom(transactions);
f(root);
@ -39,40 +46,45 @@ function applyRandomTransactions (users, objects, transactions, numberOfTransact
} else {
randomTransaction(getRandom(objects));
}
wait();
}
}
function compareAllUsers(users){//eslint-disable-line
async function compareAllUsers(users){//eslint-disable-line
var s1, s2;
var db1 = [];
function* t1(){
s1 = yield* this.getStateSet();
}
function* t2(){
s2 = yield* this.getStateSet();
}
users[0].connector.flushAll();
for (var uid = 0; uid + 1 < users.length; uid++) {
var u1 = users[uid];
var u2 = users[uid + 1];
u1.db.requestTransaction(t1);
u2.db.requestTransaction(t2);
expect(s1).toEqual(s2);
var db1 = [];
var db2 = [];
u1.db.os.iterate(null, null, function(o){//eslint-disable-line
db1.push(o);
});
u2.db.os.iterate(null, null, function(o){//eslint-disable-line
db2.push(o);
});
for (var key in db1) {
expect(db1[key]).toEqual(db2[key]);
await users[0].connector.flushAll();
for (var uid = 0; uid < users.length; uid++) {
if (s1 == null) {
var u = users[uid];
u.db.requestTransaction(t1);
await wait();
u.db.os.iterate(null, null, function(o){//eslint-disable-line
db1.push(o);
});
} else {
var u2 = users[uid];
u2.db.requestTransaction(t2);
await wait();
expect(s1).toEqual(s2);
var count = 0;
u2.db.os.iterate(null, null, function(o){//eslint-disable-line
expect(db1[count++]).toEqual(o);
});
}
}
}
function createUsers(self, numberOfUsers, done) {//eslint-disable-line
async function createUsers(self, numberOfUsers) {//eslint-disable-line
if (globalRoom.users[0] != null) {//eslint-disable-line
await globalRoom.users[0].flushAll();//eslint-disable-line
}
//destroy old users
for (var u in globalRoom.users) {//eslint-disable-line
globalRoom.users[u].y.destroy()//eslint-disable-line
@ -91,8 +103,5 @@ function createUsers(self, numberOfUsers, done) {//eslint-disable-line
}
}));
}
Promise.all(promises).then( users => {
self.users = users;
done();
});
self.users = await Promise.all(promises);
}

View File

@ -126,7 +126,7 @@ Y.Memory = (function(){ //eslint-disable-line no-unused-vars
requestTransaction (_makeGen : Function) {
if (!this.transactionInProgress) {
this.transactionInProgress = true;
window.setTimeout(() => {
setTimeout(() => {
var makeGen = _makeGen;
while (makeGen != null) {
var t = new Transaction(this);

View File

@ -1,116 +1,98 @@
/* @flow */
/*eslint-env browser,jasmine */
var numberOfYArrayTests = 20;
var numberOfYArrayTests = 80;
describe("Array Type", function(){
jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000;
beforeEach(function(done){
createUsers(this, 5, done);
var y1, y2, y3, flushAll;
jasmine.DEFAULT_TIMEOUT_INTERVAL = 50000;
beforeEach(async function(done){
await createUsers(this, 5);
y1 = this.users[0].root;
y2 = this.users[1].root;
y3 = this.users[2].root;
flushAll = this.users[0].connector.flushAll;
done();
});
afterEach(async function(done) {
await compareAllUsers(this.users);
done();
});
describe("Basic tests", function(){
it("insert three elements", function(done){
var y = this.users[0].root;
y.set("Array", Y.Array).then(function(array) {
array.insert(0, [1, 2, 3]);
return y.get("Array");
}).then(function(array){
expect(array.toArray()).toEqual([1, 2, 3]);
done();
});
it("insert three elements, try re-get property", async function(done){
var array = await y1.set("Array", Y.Array);
array.insert(0, [1, 2, 3]);
array = await y1.get("Array"); // re-get property
expect(array.toArray()).toEqual([1, 2, 3]);
done();
});
it("Basic insert in array (handle three conflicts)", function(done){
var y = this.users[0];
it("Basic insert in array (handle three conflicts)", async function(done){
var l1, l2, l3;
y.root.set("Array", Y.Array).then((array)=>{
l1 = array;
y.connector.flushAll();
l1.insert(0, [0]);
return this.users[1].root.get("Array");
}).then((array)=>{
l2 = array;
l2.insert(0, [1]);
return this.users[2].root.get("Array");
}).then((array)=>{
l3 = array;
l3.insert(0, [2]);
y.connector.flushAll();
expect(l1.toArray()).toEqual(l2.toArray());
expect(l2.toArray()).toEqual(l3.toArray());
compareAllUsers(this.users);
done();
});
await y1.set("Array", Y.Array);
await flushAll();
(l1 = await y1.get("Array")).insert(0, [0]);
(l2 = await y2.get("Array")).insert(0, [1]);
(l3 = await y3.get("Array")).insert(0, [2]);
await flushAll();
expect(l1.toArray()).toEqual(l2.toArray());
expect(l2.toArray()).toEqual(l3.toArray());
done();
});
it("Basic insert&delete in array (handle three conflicts)", function(done){
var y = this.users[0];
it("Basic insert&delete in array (handle three conflicts)", async function(done){
var l1, l2, l3;
y.root.set("Array", Y.Array).then((array)=>{
l1 = array;
l1.insert(0, ["x", "y", "z"]);
y.connector.flushAll();
l1.insert(1, [0]);
return this.users[1].root.get("Array");
}).then((array)=>{
l2 = array;
l2.delete(0);
l2.delete(1);
return this.users[2].root.get("Array");
}).then((array)=>{
l3 = array;
l3.insert(1, [2]);
y.connector.flushAll();
expect(l1.toArray()).toEqual(l2.toArray());
expect(l2.toArray()).toEqual(l3.toArray());
expect(l2.toArray()).toEqual([0, 2, "y"]);
compareAllUsers(this.users);
done();
});
l1 = await y1.set("Array", Y.Array);
l1.insert(0, ["x", "y", "z"]);
await flushAll();
l1.insert(1, [0]);
l2 = await y2.get("Array");
l2.delete(0);
l2.delete(1);
l3 = await y3.get("Array");
l3.insert(1, [2]);
await flushAll();
expect(l1.toArray()).toEqual(l2.toArray());
expect(l2.toArray()).toEqual(l3.toArray());
expect(l2.toArray()).toEqual([0, 2, "y"]);
done();
});
it("Basic insert. Then delete the whole array", function(done){
var y = this.users[0];
it("Basic insert. Then delete the whole array", async function(done){
var l1, l2, l3;
y.root.set("Array", Y.Array).then((array)=>{
l1 = array;
l1.insert(0, ["x", "y", "z"]);
y.connector.flushAll();
l1.delete(0, 3);
return this.users[1].root.get("Array");
}).then((array)=>{
l2 = array;
return this.users[2].root.get("Array");
}).then((array)=>{
l3 = array;
y.connector.flushAll();
expect(l1.toArray()).toEqual(l2.toArray());
expect(l2.toArray()).toEqual(l3.toArray());
expect(l2.toArray()).toEqual([]);
compareAllUsers(this.users);
done();
});
l1 = await y1.set("Array", Y.Array);
l1.insert(0, ["x", "y", "z"]);
await flushAll();
l1.delete(0, 3);
l2 = await y2.get("Array");
l3 = await y3.get("Array");
await flushAll();
expect(l1.toArray()).toEqual(l2.toArray());
expect(l2.toArray()).toEqual(l3.toArray());
expect(l2.toArray()).toEqual([]);
done();
});
it("throw insert & delete events", function(done){
this.users[0].root.set("array", Y.Array).then(function(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
}]);
done();
it("throw insert & delete events", async function(done){
var array = await 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
}]);
await wait(50);
done();
});
});
describe(`${numberOfYArrayTests} Random tests`, function(){
@ -136,34 +118,26 @@ describe("Array Type", function(){
}
}
}
beforeEach(function(done){
this.users[0].root.set("Array", Y.Array);
this.users[0].connector.flushAll();
beforeEach(async function(done){
await this.users[0].root.set("Array", Y.Array);
await flushAll();
var then = Promise.resolve();
var arrays = [];
for (var u of this.users) {
then = then.then(function(){ //eslint-disable-line
return u.root.get("Array");
}).then(function(array){//eslint-disable-line
arrays.push(array);
});
var promises = [];
for (var u = 0; u < this.users.length; u++) {
promises.push(this.users[u].root.get("Array"));
}
this.arrays = arrays;
then.then(function(){
done();
});
this.arrays = await Promise.all(promises);
done();
});
it("arrays.length equals users.length", function(){
it("arrays.length equals users.length", async function(done){
expect(this.arrays.length).toEqual(this.users.length);
done();
});
it(`succeed after ${numberOfYArrayTests} actions`, function(done){
applyRandomTransactions(this.users, this.arrays, randomArrayTransactions, numberOfYArrayTests);
setTimeout(()=>{
compareAllUsers(this.users);
compareArrayValues(this.arrays);
done();
}, 500);
it(`succeed after ${numberOfYArrayTests} actions`, async function(done){
await applyRandomTransactions(this.users, this.arrays, randomArrayTransactions, numberOfYArrayTests);
await flushAll();
await compareArrayValues(this.arrays);
done();
});
});
});