2017-03-03 06:45:34 +08:00
|
|
|
import IMAPConnectionPool from '../src/imap-connection-pool';
|
2017-02-18 04:05:50 +08:00
|
|
|
import IMAPConnection from '../src/imap-connection';
|
|
|
|
import IMAPErrors from '../src/imap-errors';
|
|
|
|
|
|
|
|
describe('IMAPConnectionPool', function describeBlock() {
|
|
|
|
beforeEach(() => {
|
|
|
|
this.account = {
|
|
|
|
id: 'test-account',
|
|
|
|
decryptedCredentials: () => { return {}; },
|
|
|
|
connectionSettings: {
|
|
|
|
imap_host: 'imap.foobar.com',
|
|
|
|
},
|
|
|
|
};
|
|
|
|
IMAPConnectionPool._poolMap = {};
|
|
|
|
this.logger = {};
|
2017-03-01 05:38:14 +08:00
|
|
|
spyOn(IMAPConnection.prototype, 'connect').andCallFake(function connectFake() {
|
2017-02-18 04:05:50 +08:00
|
|
|
return this;
|
|
|
|
});
|
2017-03-01 05:38:14 +08:00
|
|
|
spyOn(IMAPConnection.prototype, 'end').andCallFake(() => {});
|
2017-02-18 04:05:50 +08:00
|
|
|
});
|
|
|
|
|
|
|
|
it('opens IMAP connection and properly returns to pool at end of scope', async () => {
|
|
|
|
let invokedCallback = false;
|
|
|
|
await IMAPConnectionPool.withConnectionsForAccount(this.account, {
|
|
|
|
desiredCount: 1,
|
|
|
|
logger: this.logger,
|
2017-03-22 05:07:45 +08:00
|
|
|
socketTimeout: 5 * 1000,
|
2017-02-18 04:05:50 +08:00
|
|
|
onConnected: ([conn]) => {
|
|
|
|
expect(conn instanceof IMAPConnection).toBe(true);
|
|
|
|
invokedCallback = true;
|
|
|
|
return false;
|
|
|
|
},
|
|
|
|
});
|
|
|
|
expect(invokedCallback).toBe(true);
|
2017-03-01 05:38:14 +08:00
|
|
|
expect(IMAPConnection.prototype.connect.calls.length).toBe(1);
|
|
|
|
expect(IMAPConnection.prototype.end.calls.length).toBe(0);
|
2017-02-18 04:05:50 +08:00
|
|
|
});
|
|
|
|
|
|
|
|
it('opens multiple IMAP connections and properly returns to pool at end of scope', async () => {
|
|
|
|
let invokedCallback = false;
|
|
|
|
await IMAPConnectionPool.withConnectionsForAccount(this.account, {
|
|
|
|
desiredCount: 2,
|
|
|
|
logger: this.logger,
|
2017-03-22 05:07:45 +08:00
|
|
|
socketTimeout: 5 * 1000,
|
2017-02-18 04:05:50 +08:00
|
|
|
onConnected: ([conn, otherConn]) => {
|
|
|
|
expect(conn instanceof IMAPConnection).toBe(true);
|
|
|
|
expect(otherConn instanceof IMAPConnection).toBe(true);
|
|
|
|
invokedCallback = true;
|
|
|
|
return false;
|
|
|
|
},
|
|
|
|
});
|
|
|
|
expect(invokedCallback).toBe(true);
|
2017-03-01 05:38:14 +08:00
|
|
|
expect(IMAPConnection.prototype.connect.calls.length).toBe(2);
|
|
|
|
expect(IMAPConnection.prototype.end.calls.length).toBe(0);
|
2017-02-18 04:05:50 +08:00
|
|
|
});
|
|
|
|
|
|
|
|
it('opens an IMAP connection properly and only returns to pool on done', async () => {
|
|
|
|
let invokedCallback = false;
|
|
|
|
let doneCallback = null;
|
|
|
|
await IMAPConnectionPool.withConnectionsForAccount(this.account, {
|
|
|
|
desiredCount: 1,
|
|
|
|
logger: this.logger,
|
2017-03-22 05:07:45 +08:00
|
|
|
socketTimeout: 5 * 1000,
|
2017-02-18 04:05:50 +08:00
|
|
|
onConnected: ([conn], done) => {
|
|
|
|
expect(conn instanceof IMAPConnection).toBe(true);
|
|
|
|
invokedCallback = true;
|
|
|
|
doneCallback = done;
|
|
|
|
return true;
|
|
|
|
},
|
|
|
|
});
|
|
|
|
expect(invokedCallback).toBe(true);
|
2017-03-01 05:38:14 +08:00
|
|
|
expect(IMAPConnection.prototype.connect.calls.length).toBe(1);
|
|
|
|
expect(IMAPConnection.prototype.end.calls.length).toBe(0);
|
2017-02-18 04:05:50 +08:00
|
|
|
expect(IMAPConnectionPool._poolMap[this.account.id]._availableConns.length === 2);
|
|
|
|
doneCallback();
|
|
|
|
expect(IMAPConnectionPool._poolMap[this.account.id]._availableConns.length === 3);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('does not call connect if already connected', async () => {
|
|
|
|
let invokedCallback = false;
|
|
|
|
await IMAPConnectionPool.withConnectionsForAccount(this.account, {
|
|
|
|
desiredCount: 1,
|
|
|
|
logger: this.logger,
|
2017-03-22 05:07:45 +08:00
|
|
|
socketTimeout: 5 * 1000,
|
2017-02-18 04:05:50 +08:00
|
|
|
onConnected: ([conn]) => {
|
|
|
|
expect(conn instanceof IMAPConnection).toBe(true);
|
|
|
|
invokedCallback = true;
|
|
|
|
return false;
|
|
|
|
},
|
|
|
|
});
|
|
|
|
expect(invokedCallback).toBe(true);
|
2017-03-01 05:38:14 +08:00
|
|
|
expect(IMAPConnection.prototype.connect.calls.length).toBe(1);
|
|
|
|
expect(IMAPConnection.prototype.end.calls.length).toBe(0);
|
2017-02-18 04:05:50 +08:00
|
|
|
|
|
|
|
invokedCallback = false;
|
|
|
|
await IMAPConnectionPool.withConnectionsForAccount(this.account, {
|
|
|
|
desiredCount: 1,
|
|
|
|
logger: this.logger,
|
2017-03-22 05:07:45 +08:00
|
|
|
socketTimeout: 5 * 1000,
|
2017-02-18 04:05:50 +08:00
|
|
|
onConnected: ([conn]) => {
|
|
|
|
expect(conn instanceof IMAPConnection).toBe(true);
|
|
|
|
invokedCallback = true;
|
|
|
|
return false;
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
expect(invokedCallback).toBe(true);
|
2017-03-01 05:38:14 +08:00
|
|
|
expect(IMAPConnection.prototype.connect.calls.length).toBe(1);
|
|
|
|
expect(IMAPConnection.prototype.end.calls.length).toBe(0);
|
2017-02-18 04:05:50 +08:00
|
|
|
});
|
|
|
|
|
|
|
|
it('waits for an available IMAP connection', async () => {
|
|
|
|
let invokedCallback = false;
|
|
|
|
let doneCallback = null;
|
|
|
|
await IMAPConnectionPool.withConnectionsForAccount(this.account, {
|
|
|
|
desiredCount: 3,
|
|
|
|
logger: this.logger,
|
2017-03-22 05:07:45 +08:00
|
|
|
socketTimeout: 5 * 1000,
|
2017-02-18 04:05:50 +08:00
|
|
|
onConnected: ([conn], done) => {
|
|
|
|
expect(conn instanceof IMAPConnection).toBe(true);
|
|
|
|
invokedCallback = true;
|
|
|
|
doneCallback = done;
|
|
|
|
return true;
|
|
|
|
},
|
|
|
|
});
|
|
|
|
expect(invokedCallback).toBe(true);
|
2017-03-01 05:38:14 +08:00
|
|
|
expect(IMAPConnection.prototype.connect.calls.length).toBe(3);
|
|
|
|
expect(IMAPConnection.prototype.end.calls.length).toBe(0);
|
2017-02-18 04:05:50 +08:00
|
|
|
|
|
|
|
invokedCallback = false;
|
|
|
|
const promise = IMAPConnectionPool.withConnectionsForAccount(this.account, {
|
|
|
|
desiredCount: 1,
|
|
|
|
logger: this.logger,
|
2017-03-22 05:07:45 +08:00
|
|
|
socketTimeout: 5 * 1000,
|
2017-02-18 04:05:50 +08:00
|
|
|
onConnected: ([conn]) => {
|
|
|
|
expect(conn instanceof IMAPConnection).toBe(true);
|
|
|
|
invokedCallback = true;
|
|
|
|
return false;
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
expect(IMAPConnectionPool._poolMap[this.account.id]._queue.length).toBe(1)
|
|
|
|
doneCallback();
|
|
|
|
await promise;
|
|
|
|
|
|
|
|
expect(invokedCallback).toBe(true);
|
2017-03-01 05:38:14 +08:00
|
|
|
expect(IMAPConnection.prototype.connect.calls.length).toBe(3);
|
|
|
|
expect(IMAPConnection.prototype.end.calls.length).toBe(0);
|
2017-02-18 04:05:50 +08:00
|
|
|
});
|
|
|
|
|
2017-03-22 05:07:45 +08:00
|
|
|
it('does not retry on IMAP connection timeout', async () => {
|
2017-02-18 04:05:50 +08:00
|
|
|
let invokeCount = 0;
|
2017-03-22 05:07:45 +08:00
|
|
|
try {
|
|
|
|
await IMAPConnectionPool.withConnectionsForAccount(this.account, {
|
|
|
|
desiredCount: 1,
|
|
|
|
logger: this.logger,
|
|
|
|
socketTimeout: 5 * 1000,
|
|
|
|
onConnected: ([conn]) => {
|
|
|
|
expect(conn instanceof IMAPConnection).toBe(true);
|
|
|
|
if (invokeCount === 0) {
|
|
|
|
invokeCount += 1;
|
|
|
|
throw new IMAPErrors.IMAPConnectionTimeoutError();
|
|
|
|
}
|
2017-02-18 04:05:50 +08:00
|
|
|
invokeCount += 1;
|
2017-03-22 05:07:45 +08:00
|
|
|
return false;
|
|
|
|
},
|
|
|
|
});
|
|
|
|
} catch (err) {
|
|
|
|
expect(err instanceof IMAPErrors.IMAPConnectionTimeoutError).toBe(true);
|
|
|
|
}
|
2017-02-18 04:05:50 +08:00
|
|
|
|
2017-03-22 05:07:45 +08:00
|
|
|
expect(invokeCount).toBe(1);
|
|
|
|
expect(IMAPConnection.prototype.connect.calls.length).toBe(1);
|
2017-03-01 05:38:14 +08:00
|
|
|
expect(IMAPConnection.prototype.end.calls.length).toBe(1);
|
2017-02-18 04:05:50 +08:00
|
|
|
});
|
|
|
|
|
|
|
|
it('does not retry on other IMAP error', async () => {
|
|
|
|
let invokeCount = 0;
|
|
|
|
let errorCount = 0;
|
|
|
|
try {
|
|
|
|
await IMAPConnectionPool.withConnectionsForAccount(this.account, {
|
|
|
|
desiredCount: 1,
|
|
|
|
logger: this.logger,
|
2017-03-22 05:07:45 +08:00
|
|
|
socketTimeout: 5 * 1000,
|
2017-02-18 04:05:50 +08:00
|
|
|
onConnected: ([conn]) => {
|
|
|
|
expect(conn instanceof IMAPConnection).toBe(true);
|
|
|
|
if (invokeCount === 0) {
|
|
|
|
invokeCount += 1;
|
|
|
|
throw new IMAPErrors.IMAPSocketError();
|
|
|
|
}
|
|
|
|
invokeCount += 1;
|
|
|
|
return false;
|
|
|
|
},
|
|
|
|
});
|
|
|
|
} catch (err) {
|
|
|
|
errorCount += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
expect(invokeCount).toBe(1);
|
|
|
|
expect(errorCount).toBe(1);
|
2017-03-01 05:38:14 +08:00
|
|
|
expect(IMAPConnection.prototype.connect.calls.length).toBe(1);
|
|
|
|
expect(IMAPConnection.prototype.end.calls.length).toBe(1);
|
2017-02-18 04:05:50 +08:00
|
|
|
});
|
|
|
|
});
|