mirror of
https://github.com/binwiederhier/ntfy.git
synced 2026-03-18 21:30:44 +01:00
Unify webpush store tests across SQLite and PostgreSQL backends
Share test logic in store_test.go with thin per-backend wrappers. Add SetSubscriptionUpdatedAt to both stores, removing the need for raw SQL and the DB() accessor in tests.
This commit is contained in:
@@ -237,11 +237,11 @@ func TestServer_WebPush_Expiry(t *testing.T) {
|
|||||||
}))
|
}))
|
||||||
defer pushService.Close()
|
defer pushService.Close()
|
||||||
|
|
||||||
addSubscription(t, s, pushService.URL+"/push-receive", "test-topic")
|
endpoint := pushService.URL + "/push-receive"
|
||||||
|
addSubscription(t, s, endpoint, "test-topic")
|
||||||
requireSubscriptionCount(t, s, "test-topic", 1)
|
requireSubscriptionCount(t, s, "test-topic", 1)
|
||||||
|
|
||||||
_, err := s.webPush.(*wpush.SQLiteStore).DB().Exec("UPDATE subscription SET updated_at = ?", time.Now().Add(-55*24*time.Hour).Unix())
|
require.Nil(t, s.webPush.(*wpush.SQLiteStore).SetSubscriptionUpdatedAt(endpoint, time.Now().Add(-55*24*time.Hour).Unix()))
|
||||||
require.Nil(t, err)
|
|
||||||
|
|
||||||
s.pruneAndNotifyWebPushSubscriptions()
|
s.pruneAndNotifyWebPushSubscriptions()
|
||||||
requireSubscriptionCount(t, s, "test-topic", 1)
|
requireSubscriptionCount(t, s, "test-topic", 1)
|
||||||
@@ -250,8 +250,7 @@ func TestServer_WebPush_Expiry(t *testing.T) {
|
|||||||
return received.Load()
|
return received.Load()
|
||||||
})
|
})
|
||||||
|
|
||||||
_, err = s.webPush.(*wpush.SQLiteStore).DB().Exec("UPDATE subscription SET updated_at = ?", time.Now().Add(-60*24*time.Hour).Unix())
|
require.Nil(t, s.webPush.(*wpush.SQLiteStore).SetSubscriptionUpdatedAt(endpoint, time.Now().Add(-60*24*time.Hour).Unix()))
|
||||||
require.Nil(t, err)
|
|
||||||
|
|
||||||
s.pruneAndNotifyWebPushSubscriptions()
|
s.pruneAndNotifyWebPushSubscriptions()
|
||||||
waitFor(t, func() bool {
|
waitFor(t, func() bool {
|
||||||
|
|||||||
@@ -94,11 +94,6 @@ func NewPostgresStore(dsn string) (*PostgresStore, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DB returns the underlying database connection. This is exported for testing purposes.
|
|
||||||
func (c *PostgresStore) DB() *sql.DB {
|
|
||||||
return c.db
|
|
||||||
}
|
|
||||||
|
|
||||||
func setupPostgresDB(db *sql.DB) error {
|
func setupPostgresDB(db *sql.DB) error {
|
||||||
// If 'wp_schema_version' table does not exist, this must be a new database
|
// If 'wp_schema_version' table does not exist, this must be a new database
|
||||||
rows, err := db.Query(pgSelectSchemaVersionQuery)
|
rows, err := db.Query(pgSelectSchemaVersionQuery)
|
||||||
@@ -218,6 +213,13 @@ func (c *PostgresStore) RemoveExpiredSubscriptions(expireAfter time.Duration) er
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetSubscriptionUpdatedAt updates the updated_at timestamp for a subscription by endpoint. This is
|
||||||
|
// exported for testing purposes and is not part of the Store interface.
|
||||||
|
func (c *PostgresStore) SetSubscriptionUpdatedAt(endpoint string, updatedAt int64) error {
|
||||||
|
_, err := c.db.Exec("UPDATE webpush_subscription SET updated_at = $1 WHERE endpoint = $2", updatedAt, endpoint)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// Close closes the underlying database connection.
|
// Close closes the underlying database connection.
|
||||||
func (c *PostgresStore) Close() error {
|
func (c *PostgresStore) Close() error {
|
||||||
return c.db.Close()
|
return c.db.Close()
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
package webpush_test
|
package webpush_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"database/sql"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/netip"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
"heckel.io/ntfy/v2/util"
|
||||||
"heckel.io/ntfy/v2/webpush"
|
"heckel.io/ntfy/v2/webpush"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -16,192 +17,67 @@ func newTestPostgresStore(t *testing.T) *webpush.PostgresStore {
|
|||||||
if dsn == "" {
|
if dsn == "" {
|
||||||
t.Skip("NTFY_TEST_DATABASE_URL not set, skipping PostgreSQL tests")
|
t.Skip("NTFY_TEST_DATABASE_URL not set, skipping PostgreSQL tests")
|
||||||
}
|
}
|
||||||
store, err := webpush.NewPostgresStore(dsn)
|
// Create a unique schema for this test
|
||||||
|
schema := fmt.Sprintf("test_%s", util.RandomString(10))
|
||||||
|
setupDB, err := sql.Open("pgx", dsn)
|
||||||
|
require.Nil(t, err)
|
||||||
|
_, err = setupDB.Exec(fmt.Sprintf("CREATE SCHEMA %s", schema))
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Nil(t, setupDB.Close())
|
||||||
|
// Open store with search_path set to the new schema
|
||||||
|
u, err := url.Parse(dsn)
|
||||||
|
require.Nil(t, err)
|
||||||
|
q := u.Query()
|
||||||
|
q.Set("search_path", schema)
|
||||||
|
u.RawQuery = q.Encode()
|
||||||
|
store, err := webpush.NewPostgresStore(u.String())
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
t.Cleanup(func() {
|
t.Cleanup(func() {
|
||||||
// Clean up tables after each test
|
|
||||||
db := store.DB()
|
|
||||||
db.Exec("DELETE FROM webpush_subscription_topic")
|
|
||||||
db.Exec("DELETE FROM webpush_subscription")
|
|
||||||
store.Close()
|
store.Close()
|
||||||
|
cleanDB, err := sql.Open("pgx", dsn)
|
||||||
|
if err == nil {
|
||||||
|
cleanDB.Exec(fmt.Sprintf("DROP SCHEMA %s CASCADE", schema))
|
||||||
|
cleanDB.Close()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
// Clean up tables before test
|
|
||||||
db := store.DB()
|
|
||||||
db.Exec("DELETE FROM webpush_subscription_topic")
|
|
||||||
db.Exec("DELETE FROM webpush_subscription")
|
|
||||||
return store
|
return store
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPostgresStore_UpsertSubscription_SubscriptionsForTopic(t *testing.T) {
|
func TestPostgresStore_UpsertSubscription_SubscriptionsForTopic(t *testing.T) {
|
||||||
store := newTestPostgresStore(t)
|
testStoreUpsertSubscription_SubscriptionsForTopic(t, newTestPostgresStore(t))
|
||||||
|
|
||||||
require.Nil(t, store.UpsertSubscription(testWebPushEndpoint, "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"test-topic", "mytopic"}))
|
|
||||||
|
|
||||||
subs, err := store.SubscriptionsForTopic("test-topic")
|
|
||||||
require.Nil(t, err)
|
|
||||||
require.Len(t, subs, 1)
|
|
||||||
require.Equal(t, subs[0].Endpoint, testWebPushEndpoint)
|
|
||||||
require.Equal(t, subs[0].P256dh, "p256dh-key")
|
|
||||||
require.Equal(t, subs[0].Auth, "auth-key")
|
|
||||||
require.Equal(t, subs[0].UserID, "u_1234")
|
|
||||||
|
|
||||||
subs2, err := store.SubscriptionsForTopic("mytopic")
|
|
||||||
require.Nil(t, err)
|
|
||||||
require.Len(t, subs2, 1)
|
|
||||||
require.Equal(t, subs[0].Endpoint, subs2[0].Endpoint)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPostgresStore_UpsertSubscription_SubscriberIPLimitReached(t *testing.T) {
|
func TestPostgresStore_UpsertSubscription_SubscriberIPLimitReached(t *testing.T) {
|
||||||
store := newTestPostgresStore(t)
|
testStoreUpsertSubscription_SubscriberIPLimitReached(t, newTestPostgresStore(t))
|
||||||
|
|
||||||
// Insert 10 subscriptions with the same IP address
|
|
||||||
for i := 0; i < 10; i++ {
|
|
||||||
endpoint := fmt.Sprintf(testWebPushEndpoint+"%d", i)
|
|
||||||
require.Nil(t, store.UpsertSubscription(endpoint, "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"test-topic", "mytopic"}))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Another one for the same endpoint should be fine
|
|
||||||
require.Nil(t, store.UpsertSubscription(testWebPushEndpoint+"0", "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"test-topic", "mytopic"}))
|
|
||||||
|
|
||||||
// But with a different endpoint it should fail
|
|
||||||
require.Equal(t, webpush.ErrWebPushTooManySubscriptions, store.UpsertSubscription(testWebPushEndpoint+"11", "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"test-topic", "mytopic"}))
|
|
||||||
|
|
||||||
// But with a different IP address it should be fine again
|
|
||||||
require.Nil(t, store.UpsertSubscription(testWebPushEndpoint+"99", "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("9.9.9.9"), []string{"test-topic", "mytopic"}))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPostgresStore_UpsertSubscription_UpdateTopics(t *testing.T) {
|
func TestPostgresStore_UpsertSubscription_UpdateTopics(t *testing.T) {
|
||||||
store := newTestPostgresStore(t)
|
testStoreUpsertSubscription_UpdateTopics(t, newTestPostgresStore(t))
|
||||||
|
|
||||||
// Insert subscription with two topics, and another with one topic
|
|
||||||
require.Nil(t, store.UpsertSubscription(testWebPushEndpoint+"0", "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"topic1", "topic2"}))
|
|
||||||
require.Nil(t, store.UpsertSubscription(testWebPushEndpoint+"1", "auth-key", "p256dh-key", "", netip.MustParseAddr("9.9.9.9"), []string{"topic1"}))
|
|
||||||
|
|
||||||
subs, err := store.SubscriptionsForTopic("topic1")
|
|
||||||
require.Nil(t, err)
|
|
||||||
require.Len(t, subs, 2)
|
|
||||||
require.Equal(t, testWebPushEndpoint+"0", subs[0].Endpoint)
|
|
||||||
require.Equal(t, testWebPushEndpoint+"1", subs[1].Endpoint)
|
|
||||||
|
|
||||||
subs, err = store.SubscriptionsForTopic("topic2")
|
|
||||||
require.Nil(t, err)
|
|
||||||
require.Len(t, subs, 1)
|
|
||||||
require.Equal(t, testWebPushEndpoint+"0", subs[0].Endpoint)
|
|
||||||
|
|
||||||
// Update the first subscription to have only one topic
|
|
||||||
require.Nil(t, store.UpsertSubscription(testWebPushEndpoint+"0", "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"topic1"}))
|
|
||||||
|
|
||||||
subs, err = store.SubscriptionsForTopic("topic1")
|
|
||||||
require.Nil(t, err)
|
|
||||||
require.Len(t, subs, 2)
|
|
||||||
require.Equal(t, testWebPushEndpoint+"0", subs[0].Endpoint)
|
|
||||||
|
|
||||||
subs, err = store.SubscriptionsForTopic("topic2")
|
|
||||||
require.Nil(t, err)
|
|
||||||
require.Len(t, subs, 0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPostgresStore_RemoveSubscriptionsByEndpoint(t *testing.T) {
|
func TestPostgresStore_RemoveSubscriptionsByEndpoint(t *testing.T) {
|
||||||
store := newTestPostgresStore(t)
|
testStoreRemoveSubscriptionsByEndpoint(t, newTestPostgresStore(t))
|
||||||
|
|
||||||
// Insert subscription with two topics
|
|
||||||
require.Nil(t, store.UpsertSubscription(testWebPushEndpoint, "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"topic1", "topic2"}))
|
|
||||||
subs, err := store.SubscriptionsForTopic("topic1")
|
|
||||||
require.Nil(t, err)
|
|
||||||
require.Len(t, subs, 1)
|
|
||||||
|
|
||||||
// And remove it again
|
|
||||||
require.Nil(t, store.RemoveSubscriptionsByEndpoint(testWebPushEndpoint))
|
|
||||||
subs, err = store.SubscriptionsForTopic("topic1")
|
|
||||||
require.Nil(t, err)
|
|
||||||
require.Len(t, subs, 0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPostgresStore_RemoveSubscriptionsByUserID(t *testing.T) {
|
func TestPostgresStore_RemoveSubscriptionsByUserID(t *testing.T) {
|
||||||
store := newTestPostgresStore(t)
|
testStoreRemoveSubscriptionsByUserID(t, newTestPostgresStore(t))
|
||||||
|
|
||||||
// Insert subscription with two topics
|
|
||||||
require.Nil(t, store.UpsertSubscription(testWebPushEndpoint, "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"topic1", "topic2"}))
|
|
||||||
subs, err := store.SubscriptionsForTopic("topic1")
|
|
||||||
require.Nil(t, err)
|
|
||||||
require.Len(t, subs, 1)
|
|
||||||
|
|
||||||
// And remove it again
|
|
||||||
require.Nil(t, store.RemoveSubscriptionsByUserID("u_1234"))
|
|
||||||
subs, err = store.SubscriptionsForTopic("topic1")
|
|
||||||
require.Nil(t, err)
|
|
||||||
require.Len(t, subs, 0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPostgresStore_RemoveSubscriptionsByUserID_Empty(t *testing.T) {
|
func TestPostgresStore_RemoveSubscriptionsByUserID_Empty(t *testing.T) {
|
||||||
store := newTestPostgresStore(t)
|
testStoreRemoveSubscriptionsByUserID_Empty(t, newTestPostgresStore(t))
|
||||||
require.Equal(t, webpush.ErrWebPushUserIDCannotBeEmpty, store.RemoveSubscriptionsByUserID(""))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPostgresStore_MarkExpiryWarningSent(t *testing.T) {
|
func TestPostgresStore_MarkExpiryWarningSent(t *testing.T) {
|
||||||
store := newTestPostgresStore(t)
|
store := newTestPostgresStore(t)
|
||||||
|
testStoreMarkExpiryWarningSent(t, store, store.SetSubscriptionUpdatedAt)
|
||||||
// Insert subscription with two topics
|
|
||||||
require.Nil(t, store.UpsertSubscription(testWebPushEndpoint, "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"topic1", "topic2"}))
|
|
||||||
subs, err := store.SubscriptionsForTopic("topic1")
|
|
||||||
require.Nil(t, err)
|
|
||||||
require.Len(t, subs, 1)
|
|
||||||
|
|
||||||
// Mark them as warning sent
|
|
||||||
require.Nil(t, store.MarkExpiryWarningSent(subs))
|
|
||||||
|
|
||||||
rows, err := store.DB().Query("SELECT endpoint FROM webpush_subscription WHERE warned_at > 0")
|
|
||||||
require.Nil(t, err)
|
|
||||||
defer rows.Close()
|
|
||||||
var endpoint string
|
|
||||||
require.True(t, rows.Next())
|
|
||||||
require.Nil(t, rows.Scan(&endpoint))
|
|
||||||
require.Nil(t, err)
|
|
||||||
require.Equal(t, testWebPushEndpoint, endpoint)
|
|
||||||
require.False(t, rows.Next())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPostgresStore_SubscriptionsExpiring(t *testing.T) {
|
func TestPostgresStore_SubscriptionsExpiring(t *testing.T) {
|
||||||
store := newTestPostgresStore(t)
|
store := newTestPostgresStore(t)
|
||||||
|
testStoreSubscriptionsExpiring(t, store, store.SetSubscriptionUpdatedAt)
|
||||||
// Insert subscription with two topics
|
|
||||||
require.Nil(t, store.UpsertSubscription(testWebPushEndpoint, "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"topic1", "topic2"}))
|
|
||||||
subs, err := store.SubscriptionsForTopic("topic1")
|
|
||||||
require.Nil(t, err)
|
|
||||||
require.Len(t, subs, 1)
|
|
||||||
|
|
||||||
// Fake-mark them as soon-to-expire
|
|
||||||
_, err = store.DB().Exec("UPDATE webpush_subscription SET updated_at = $1 WHERE endpoint = $2", time.Now().Add(-8*24*time.Hour).Unix(), testWebPushEndpoint)
|
|
||||||
require.Nil(t, err)
|
|
||||||
|
|
||||||
// Should not be cleaned up yet
|
|
||||||
require.Nil(t, store.RemoveExpiredSubscriptions(9*24*time.Hour))
|
|
||||||
|
|
||||||
// Run expiration
|
|
||||||
subs, err = store.SubscriptionsExpiring(7 * 24 * time.Hour)
|
|
||||||
require.Nil(t, err)
|
|
||||||
require.Len(t, subs, 1)
|
|
||||||
require.Equal(t, testWebPushEndpoint, subs[0].Endpoint)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPostgresStore_RemoveExpiredSubscriptions(t *testing.T) {
|
func TestPostgresStore_RemoveExpiredSubscriptions(t *testing.T) {
|
||||||
store := newTestPostgresStore(t)
|
store := newTestPostgresStore(t)
|
||||||
|
testStoreRemoveExpiredSubscriptions(t, store, store.SetSubscriptionUpdatedAt)
|
||||||
// Insert subscription with two topics
|
|
||||||
require.Nil(t, store.UpsertSubscription(testWebPushEndpoint, "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"topic1", "topic2"}))
|
|
||||||
subs, err := store.SubscriptionsForTopic("topic1")
|
|
||||||
require.Nil(t, err)
|
|
||||||
require.Len(t, subs, 1)
|
|
||||||
|
|
||||||
// Fake-mark them as expired
|
|
||||||
_, err = store.DB().Exec("UPDATE webpush_subscription SET updated_at = $1 WHERE endpoint = $2", time.Now().Add(-10*24*time.Hour).Unix(), testWebPushEndpoint)
|
|
||||||
require.Nil(t, err)
|
|
||||||
|
|
||||||
// Run expiration
|
|
||||||
require.Nil(t, store.RemoveExpiredSubscriptions(9*24*time.Hour))
|
|
||||||
|
|
||||||
// List again, should be 0
|
|
||||||
subs, err = store.SubscriptionsForTopic("topic1")
|
|
||||||
require.Nil(t, err)
|
|
||||||
require.Len(t, subs, 0)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,11 +101,6 @@ func NewSQLiteStore(filename, startupQueries string) (*SQLiteStore, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DB returns the underlying database connection. This is exported for testing purposes.
|
|
||||||
func (c *SQLiteStore) DB() *sql.DB {
|
|
||||||
return c.db
|
|
||||||
}
|
|
||||||
|
|
||||||
func setupSQLiteWebPushDB(db *sql.DB) error {
|
func setupSQLiteWebPushDB(db *sql.DB) error {
|
||||||
// If 'schemaVersion' table does not exist, this must be a new database
|
// If 'schemaVersion' table does not exist, this must be a new database
|
||||||
rows, err := db.Query(sqliteSelectWebPushSchemaVersionQuery)
|
rows, err := db.Query(sqliteSelectWebPushSchemaVersionQuery)
|
||||||
@@ -256,6 +251,13 @@ func (c *SQLiteStore) RemoveExpiredSubscriptions(expireAfter time.Duration) erro
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetSubscriptionUpdatedAt updates the updated_at timestamp for a subscription by endpoint. This is
|
||||||
|
// exported for testing purposes and is not part of the Store interface.
|
||||||
|
func (c *SQLiteStore) SetSubscriptionUpdatedAt(endpoint string, updatedAt int64) error {
|
||||||
|
_, err := c.db.Exec("UPDATE subscription SET updated_at = ? WHERE endpoint = ?", updatedAt, endpoint)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// Close closes the underlying database connection.
|
// Close closes the underlying database connection.
|
||||||
func (c *SQLiteStore) Close() error {
|
func (c *SQLiteStore) Close() error {
|
||||||
return c.db.Close()
|
return c.db.Close()
|
||||||
|
|||||||
@@ -1,203 +1,55 @@
|
|||||||
package webpush_test
|
package webpush_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"net/netip"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"heckel.io/ntfy/v2/webpush"
|
"heckel.io/ntfy/v2/webpush"
|
||||||
)
|
)
|
||||||
|
|
||||||
const testWebPushEndpoint = "https://updates.push.services.mozilla.com/wpush/v1/AAABBCCCDDEEEFFF"
|
func newTestSQLiteStore(t *testing.T) *webpush.SQLiteStore {
|
||||||
|
store, err := webpush.NewSQLiteStore(filepath.Join(t.TempDir(), "webpush.db"), "")
|
||||||
|
require.Nil(t, err)
|
||||||
|
t.Cleanup(func() { store.Close() })
|
||||||
|
return store
|
||||||
|
}
|
||||||
|
|
||||||
func TestSQLiteStore_UpsertSubscription_SubscriptionsForTopic(t *testing.T) {
|
func TestSQLiteStore_UpsertSubscription_SubscriptionsForTopic(t *testing.T) {
|
||||||
store := newTestSQLiteStore(t)
|
testStoreUpsertSubscription_SubscriptionsForTopic(t, newTestSQLiteStore(t))
|
||||||
defer store.Close()
|
|
||||||
|
|
||||||
require.Nil(t, store.UpsertSubscription(testWebPushEndpoint, "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"test-topic", "mytopic"}))
|
|
||||||
|
|
||||||
subs, err := store.SubscriptionsForTopic("test-topic")
|
|
||||||
require.Nil(t, err)
|
|
||||||
require.Len(t, subs, 1)
|
|
||||||
require.Equal(t, subs[0].Endpoint, testWebPushEndpoint)
|
|
||||||
require.Equal(t, subs[0].P256dh, "p256dh-key")
|
|
||||||
require.Equal(t, subs[0].Auth, "auth-key")
|
|
||||||
require.Equal(t, subs[0].UserID, "u_1234")
|
|
||||||
|
|
||||||
subs2, err := store.SubscriptionsForTopic("mytopic")
|
|
||||||
require.Nil(t, err)
|
|
||||||
require.Len(t, subs2, 1)
|
|
||||||
require.Equal(t, subs[0].Endpoint, subs2[0].Endpoint)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSQLiteStore_UpsertSubscription_SubscriberIPLimitReached(t *testing.T) {
|
func TestSQLiteStore_UpsertSubscription_SubscriberIPLimitReached(t *testing.T) {
|
||||||
store := newTestSQLiteStore(t)
|
testStoreUpsertSubscription_SubscriberIPLimitReached(t, newTestSQLiteStore(t))
|
||||||
defer store.Close()
|
|
||||||
|
|
||||||
// Insert 10 subscriptions with the same IP address
|
|
||||||
for i := 0; i < 10; i++ {
|
|
||||||
endpoint := fmt.Sprintf(testWebPushEndpoint+"%d", i)
|
|
||||||
require.Nil(t, store.UpsertSubscription(endpoint, "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"test-topic", "mytopic"}))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Another one for the same endpoint should be fine
|
|
||||||
require.Nil(t, store.UpsertSubscription(testWebPushEndpoint+"0", "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"test-topic", "mytopic"}))
|
|
||||||
|
|
||||||
// But with a different endpoint it should fail
|
|
||||||
require.Equal(t, webpush.ErrWebPushTooManySubscriptions, store.UpsertSubscription(testWebPushEndpoint+"11", "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"test-topic", "mytopic"}))
|
|
||||||
|
|
||||||
// But with a different IP address it should be fine again
|
|
||||||
require.Nil(t, store.UpsertSubscription(testWebPushEndpoint+"99", "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("9.9.9.9"), []string{"test-topic", "mytopic"}))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSQLiteStore_UpsertSubscription_UpdateTopics(t *testing.T) {
|
func TestSQLiteStore_UpsertSubscription_UpdateTopics(t *testing.T) {
|
||||||
store := newTestSQLiteStore(t)
|
testStoreUpsertSubscription_UpdateTopics(t, newTestSQLiteStore(t))
|
||||||
defer store.Close()
|
|
||||||
|
|
||||||
// Insert subscription with two topics, and another with one topic
|
|
||||||
require.Nil(t, store.UpsertSubscription(testWebPushEndpoint+"0", "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"topic1", "topic2"}))
|
|
||||||
require.Nil(t, store.UpsertSubscription(testWebPushEndpoint+"1", "auth-key", "p256dh-key", "", netip.MustParseAddr("9.9.9.9"), []string{"topic1"}))
|
|
||||||
|
|
||||||
subs, err := store.SubscriptionsForTopic("topic1")
|
|
||||||
require.Nil(t, err)
|
|
||||||
require.Len(t, subs, 2)
|
|
||||||
require.Equal(t, testWebPushEndpoint+"0", subs[0].Endpoint)
|
|
||||||
require.Equal(t, testWebPushEndpoint+"1", subs[1].Endpoint)
|
|
||||||
|
|
||||||
subs, err = store.SubscriptionsForTopic("topic2")
|
|
||||||
require.Nil(t, err)
|
|
||||||
require.Len(t, subs, 1)
|
|
||||||
require.Equal(t, testWebPushEndpoint+"0", subs[0].Endpoint)
|
|
||||||
|
|
||||||
// Update the first subscription to have only one topic
|
|
||||||
require.Nil(t, store.UpsertSubscription(testWebPushEndpoint+"0", "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"topic1"}))
|
|
||||||
|
|
||||||
subs, err = store.SubscriptionsForTopic("topic1")
|
|
||||||
require.Nil(t, err)
|
|
||||||
require.Len(t, subs, 2)
|
|
||||||
require.Equal(t, testWebPushEndpoint+"0", subs[0].Endpoint)
|
|
||||||
|
|
||||||
subs, err = store.SubscriptionsForTopic("topic2")
|
|
||||||
require.Nil(t, err)
|
|
||||||
require.Len(t, subs, 0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSQLiteStore_RemoveSubscriptionsByEndpoint(t *testing.T) {
|
func TestSQLiteStore_RemoveSubscriptionsByEndpoint(t *testing.T) {
|
||||||
store := newTestSQLiteStore(t)
|
testStoreRemoveSubscriptionsByEndpoint(t, newTestSQLiteStore(t))
|
||||||
defer store.Close()
|
|
||||||
|
|
||||||
// Insert subscription with two topics
|
|
||||||
require.Nil(t, store.UpsertSubscription(testWebPushEndpoint, "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"topic1", "topic2"}))
|
|
||||||
subs, err := store.SubscriptionsForTopic("topic1")
|
|
||||||
require.Nil(t, err)
|
|
||||||
require.Len(t, subs, 1)
|
|
||||||
|
|
||||||
// And remove it again
|
|
||||||
require.Nil(t, store.RemoveSubscriptionsByEndpoint(testWebPushEndpoint))
|
|
||||||
subs, err = store.SubscriptionsForTopic("topic1")
|
|
||||||
require.Nil(t, err)
|
|
||||||
require.Len(t, subs, 0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSQLiteStore_RemoveSubscriptionsByUserID(t *testing.T) {
|
func TestSQLiteStore_RemoveSubscriptionsByUserID(t *testing.T) {
|
||||||
store := newTestSQLiteStore(t)
|
testStoreRemoveSubscriptionsByUserID(t, newTestSQLiteStore(t))
|
||||||
defer store.Close()
|
|
||||||
|
|
||||||
// Insert subscription with two topics
|
|
||||||
require.Nil(t, store.UpsertSubscription(testWebPushEndpoint, "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"topic1", "topic2"}))
|
|
||||||
subs, err := store.SubscriptionsForTopic("topic1")
|
|
||||||
require.Nil(t, err)
|
|
||||||
require.Len(t, subs, 1)
|
|
||||||
|
|
||||||
// And remove it again
|
|
||||||
require.Nil(t, store.RemoveSubscriptionsByUserID("u_1234"))
|
|
||||||
subs, err = store.SubscriptionsForTopic("topic1")
|
|
||||||
require.Nil(t, err)
|
|
||||||
require.Len(t, subs, 0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSQLiteStore_RemoveSubscriptionsByUserID_Empty(t *testing.T) {
|
func TestSQLiteStore_RemoveSubscriptionsByUserID_Empty(t *testing.T) {
|
||||||
store := newTestSQLiteStore(t)
|
testStoreRemoveSubscriptionsByUserID_Empty(t, newTestSQLiteStore(t))
|
||||||
defer store.Close()
|
|
||||||
require.Equal(t, webpush.ErrWebPushUserIDCannotBeEmpty, store.RemoveSubscriptionsByUserID(""))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSQLiteStore_MarkExpiryWarningSent(t *testing.T) {
|
func TestSQLiteStore_MarkExpiryWarningSent(t *testing.T) {
|
||||||
store := newTestSQLiteStore(t)
|
store := newTestSQLiteStore(t)
|
||||||
defer store.Close()
|
testStoreMarkExpiryWarningSent(t, store, store.SetSubscriptionUpdatedAt)
|
||||||
|
|
||||||
// Insert subscription with two topics
|
|
||||||
require.Nil(t, store.UpsertSubscription(testWebPushEndpoint, "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"topic1", "topic2"}))
|
|
||||||
subs, err := store.SubscriptionsForTopic("topic1")
|
|
||||||
require.Nil(t, err)
|
|
||||||
require.Len(t, subs, 1)
|
|
||||||
|
|
||||||
// Mark them as warning sent
|
|
||||||
require.Nil(t, store.MarkExpiryWarningSent(subs))
|
|
||||||
|
|
||||||
rows, err := store.DB().Query("SELECT endpoint FROM subscription WHERE warned_at > 0")
|
|
||||||
require.Nil(t, err)
|
|
||||||
defer rows.Close()
|
|
||||||
var endpoint string
|
|
||||||
require.True(t, rows.Next())
|
|
||||||
require.Nil(t, rows.Scan(&endpoint))
|
|
||||||
require.Nil(t, err)
|
|
||||||
require.Equal(t, testWebPushEndpoint, endpoint)
|
|
||||||
require.False(t, rows.Next())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSQLiteStore_SubscriptionsExpiring(t *testing.T) {
|
func TestSQLiteStore_SubscriptionsExpiring(t *testing.T) {
|
||||||
store := newTestSQLiteStore(t)
|
store := newTestSQLiteStore(t)
|
||||||
defer store.Close()
|
testStoreSubscriptionsExpiring(t, store, store.SetSubscriptionUpdatedAt)
|
||||||
|
|
||||||
// Insert subscription with two topics
|
|
||||||
require.Nil(t, store.UpsertSubscription(testWebPushEndpoint, "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"topic1", "topic2"}))
|
|
||||||
subs, err := store.SubscriptionsForTopic("topic1")
|
|
||||||
require.Nil(t, err)
|
|
||||||
require.Len(t, subs, 1)
|
|
||||||
|
|
||||||
// Fake-mark them as soon-to-expire
|
|
||||||
_, err = store.DB().Exec("UPDATE subscription SET updated_at = ? WHERE endpoint = ?", time.Now().Add(-8*24*time.Hour).Unix(), testWebPushEndpoint)
|
|
||||||
require.Nil(t, err)
|
|
||||||
|
|
||||||
// Should not be cleaned up yet
|
|
||||||
require.Nil(t, store.RemoveExpiredSubscriptions(9*24*time.Hour))
|
|
||||||
|
|
||||||
// Run expiration
|
|
||||||
subs, err = store.SubscriptionsExpiring(7 * 24 * time.Hour)
|
|
||||||
require.Nil(t, err)
|
|
||||||
require.Len(t, subs, 1)
|
|
||||||
require.Equal(t, testWebPushEndpoint, subs[0].Endpoint)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSQLiteStore_RemoveExpiredSubscriptions(t *testing.T) {
|
func TestSQLiteStore_RemoveExpiredSubscriptions(t *testing.T) {
|
||||||
store := newTestSQLiteStore(t)
|
store := newTestSQLiteStore(t)
|
||||||
defer store.Close()
|
testStoreRemoveExpiredSubscriptions(t, store, store.SetSubscriptionUpdatedAt)
|
||||||
|
|
||||||
// Insert subscription with two topics
|
|
||||||
require.Nil(t, store.UpsertSubscription(testWebPushEndpoint, "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"topic1", "topic2"}))
|
|
||||||
subs, err := store.SubscriptionsForTopic("topic1")
|
|
||||||
require.Nil(t, err)
|
|
||||||
require.Len(t, subs, 1)
|
|
||||||
|
|
||||||
// Fake-mark them as expired
|
|
||||||
_, err = store.DB().Exec("UPDATE subscription SET updated_at = ? WHERE endpoint = ?", time.Now().Add(-10*24*time.Hour).Unix(), testWebPushEndpoint)
|
|
||||||
require.Nil(t, err)
|
|
||||||
|
|
||||||
// Run expiration
|
|
||||||
require.Nil(t, store.RemoveExpiredSubscriptions(9*24*time.Hour))
|
|
||||||
|
|
||||||
// List again, should be 0
|
|
||||||
subs, err = store.SubscriptionsForTopic("topic1")
|
|
||||||
require.Nil(t, err)
|
|
||||||
require.Len(t, subs, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func newTestSQLiteStore(t *testing.T) *webpush.SQLiteStore {
|
|
||||||
store, err := webpush.NewSQLiteStore(filepath.Join(t.TempDir(), "webpush.db"), "")
|
|
||||||
require.Nil(t, err)
|
|
||||||
return store
|
|
||||||
}
|
}
|
||||||
|
|||||||
169
webpush/store_test.go
Normal file
169
webpush/store_test.go
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
package webpush_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/netip"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"heckel.io/ntfy/v2/webpush"
|
||||||
|
)
|
||||||
|
|
||||||
|
const testWebPushEndpoint = "https://updates.push.services.mozilla.com/wpush/v1/AAABBCCCDDEEEFFF"
|
||||||
|
|
||||||
|
func testStoreUpsertSubscription_SubscriptionsForTopic(t *testing.T, store webpush.Store) {
|
||||||
|
require.Nil(t, store.UpsertSubscription(testWebPushEndpoint, "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"test-topic", "mytopic"}))
|
||||||
|
|
||||||
|
subs, err := store.SubscriptionsForTopic("test-topic")
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Len(t, subs, 1)
|
||||||
|
require.Equal(t, subs[0].Endpoint, testWebPushEndpoint)
|
||||||
|
require.Equal(t, subs[0].P256dh, "p256dh-key")
|
||||||
|
require.Equal(t, subs[0].Auth, "auth-key")
|
||||||
|
require.Equal(t, subs[0].UserID, "u_1234")
|
||||||
|
|
||||||
|
subs2, err := store.SubscriptionsForTopic("mytopic")
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Len(t, subs2, 1)
|
||||||
|
require.Equal(t, subs[0].Endpoint, subs2[0].Endpoint)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testStoreUpsertSubscription_SubscriberIPLimitReached(t *testing.T, store webpush.Store) {
|
||||||
|
// Insert 10 subscriptions with the same IP address
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
endpoint := fmt.Sprintf(testWebPushEndpoint+"%d", i)
|
||||||
|
require.Nil(t, store.UpsertSubscription(endpoint, "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"test-topic", "mytopic"}))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Another one for the same endpoint should be fine
|
||||||
|
require.Nil(t, store.UpsertSubscription(testWebPushEndpoint+"0", "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"test-topic", "mytopic"}))
|
||||||
|
|
||||||
|
// But with a different endpoint it should fail
|
||||||
|
require.Equal(t, webpush.ErrWebPushTooManySubscriptions, store.UpsertSubscription(testWebPushEndpoint+"11", "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"test-topic", "mytopic"}))
|
||||||
|
|
||||||
|
// But with a different IP address it should be fine again
|
||||||
|
require.Nil(t, store.UpsertSubscription(testWebPushEndpoint+"99", "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("9.9.9.9"), []string{"test-topic", "mytopic"}))
|
||||||
|
}
|
||||||
|
|
||||||
|
func testStoreUpsertSubscription_UpdateTopics(t *testing.T, store webpush.Store) {
|
||||||
|
// Insert subscription with two topics, and another with one topic
|
||||||
|
require.Nil(t, store.UpsertSubscription(testWebPushEndpoint+"0", "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"topic1", "topic2"}))
|
||||||
|
require.Nil(t, store.UpsertSubscription(testWebPushEndpoint+"1", "auth-key", "p256dh-key", "", netip.MustParseAddr("9.9.9.9"), []string{"topic1"}))
|
||||||
|
|
||||||
|
subs, err := store.SubscriptionsForTopic("topic1")
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Len(t, subs, 2)
|
||||||
|
require.Equal(t, testWebPushEndpoint+"0", subs[0].Endpoint)
|
||||||
|
require.Equal(t, testWebPushEndpoint+"1", subs[1].Endpoint)
|
||||||
|
|
||||||
|
subs, err = store.SubscriptionsForTopic("topic2")
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Len(t, subs, 1)
|
||||||
|
require.Equal(t, testWebPushEndpoint+"0", subs[0].Endpoint)
|
||||||
|
|
||||||
|
// Update the first subscription to have only one topic
|
||||||
|
require.Nil(t, store.UpsertSubscription(testWebPushEndpoint+"0", "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"topic1"}))
|
||||||
|
|
||||||
|
subs, err = store.SubscriptionsForTopic("topic1")
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Len(t, subs, 2)
|
||||||
|
require.Equal(t, testWebPushEndpoint+"0", subs[0].Endpoint)
|
||||||
|
|
||||||
|
subs, err = store.SubscriptionsForTopic("topic2")
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Len(t, subs, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testStoreRemoveSubscriptionsByEndpoint(t *testing.T, store webpush.Store) {
|
||||||
|
// Insert subscription with two topics
|
||||||
|
require.Nil(t, store.UpsertSubscription(testWebPushEndpoint, "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"topic1", "topic2"}))
|
||||||
|
subs, err := store.SubscriptionsForTopic("topic1")
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Len(t, subs, 1)
|
||||||
|
|
||||||
|
// And remove it again
|
||||||
|
require.Nil(t, store.RemoveSubscriptionsByEndpoint(testWebPushEndpoint))
|
||||||
|
subs, err = store.SubscriptionsForTopic("topic1")
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Len(t, subs, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testStoreRemoveSubscriptionsByUserID(t *testing.T, store webpush.Store) {
|
||||||
|
// Insert subscription with two topics
|
||||||
|
require.Nil(t, store.UpsertSubscription(testWebPushEndpoint, "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"topic1", "topic2"}))
|
||||||
|
subs, err := store.SubscriptionsForTopic("topic1")
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Len(t, subs, 1)
|
||||||
|
|
||||||
|
// And remove it again
|
||||||
|
require.Nil(t, store.RemoveSubscriptionsByUserID("u_1234"))
|
||||||
|
subs, err = store.SubscriptionsForTopic("topic1")
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Len(t, subs, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testStoreRemoveSubscriptionsByUserID_Empty(t *testing.T, store webpush.Store) {
|
||||||
|
require.Equal(t, webpush.ErrWebPushUserIDCannotBeEmpty, store.RemoveSubscriptionsByUserID(""))
|
||||||
|
}
|
||||||
|
|
||||||
|
func testStoreMarkExpiryWarningSent(t *testing.T, store webpush.Store, setUpdatedAt func(endpoint string, updatedAt int64) error) {
|
||||||
|
// Insert subscription with two topics
|
||||||
|
require.Nil(t, store.UpsertSubscription(testWebPushEndpoint, "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"topic1", "topic2"}))
|
||||||
|
|
||||||
|
// Set updated_at to the past so it shows up as expiring
|
||||||
|
require.Nil(t, setUpdatedAt(testWebPushEndpoint, time.Now().Add(-8*24*time.Hour).Unix()))
|
||||||
|
|
||||||
|
// Verify subscription appears in expiring list (warned_at == 0)
|
||||||
|
subs, err := store.SubscriptionsExpiring(7 * 24 * time.Hour)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Len(t, subs, 1)
|
||||||
|
require.Equal(t, testWebPushEndpoint, subs[0].Endpoint)
|
||||||
|
|
||||||
|
// Mark them as warning sent
|
||||||
|
require.Nil(t, store.MarkExpiryWarningSent(subs))
|
||||||
|
|
||||||
|
// Verify subscription no longer appears in expiring list (warned_at > 0)
|
||||||
|
subs, err = store.SubscriptionsExpiring(7 * 24 * time.Hour)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Len(t, subs, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testStoreSubscriptionsExpiring(t *testing.T, store webpush.Store, setUpdatedAt func(endpoint string, updatedAt int64) error) {
|
||||||
|
// Insert subscription with two topics
|
||||||
|
require.Nil(t, store.UpsertSubscription(testWebPushEndpoint, "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"topic1", "topic2"}))
|
||||||
|
subs, err := store.SubscriptionsForTopic("topic1")
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Len(t, subs, 1)
|
||||||
|
|
||||||
|
// Fake-mark them as soon-to-expire
|
||||||
|
require.Nil(t, setUpdatedAt(testWebPushEndpoint, time.Now().Add(-8*24*time.Hour).Unix()))
|
||||||
|
|
||||||
|
// Should not be cleaned up yet
|
||||||
|
require.Nil(t, store.RemoveExpiredSubscriptions(9*24*time.Hour))
|
||||||
|
|
||||||
|
// Run expiration
|
||||||
|
subs, err = store.SubscriptionsExpiring(7 * 24 * time.Hour)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Len(t, subs, 1)
|
||||||
|
require.Equal(t, testWebPushEndpoint, subs[0].Endpoint)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testStoreRemoveExpiredSubscriptions(t *testing.T, store webpush.Store, setUpdatedAt func(endpoint string, updatedAt int64) error) {
|
||||||
|
// Insert subscription with two topics
|
||||||
|
require.Nil(t, store.UpsertSubscription(testWebPushEndpoint, "auth-key", "p256dh-key", "u_1234", netip.MustParseAddr("1.2.3.4"), []string{"topic1", "topic2"}))
|
||||||
|
subs, err := store.SubscriptionsForTopic("topic1")
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Len(t, subs, 1)
|
||||||
|
|
||||||
|
// Fake-mark them as expired
|
||||||
|
require.Nil(t, setUpdatedAt(testWebPushEndpoint, time.Now().Add(-10*24*time.Hour).Unix()))
|
||||||
|
|
||||||
|
// Run expiration
|
||||||
|
require.Nil(t, store.RemoveExpiredSubscriptions(9*24*time.Hour))
|
||||||
|
|
||||||
|
// List again, should be 0
|
||||||
|
subs, err = store.SubscriptionsForTopic("topic1")
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Len(t, subs, 0)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user