webpush_store_test.go 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. package server
  2. import (
  3. "fmt"
  4. "github.com/stretchr/testify/require"
  5. "net/netip"
  6. "path/filepath"
  7. "testing"
  8. "time"
  9. )
  10. func TestWebPushStore_UpsertSubscription_SubscriptionsForTopic(t *testing.T) {
  11. webPush := newTestWebPushStore(t)
  12. defer webPush.Close()
  13. require.Nil(t, webPush.UpsertSubscription(testWebPushEndpoint, "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"test-topic", "mytopic"}))
  14. subs, err := webPush.SubscriptionsForTopic("test-topic")
  15. require.Nil(t, err)
  16. require.Len(t, subs, 1)
  17. require.Equal(t, subs[0].Endpoint, testWebPushEndpoint)
  18. require.Equal(t, subs[0].P256dh, "p256dh-key")
  19. require.Equal(t, subs[0].Auth, "auth-key")
  20. require.Equal(t, subs[0].UserID, "u_1234")
  21. subs2, err := webPush.SubscriptionsForTopic("mytopic")
  22. require.Nil(t, err)
  23. require.Len(t, subs2, 1)
  24. require.Equal(t, subs[0].Endpoint, subs2[0].Endpoint)
  25. }
  26. func TestWebPushStore_UpsertSubscription_SubscriberIPLimitReached(t *testing.T) {
  27. webPush := newTestWebPushStore(t)
  28. defer webPush.Close()
  29. // Insert 10 subscriptions with the same IP address
  30. for i := 0; i < 10; i++ {
  31. endpoint := fmt.Sprintf(testWebPushEndpoint+"%d", i)
  32. require.Nil(t, webPush.UpsertSubscription(endpoint, "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"test-topic", "mytopic"}))
  33. }
  34. // Another one for the same endpoint should be fine
  35. require.Nil(t, webPush.UpsertSubscription(testWebPushEndpoint+"0", "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"test-topic", "mytopic"}))
  36. // But with a different endpoint it should fail
  37. require.Equal(t, errWebPushTooManySubscriptions, webPush.UpsertSubscription(testWebPushEndpoint+"11", "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"test-topic", "mytopic"}))
  38. // But with a different IP address it should be fine again
  39. require.Nil(t, webPush.UpsertSubscription(testWebPushEndpoint+"99", "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("9.9.9.9"), []string{"test-topic", "mytopic"}))
  40. }
  41. func TestWebPushStore_UpsertSubscription_UpdateTopics(t *testing.T) {
  42. webPush := newTestWebPushStore(t)
  43. defer webPush.Close()
  44. // Insert subscription with two topics, and another with one topic
  45. require.Nil(t, webPush.UpsertSubscription(testWebPushEndpoint+"0", "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"topic1", "topic2"}))
  46. require.Nil(t, webPush.UpsertSubscription(testWebPushEndpoint+"1", "auth-key", "p256dh-key", "", netip.MustParseAddr("9.9.9.9"), []string{"topic1"}))
  47. subs, err := webPush.SubscriptionsForTopic("topic1")
  48. require.Nil(t, err)
  49. require.Len(t, subs, 2)
  50. require.Equal(t, testWebPushEndpoint+"0", subs[0].Endpoint)
  51. require.Equal(t, testWebPushEndpoint+"1", subs[1].Endpoint)
  52. subs, err = webPush.SubscriptionsForTopic("topic2")
  53. require.Nil(t, err)
  54. require.Len(t, subs, 1)
  55. require.Equal(t, testWebPushEndpoint+"0", subs[0].Endpoint)
  56. // Update the first subscription to have only one topic
  57. require.Nil(t, webPush.UpsertSubscription(testWebPushEndpoint+"0", "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"topic1"}))
  58. subs, err = webPush.SubscriptionsForTopic("topic1")
  59. require.Nil(t, err)
  60. require.Len(t, subs, 2)
  61. require.Equal(t, testWebPushEndpoint+"0", subs[0].Endpoint)
  62. subs, err = webPush.SubscriptionsForTopic("topic2")
  63. require.Nil(t, err)
  64. require.Len(t, subs, 0)
  65. }
  66. func TestWebPushStore_RemoveSubscriptionsByEndpoint(t *testing.T) {
  67. webPush := newTestWebPushStore(t)
  68. defer webPush.Close()
  69. // Insert subscription with two topics
  70. require.Nil(t, webPush.UpsertSubscription(testWebPushEndpoint, "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"topic1", "topic2"}))
  71. subs, err := webPush.SubscriptionsForTopic("topic1")
  72. require.Nil(t, err)
  73. require.Len(t, subs, 1)
  74. // And remove it again
  75. require.Nil(t, webPush.RemoveSubscriptionsByEndpoint(testWebPushEndpoint))
  76. subs, err = webPush.SubscriptionsForTopic("topic1")
  77. require.Nil(t, err)
  78. require.Len(t, subs, 0)
  79. }
  80. func TestWebPushStore_RemoveSubscriptionsByUserID(t *testing.T) {
  81. webPush := newTestWebPushStore(t)
  82. defer webPush.Close()
  83. // Insert subscription with two topics
  84. require.Nil(t, webPush.UpsertSubscription(testWebPushEndpoint, "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"topic1", "topic2"}))
  85. subs, err := webPush.SubscriptionsForTopic("topic1")
  86. require.Nil(t, err)
  87. require.Len(t, subs, 1)
  88. // And remove it again
  89. require.Nil(t, webPush.RemoveSubscriptionsByUserID("u_1234"))
  90. subs, err = webPush.SubscriptionsForTopic("topic1")
  91. require.Nil(t, err)
  92. require.Len(t, subs, 0)
  93. }
  94. func TestWebPushStore_RemoveSubscriptionsByUserID_Empty(t *testing.T) {
  95. webPush := newTestWebPushStore(t)
  96. defer webPush.Close()
  97. require.Equal(t, errWebPushUserIDCannotBeEmpty, webPush.RemoveSubscriptionsByUserID(""))
  98. }
  99. func TestWebPushStore_MarkExpiryWarningSent(t *testing.T) {
  100. webPush := newTestWebPushStore(t)
  101. defer webPush.Close()
  102. // Insert subscription with two topics
  103. require.Nil(t, webPush.UpsertSubscription(testWebPushEndpoint, "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"topic1", "topic2"}))
  104. subs, err := webPush.SubscriptionsForTopic("topic1")
  105. require.Nil(t, err)
  106. require.Len(t, subs, 1)
  107. // Mark them as warning sent
  108. require.Nil(t, webPush.MarkExpiryWarningSent(subs))
  109. rows, err := webPush.db.Query("SELECT endpoint FROM subscription WHERE warned_at > 0")
  110. require.Nil(t, err)
  111. defer rows.Close()
  112. var endpoint string
  113. require.True(t, rows.Next())
  114. require.Nil(t, rows.Scan(&endpoint))
  115. require.Nil(t, err)
  116. require.Equal(t, testWebPushEndpoint, endpoint)
  117. require.False(t, rows.Next())
  118. }
  119. func TestWebPushStore_SubscriptionsExpiring(t *testing.T) {
  120. webPush := newTestWebPushStore(t)
  121. defer webPush.Close()
  122. // Insert subscription with two topics
  123. require.Nil(t, webPush.UpsertSubscription(testWebPushEndpoint, "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"topic1", "topic2"}))
  124. subs, err := webPush.SubscriptionsForTopic("topic1")
  125. require.Nil(t, err)
  126. require.Len(t, subs, 1)
  127. // Fake-mark them as soon-to-expire
  128. _, err = webPush.db.Exec("UPDATE subscription SET updated_at = ? WHERE endpoint = ?", time.Now().Add(-8*24*time.Hour).Unix(), testWebPushEndpoint)
  129. require.Nil(t, err)
  130. // Should not be cleaned up yet
  131. require.Nil(t, webPush.RemoveExpiredSubscriptions(9*24*time.Hour))
  132. // Run expiration
  133. subs, err = webPush.SubscriptionsExpiring(7 * 24 * time.Hour)
  134. require.Nil(t, err)
  135. require.Len(t, subs, 1)
  136. require.Equal(t, testWebPushEndpoint, subs[0].Endpoint)
  137. }
  138. func TestWebPushStore_RemoveExpiredSubscriptions(t *testing.T) {
  139. webPush := newTestWebPushStore(t)
  140. defer webPush.Close()
  141. // Insert subscription with two topics
  142. require.Nil(t, webPush.UpsertSubscription(testWebPushEndpoint, "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"topic1", "topic2"}))
  143. subs, err := webPush.SubscriptionsForTopic("topic1")
  144. require.Nil(t, err)
  145. require.Len(t, subs, 1)
  146. // Fake-mark them as expired
  147. _, err = webPush.db.Exec("UPDATE subscription SET updated_at = ? WHERE endpoint = ?", time.Now().Add(-10*24*time.Hour).Unix(), testWebPushEndpoint)
  148. require.Nil(t, err)
  149. // Run expiration
  150. require.Nil(t, webPush.RemoveExpiredSubscriptions(9*24*time.Hour))
  151. // List again, should be 0
  152. subs, err = webPush.SubscriptionsForTopic("topic1")
  153. require.Nil(t, err)
  154. require.Len(t, subs, 0)
  155. }
  156. func newTestWebPushStore(t *testing.T) *webPushStore {
  157. webPush, err := newWebPushStore(filepath.Join(t.TempDir(), "webpush.db"), "")
  158. require.Nil(t, err)
  159. return webPush
  160. }