diff options
| author | Owen Jacobson <owen@grimoire.ca> | 2026-02-27 16:41:37 -0500 |
|---|---|---|
| committer | Owen Jacobson <owen@grimoire.ca> | 2026-02-27 18:15:33 -0500 |
| commit | b32c7682f0a84619a6d1845516a6a1829fa0c59b (patch) | |
| tree | fad8bf5bd8eb628253611f0b3d1a91febe3b9266 /src/push/handlers/ping/test.rs | |
| parent | 6ab0f42250294e38e8da6a48260ff83544a6be9a (diff) | |
I want push publication to be "fire and forget," and ultimately also for it to be asynchronous and retriable. To facilitate that, the caller needs to be insulated from the final outcome of publishing a push message. I've opted to preserve the `Failure` possibility, but any delivery issues are now handled inside the publisher.
Diffstat (limited to 'src/push/handlers/ping/test.rs')
| -rw-r--r-- | src/push/handlers/ping/test.rs | 200 |
1 files changed, 0 insertions, 200 deletions
diff --git a/src/push/handlers/ping/test.rs b/src/push/handlers/ping/test.rs index cc07ef0..70ba4bf 100644 --- a/src/push/handlers/ping/test.rs +++ b/src/push/handlers/ping/test.rs @@ -172,203 +172,3 @@ async fn ping_recipient_only() { .any(|publish| publish.recipients.contains(&spectator_subscription)) ); } - -#[tokio::test] -async fn ping_permanent_error() { - let app = fixtures::scratch_app().await; - - let recipient = fixtures::identity::create(&app, &fixtures::now()).await; - - let vapid = fixtures::vapid::key(&app).await; - - // Create subscriptions - let subscription = SubscriptionInfo::new( - "https://push.example.com/recipient/endpoint", - "recipient-p256dh-key", - "recipient-auth", - ); - app.push() - .subscribe(&recipient, &subscription, &vapid) - .await - .expect("creating a subscription succeeds"); - - // Prepare the next ping attempt to fail - app.publisher() - .fail_next(&subscription, WebPushError::InvalidUri); - - // Send a ping - super::handler( - State(app.push()), - recipient.clone(), - Json(super::Request {}), - ) - .await - .expect_err("sending a ping with a permanently-failing subscription fails"); - - // Confirm that it was actually sent - let sent = app.publisher().sent(); - - let subscriptions = HashSet::from([subscription.clone()]); - assert!( - sent.iter() - .filter(|publish| publish.message_eq(&Heartbeat::Heartbeat) - && publish.recipients == subscriptions) - .exactly_one() - .is_ok() - ); - - // Send a second ping - let response = super::handler(State(app.push()), recipient, Json(super::Request {})) - .await - .expect("sending a ping with no subscriptions always succeeds"); - - assert_eq!(StatusCode::ACCEPTED, response); - - // Confirm that it was _not_ sent this time, since it failed permanently last time - let sent = app.publisher().sent(); - - assert!( - !sent - .iter() - .any(|publish| publish.recipients.contains(&subscription)) - ); -} - -#[tokio::test] -async fn ping_temporary_error() { - let app = fixtures::scratch_app().await; - - let recipient = fixtures::identity::create(&app, &fixtures::now()).await; - - let vapid = fixtures::vapid::key(&app).await; - - // Create subscriptions - let subscription = SubscriptionInfo::new( - "https://push.example.com/recipient/endpoint", - "recipient-p256dh-key", - "recipient-auth", - ); - app.push() - .subscribe(&recipient, &subscription, &vapid) - .await - .expect("creating a subscription succeeds"); - - // Prepare the next ping attempt to fail - app.publisher().fail_next( - &subscription, - WebPushError::from(io::Error::other("transient IO error")), - ); - - // Send a ping - super::handler( - State(app.push()), - recipient.clone(), - Json(super::Request {}), - ) - .await - .expect_err("sending a ping with a temporarily-failing subscription fails"); - - // Confirm that it was actually sent - let sent = app.publisher().sent(); - - let subscriptions = HashSet::from([subscription.clone()]); - assert!( - sent.iter() - .filter(|publish| publish.message_eq(&Heartbeat::Heartbeat) - && publish.recipients == subscriptions) - .exactly_one() - .is_ok() - ); - - // Send a second ping - let response = super::handler(State(app.push()), recipient, Json(super::Request {})) - .await - .expect("sending a ping subscription succeeds now that the transient error has cleared"); - assert_eq!(StatusCode::ACCEPTED, response); - - // Confirm that it was _not_ sent this time, since it failed permanently last time - let sent = app.publisher().sent(); - - let subscriptions = HashSet::from([subscription]); - assert!( - sent.iter() - .filter(|publish| publish.message_eq(&Heartbeat::Heartbeat) - && publish.recipients == subscriptions) - .exactly_one() - .is_ok() - ); -} - -#[tokio::test] -async fn ping_multiple_subscriptions_with_failure() { - let app = fixtures::scratch_app().await; - - let recipient = fixtures::identity::create(&app, &fixtures::now()).await; - let vapid = fixtures::vapid::key(&app).await; - - // Create subscriptions - let failing = SubscriptionInfo::new( - "https://push.example.com/endpoint-failing", - "testing-p256dh-key-failing", - "testing-auth-failing", - ); - let succeeding = SubscriptionInfo::new( - "https://push.example.com/endpoint-succeeding", - "testing-p256dh-key-succeeding", - "testing-auth-succeeding", - ); - let subscriptions = HashSet::from([failing.clone(), succeeding.clone()]); - for subscription in &subscriptions { - app.push() - .subscribe(&recipient, subscription, &vapid) - .await - .expect("creating a subscription succeeds"); - } - - // Rig one of them to fail permanently - app.publisher() - .fail_next(&failing, WebPushError::InvalidUri); - - // Send a ping - super::handler( - State(app.push()), - recipient.clone(), - Json(super::Request {}), - ) - .await - .expect_err("sending a ping with a failing subscription fails"); - - // Confirm that it was actually sent to both subs the first time - let subscriptions = HashSet::from([failing.clone(), succeeding.clone()]); - assert!( - app.publisher() - .sent() - .iter() - .filter(|publish| publish.message_eq(&Heartbeat::Heartbeat) - && publish.recipients == subscriptions) - .exactly_one() - .is_ok() - ); - - // Send a second ping - let response = super::handler(State(app.push()), recipient, Json(super::Request {})) - .await - .expect("sending a second ping succeeds after the failing subscription is removed"); - assert_eq!(StatusCode::ACCEPTED, response); - - // Confirm that it was only sent to the succeeding subscription - let subscriptions = HashSet::from([succeeding]); - let sent = app.publisher().sent(); - assert!( - sent.iter() - .filter(|publish| publish.message_eq(&Heartbeat::Heartbeat) - && publish.recipients == subscriptions) - .exactly_one() - .is_ok() - ); - assert!( - !sent - .iter() - .any(|publish| publish.recipients.contains(&failing)) - ); -} |
