omemo_dart/test/omemomanager_test.dart

247 lines
6.6 KiB
Dart

import 'dart:convert';
import 'package:logging/logging.dart';
import 'package:omemo_dart/omemo_dart.dart';
import 'package:omemo_dart/src/omemo/omemomanager.dart' as omemo;
import 'package:omemo_dart/src/trust/always.dart';
import 'package:test/test.dart';
void main() {
Logger.root
..level = Level.ALL
..onRecord.listen((record) {
// ignore: avoid_print
print('${record.level.name}: ${record.message}');
});
test('Test sending a message without the device list cache', () async {
const aliceJid = 'alice@server1';
const bobJid = 'bob@server2';
var aliceEmptyMessageSent = 0;
var bobEmptyMessageSent = 0;
final aliceDevice = await Device.generateNewDevice(aliceJid, opkAmount: 1);
final bobDevice = await Device.generateNewDevice(bobJid, opkAmount: 1);
final aliceManager = omemo.OmemoManager(
aliceDevice,
AlwaysTrustingTrustManager(),
(result, recipientJid) async {
aliceEmptyMessageSent++;
},
(jid) async {
expect(jid, bobJid);
return [ bobDevice.id ];
},
(jid, id) async {
expect(jid, bobJid);
return bobDevice.toBundle();
},
);
final bobManager = omemo.OmemoManager(
bobDevice,
AlwaysTrustingTrustManager(),
(result, recipientJid) async {
bobEmptyMessageSent++;
},
(jid) async {
expect(jid, aliceJid);
return [aliceDevice.id];
},
(jid, id) async {
expect(jid, aliceJid);
return aliceDevice.toBundle();
},
);
// Alice sends a message
final aliceResult = await aliceManager.onOutgoingStanza(
const OmemoOutgoingStanza(
[bobJid],
'Hello world',
),
);
// Bob must be able to decrypt the message
final bobResult = await bobManager.onIncomingStanza(
OmemoIncomingStanza(
aliceJid,
aliceDevice.id,
DateTime.now().millisecondsSinceEpoch,
aliceResult!.encryptedKeys,
base64.encode(aliceResult.ciphertext!),
),
);
expect(aliceEmptyMessageSent, 0);
expect(bobEmptyMessageSent, 1);
expect(bobResult.payload, 'Hello world');
// Alice receives the ack message
await aliceManager.ratchetAcknowledged(
bobJid,
bobDevice.id,
);
// Bob now responds
final bobResult2 = await bobManager.onOutgoingStanza(
const OmemoOutgoingStanza(
[aliceJid],
'Hello world, Alice',
),
);
final aliceResult2 = await aliceManager.onIncomingStanza(
OmemoIncomingStanza(
bobJid,
bobDevice.id,
DateTime.now().millisecondsSinceEpoch,
bobResult2!.encryptedKeys,
base64.encode(bobResult2.ciphertext!),
),
);
expect(aliceResult2.error, null);
expect(aliceEmptyMessageSent, 0);
expect(bobEmptyMessageSent, 1);
expect(aliceResult2.payload, 'Hello world, Alice');
});
test('Test triggering the heartbeat', () async {
const aliceJid = 'alice@server1';
const bobJid = 'bob@server2';
var aliceEmptyMessageSent = 0;
var bobEmptyMessageSent = 0;
final aliceDevice = await Device.generateNewDevice(aliceJid, opkAmount: 1);
final bobDevice = await Device.generateNewDevice(bobJid, opkAmount: 1);
final aliceManager = omemo.OmemoManager(
aliceDevice,
AlwaysTrustingTrustManager(),
(result, recipientJid) async {
aliceEmptyMessageSent++;
},
(jid) async {
expect(jid, bobJid);
return [ bobDevice.id ];
},
(jid, id) async {
expect(jid, bobJid);
return bobDevice.toBundle();
},
);
final bobManager = omemo.OmemoManager(
bobDevice,
AlwaysTrustingTrustManager(),
(result, recipientJid) async {
bobEmptyMessageSent++;
},
(jid) async {
expect(jid, aliceJid);
return [aliceDevice.id];
},
(jid, id) async {
expect(jid, aliceJid);
return aliceDevice.toBundle();
},
);
// Alice sends a message
final aliceResult = await aliceManager.onOutgoingStanza(
const OmemoOutgoingStanza(
[bobJid],
'Hello world',
),
);
// Bob must be able to decrypt the message
final bobResult = await bobManager.onIncomingStanza(
OmemoIncomingStanza(
aliceJid,
aliceDevice.id,
DateTime.now().millisecondsSinceEpoch,
aliceResult!.encryptedKeys,
base64.encode(aliceResult.ciphertext!),
),
);
expect(aliceEmptyMessageSent, 0);
expect(bobEmptyMessageSent, 1);
expect(bobResult.payload, 'Hello world');
// Bob acknowledges the message
await aliceManager.ratchetAcknowledged(bobJid, bobDevice.id);
// Alice now sends 52 messages that Bob decrypts
for (var i = 0; i <= 51; i++) {
final aliceResultLoop = await aliceManager.onOutgoingStanza(
OmemoOutgoingStanza(
[bobJid],
'Test message $i',
),
);
final bobResultLoop = await bobManager.onIncomingStanza(
OmemoIncomingStanza(
aliceJid,
aliceDevice.id,
DateTime.now().millisecondsSinceEpoch,
aliceResultLoop!.encryptedKeys,
base64.encode(aliceResultLoop.ciphertext!),
),
);
expect(aliceEmptyMessageSent, 0);
expect(bobEmptyMessageSent, 1);
expect(bobResultLoop.payload, 'Test message $i');
}
// Alice sends a final message that triggers a heartbeat
final aliceResultFinal = await aliceManager.onOutgoingStanza(
const OmemoOutgoingStanza(
[bobJid],
'Test message last',
),
);
final bobResultFinal = await bobManager.onIncomingStanza(
OmemoIncomingStanza(
aliceJid,
aliceDevice.id,
DateTime.now().millisecondsSinceEpoch,
aliceResultFinal!.encryptedKeys,
base64.encode(aliceResultFinal.ciphertext!),
),
);
expect(aliceEmptyMessageSent, 0);
expect(bobEmptyMessageSent, 2);
expect(bobResultFinal.payload, 'Test message last');
});
test('Test accessing data without it existing', () async {
const aliceJid = 'alice@server1';
const bobJid = 'bob@server2';
final aliceDevice = await Device.generateNewDevice(aliceJid, opkAmount: 1);
final aliceManager = omemo.OmemoManager(
aliceDevice,
AlwaysTrustingTrustManager(),
(result, recipientJid) async {},
(jid) async => [],
(jid, id) async => null,
);
// Get non-existant fingerprints
expect(
await aliceManager.getFingerprintsForJid(bobJid),
null,
);
// Ack a non-existant ratchet
await aliceManager.ratchetAcknowledged(
bobJid,
42,
);
});
}