pad.libre-service.eu-etherpad/src/tests/backend/specs/messages.js

142 lines
4.6 KiB
JavaScript
Raw Normal View History

'use strict';
const assert = require('assert').strict;
const common = require('../common');
const padManager = require('../../../node/db/PadManager');
const plugins = require('../../../static/js/pluginfw/plugin_defs');
const readOnlyManager = require('../../../node/db/ReadOnlyManager');
describe(__filename, function () {
let agent;
let pad;
let padId;
let roPadId;
let rev;
let socket;
let roSocket;
const backups = {};
before(async function () {
agent = await common.init();
});
beforeEach(async function () {
backups.hooks = {handleMessageSecurity: plugins.hooks.handleMessageSecurity};
plugins.hooks.handleMessageSecurity = [];
padId = common.randomString();
assert(!await padManager.doesPadExist(padId));
pad = await padManager.getPad(padId, 'dummy text');
await pad.setText('\n'); // Make sure the pad is created.
assert.equal(pad.text(), '\n');
let res = await agent.get(`/p/${padId}`).expect(200);
socket = await common.connect(res);
const {type, data: clientVars} = await common.handshake(socket, padId);
assert.equal(type, 'CLIENT_VARS');
rev = clientVars.collab_client_vars.rev;
roPadId = await readOnlyManager.getReadOnlyId(padId);
res = await agent.get(`/p/${roPadId}`).expect(200);
roSocket = await common.connect(res);
await common.handshake(roSocket, roPadId, `t.${common.randomString(8)}`);
});
afterEach(async function () {
Object.assign(plugins.hooks, backups.hooks);
if (socket != null) socket.close();
socket = null;
if (roSocket != null) roSocket.close();
roSocket = null;
if (pad != null) await pad.remove();
pad = null;
});
describe('USER_CHANGES', function () {
const sendUserChanges =
async (socket, cs) => await common.sendUserChanges(socket, {baseRev: rev, changeset: cs});
const assertAccepted = async (socket, wantRev) => {
await common.waitForAcceptCommit(socket, wantRev);
rev = wantRev;
};
const assertRejected = async (socket) => {
const msg = await common.waitForSocketEvent(socket, 'message');
assert.deepEqual(msg, {disconnect: 'badChangeset'});
};
it('changes are applied', async function () {
await Promise.all([
assertAccepted(socket, rev + 1),
sendUserChanges(socket, 'Z:1>5+5$hello'),
]);
assert.equal(pad.text(), 'hello\n');
});
it('bad changeset is rejected', async function () {
await Promise.all([
assertRejected(socket),
sendUserChanges(socket, 'this is not a valid changeset'),
]);
});
it('retransmission is accepted, has no effect', async function () {
const cs = 'Z:1>5+5$hello';
await Promise.all([
assertAccepted(socket, rev + 1),
sendUserChanges(socket, cs),
]);
--rev;
await Promise.all([
assertAccepted(socket, rev + 1),
sendUserChanges(socket, cs),
]);
assert.equal(pad.text(), 'hello\n');
});
2021-12-12 02:03:35 +01:00
it('identity changeset is accepted, has no effect', async function () {
await Promise.all([
assertAccepted(socket, rev + 1),
sendUserChanges(socket, 'Z:1>5+5$hello'),
]);
await Promise.all([
assertAccepted(socket, rev),
sendUserChanges(socket, 'Z:6>0$'),
]);
assert.equal(pad.text(), 'hello\n');
});
2021-12-12 02:03:35 +01:00
it('non-identity changeset with no net change is accepted, has no effect', async function () {
await Promise.all([
assertAccepted(socket, rev + 1),
sendUserChanges(socket, 'Z:1>5+5$hello'),
]);
await Promise.all([
assertAccepted(socket, rev),
sendUserChanges(socket, 'Z:6>0-5+5$hello'),
]);
assert.equal(pad.text(), 'hello\n');
});
it('handleMessageSecurity can grant one-time write access', async function () {
const cs = 'Z:1>5+5$hello';
// First try to send a change and verify that it was dropped.
await sendUserChanges(roSocket, cs);
// sendUserChanges() waits for message ack, so if the message was accepted then head should
// have already incremented by the time we get here.
assert.equal(pad.head, rev); // Not incremented.
// Now allow the change.
plugins.hooks.handleMessageSecurity.push({hook_fn: () => 'permitOnce'});
await Promise.all([
assertAccepted(roSocket, rev + 1),
sendUserChanges(roSocket, cs),
]);
assert.equal(pad.text(), 'hello\n');
// The next change should be dropped.
plugins.hooks.handleMessageSecurity = [];
await sendUserChanges(roSocket, 'Z:6>6=5+6$ world');
assert.equal(pad.head, rev); // Not incremented.
assert.equal(pad.text(), 'hello\n');
});
});
});