@@ -17,6 +17,8 @@ limitations under the License.
17
17
18
18
import anotherjson from "another-json" ;
19
19
import MockHttpBackend from "matrix-mock-request" ;
20
+ import "fake-indexeddb/auto" ;
21
+ import { IDBFactory } from "fake-indexeddb" ;
20
22
21
23
import * as testUtils from "../test-utils/test-utils" ;
22
24
import { TestClient } from "../TestClient" ;
@@ -38,9 +40,17 @@ import {
38
40
} from "../../src/matrix" ;
39
41
import { IDeviceKeys } from "../../src/crypto/dehydration" ;
40
42
import { DeviceInfo } from "../../src/crypto/deviceinfo" ;
43
+ import { CRYPTO_BACKENDS , InitCrypto } from "../test-utils/test-utils" ;
41
44
42
45
const ROOM_ID = "!room:id" ;
43
46
47
+ afterEach ( ( ) => {
48
+ // reset fake-indexeddb after each test, to make sure we don't leak connections
49
+ // cf https://github.com/dumbmatter/fakeIndexedDB#wipingresetting-the-indexeddb-for-a-fresh-state
50
+ // eslint-disable-next-line no-global-assign
51
+ indexedDB = new IDBFactory ( ) ;
52
+ } ) ;
53
+
44
54
// start an Olm session with a given recipient
45
55
async function createOlmSession ( olmAccount : Olm . Account , recipientTestClient : TestClient ) : Promise < Olm . Session > {
46
56
const keys = await recipientTestClient . awaitOneTimeKeyUpload ( ) ;
@@ -341,11 +351,17 @@ async function expectSendMegolmMessage(
341
351
return JSON . parse ( r . plaintext ) ;
342
352
}
343
353
344
- describe ( "megolm" , ( ) => {
354
+ describe . each ( Object . entries ( CRYPTO_BACKENDS ) ) ( "megolm (%s) " , ( backend : string , initCrypto : InitCrypto ) => {
345
355
if ( ! global . Olm ) {
356
+ // currently we use libolm to implement the crypto in the tests, so need it to be present.
346
357
logger . warn ( "not running megolm tests: Olm not present" ) ;
347
358
return ;
348
359
}
360
+
361
+ // oldBackendOnly is an alternative to `it` or `test` which will skip the test if we are running against the
362
+ // Rust backend. Once we have full support in the rust sdk, it will go away.
363
+ const oldBackendOnly = backend === "rust-sdk" ? test . skip : test ;
364
+
349
365
const Olm = global . Olm ;
350
366
351
367
let testOlmAccount = { } as unknown as Olm . Account ;
@@ -410,8 +426,10 @@ describe("megolm", () => {
410
426
411
427
beforeEach ( async ( ) => {
412
428
aliceTestClient = new TestClient ( "@alice:localhost" , "xzcvb" , "akjgkrgjs" ) ;
413
- await aliceTestClient . client . initCrypto ( ) ;
429
+ await initCrypto ( aliceTestClient . client ) ;
414
430
431
+ // create a test olm device which we will use to communicate with alice. We use libolm to implement this.
432
+ await Olm . init ( ) ;
415
433
testOlmAccount = new Olm . Account ( ) ;
416
434
testOlmAccount . create ( ) ;
417
435
const testE2eKeys = JSON . parse ( testOlmAccount . identity_keys ( ) ) ;
@@ -424,13 +442,18 @@ describe("megolm", () => {
424
442
425
443
it ( "Alice receives a megolm message" , async ( ) => {
426
444
await aliceTestClient . start ( ) ;
427
- aliceTestClient . client . crypto ! . deviceList . downloadKeys = ( ) => Promise . resolve ( { } ) ;
445
+
446
+ // if we're using the old crypto impl, stub out some methods in the device manager.
447
+ // TODO: replace this with intercepts of the /keys/query endpoint to make it impl agnostic.
448
+ if ( aliceTestClient . client . crypto ) {
449
+ aliceTestClient . client . crypto . deviceList . downloadKeys = ( ) => Promise . resolve ( { } ) ;
450
+ aliceTestClient . client . crypto . deviceList . getUserByIdentityKey = ( ) => "@bob:xyz" ;
451
+ }
452
+
428
453
const p2pSession = await createOlmSession ( testOlmAccount , aliceTestClient ) ;
429
454
const groupSession = new Olm . OutboundGroupSession ( ) ;
430
455
groupSession . create ( ) ;
431
456
432
- aliceTestClient . client . crypto ! . deviceList . getUserByIdentityKey = ( ) => "@bob:xyz" ;
433
-
434
457
// make the room_key event
435
458
const roomKeyEncrypted = encryptGroupSessionKey ( {
436
459
recipient : aliceTestClient ,
@@ -472,16 +495,21 @@ describe("megolm", () => {
472
495
expect ( decryptedEvent . getContent ( ) . body ) . toEqual ( "42" ) ;
473
496
} ) ;
474
497
475
- it ( "Alice receives a megolm message before the session keys" , async ( ) => {
498
+ oldBackendOnly ( "Alice receives a megolm message before the session keys" , async ( ) => {
476
499
// https://github.com/vector-im/element-web/issues/2273
477
500
await aliceTestClient . start ( ) ;
478
- aliceTestClient . client . crypto ! . deviceList . downloadKeys = ( ) => Promise . resolve ( { } ) ;
501
+
502
+ // if we're using the old crypto impl, stub out some methods in the device manager.
503
+ // TODO: replace this with intercepts of the /keys/query endpoint to make it impl agnostic.
504
+ if ( aliceTestClient . client . crypto ) {
505
+ aliceTestClient . client . crypto . deviceList . downloadKeys = ( ) => Promise . resolve ( { } ) ;
506
+ aliceTestClient . client . crypto . deviceList . getUserByIdentityKey = ( ) => "@bob:xyz" ;
507
+ }
508
+
479
509
const p2pSession = await createOlmSession ( testOlmAccount , aliceTestClient ) ;
480
510
const groupSession = new Olm . OutboundGroupSession ( ) ;
481
511
groupSession . create ( ) ;
482
512
483
- aliceTestClient . client . crypto ! . deviceList . getUserByIdentityKey = ( ) => "@bob:xyz" ;
484
-
485
513
// make the room_key event, but don't send it yet
486
514
const roomKeyEncrypted = encryptGroupSessionKey ( {
487
515
recipient : aliceTestClient ,
@@ -535,13 +563,18 @@ describe("megolm", () => {
535
563
536
564
it ( "Alice gets a second room_key message" , async ( ) => {
537
565
await aliceTestClient . start ( ) ;
538
- aliceTestClient . client . crypto ! . deviceList . downloadKeys = ( ) => Promise . resolve ( { } ) ;
566
+
567
+ // if we're using the old crypto impl, stub out some methods in the device manager.
568
+ // TODO: replace this with intercepts of the /keys/query endpoint to make it impl agnostic.
569
+ if ( aliceTestClient . client . crypto ) {
570
+ aliceTestClient . client . crypto . deviceList . downloadKeys = ( ) => Promise . resolve ( { } ) ;
571
+ aliceTestClient . client . crypto . deviceList . getUserByIdentityKey = ( ) => "@bob:xyz" ;
572
+ }
573
+
539
574
const p2pSession = await createOlmSession ( testOlmAccount , aliceTestClient ) ;
540
575
const groupSession = new Olm . OutboundGroupSession ( ) ;
541
576
groupSession . create ( ) ;
542
577
543
- aliceTestClient . client . crypto ! . deviceList . getUserByIdentityKey = ( ) => "@bob:xyz" ;
544
-
545
578
// make the room_key event
546
579
const roomKeyEncrypted1 = encryptGroupSessionKey ( {
547
580
recipient : aliceTestClient ,
@@ -600,7 +633,7 @@ describe("megolm", () => {
600
633
expect ( event . getContent ( ) . body ) . toEqual ( "42" ) ;
601
634
} ) ;
602
635
603
- it ( "Alice sends a megolm message" , async ( ) => {
636
+ oldBackendOnly ( "Alice sends a megolm message" , async ( ) => {
604
637
aliceTestClient . expectKeyQuery ( { device_keys : { "@alice:localhost" : { } } , failures : { } } ) ;
605
638
await aliceTestClient . start ( ) ;
606
639
const p2pSession = await establishOlmSession ( aliceTestClient , testOlmAccount ) ;
@@ -643,7 +676,7 @@ describe("megolm", () => {
643
676
] ) ;
644
677
} ) ;
645
678
646
- it ( "We shouldn't attempt to send to blocked devices" , async ( ) => {
679
+ oldBackendOnly ( "We shouldn't attempt to send to blocked devices" , async ( ) => {
647
680
aliceTestClient . expectKeyQuery ( { device_keys : { "@alice:localhost" : { } } , failures : { } } ) ;
648
681
await aliceTestClient . start ( ) ;
649
682
await establishOlmSession ( aliceTestClient , testOlmAccount ) ;
@@ -687,7 +720,7 @@ describe("megolm", () => {
687
720
expect ( ( ) => aliceTestClient . client . getGlobalErrorOnUnknownDevices ( ) ) . toThrowError ( "encryption disabled" ) ;
688
721
} ) ;
689
722
690
- it ( "should permit sending to unknown devices" , async ( ) => {
723
+ oldBackendOnly ( "should permit sending to unknown devices" , async ( ) => {
691
724
expect ( aliceTestClient . client . getGlobalErrorOnUnknownDevices ( ) ) . toBeTruthy ( ) ;
692
725
693
726
aliceTestClient . expectKeyQuery ( { device_keys : { "@alice:localhost" : { } } , failures : { } } ) ;
@@ -745,7 +778,7 @@ describe("megolm", () => {
745
778
) ;
746
779
} ) ;
747
780
748
- it ( "should disable sending to unverified devices" , async ( ) => {
781
+ oldBackendOnly ( "should disable sending to unverified devices" , async ( ) => {
749
782
aliceTestClient . expectKeyQuery ( { device_keys : { "@alice:localhost" : { } } , failures : { } } ) ;
750
783
await aliceTestClient . start ( ) ;
751
784
const p2pSession = await establishOlmSession ( aliceTestClient , testOlmAccount ) ;
@@ -803,7 +836,7 @@ describe("megolm", () => {
803
836
} ) ;
804
837
} ) ;
805
838
806
- it ( "We should start a new megolm session when a device is blocked" , async ( ) => {
839
+ oldBackendOnly ( "We should start a new megolm session when a device is blocked" , async ( ) => {
807
840
aliceTestClient . expectKeyQuery ( { device_keys : { "@alice:localhost" : { } } , failures : { } } ) ;
808
841
await aliceTestClient . start ( ) ;
809
842
const p2pSession = await establishOlmSession ( aliceTestClient , testOlmAccount ) ;
@@ -861,7 +894,7 @@ describe("megolm", () => {
861
894
} ) ;
862
895
863
896
// https://github.com/vector-im/element-web/issues/2676
864
- it ( "Alice should send to her other devices" , async ( ) => {
897
+ oldBackendOnly ( "Alice should send to her other devices" , async ( ) => {
865
898
// for this test, we make the testOlmAccount be another of Alice's devices.
866
899
// it ought to get included in messages Alice sends.
867
900
await aliceTestClient . start ( ) ;
@@ -942,7 +975,7 @@ describe("megolm", () => {
942
975
expect ( decrypted . content ?. body ) . toEqual ( "test" ) ;
943
976
} ) ;
944
977
945
- it ( "Alice should wait for device list to complete when sending a megolm message" , async ( ) => {
978
+ oldBackendOnly ( "Alice should wait for device list to complete when sending a megolm message" , async ( ) => {
946
979
aliceTestClient . expectKeyQuery ( { device_keys : { "@alice:localhost" : { } } , failures : { } } ) ;
947
980
await aliceTestClient . start ( ) ;
948
981
await establishOlmSession ( aliceTestClient , testOlmAccount ) ;
@@ -972,15 +1005,20 @@ describe("megolm", () => {
972
1005
await Promise . all ( [ downloadPromise , sendPromise ] ) ;
973
1006
} ) ;
974
1007
975
- it ( "Alice exports megolm keys and imports them to a new device" , async ( ) => {
1008
+ oldBackendOnly ( "Alice exports megolm keys and imports them to a new device" , async ( ) => {
976
1009
aliceTestClient . expectKeyQuery ( { device_keys : { "@alice:localhost" : { } } , failures : { } } ) ;
977
1010
await aliceTestClient . start ( ) ;
978
- aliceTestClient . client . crypto ! . deviceList . downloadKeys = ( ) => Promise . resolve ( { } ) ;
1011
+
1012
+ // if we're using the old crypto impl, stub out some methods in the device manager.
1013
+ // TODO: replace this with intercepts of the /keys/query endpoint to make it impl agnostic.
1014
+ if ( aliceTestClient . client . crypto ) {
1015
+ aliceTestClient . client . crypto . deviceList . downloadKeys = ( ) => Promise . resolve ( { } ) ;
1016
+ aliceTestClient . client . crypto . deviceList . getUserByIdentityKey = ( ) => "@bob:xyz" ;
1017
+ }
1018
+
979
1019
// establish an olm session with alice
980
1020
const p2pSession = await createOlmSession ( testOlmAccount , aliceTestClient ) ;
981
1021
982
- aliceTestClient . client . crypto ! . deviceList . getUserByIdentityKey = ( ) => "@bob:xyz" ;
983
-
984
1022
const groupSession = new Olm . OutboundGroupSession ( ) ;
985
1023
groupSession . create ( ) ;
986
1024
@@ -1027,11 +1065,15 @@ describe("megolm", () => {
1027
1065
aliceTestClient . stop ( ) ;
1028
1066
1029
1067
aliceTestClient = new TestClient ( "@alice:localhost" , "device2" , "access_token2" ) ;
1030
- await aliceTestClient . client . initCrypto ( ) ;
1068
+ await initCrypto ( aliceTestClient . client ) ;
1031
1069
await aliceTestClient . client . importRoomKeys ( exported ) ;
1032
1070
await aliceTestClient . start ( ) ;
1033
1071
1034
- aliceTestClient . client . crypto ! . deviceList . getUserByIdentityKey = ( ) => "@bob:xyz" ;
1072
+ // if we're using the old crypto impl, stub out some methods in the device manager.
1073
+ // TODO: replace this with intercepts of the /keys/query endpoint to make it impl agnostic.
1074
+ if ( aliceTestClient . client . crypto ) {
1075
+ aliceTestClient . client . crypto . deviceList . getUserByIdentityKey = ( ) => "@bob:xyz" ;
1076
+ }
1035
1077
1036
1078
const syncResponse = {
1037
1079
next_batch : 1 ,
@@ -1107,13 +1149,18 @@ describe("megolm", () => {
1107
1149
1108
1150
it ( "Alice can decrypt a message with falsey content" , async ( ) => {
1109
1151
await aliceTestClient . start ( ) ;
1110
- aliceTestClient . client . crypto ! . deviceList . downloadKeys = ( ) => Promise . resolve ( { } ) ;
1152
+
1153
+ // if we're using the old crypto impl, stub out some methods in the device manager.
1154
+ // TODO: replace this with intercepts of the /keys/query endpoint to make it impl agnostic.
1155
+ if ( aliceTestClient . client . crypto ) {
1156
+ aliceTestClient . client . crypto . deviceList . downloadKeys = ( ) => Promise . resolve ( { } ) ;
1157
+ aliceTestClient . client . crypto . deviceList . getUserByIdentityKey = ( ) => "@bob:xyz" ;
1158
+ }
1159
+
1111
1160
const p2pSession = await createOlmSession ( testOlmAccount , aliceTestClient ) ;
1112
1161
const groupSession = new Olm . OutboundGroupSession ( ) ;
1113
1162
groupSession . create ( ) ;
1114
1163
1115
- aliceTestClient . client . crypto ! . deviceList . getUserByIdentityKey = ( ) => "@bob:xyz" ;
1116
-
1117
1164
// make the room_key event
1118
1165
const roomKeyEncrypted = encryptGroupSessionKey ( {
1119
1166
recipient : aliceTestClient ,
@@ -1160,14 +1207,21 @@ describe("megolm", () => {
1160
1207
expect ( decryptedEvent . getClearContent ( ) ) . toBeUndefined ( ) ;
1161
1208
} ) ;
1162
1209
1163
- it ( "Alice receives shared history before being invited to a room by the sharer" , async ( ) => {
1210
+ oldBackendOnly ( "Alice receives shared history before being invited to a room by the sharer" , async ( ) => {
1164
1211
const beccaTestClient = new TestClient ( "@becca:localhost" , "foobar" , "bazquux" ) ;
1165
1212
await beccaTestClient . client . initCrypto ( ) ;
1166
1213
1167
1214
await aliceTestClient . start ( ) ;
1168
- aliceTestClient . client . crypto ! . deviceList . downloadKeys = ( ) => Promise . resolve ( { } ) ;
1169
1215
await beccaTestClient . start ( ) ;
1170
1216
1217
+ // if we're using the old crypto impl, stub out some methods in the device manager.
1218
+ // TODO: replace this with intercepts of the /keys/query endpoint to make it impl agnostic.
1219
+ if ( aliceTestClient . client . crypto ) {
1220
+ aliceTestClient . client . crypto ! . deviceList . downloadKeys = ( ) => Promise . resolve ( { } ) ;
1221
+ aliceTestClient . client . crypto ! . deviceList . getDeviceByIdentityKey = ( ) => device ;
1222
+ aliceTestClient . client . crypto ! . deviceList . getUserByIdentityKey = ( ) => beccaTestClient . client . getUserId ( ) ! ;
1223
+ }
1224
+
1171
1225
const beccaRoom = new Room ( ROOM_ID , beccaTestClient . client , "@becca:localhost" , { } ) ;
1172
1226
beccaTestClient . client . store . storeRoom ( beccaRoom ) ;
1173
1227
await beccaTestClient . client . setRoomEncryption ( ROOM_ID , { algorithm : "m.megolm.v1.aes-sha2" } ) ;
@@ -1193,8 +1247,6 @@ describe("megolm", () => {
1193
1247
event . claimedEd25519Key = null ;
1194
1248
1195
1249
const device = new DeviceInfo ( beccaTestClient . client . deviceId ! ) ;
1196
- aliceTestClient . client . crypto ! . deviceList . getDeviceByIdentityKey = ( ) => device ;
1197
- aliceTestClient . client . crypto ! . deviceList . getUserByIdentityKey = ( ) => beccaTestClient . client . getUserId ( ) ! ;
1198
1250
1199
1251
// Create an olm session for Becca and Alice's devices
1200
1252
const aliceOtks = await aliceTestClient . awaitOneTimeKeyUpload ( ) ;
@@ -1307,7 +1359,7 @@ describe("megolm", () => {
1307
1359
await beccaTestClient . stop ( ) ;
1308
1360
} ) ;
1309
1361
1310
- it ( "Alice receives shared history before being invited to a room by someone else" , async ( ) => {
1362
+ oldBackendOnly ( "Alice receives shared history before being invited to a room by someone else" , async ( ) => {
1311
1363
const beccaTestClient = new TestClient ( "@becca:localhost" , "foobar" , "bazquux" ) ;
1312
1364
await beccaTestClient . client . initCrypto ( ) ;
1313
1365
@@ -1453,7 +1505,7 @@ describe("megolm", () => {
1453
1505
await beccaTestClient . stop ( ) ;
1454
1506
} ) ;
1455
1507
1456
- it ( "allows sending an encrypted event as soon as room state arrives" , async ( ) => {
1508
+ oldBackendOnly ( "allows sending an encrypted event as soon as room state arrives" , async ( ) => {
1457
1509
/* Empirically, clients expect to be able to send encrypted events as soon as the
1458
1510
* RoomStateEvent.NewMember notification is emitted, so test that works correctly.
1459
1511
*/
@@ -1578,7 +1630,7 @@ describe("megolm", () => {
1578
1630
await aliceTestClient . httpBackend . flush ( membersPath , 1 ) ;
1579
1631
}
1580
1632
1581
- it ( "Sending an event initiates a member list sync" , async ( ) => {
1633
+ oldBackendOnly ( "Sending an event initiates a member list sync" , async ( ) => {
1582
1634
// we expect a call to the /members list...
1583
1635
const memberListPromise = expectMembershipRequest ( ROOM_ID , [ "@bob:xyz" ] ) ;
1584
1636
@@ -1610,7 +1662,7 @@ describe("megolm", () => {
1610
1662
] ) ;
1611
1663
} ) ;
1612
1664
1613
- it ( "loading the membership list inhibits a later load" , async ( ) => {
1665
+ oldBackendOnly ( "loading the membership list inhibits a later load" , async ( ) => {
1614
1666
const room = aliceTestClient . client . getRoom ( ROOM_ID ) ! ;
1615
1667
await Promise . all ( [ room . loadMembersIfNeeded ( ) , expectMembershipRequest ( ROOM_ID , [ "@bob:xyz" ] ) ] ) ;
1616
1668
@@ -1642,7 +1694,7 @@ describe("megolm", () => {
1642
1694
// TODO: there are a bunch more tests for this sort of thing in spec/unit/crypto/algorithms/megolm.spec.ts.
1643
1695
// They should be converted to integ tests and moved.
1644
1696
1645
- it ( "does not block decryption on an 'm.unavailable' report" , async function ( ) {
1697
+ oldBackendOnly ( "does not block decryption on an 'm.unavailable' report" , async function ( ) {
1646
1698
await aliceTestClient . start ( ) ;
1647
1699
1648
1700
// there may be a key downloads for alice
0 commit comments