@@ -153,7 +153,7 @@ impl LatestEventValue {
153
153
}
154
154
}
155
155
156
- pub fn find_and_map (
156
+ fn find_and_map (
157
157
event : & Event ,
158
158
power_levels : & Option < ( & UserId , RoomPowerLevels ) > ,
159
159
) -> Option < LatestEventValue > {
@@ -239,3 +239,366 @@ pub fn find_and_map(
239
239
}
240
240
}
241
241
}
242
+
243
+ #[ cfg( test) ]
244
+ mod tests {
245
+ use assert_matches:: assert_matches;
246
+ use matrix_sdk_test:: event_factory:: EventFactory ;
247
+ use ruma:: { event_id, user_id} ;
248
+
249
+ use super :: { find_and_map, LatestEventValue } ;
250
+
251
+ macro_rules! assert_latest_event_value {
252
+ ( with | $event_factory: ident | $event_builder: block
253
+ it produces $match: pat ) => {
254
+ let user_id = user_id!( "@mnt_io:matrix.org" ) ;
255
+ let event_factory = EventFactory :: new( ) . sender( user_id) ;
256
+ let event = {
257
+ let $event_factory = event_factory;
258
+ $event_builder
259
+ } ;
260
+
261
+ assert_matches!( find_and_map( & event, & None ) , $match) ;
262
+ } ;
263
+ }
264
+
265
+ #[ test]
266
+ fn test_latest_event_value_room_message ( ) {
267
+ assert_latest_event_value ! (
268
+ with |event_factory| {
269
+ event_factory. text_msg( "hello" ) . into_event( )
270
+ }
271
+ it produces Some ( LatestEventValue :: RoomMessage ( _) )
272
+ ) ;
273
+ }
274
+
275
+ #[ test]
276
+ fn test_latest_event_value_room_message_redacted ( ) {
277
+ assert_latest_event_value ! (
278
+ with |event_factory| {
279
+ event_factory
280
+ . redacted(
281
+ user_id!( "@mnt_io:matrix.org" ) ,
282
+ ruma:: events:: room:: message:: RedactedRoomMessageEventContent :: new( )
283
+ )
284
+ . into_event( )
285
+ }
286
+ it produces Some ( LatestEventValue :: RoomMessage ( _) )
287
+ ) ;
288
+ }
289
+
290
+ #[ test]
291
+ fn test_latest_event_value_room_message_replacement ( ) {
292
+ assert_latest_event_value ! (
293
+ with |event_factory| {
294
+ event_factory
295
+ . text_msg( "bonjour" )
296
+ . edit(
297
+ event_id!( "$ev0" ) ,
298
+ ruma:: events:: room:: message:: RoomMessageEventContent :: text_plain( "hello" ) . into( )
299
+ )
300
+ . into_event( )
301
+ }
302
+ it produces None
303
+ ) ;
304
+ }
305
+
306
+ #[ test]
307
+ fn test_latest_event_value_poll ( ) {
308
+ assert_latest_event_value ! (
309
+ with |event_factory| {
310
+ event_factory
311
+ . poll_start(
312
+ "the people need to know" ,
313
+ "comté > gruyère" ,
314
+ vec![ "yes" , "oui" ]
315
+ )
316
+ . into_event( )
317
+ }
318
+ it produces Some ( LatestEventValue :: Poll ( _) )
319
+ ) ;
320
+ }
321
+
322
+ #[ test]
323
+ fn test_latest_event_value_call_invite ( ) {
324
+ assert_latest_event_value ! (
325
+ with |event_factory| {
326
+ event_factory
327
+ . call_invite(
328
+ ruma:: OwnedVoipId :: from( "vvooiipp" . to_owned( ) ) ,
329
+ ruma:: UInt :: from( 1234u32 ) ,
330
+ ruma:: events:: call:: SessionDescription :: new( "type" . to_owned( ) , "sdp" . to_owned( ) ) ,
331
+ ruma:: VoipVersionId :: V1 ,
332
+ )
333
+ . into_event( )
334
+ }
335
+ it produces Some ( LatestEventValue :: CallInvite ( _) )
336
+ ) ;
337
+ }
338
+
339
+ #[ test]
340
+ fn test_latest_event_value_call_notify ( ) {
341
+ assert_latest_event_value ! (
342
+ with |event_factory| {
343
+ event_factory
344
+ . call_notify(
345
+ "call_id" . to_owned( ) ,
346
+ ruma:: events:: call:: notify:: ApplicationType :: Call ,
347
+ ruma:: events:: call:: notify:: NotifyType :: Ring ,
348
+ ruma:: events:: Mentions :: new( ) ,
349
+ )
350
+ . into_event( )
351
+ }
352
+ it produces Some ( LatestEventValue :: CallNotify ( _) )
353
+ ) ;
354
+ }
355
+
356
+ #[ test]
357
+ fn test_latest_event_value_sticker ( ) {
358
+ assert_latest_event_value ! (
359
+ with |event_factory| {
360
+ event_factory
361
+ . sticker(
362
+ "wink wink" ,
363
+ ruma:: events:: room:: ImageInfo :: new( ) ,
364
+ ruma:: OwnedMxcUri :: from( "mxc://foo/bar" )
365
+ )
366
+ . into_event( )
367
+ }
368
+ it produces Some ( LatestEventValue :: Sticker ( _) )
369
+ ) ;
370
+ }
371
+
372
+ #[ test]
373
+ fn test_latest_event_value_encrypted_room_message ( ) {
374
+ assert_latest_event_value ! (
375
+ with |event_factory| {
376
+ event_factory
377
+ . event( ruma:: events:: room:: encrypted:: RoomEncryptedEventContent :: new(
378
+ ruma:: events:: room:: encrypted:: EncryptedEventScheme :: MegolmV1AesSha2 (
379
+ ruma:: events:: room:: encrypted:: MegolmV1AesSha2ContentInit {
380
+ ciphertext: "cipher" . to_owned( ) ,
381
+ sender_key: "sender_key" . to_owned( ) ,
382
+ device_id: "device_id" . into( ) ,
383
+ session_id: "session_id" . to_owned( ) ,
384
+ }
385
+ . into( ) ,
386
+ ) ,
387
+ None ,
388
+ ) )
389
+ . into_event( )
390
+ }
391
+ it produces None
392
+ ) ;
393
+ }
394
+
395
+ #[ test]
396
+ fn test_latest_event_value_reaction ( ) {
397
+ // Take a random message-like event.
398
+ assert_latest_event_value ! (
399
+ with |event_factory| {
400
+ event_factory
401
+ . reaction( event_id!( "$ev0" ) , "+1" )
402
+ . into_event( )
403
+ }
404
+ it produces None
405
+ ) ;
406
+ }
407
+
408
+ #[ test]
409
+ fn test_latest_event_state_event ( ) {
410
+ assert_latest_event_value ! (
411
+ with |event_factory| {
412
+ event_factory
413
+ . room_topic( "new room topic" )
414
+ . into_event( )
415
+ }
416
+ it produces None
417
+ ) ;
418
+ }
419
+
420
+ #[ test]
421
+ fn test_latest_event_knocked_state_event_without_power_levels ( ) {
422
+ assert_latest_event_value ! (
423
+ with |event_factory| {
424
+ event_factory
425
+ . member( user_id!( "@other_mnt_io:server.name" ) )
426
+ . membership( ruma:: events:: room:: member:: MembershipState :: Knock )
427
+ . into_event( )
428
+ }
429
+ it produces None
430
+ ) ;
431
+ }
432
+
433
+ #[ test]
434
+ fn test_latest_event_knocked_state_event_with_power_levels ( ) {
435
+ use ruma:: events:: room:: power_levels:: { RoomPowerLevels , RoomPowerLevelsEventContent } ;
436
+
437
+ let user_id = user_id ! ( "@mnt_io:matrix.org" ) ;
438
+ let other_user_id = user_id ! ( "@other_mnt_io:server.name" ) ;
439
+ let event_factory = EventFactory :: new ( ) . sender ( user_id) ;
440
+ let event = event_factory
441
+ . member ( other_user_id)
442
+ . membership ( ruma:: events:: room:: member:: MembershipState :: Knock )
443
+ . into_event ( ) ;
444
+
445
+ let room_power_levels_event = RoomPowerLevelsEventContent :: new ( ) ;
446
+ let mut room_power_levels = RoomPowerLevels :: from ( room_power_levels_event) ;
447
+ room_power_levels. users_default = 5 . into ( ) ;
448
+
449
+ // Cannot accept. Cannot decline.
450
+ {
451
+ let mut room_power_levels = room_power_levels. clone ( ) ;
452
+ room_power_levels. invite = 10 . into ( ) ;
453
+ room_power_levels. kick = 10 . into ( ) ;
454
+ assert_matches ! (
455
+ find_and_map( & event, & Some ( ( user_id, room_power_levels) ) ) ,
456
+ None ,
457
+ "cannot accept, cannot decline" ,
458
+ ) ;
459
+ }
460
+
461
+ // Can accept. Cannot decline.
462
+ {
463
+ let mut room_power_levels = room_power_levels. clone ( ) ;
464
+ room_power_levels. invite = 0 . into ( ) ;
465
+ room_power_levels. kick = 10 . into ( ) ;
466
+ assert_matches ! (
467
+ find_and_map( & event, & Some ( ( user_id, room_power_levels) ) ) ,
468
+ Some ( LatestEventValue :: KnockedStateEvent ( _) ) ,
469
+ "can accept, cannot decline" ,
470
+ ) ;
471
+ }
472
+
473
+ // Cannot accept. Can decline.
474
+ {
475
+ let mut room_power_levels = room_power_levels. clone ( ) ;
476
+ room_power_levels. invite = 10 . into ( ) ;
477
+ room_power_levels. kick = 0 . into ( ) ;
478
+ assert_matches ! (
479
+ find_and_map( & event, & Some ( ( user_id, room_power_levels) ) ) ,
480
+ Some ( LatestEventValue :: KnockedStateEvent ( _) ) ,
481
+ "cannot accept, can decline" ,
482
+ ) ;
483
+ }
484
+
485
+ // Can accept. Can decline.
486
+ {
487
+ room_power_levels. invite = 0 . into ( ) ;
488
+ room_power_levels. kick = 0 . into ( ) ;
489
+ assert_matches ! (
490
+ find_and_map( & event, & Some ( ( user_id, room_power_levels) ) ) ,
491
+ Some ( LatestEventValue :: KnockedStateEvent ( _) ) ,
492
+ "can accept, can decline" ,
493
+ ) ;
494
+ }
495
+ }
496
+
497
+ #[ test]
498
+ fn test_latest_event_value_room_message_verification_request ( ) {
499
+ assert_latest_event_value ! (
500
+ with |event_factory| {
501
+ event_factory
502
+ . event(
503
+ ruma:: events:: room:: message:: RoomMessageEventContent :: new(
504
+ ruma:: events:: room:: message:: MessageType :: VerificationRequest (
505
+ ruma:: events:: room:: message:: KeyVerificationRequestEventContent :: new(
506
+ "body" . to_owned( ) ,
507
+ vec![ ] ,
508
+ ruma:: OwnedDeviceId :: from( "device_id" ) ,
509
+ user_id!( "@user:server.name" ) . to_owned( ) ,
510
+ )
511
+ )
512
+ )
513
+ )
514
+ . into_event( )
515
+ }
516
+ it produces None
517
+ ) ;
518
+ }
519
+ }
520
+
521
+ #[ cfg( all( not( target_family = "wasm" ) , test) ) ]
522
+ mod tests_non_wasm {
523
+ use assert_matches:: assert_matches;
524
+ use matrix_sdk_test:: { async_test, event_factory:: EventFactory } ;
525
+ use ruma:: { event_id, room_id, user_id} ;
526
+
527
+ use super :: LatestEventValue ;
528
+ use crate :: test_utils:: mocks:: MatrixMockServer ;
529
+
530
+ #[ async_test]
531
+ async fn test_latest_event_value_is_scanning_event_backwards_from_event_cache ( ) {
532
+ use matrix_sdk_base:: {
533
+ linked_chunk:: { ChunkIdentifier , Position , Update } ,
534
+ RoomState ,
535
+ } ;
536
+
537
+ use crate :: { client:: WeakClient , room:: WeakRoom } ;
538
+
539
+ let room_id = room_id ! ( "!r0" ) ;
540
+ let user_id = user_id ! ( "@mnt_io:matrix.org" ) ;
541
+ let event_factory = EventFactory :: new ( ) . sender ( user_id) . room ( room_id) ;
542
+ let event_id_0 = event_id ! ( "$ev0" ) ;
543
+ let event_id_1 = event_id ! ( "$ev1" ) ;
544
+ let event_id_2 = event_id ! ( "$ev2" ) ;
545
+
546
+ let server = MatrixMockServer :: new ( ) . await ;
547
+ let client = server. client_builder ( ) . build ( ) . await ;
548
+
549
+ // Prelude.
550
+ {
551
+ // Create the room.
552
+ client. base_client ( ) . get_or_create_room ( room_id, RoomState :: Joined ) ;
553
+
554
+ // Initialise the event cache store.
555
+ client
556
+ . event_cache_store ( )
557
+ . lock ( )
558
+ . await
559
+ . unwrap ( )
560
+ . handle_linked_chunk_updates (
561
+ matrix_sdk_base:: linked_chunk:: LinkedChunkId :: Room ( room_id) ,
562
+ vec ! [
563
+ Update :: NewItemsChunk {
564
+ previous: None ,
565
+ new: ChunkIdentifier :: new( 0 ) ,
566
+ next: None ,
567
+ } ,
568
+ Update :: PushItems {
569
+ at: Position :: new( ChunkIdentifier :: new( 0 ) , 0 ) ,
570
+ items: vec![
571
+ // a latest event candidate
572
+ event_factory. text_msg( "hello" ) . event_id( event_id_0) . into( ) ,
573
+ // a latest event candidate
574
+ event_factory. text_msg( "world" ) . event_id( event_id_1) . into( ) ,
575
+ // not a latest event candidate
576
+ event_factory
577
+ . room_topic( "new room topic" )
578
+ . event_id( event_id_2)
579
+ . into( ) ,
580
+ ] ,
581
+ } ,
582
+ ] ,
583
+ )
584
+ . await
585
+ . unwrap ( ) ;
586
+ }
587
+
588
+ let event_cache = client. event_cache ( ) ;
589
+ event_cache. subscribe ( ) . unwrap ( ) ;
590
+
591
+ let ( room_event_cache, _) = event_cache. for_room ( room_id) . await . unwrap ( ) ;
592
+ let weak_room = WeakRoom :: new ( WeakClient :: from_client ( & client) , room_id. to_owned ( ) ) ;
593
+
594
+ assert_matches ! (
595
+ LatestEventValue :: new( room_id, None , & room_event_cache, & weak_room) . await ,
596
+ LatestEventValue :: RoomMessage ( given_event) => {
597
+ // We get `event_id_1` because `event_id_2` isn't a candidate,
598
+ // and `event_id_0` hasn't been read yet (because events are
599
+ // read backwards).
600
+ assert_eq!( given_event. event_id( ) , event_id_1) ;
601
+ }
602
+ ) ;
603
+ }
604
+ }
0 commit comments