Skip to content

Commit

Permalink
Add tests for room version 6. (#869)
Browse files Browse the repository at this point in the history
  • Loading branch information
clokep authored Jun 3, 2020
1 parent 84d7cf9 commit dd51dcb
Show file tree
Hide file tree
Showing 11 changed files with 646 additions and 25 deletions.
3 changes: 1 addition & 2 deletions lib/SyTest/Federation/Client.pm
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ use SyTest::Assertions qw( :all );
use URI::Escape qw( uri_escape );

use constant SUPPORTED_ROOM_VERSIONS => [qw(
1 2 3 4 5
org.matrix.msc2260
1 2 3 4 5 6
)];

sub configure
Expand Down
5 changes: 4 additions & 1 deletion lib/SyTest/Federation/Datastore.pm
Original file line number Diff line number Diff line change
Expand Up @@ -268,10 +268,13 @@ sub get_backfill_events
my $event = eval { $self->get_event( $id ) }
or next;

my $room = $self->get_room( $event->{room_id} ) or
croak "Unknown room $event->{room_id}";

push @events, $event;

push @event_ids, grep { !$exclude{$_} }
map { $_->[0] } @{ $event->{prev_events} };
@{ $room->event_ids_from_refs( $event->{prev_events} ) };

# Don't include this event if we encounter it again
$exclude{$id} = 1;
Expand Down
10 changes: 10 additions & 0 deletions tests/00expect_http_fail.pl
Original file line number Diff line number Diff line change
Expand Up @@ -172,3 +172,13 @@ sub expect_m_not_found
);
}
push @EXPORT, qw( expect_m_not_found );


sub expect_m_bad_json
{
my $f = shift;
return expect_matrix_error(
$f, 400, 'M_BAD_JSON',
);
}
push @EXPORT, qw( expect_m_bad_json );
27 changes: 25 additions & 2 deletions tests/30rooms/08levels.pl
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,16 @@

sub lockeddown_room_fixture
{
my ( %options ) = @_;

fixture(
requires => [ $creator_fixture, $user_fixture,
qw( can_change_power_levels ) ],

setup => sub {
my ( $creator, $test_user ) = @_;

matrix_create_and_join_room( [ $creator, $test_user ] )
matrix_create_and_join_room( [ $creator, $test_user ], %options )
->then( sub {
my ( $room_id ) = @_;

Expand Down Expand Up @@ -154,6 +156,27 @@ sub test_powerlevel

$levels->{$levelname} = 10000000;
})->main::expect_http_403
})->SyTest::pass_on_done( "Fails at setting 75" );
})->SyTest::pass_on_done( "Fails at setting 10000000" );
};
}

multi_test "Users cannot set notifications powerlevel higher than their own",
requires => [ $creator_fixture, $user_fixture, lockeddown_room_fixture( room_version => "6" ),
qw( can_change_power_levels )],

do => sub {
my ( $user, undef, $room_id ) = @_;

matrix_change_room_power_levels( $user, $room_id, sub {
my ( $levels ) = @_;

$levels->{notifications}{room} = 25;
})->SyTest::pass_on_done( "Succeeds at setting 25" )
->then( sub {
matrix_change_room_power_levels( $user, $room_id, sub {
my ( $levels ) = @_;

$levels->{notifications}{room} = 10000000;
})->main::expect_http_403
})->SyTest::pass_on_done( "Fails at setting 10000000" );
};
2 changes: 1 addition & 1 deletion tests/32room-versions.pl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use URI::Escape qw( uri_escape );

# We test that some basic functionality works across all room versions
foreach my $version ( qw ( 1 2 3 4 5 ) ) {
foreach my $version ( qw ( 1 2 3 4 5 6 ) ) {
multi_test "User can create and send/receive messages in a room with version $version",
requires => [ local_user_fixture() ],

Expand Down
59 changes: 59 additions & 0 deletions tests/50federation/30room-join.pl
Original file line number Diff line number Diff line change
Expand Up @@ -1061,3 +1061,62 @@ sub assert_is_valid_pdu {
}),
)
};

# A homeserver receiving a `send_join` request for a room version 6 room with
# a bad JSON value (e.g. a float) should reject the request.
#
# To test this we need to:
# * Send a successful `make_join` request.
# * Add a "bad" value into the returned prototype event.
# * Make a request to `send_join`.
# * Check that the response is M_BAD_JSON.
test "Inbound: send_join rejects invalid JSON for room version 6",
requires => [ $main::OUTBOUND_CLIENT, $main::INBOUND_SERVER,
local_user_and_room_fixtures( room_opts => { room_version => "6" } ),
federation_user_id_fixture() ],

do => sub {
my ( $outbound_client, $inbound_server, $creator, $room_id, $user_id ) = @_;
my $first_home_server = $creator->server_name;

my $local_server_name = $outbound_client->server_name;
my $datastore = $inbound_server->datastore;

$outbound_client->do_request_json(
method => "GET",
hostname => $first_home_server,
uri => "/v1/make_join/$room_id/$user_id",
params => {
ver => ["6"],
},
)->then( sub {
my ( $body ) = @_;

log_if_fail "make_join body", $body;

my $protoevent = $body->{event};

# It is assumed that the make_join response is sane, other tests ensure
# this behavior.

my %event = (
( map { $_ => $protoevent->{$_} } qw(
auth_events content depth prev_events room_id sender
state_key type ) ),

origin => $local_server_name,
origin_server_ts => $inbound_server->time_ms,
);
# Insert a "bad" value into the send join, in this case a float.
${event}{content}{bad_val} = 1.1;

$datastore->sign_event( \%event );

$outbound_client->do_request_json(
method => "PUT",
hostname => $first_home_server,
uri => "/v2/send_join/$room_id/xxx",
content => \%event,
)
})->main::expect_m_bad_json;
};
137 changes: 127 additions & 10 deletions tests/50federation/33room-get-missing-events.pl
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
test "Outbound federation can request missing events",
requires => [ $main::OUTBOUND_CLIENT, $main::INBOUND_SERVER,
local_user_and_room_fixtures(
user_opts => { with_events => 1 },
room_opts => { room_version => "1" },
),
federation_user_id_fixture() ],
Expand All @@ -10,10 +9,9 @@
my ( $outbound_client, $inbound_server, $creator, $room_id, $user_id ) = @_;
my $first_home_server = $creator->server_name;

my $local_server_name = $inbound_server->server_name;
my $datastore = $inbound_server->datastore;

my $missing_event;
my $missing_event_id;

$outbound_client->join_room(
server_name => $first_home_server,
Expand All @@ -27,14 +25,15 @@
my $latest_event = $room->get_current_state_event( "m.room.member", $user_id );

# Generate but don't send an event
$missing_event = $room->create_and_insert_event(
my $missing_event = $room->create_and_insert_event(
type => "m.room.message",

sender => $user_id,
content => {
body => "Message 1",
},
);
$missing_event_id = $room->id_for_event( $missing_event );

# Generate another one and do send it so it will refer to the
# previous in its prev_events field
Expand All @@ -43,9 +42,7 @@

# This would be done by $room->create_and_insert_event anyway but lets be
# sure for this test
prev_events => [
[ $missing_event->{event_id}, $missing_event->{hashes} ],
],
prev_events => $room->make_event_refs( $missing_event ),

sender => $user_id,
content => {
Expand All @@ -65,13 +62,13 @@
assert_json_list( my $earliest = $body->{earliest_events} );
@$earliest == 1 or
die "Expected a single 'earliest_event' ID";
assert_eq( $earliest->[0], $latest_event->{event_id},
assert_eq( $earliest->[0], $room->id_for_event( $latest_event ),
'earliest_events[0]' );

assert_json_list( my $latest = $body->{latest_events} );
@$latest == 1 or
die "Expected a single 'latest_events' ID";
assert_eq( $latest->[0], $sent_event->{event_id},
assert_eq( $latest->[0], $room->id_for_event( $sent_event ),
'latest_events[0]' );

my @events = $datastore->get_backfill_events(
Expand Down Expand Up @@ -99,7 +96,7 @@
check => sub {
my ( $event ) = @_;
$event->{type} eq "m.room.message" &&
$event->{event_id} eq $missing_event->{event_id};
$event->{event_id} eq $missing_event_id;
},
);
});
Expand Down Expand Up @@ -413,3 +410,123 @@ sub sytest_user_and_room_fixture {
Future->done;
});
};

# A homeserver receiving a response from `get_missing_events` for a version 6
# room with a bad JSON value (e.g. a float) should discard the bad data.
#
# To test this we need to:
# * Add an event with "bad" data into the room history, but don't send it.
# * Add a "good" event into the room history and send it.
# * The homeserver attempts to get the missing event (with the bad data).
# * Ensure that fetching the event results in an error.
test "Outbound federation will ignore a missing event with bad JSON for room version 6",
requires => [ $main::OUTBOUND_CLIENT, $main::INBOUND_SERVER,
federated_rooms_fixture( room_opts => { room_version => "6" } ) ],

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

my $room = @rooms[0];
my $room_id = $room->{room_id};
my $first_home_server = $creator->server_name;

my $datastore = $inbound_server->datastore;

# TODO: We happen to know the latest event in the server should be my
# m.room.member state event, but that's a bit fragile
my $latest_event = $room->get_current_state_event( "m.room.member", $user_id );

log_if_fail "Latest event", $latest_event;

# Generate but don't send an event
my $missing_event = $room->create_and_insert_event(
type => "m.room.message",

sender => $user_id,
content => {
body => "Message 1",
# Insert a bad value here so that this event cannot be fetched.
bad_val => 1.1,
},
);

log_if_fail "Missing event", $missing_event;

# Generate another one and do send it so it will refer to the
# previous in its prev_events field
my $sent_event = $room->create_and_insert_event(
type => "m.room.message",

# This would be done by $room->create_and_insert_event anyway but lets be
# sure for this test
prev_events => $room->make_event_refs( $missing_event ),

sender => $user_id,
content => {
body => "Message 2",
},
);
my $sent_event_id = $room->id_for_event( $sent_event );

log_if_fail "Sent event", $sent_event;

Future->needs_all(
$inbound_server->await_request_get_missing_events( $room_id )
->then( sub {
my ( $req ) = @_;
my $body = $req->body_from_json;

log_if_fail "Body", $body;

assert_json_keys( $body, qw( earliest_events latest_events limit ));
# TODO: min_depth but I have no idea what it does

assert_json_list( my $earliest = $body->{earliest_events} );
@$earliest == 1 or
die "Expected a single 'earliest_event' ID";
assert_eq( $earliest->[0], $room->id_for_event( $latest_event ),
'earliest_events[0]' );

assert_json_list( my $latest = $body->{latest_events} );
@$latest == 1 or
die "Expected a single 'latest_events' ID";
assert_eq( $latest->[0], $sent_event_id,
'latest_events[0]' );

my @events = $datastore->get_backfill_events(
start_at => $latest,
stop_before => $earliest,
limit => $body->{limit},
);

log_if_fail "Backfilling", @events;

$req->respond_json( {
events => \@events,
} );

Future->done;
}),

# Can't use send_event here because that checks none were rejected.
$outbound_client->send_transaction(
destination => $first_home_server,
pdus => [ $sent_event ],
)->then( sub {
my ( $body ) = @_;

log_if_fail "Send response", $body;

assert_json_keys( $body, 'pdus' );
# 'pdus' is a map from event id to error details.
my $pdus = $body->{pdus};

# Sending the event fails since fetching the event results in
# invalid JSON, thus we expect an error for the sent PDU.
assert_json_keys( $pdus, $sent_event_id );
assert_json_keys( $pdus->{$sent_event_id}, qw( error ) );

Future->done;
}),
);
};
Loading

0 comments on commit dd51dcb

Please sign in to comment.