From 6deb595fecfb66c5d0e62421c8c852cd759462a5 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 14 Sep 2018 12:17:22 +0200 Subject: [PATCH 1/5] add logging to rest session actions --- src/rest/creator.js | 4 ++-- src/rest/multi.js | 49 ++++++++++++++++++++++++++++++++++++--------- src/rest/room.js | 7 ++++++- src/rest/session.js | 12 +++++++++-- src/scenario.js | 2 +- 5 files changed, 58 insertions(+), 16 deletions(-) diff --git a/src/rest/creator.js b/src/rest/creator.js index 9090a21e70..84b1fbc70a 100644 --- a/src/rest/creator.js +++ b/src/rest/creator.js @@ -27,10 +27,10 @@ module.exports = class RestSessionCreator { this.cwd = cwd; } - async createSessionRange(usernames, password) { + async createSessionRange(usernames, password, groupName) { const sessionPromises = usernames.map((username) => this.createSession(username, password)); const sessions = await Promise.all(sessionPromises); - return new RestMultiSession(sessions); + return new RestMultiSession(sessions, groupName); } async createSession(username, password) { diff --git a/src/rest/multi.js b/src/rest/multi.js index 12ebe9d4ab..35bb11a0cf 100644 --- a/src/rest/multi.js +++ b/src/rest/multi.js @@ -17,14 +17,16 @@ limitations under the License. const request = require('request-promise-native'); const RestRoom = require('./room'); const {approveConsent} = require('./consent'); +const Logger = require('../logger'); module.exports = class RestMultiSession { - constructor(sessions) { + constructor(sessions, groupName) { + this.log = new Logger(groupName); this.sessions = sessions; } - slice(start, end) { - return new RestMultiSession(this.sessions.slice(start, end)); + slice(start, end, groupName) { + return new RestMultiSession(this.sessions.slice(start, end), groupName); } pop(userName) { @@ -37,25 +39,52 @@ module.exports = class RestMultiSession { } async setDisplayName(fn) { - await Promise.all(this.sessions.map((s) => s.setDisplayName(fn(s)))); + this.log.step("set their display name") + await Promise.all(this.sessions.map(async (s) => { + s.log.mute(); + await s.setDisplayName(fn(s)); + s.log.unmute(); + })); + this.log.done(); } - async join(roomId) { - const rooms = await Promise.all(this.sessions.map((s) => s.join(roomId))); - return new RestMultiRoom(rooms); + async join(roomIdOrAlias) { + this.log.step(`join ${roomIdOrAlias}`) + const rooms = await Promise.all(this.sessions.map(async (s) => { + s.log.mute(); + const room = await s.join(roomIdOrAlias); + s.log.unmute(); + return room; + })); + this.log.done(); + return new RestMultiRoom(rooms, roomIdOrAlias, this.log); } } class RestMultiRoom { - constructor(rooms) { + constructor(rooms, roomIdOrAlias, log) { this.rooms = rooms; + this.roomIdOrAlias = roomIdOrAlias; + this.log = log; } async talk(message) { - await Promise.all(this.rooms.map((r) => r.talk(message))); + this.log.step(`say "${message}" in ${this.roomIdOrAlias}`) + await Promise.all(this.rooms.map(async (r) => { + r.log.mute(); + await r.talk(message); + r.log.unmute(); + })); + this.log.done(); } async leave() { - await Promise.all(this.rooms.map((r) => r.leave())); + this.log.step(`leave ${this.roomIdOrAlias}`) + await Promise.all(this.rooms.map(async (r) => { + r.log.mute(); + await r.leave(message); + r.log.unmute(); + })); + this.log.done(); } } diff --git a/src/rest/room.js b/src/rest/room.js index d8de958a27..a7f40af594 100644 --- a/src/rest/room.js +++ b/src/rest/room.js @@ -18,22 +18,27 @@ const uuidv4 = require('uuid/v4'); /* no pun intented */ module.exports = class RestRoom { - constructor(session, roomId) { + constructor(session, roomId, log) { this.session = session; this._roomId = roomId; + this.log = log; } async talk(message) { + this.log.step(`says "${message}" in ${this._roomId}`) const txId = uuidv4(); await this.session._put(`/rooms/${this._roomId}/send/m.room.message/${txId}`, { "msgtype": "m.text", "body": message }); + this.log.done(); return txId; } async leave() { + this.log.step(`leaves ${this._roomId}`) await this.session._post(`/rooms/${this._roomId}/leave`); + this.log.done(); } roomId() { diff --git a/src/rest/session.js b/src/rest/session.js index ece04f3352..21922a69f1 100644 --- a/src/rest/session.js +++ b/src/rest/session.js @@ -15,11 +15,13 @@ limitations under the License. */ const request = require('request-promise-native'); +const Logger = require('../logger'); const RestRoom = require('./room'); const {approveConsent} = require('./consent'); module.exports = class RestSession { constructor(credentials) { + this.log = new Logger(credentials.userId); this._credentials = credentials; this._displayName = null; } @@ -37,18 +39,23 @@ module.exports = class RestSession { } async setDisplayName(displayName) { + this.log.step(`sets their display name to ${displayName}`); this._displayName = displayName; await this._put(`/profile/${this._credentials.userId}/displayname`, { displayname: displayName }); + this.log.done(); } async join(roomIdOrAlias) { + this.log.step(`joins ${roomIdOrAlias}`); const {room_id} = await this._post(`/join/${encodeURIComponent(roomIdOrAlias)}`); - return new RestRoom(this, room_id); + this.log.done(); + return new RestRoom(this, room_id, this.log); } async createRoom(name, options) { + this.log.step(`creates room ${name}`); const body = { name, }; @@ -68,7 +75,8 @@ module.exports = class RestSession { } const {room_id} = await this._post(`/createRoom`, body); - return new RestRoom(this, room_id); + this.log.done(); + return new RestRoom(this, room_id, this.log); } _post(csApiPath, body) { diff --git a/src/scenario.js b/src/scenario.js index f0b4ad988b..12cff7d498 100644 --- a/src/scenario.js +++ b/src/scenario.js @@ -41,7 +41,7 @@ module.exports = async function scenario(createSession, restCreator) { async function createRestUsers(restCreator) { const usernames = range(1, 10).map((i) => `charly-${i}`); - const charlies = await restCreator.createSessionRange(usernames, 'testtest'); + const charlies = await restCreator.createSessionRange(usernames, "testtest", "charly-1..10"); await charlies.setDisplayName((s) => `Charly #${s.userName().split('-')[1]}`); return charlies; } From 16b2f09915cce5781cf8da90cf101491158044fc Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 14 Sep 2018 12:44:01 +0200 Subject: [PATCH 2/5] Test if members joining while user is offline are received after returning online with LL enabled --- src/rest/multi.js | 2 +- src/scenarios/lazy-loading.js | 29 +++++++++++++++++++++++++---- src/session.js | 7 +++++++ 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/rest/multi.js b/src/rest/multi.js index 35bb11a0cf..3d24245ddf 100644 --- a/src/rest/multi.js +++ b/src/rest/multi.js @@ -25,7 +25,7 @@ module.exports = class RestMultiSession { this.sessions = sessions; } - slice(start, end, groupName) { + slice(groupName, start, end) { return new RestMultiSession(this.sessions.slice(start, end), groupName); } diff --git a/src/scenarios/lazy-loading.js b/src/scenarios/lazy-loading.js index bd7c1d1507..a606cc0421 100644 --- a/src/scenarios/lazy-loading.js +++ b/src/scenarios/lazy-loading.js @@ -31,9 +31,15 @@ const assert = require('assert'); module.exports = async function lazyLoadingScenarios(alice, bob, charlies) { console.log(" creating a room for lazy loading member scenarios:"); await enableLazyLoading(alice); - await setupRoomWithBobAliceAndCharlies(alice, bob, charlies); - await checkPaginatedDisplayNames(alice, charlies); - await checkMemberList(alice, charlies); + const charly1to5 = charlies.slice("charly-1..5", 0, 5); + const charly6to10 = charlies.slice("charly-6..10", 5); + assert(charly1to5.sessions.length, 5); + assert(charly6to10.sessions.length, 5); + await setupRoomWithBobAliceAndCharlies(alice, bob, charly1to5); + await checkPaginatedDisplayNames(alice, charly1to5); + await checkMemberList(alice, charly1to5); + await joinCharliesWhileAliceIsOffline(alice, charly6to10); + await checkMemberList(alice, charly6to10); } const room = "Lazy Loading Test"; @@ -70,7 +76,7 @@ async function checkPaginatedDisplayNames(alice, charlies) { }); }, messages); }, []); - await checkTimelineContains(alice, expectedMessages, "Charly #1-10"); + await checkTimelineContains(alice, expectedMessages, "Charly #1-5"); } async function checkMemberList(alice, charlies) { @@ -85,3 +91,18 @@ async function checkMemberList(alice, charlies) { }); alice.log.done(); } + +async function joinCharliesWhileAliceIsOffline(alice, charly6to10) { + await alice.setOffline(true); + await delay(1000); + const members6to10 = await charly6to10.join(alias); + const member6 = members6to10.rooms[0]; + member6.log.step("sends 20 messages").mute(); + for(let i = 20; i >= 1; --i) { + await member6.talk("where is charly?"); + } + member6.log.unmute().done(); + await delay(1000); + await alice.setOffline(false); + await delay(1000); +} diff --git a/src/session.js b/src/session.js index 3f233ee8f2..82a66fda39 100644 --- a/src/session.js +++ b/src/session.js @@ -173,6 +173,13 @@ module.exports = class RiotSession { return delay(ms); } + async setOffline(enabled) { + const description = enabled ? "offline" : "back online"; + this.log.step(`goes ${description}`); + await this.page.setOfflineMode(enabled); + this.log.done(); + } + close() { return this.browser.close(); } From 36708cc5db5cc303904884bc9ea50ac76bcb3a5c Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 14 Sep 2018 14:45:40 +0200 Subject: [PATCH 3/5] wait for next sync before inspecting memberlist before we needed a 10s delay here to make the test work reliable, this should be faster in the best case. --- src/scenarios/lazy-loading.js | 5 +++-- src/session.js | 27 +++++++++++++++++++++++++++ src/usecases/timeline.js | 5 +---- 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/scenarios/lazy-loading.js b/src/scenarios/lazy-loading.js index a606cc0421..15826af568 100644 --- a/src/scenarios/lazy-loading.js +++ b/src/scenarios/lazy-loading.js @@ -102,7 +102,8 @@ async function joinCharliesWhileAliceIsOffline(alice, charly6to10) { await member6.talk("where is charly?"); } member6.log.unmute().done(); - await delay(1000); + const catchupPromise = alice.waitForNextSuccessfulSync(); await alice.setOffline(false); - await delay(1000); + await catchupPromise; + await delay(2000); } diff --git a/src/session.js b/src/session.js index 82a66fda39..7ea980bd32 100644 --- a/src/session.js +++ b/src/session.js @@ -161,6 +161,33 @@ module.exports = class RiotSession { }); } + waitForSyncResponseWith(predicate) { + return this.page.waitForResponse(async (response) => { + if (response.request().url().indexOf("/sync") === -1) { + return false; + } + return predicate(response); + }); + } + + /** wait for a /sync request started after this call that gets a 200 response */ + async waitForNextSuccessfulSync() { + const syncUrls = []; + function onRequest(request) { + if (request.url().indexOf("/sync") !== -1) { + syncUrls.push(request.url()); + } + } + + this.page.on('request', onRequest); + + await this.page.waitForResponse((response) => { + return syncUrls.includes(response.request().url()) && response.status() === 200; + }); + + this.page.removeListener('request', onRequest); + } + goto(url) { return this.page.goto(url); } diff --git a/src/usecases/timeline.js b/src/usecases/timeline.js index 466d7fb222..dce0203660 100644 --- a/src/usecases/timeline.js +++ b/src/usecases/timeline.js @@ -64,10 +64,7 @@ module.exports.receiveMessage = async function(session, expectedMessage) { if (isExpectedMessage) { assertMessage(lastMessage, expectedMessage); } else { - await session.page.waitForResponse(async (response) => { - if (response.request().url().indexOf("/sync") === -1) { - return false; - } + await session.waitForSyncResponseWith(async (response) => { const body = await response.text(); if (expectedMessage.encrypted) { return body.indexOf(expectedMessage.sender) !== -1 && From 992a0be4d08f877e731b71db3d0da0b1687ae8fd Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 14 Sep 2018 14:46:25 +0200 Subject: [PATCH 4/5] DRY usernames --- src/scenarios/lazy-loading.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/scenarios/lazy-loading.js b/src/scenarios/lazy-loading.js index 15826af568..c33e83215c 100644 --- a/src/scenarios/lazy-loading.js +++ b/src/scenarios/lazy-loading.js @@ -76,11 +76,11 @@ async function checkPaginatedDisplayNames(alice, charlies) { }); }, messages); }, []); - await checkTimelineContains(alice, expectedMessages, "Charly #1-5"); + await checkTimelineContains(alice, expectedMessages, charlies.log.username); } async function checkMemberList(alice, charlies) { - alice.log.step("checks the memberlist contains herself, bob and all charlies"); + alice.log.step(`checks the memberlist contains herself, bob and ${charlies.log.username}`); const displayNames = (await getMembersInMemberlist(alice)).map((m) => m.displayName); assert(displayNames.includes("alice")); assert(displayNames.includes("bob")); From 8cff961ec82469e5321634992d45aad9a00c2e25 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 14 Sep 2018 14:46:42 +0200 Subject: [PATCH 5/5] use develop for now as LL with gappy syncs is fixed on that branch for now --- synapse/install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/synapse/install.sh b/synapse/install.sh index 3d8172a9f6..37dfd7d7e2 100755 --- a/synapse/install.sh +++ b/synapse/install.sh @@ -1,6 +1,6 @@ #!/bin/bash # config -SYNAPSE_BRANCH=master +SYNAPSE_BRANCH=develop INSTALLATION_NAME=consent SERVER_DIR=installations/$INSTALLATION_NAME CONFIG_TEMPLATE=consent