@@ -28,6 +28,12 @@ use ruma::{
28
28
use serde_json:: json;
29
29
use tokio:: { spawn, sync:: broadcast, task:: yield_now, time:: sleep} ;
30
30
31
+ macro_rules! assert_event_id {
32
+ ( $timeline_event: expr, $event_id: literal) => {
33
+ assert_eq!( $timeline_event. event_id( ) . unwrap( ) . as_str( ) , $event_id) ;
34
+ } ;
35
+ }
36
+
31
37
#[ async_test]
32
38
async fn test_must_explicitly_subscribe ( ) {
33
39
let server = MatrixMockServer :: new ( ) . await ;
@@ -1543,6 +1549,145 @@ async fn test_apply_redaction_when_redaction_comes_later() {
1543
1549
assert ! ( subscriber. is_empty( ) ) ;
1544
1550
}
1545
1551
1552
+ #[ async_test]
1553
+ async fn test_apply_redaction_on_an_in_store_event ( ) {
1554
+ let room_id = room_id ! ( "!foo:bar.baz" ) ;
1555
+ let event_factory = EventFactory :: new ( ) . room ( room_id) . sender ( & ALICE ) ;
1556
+
1557
+ let mock_server = MatrixMockServer :: new ( ) . await ;
1558
+ let client = mock_server. client_builder ( ) . build ( ) . await ;
1559
+
1560
+ // Set up the event cache store.
1561
+ {
1562
+ let event_cache_store = client. event_cache_store ( ) . lock ( ) . await . unwrap ( ) ;
1563
+
1564
+ // The event cache contains 2 chunks as such (from older to newewst):
1565
+ // 1. a chunk of 1 item, the one we are going to redact!
1566
+ // 2. a chunk of 1 item, the chunk that is going to be loaded.
1567
+ event_cache_store
1568
+ . handle_linked_chunk_updates (
1569
+ room_id,
1570
+ vec ! [
1571
+ // chunk #1
1572
+ Update :: NewItemsChunk {
1573
+ previous: None ,
1574
+ new: ChunkIdentifier :: new( 0 ) ,
1575
+ next: None ,
1576
+ } ,
1577
+ // … and its item
1578
+ Update :: PushItems {
1579
+ at: Position :: new( ChunkIdentifier :: new( 0 ) , 0 ) ,
1580
+ items: vec![ event_factory
1581
+ . text_msg( "foo" )
1582
+ . event_id( event_id!( "$ev0" ) )
1583
+ . into_event( ) ] ,
1584
+ } ,
1585
+ // chunk #2
1586
+ Update :: NewItemsChunk {
1587
+ previous: Some ( ChunkIdentifier :: new( 0 ) ) ,
1588
+ new: ChunkIdentifier :: new( 1 ) ,
1589
+ next: None ,
1590
+ } ,
1591
+ // … and its item
1592
+ Update :: PushItems {
1593
+ at: Position :: new( ChunkIdentifier :: new( 1 ) , 0 ) ,
1594
+ items: vec![ event_factory
1595
+ . text_msg( "foo" )
1596
+ . event_id( event_id!( "$ev1" ) )
1597
+ . into_event( ) ] ,
1598
+ } ,
1599
+ ] ,
1600
+ )
1601
+ . await
1602
+ . unwrap ( ) ;
1603
+ }
1604
+
1605
+ // Set up the event cache.
1606
+ let event_cache = client. event_cache ( ) ;
1607
+ event_cache. subscribe ( ) . unwrap ( ) ;
1608
+ event_cache. enable_storage ( ) . unwrap ( ) ;
1609
+
1610
+ let room = mock_server. sync_joined_room ( & client, room_id) . await ;
1611
+ let ( room_event_cache, _room_event_cache_drop_handle) = room. event_cache ( ) . await . unwrap ( ) ;
1612
+
1613
+ let ( initial_updates, mut updates_stream) = room_event_cache. subscribe ( ) . await ;
1614
+
1615
+ // Initial events!
1616
+ //
1617
+ // Only 1 events is loaded, as expected, from the last chunk.
1618
+ {
1619
+ assert_eq ! ( initial_updates. len( ) , 1 ) ;
1620
+ assert_event_id ! ( initial_updates[ 0 ] , "$ev1" ) ;
1621
+
1622
+ // The stream of updates is waiting, patiently.
1623
+ assert ! ( updates_stream. is_empty( ) ) ;
1624
+ }
1625
+
1626
+ // Sync a redaction for `$ev0`.
1627
+ mock_server
1628
+ . sync_room (
1629
+ & client,
1630
+ JoinedRoomBuilder :: new ( room_id) . add_timeline_event (
1631
+ event_factory
1632
+ . redaction ( event_id ! ( "$ev0" ) )
1633
+ . event_id ( event_id ! ( "$ev2" ) )
1634
+ . into_raw_sync ( ) ,
1635
+ ) ,
1636
+ )
1637
+ . await ;
1638
+
1639
+ // Let's check the stream.
1640
+ let update = updates_stream. recv ( ) . await . unwrap ( ) ;
1641
+
1642
+ assert_matches ! ( update, RoomEventCacheUpdate :: UpdateTimelineEvents { diffs, .. } => {
1643
+ // 1 diff for the `m.room.redaction`. The event being redacted is not
1644
+ // in-memory yet, it's only in the store, so no update for it.
1645
+ assert_eq!( diffs. len( ) , 1 ) ;
1646
+
1647
+ assert_matches!( & diffs[ 0 ] , VectorDiff :: Append { values: events } => {
1648
+ assert_eq!( events. len( ) , 1 ) ;
1649
+ assert_event_id!( & events[ 0 ] , "$ev2" ) ;
1650
+ } ) ;
1651
+ } ) ;
1652
+
1653
+ assert ! ( updates_stream. is_empty( ) ) ;
1654
+
1655
+ // To see if `$ev0` has been redacted in the store, let's paginate!
1656
+ let outcome = room_event_cache. pagination ( ) . run_backwards_until ( 1 ) . await . unwrap ( ) ;
1657
+
1658
+ // 1 event, no surprise.
1659
+ assert_eq ! ( outcome. events. len( ) , 1 ) ;
1660
+ assert_event_id ! ( outcome. events[ 0 ] , "$ev0" ) ;
1661
+ assert_matches ! (
1662
+ outcome. events[ 0 ] . raw( ) . deserialize( ) . unwrap( ) ,
1663
+ AnySyncTimelineEvent :: MessageLike ( event) => {
1664
+ // The event has been redacted!
1665
+ assert!( event. is_redacted( ) ) ;
1666
+ }
1667
+ ) ;
1668
+
1669
+ // Let's check the stream. It should reflect what the `pagination_outcome`
1670
+ // provides.
1671
+ let update = updates_stream. recv ( ) . await . unwrap ( ) ;
1672
+
1673
+ assert_matches ! ( update, RoomEventCacheUpdate :: UpdateTimelineEvents { diffs, .. } => {
1674
+ assert_eq!( diffs. len( ) , 1 ) ;
1675
+
1676
+ assert_matches!( & diffs[ 0 ] , VectorDiff :: Insert { index: 0 , value: event } => {
1677
+ assert_event_id!( event, "$ev0" ) ;
1678
+ assert_matches!(
1679
+ event. raw( ) . deserialize( ) . unwrap( ) ,
1680
+ AnySyncTimelineEvent :: MessageLike ( event) => {
1681
+ // The event has been redacted!
1682
+ assert!( event. is_redacted( ) ) ;
1683
+ }
1684
+ ) ;
1685
+ } ) ;
1686
+ } ) ;
1687
+
1688
+ assert ! ( updates_stream. is_empty( ) ) ;
1689
+ }
1690
+
1546
1691
#[ async_test]
1547
1692
async fn test_apply_redaction_when_redacted_and_redaction_are_in_same_sync ( ) {
1548
1693
let server = MatrixMockServer :: new ( ) . await ;
@@ -1612,12 +1757,6 @@ async fn test_apply_redaction_when_redacted_and_redaction_are_in_same_sync() {
1612
1757
assert ! ( subscriber. is_empty( ) ) ;
1613
1758
}
1614
1759
1615
- macro_rules! assert_event_id {
1616
- ( $timeline_event: expr, $event_id: literal) => {
1617
- assert_eq!( $timeline_event. event_id( ) . unwrap( ) . as_str( ) , $event_id) ;
1618
- } ;
1619
- }
1620
-
1621
1760
#[ async_test]
1622
1761
async fn test_lazy_loading ( ) {
1623
1762
let room_id = room_id ! ( "!foo:bar.baz" ) ;
0 commit comments