1
0
mirror of https://github.com/matrix-org/matrix-react-sdk.git synced 2025-07-28 15:22:05 +03:00

Implement aggregation by error type for tracked decryption failures

This commit is contained in:
Luke Barnard
2018-07-05 13:54:44 +01:00
parent de33cf1afe
commit d53c836fd7
3 changed files with 156 additions and 60 deletions

View File

@ -16,10 +16,18 @@ limitations under the License.
import expect from 'expect';
import DecryptionFailureTracker from '../src/DecryptionFailureTracker';
import { DecryptionFailure, DecryptionFailureTracker } from '../src/DecryptionFailureTracker';
import { MatrixEvent } from 'matrix-js-sdk';
class MockDecryptionError extends Error {
constructor(code) {
super();
this.code = code || 'MOCK_DECRYPTION_ERROR';
}
}
function createFailedDecryptionEvent() {
const event = new MatrixEvent({
event_id: "event-id-" + Math.random().toString(16).slice(2),
@ -30,20 +38,21 @@ function createFailedDecryptionEvent() {
return event;
}
describe('DecryptionFailureTracker', function() {
describe.only('DecryptionFailureTracker', function() {
it('tracks a failed decryption', function(done) {
const failedDecryptionEvent = createFailedDecryptionEvent();
let count = 0;
const tracker = new DecryptionFailureTracker((total) => count += total);
tracker.eventDecrypted(failedDecryptionEvent);
const err = new MockDecryptionError();
tracker.eventDecrypted(failedDecryptionEvent, err);
// Pretend "now" is Infinity
tracker.checkFailures(Infinity);
// Immediately track the newest failure, if there is one
tracker.trackFailure();
// Immediately track the newest failures
tracker.trackFailures();
expect(count).toNotBe(0, 'should track a failure for an event that failed decryption');
@ -56,17 +65,18 @@ describe('DecryptionFailureTracker', function() {
expect(true).toBe(false, 'should not track an event that has since been decrypted correctly');
});
tracker.eventDecrypted(decryptedEvent);
const err = new MockDecryptionError();
tracker.eventDecrypted(decryptedEvent, err);
// Indicate successful decryption: clear data can be anything where the msgtype is not m.bad.encrypted
decryptedEvent._setClearData({});
tracker.eventDecrypted(decryptedEvent);
tracker.eventDecrypted(decryptedEvent, null);
// Pretend "now" is Infinity
tracker.checkFailures(Infinity);
// Immediately track the newest failure, if there is one
tracker.trackFailure();
// Immediately track the newest failures
tracker.trackFailures();
done();
});
@ -78,23 +88,24 @@ describe('DecryptionFailureTracker', function() {
const tracker = new DecryptionFailureTracker((total) => count += total);
// Arbitrary number of failed decryptions for both events
tracker.eventDecrypted(decryptedEvent);
tracker.eventDecrypted(decryptedEvent);
tracker.eventDecrypted(decryptedEvent);
tracker.eventDecrypted(decryptedEvent);
tracker.eventDecrypted(decryptedEvent);
tracker.eventDecrypted(decryptedEvent2);
tracker.eventDecrypted(decryptedEvent2);
tracker.eventDecrypted(decryptedEvent2);
const err = new MockDecryptionError();
tracker.eventDecrypted(decryptedEvent, err);
tracker.eventDecrypted(decryptedEvent, err);
tracker.eventDecrypted(decryptedEvent, err);
tracker.eventDecrypted(decryptedEvent, err);
tracker.eventDecrypted(decryptedEvent, err);
tracker.eventDecrypted(decryptedEvent2, err);
tracker.eventDecrypted(decryptedEvent2, err);
tracker.eventDecrypted(decryptedEvent2, err);
// Pretend "now" is Infinity
tracker.checkFailures(Infinity);
// Simulated polling of `trackFailure`, an arbitrary number ( > 2 ) times
tracker.trackFailure();
tracker.trackFailure();
tracker.trackFailure();
tracker.trackFailure();
// Simulated polling of `trackFailures`, an arbitrary number ( > 2 ) times
tracker.trackFailures();
tracker.trackFailures();
tracker.trackFailures();
tracker.trackFailures();
expect(count).toBe(2, count + ' failures tracked, should only track a single failure per event');
@ -108,17 +119,18 @@ describe('DecryptionFailureTracker', function() {
const tracker = new DecryptionFailureTracker((total) => count += total);
// Indicate decryption
tracker.eventDecrypted(decryptedEvent);
const err = new MockDecryptionError();
tracker.eventDecrypted(decryptedEvent, err);
// Pretend "now" is Infinity
tracker.checkFailures(Infinity);
tracker.trackFailure();
tracker.trackFailures();
// Indicate a second decryption, after having tracked the failure
tracker.eventDecrypted(decryptedEvent);
tracker.eventDecrypted(decryptedEvent, err);
tracker.trackFailure();
tracker.trackFailures();
expect(count).toBe(1, 'should only track a single failure per event');
@ -135,25 +147,68 @@ describe('DecryptionFailureTracker', function() {
const tracker = new DecryptionFailureTracker((total) => count += total);
// Indicate decryption
tracker.eventDecrypted(decryptedEvent);
const err = new MockDecryptionError();
tracker.eventDecrypted(decryptedEvent, err);
// Pretend "now" is Infinity
// NB: This saves to localStorage specific to DFT
tracker.checkFailures(Infinity);
tracker.trackFailure();
tracker.trackFailures();
// Simulate the browser refreshing by destroying tracker and creating a new tracker
const secondTracker = new DecryptionFailureTracker((total) => count += total);
//secondTracker.loadTrackedEventHashMap();
secondTracker.eventDecrypted(decryptedEvent);
secondTracker.eventDecrypted(decryptedEvent, err);
secondTracker.checkFailures(Infinity);
secondTracker.trackFailure();
secondTracker.trackFailures();
expect(count).toBe(1, count + ' failures tracked, should only track a single failure per event');
done();
});
it('should count different error codes separately for multiple failures with different error codes', () => {
const counts = {};
const tracker = new DecryptionFailureTracker(
(total, errorCode) => counts[errorCode] = (counts[errorCode] || 0) + total,
);
// One failure of ERROR_CODE_1, and effectively two for ERROR_CODE_2
tracker.addDecryptionFailure(new DecryptionFailure('$event_id1', 'ERROR_CODE_1'));
tracker.addDecryptionFailure(new DecryptionFailure('$event_id2', 'ERROR_CODE_2'));
tracker.addDecryptionFailure(new DecryptionFailure('$event_id2', 'ERROR_CODE_2'));
tracker.addDecryptionFailure(new DecryptionFailure('$event_id3', 'ERROR_CODE_2'));
// Pretend "now" is Infinity
tracker.checkFailures(Infinity);
tracker.trackFailures();
expect(counts['ERROR_CODE_1']).toBe(1, 'should track one ERROR_CODE_1');
expect(counts['ERROR_CODE_2']).toBe(2, 'should track two ERROR_CODE_2');
});
it('should map error codes correctly', () => {
const counts = {};
const tracker = new DecryptionFailureTracker(
(total, errorCode) => counts[errorCode] = (counts[errorCode] || 0) + total,
(errorCode) => 'MY_NEW_ERROR_CODE',
);
// One failure of ERROR_CODE_1, and effectively two for ERROR_CODE_2
tracker.addDecryptionFailure(new DecryptionFailure('$event_id1', 'ERROR_CODE_1'));
tracker.addDecryptionFailure(new DecryptionFailure('$event_id2', 'ERROR_CODE_2'));
tracker.addDecryptionFailure(new DecryptionFailure('$event_id3', 'ERROR_CODE_3'));
// Pretend "now" is Infinity
tracker.checkFailures(Infinity);
tracker.trackFailures();
expect(counts['MY_NEW_ERROR_CODE'])
.toBe(3, 'should track three MY_NEW_ERROR_CODE, got ' + counts['MY_NEW_ERROR_CODE']);
});
});