Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 85 additions & 6 deletions tests/50federation/51transactions.pl
Original file line number Diff line number Diff line change
Expand Up @@ -51,35 +51,114 @@
# on PDUs. Test that a transaction to `send` with a PDU that has bad data will
# be handled properly.
#
# This enforces that the entire transaction is rejected if a single bad PDU is
# sent. It is unclear if this is the correct behavior or not.
# This enforces that invalid PDUs are discarded rather than failing the entire
# transaction.
#
# It is unclear whether the invalid PDU should be included in the /send response
# with an error, which is why there is no assertion on the response.
#
# See https://github.com/matrix-org/synapse/issues/7543
test "Server discards events with invalid JSON in a version 6 room",
requires => [ $main::OUTBOUND_CLIENT,
federated_rooms_fixture( room_opts => { room_version => "6" } ) ],
# This behaviour has only been changed in Synapse, not Dendrite
implementation_specific => ['synapse'],

do => sub {
my ( $outbound_client, $creator, $user_id, @rooms ) = @_;

my $room = $rooms[0];
my $room_id = $room->room_id;

my $good_event = $room->create_and_insert_event(
type => "m.room.message",

sender => $user_id,
content => {
body => "Good event",
},
);

my $bad_event = $room->create_and_insert_event(
type => "m.room.message",

sender => $user_id,
content => {
body => "Bad event",
# Insert a "bad" value into the PDU, in this case a float.
bad_val => 1.1,
},
);

my @pdus = ( $good_event, $bad_event );

# Send the transaction to the client and expect to succeed
$outbound_client->send_transaction(
pdus => \@pdus,
destination => $creator->server_name,
)->then(sub {
# Wait for the good event to be sent down through sync
await_sync_timeline_contains( $creator, $room_id, check => sub {
my ( $event ) = @_;
$event->{type} eq "m.room.message" &&
$event->{content}{body} eq "Good event"
})
Comment on lines +100 to +105
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we also check that we don't receive the bad event down sync?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I couldn't find utilities to make sure that the sync timeline doesn't contain something :(

Copy link
Copy Markdown
Member

@anoadragon453 anoadragon453 Apr 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't it be just adding && $event->{content}{body} neq "Bad event"?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It only checks if one event in the timeline checks that constraint

})->then(sub {
# Check that we can fetch the good event
my $event_id = $room->id_for_event( $good_event );
do_request_json_for( $creator,
method => "GET",
uri => "/v3/rooms/$room_id/event/$event_id",
)
})->then(sub {
# Check that we have ignored the bad event PDU
my $event_id = $room->id_for_event( $bad_event );
do_request_json_for( $creator,
method => "GET",
uri => "/v3/rooms/$room_id/event/$event_id",
)->main::expect_m_not_found
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's an open question; the sending homeserver technically can't do anything with that information.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is why we don't yet assert on the /send response body

};

# This is an alternative behaviour that isn't spec compliant, where the server
# rejects the whole transaction if any PDU is invalid.
# This is the behaviour that Dendrite currently implements.
test "Server rejects invalid JSON in a version 6 room",
requires => [ $main::OUTBOUND_CLIENT,
federated_rooms_fixture( room_opts => { room_version => "6" } ) ],
implementation_specific => ['dendrite'],

do => sub {
my ( $outbound_client, $creator, $user_id, @rooms ) = @_;

my $room = $rooms[0];
my $room_id = $room->room_id;

my $good_event = $room->create_and_insert_event(
type => "m.room.message",

sender => $user_id,
content => {
body => "Good event",
},
);

my $bad_event = $room->create_and_insert_event(
type => "m.room.message",

sender => $user_id,
content => {
body => "Message 1",
body => "Bad event",
# Insert a "bad" value into the PDU, in this case a float.
bad_val => 1.1,
},
);

my @pdus = ( $bad_event );
my @pdus = ( $good_event, $bad_event );

# Send the transaction to the client and expect a fail
# Send the transaction to the client and expect to fail
$outbound_client->send_transaction(
pdus => \@pdus,
destination => $creator->server_name,
)->main::expect_m_bad_json;
)->main::expect_m_bad_json
};
Loading