<commit_before>multi_test "Test that a message is pushed",
   requires => [qw(
      http_clients do_request_json_for await_event_for flush_events_for
      test_http_server_uri_base await_http_request register_new_user_without_events

      can_register can_create_private_room
   )],

   do => sub {
      my (
         $clients, $do_request_json_for, $await_event_for, $flush_events_for,
         $test_http_server_uri_base, $await_http_request, $register_new_user,
      ) = @_;

      my $http = $clients->[0];

      my $alice;
      my $bob;
      my $room;
      my $event_id;

      # We use the version of register new user that doesn't start the event
      # stream for Alice. Starting an event stream will make presence
      # consider Alice to be online. If presence considers alice to be online
      # then Alice might stop receiving push messages.
      # We need to register two users because you are never pushed for
      # messages that you send yourself.
      Future->needs_all(
         $register_new_user->( $http, "50push-01-alice" ),
         $register_new_user->( $http, "50push-01-bob" ),
      )->then( sub {
         ( $alice, $bob ) = @_;
         pass "Registered users";

         # Have Alice create a new private room
         $do_request_json_for->( $alice,
            method  => "POST",
            uri     => "/createRoom",
            content => { visibility => "private" },
         )
      })->then( sub {
         ( $room ) = @_;
         # Flush Bob's event stream so that we get a token from before
         # Alice sending the invite request.
         $flush_events_for->( $bob )
      })->then( sub {
         # Now alice can invite Bob to the room.
         # We also wait for the push notification for it

         Future->needs_all(
            Future->wait_any(
               $await_event_for->( $bob, sub {
                  my ( $event ) = @_;
                  return unless $event->{type} eq "m.room.member" and
                     $event->{room_id} eq $room->{room_id} and
                     $event->{state_key} eq $bob->user_id and
                     $event->{content}{membership} eq "invite";
                  return 1;
               }),

               delay( 10 )
                  ->then_fail( "Timed out waiting for invite" ),
            ),

            $do_request_json_for->( $alice,
               method  => "POST",
               uri     => "/rooms/$room->{room_id}/invite",
               content => { user_id => $bob->user_id },
            ),
         )
      })->then( sub {
         # Bob accepts the invite by joining the room
         pass "Bob received invite";

         $do_request_json_for->( $bob,
            method  => "POST",
            uri     => "/rooms/$room->{room_id}/join",
            content => {},
         )
      })->then( sub {
         # Now that Bob has joined the room, we will create a pusher for
         # Alice. This may race with Bob joining the room. So the first
         # message received may be due to Bob joining rather than the
         # message that Bob sent.
         $do_request_json_for->( $alice,
            method  => "POST",
            uri     => "/pushers/set",
            content => {
               profile_tag         => "tag",
               kind                => "http",
               app_id              => "sytest",
               app_display_name    => "sytest_display_name",
               device_display_name => "device_display_name",
               pushkey             => "a_push_key",
               lang                => "en",
               data                => {
                  url => "$test_http_server_uri_base/alice_push",
               },
            },
         )
      })->then( sub {
         pass "Alice's pusher created";
         # Bob sends a message that should be pushed to Alice, since it is
         # in a "1:1" room with Alice

         Future->needs_all(
            # TODO(check that the HTTP poke is actually the poke we wanted)
            Future->wait_any(
               $await_http_request->("/alice_push", sub {
                  my ( $body ) = @_;
                  return unless $body->{notification}{type};
                  return unless $body->{notification}{type} eq "m.room.message";
                  return 1;
               })->then( sub {
                  my ( $body, $request ) = @_;

                  $request->respond( HTTP::Response->new( 200, "OK", [], "" ) );
                  Future->done( $body );
               }),

               delay( 10 )
                  ->then_fail( "Timed out waiting for push" ),
            ),

            $do_request_json_for->( $bob,
               method  => "POST",
               uri     => "/rooms/$room->{room_id}/send/m.room.message",
               content => {
                  msgtype => "m.text",
                  body    => "Room message for 50push-01message-pushed"
               },
            )->on_done( sub {
               my ( $body ) = @_;
               $event_id = $body->{event_id};
            }),
         )
      })->then( sub {
         my ( $request_body ) = @_;

         pass "Message sent";

         require_json_keys( my $notification = $request_body->{notification}, qw(
            id room_id type sender content devices counts
         ));
         require_json_keys( $notification->{counts}, qw(
            unread
         ));
         require_json_keys( $notification->{devices}[0], qw(
            app_id pushkey pushkey_ts data tweaks
         ));
         require_json_keys( my $content = $notification->{content}, qw(
            msgtype body
         ));

         $content->{body} eq "Room message for 50push-01message-pushed" or
            die "Unexpected message body";

         pass "Alice was pushed";  # Alice has gone down the stairs

         Future->done(1);
      });
   };<commit_msg>Add a handy log_if_fail to 50push<commit_after>multi_test "Test that a message is pushed",
   requires => [qw(
      http_clients do_request_json_for await_event_for flush_events_for
      test_http_server_uri_base await_http_request register_new_user_without_events

      can_register can_create_private_room
   )],

   do => sub {
      my (
         $clients, $do_request_json_for, $await_event_for, $flush_events_for,
         $test_http_server_uri_base, $await_http_request, $register_new_user,
      ) = @_;

      my $http = $clients->[0];

      my $alice;
      my $bob;
      my $room;
      my $event_id;

      # We use the version of register new user that doesn't start the event
      # stream for Alice. Starting an event stream will make presence
      # consider Alice to be online. If presence considers alice to be online
      # then Alice might stop receiving push messages.
      # We need to register two users because you are never pushed for
      # messages that you send yourself.
      Future->needs_all(
         $register_new_user->( $http, "50push-01-alice" ),
         $register_new_user->( $http, "50push-01-bob" ),
      )->then( sub {
         ( $alice, $bob ) = @_;
         pass "Registered users";

         # Have Alice create a new private room
         $do_request_json_for->( $alice,
            method  => "POST",
            uri     => "/createRoom",
            content => { visibility => "private" },
         )
      })->then( sub {
         ( $room ) = @_;
         # Flush Bob's event stream so that we get a token from before
         # Alice sending the invite request.
         $flush_events_for->( $bob )
      })->then( sub {
         # Now alice can invite Bob to the room.
         # We also wait for the push notification for it

         Future->needs_all(
            Future->wait_any(
               $await_event_for->( $bob, sub {
                  my ( $event ) = @_;
                  return unless $event->{type} eq "m.room.member" and
                     $event->{room_id} eq $room->{room_id} and
                     $event->{state_key} eq $bob->user_id and
                     $event->{content}{membership} eq "invite";
                  return 1;
               }),

               delay( 10 )
                  ->then_fail( "Timed out waiting for invite" ),
            ),

            $do_request_json_for->( $alice,
               method  => "POST",
               uri     => "/rooms/$room->{room_id}/invite",
               content => { user_id => $bob->user_id },
            ),
         )
      })->then( sub {
         # Bob accepts the invite by joining the room
         pass "Bob received invite";

         $do_request_json_for->( $bob,
            method  => "POST",
            uri     => "/rooms/$room->{room_id}/join",
            content => {},
         )
      })->then( sub {
         # Now that Bob has joined the room, we will create a pusher for
         # Alice. This may race with Bob joining the room. So the first
         # message received may be due to Bob joining rather than the
         # message that Bob sent.
         $do_request_json_for->( $alice,
            method  => "POST",
            uri     => "/pushers/set",
            content => {
               profile_tag         => "tag",
               kind                => "http",
               app_id              => "sytest",
               app_display_name    => "sytest_display_name",
               device_display_name => "device_display_name",
               pushkey             => "a_push_key",
               lang                => "en",
               data                => {
                  url => "$test_http_server_uri_base/alice_push",
               },
            },
         )
      })->then( sub {
         pass "Alice's pusher created";
         # Bob sends a message that should be pushed to Alice, since it is
         # in a "1:1" room with Alice

         Future->needs_all(
            # TODO(check that the HTTP poke is actually the poke we wanted)
            Future->wait_any(
               $await_http_request->("/alice_push", sub {
                  my ( $body ) = @_;
                  return unless $body->{notification}{type};
                  return unless $body->{notification}{type} eq "m.room.message";
                  return 1;
               })->then( sub {
                  my ( $body, $request ) = @_;

                  $request->respond( HTTP::Response->new( 200, "OK", [], "" ) );
                  Future->done( $body );
               }),

               delay( 10 )
                  ->then_fail( "Timed out waiting for push" ),
            ),

            $do_request_json_for->( $bob,
               method  => "POST",
               uri     => "/rooms/$room->{room_id}/send/m.room.message",
               content => {
                  msgtype => "m.text",
                  body    => "Room message for 50push-01message-pushed"
               },
            )->on_done( sub {
               my ( $body ) = @_;
               $event_id = $body->{event_id};
            }),
         )
      })->then( sub {
         my ( $request_body ) = @_;

         log_if_fail "Request body", $request_body;

         pass "Message sent";

         require_json_keys( my $notification = $request_body->{notification}, qw(
            id room_id type sender content devices counts
         ));
         require_json_keys( $notification->{counts}, qw(
            unread
         ));
         require_json_keys( $notification->{devices}[0], qw(
            app_id pushkey pushkey_ts data tweaks
         ));
         require_json_keys( my $content = $notification->{content}, qw(
            msgtype body
         ));

         $content->{body} eq "Room message for 50push-01message-pushed" or
            die "Unexpected message body";

         pass "Alice was pushed";  # Alice has gone down the stairs

         Future->done(1);
      });
   };
{'fraction_non_alphanumeric': 0.1138534358887668, 'fraction_numerical': 0.0052404699518214855, 'mean_word_length': 1.4753138075313807, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 161, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6591595', 'n_tokens_mistral': 3358, 'n_tokens_neox': 3212, 'n_words': 909}