status-go/protocol/pushnotificationclient/persistence_test.go

329 lines
10 KiB
Go
Raw Normal View History

2020-07-22 07:41:40 +00:00
package pushnotificationclient
import (
2020-07-15 08:22:43 +00:00
"crypto/ecdsa"
"testing"
2020-07-20 10:01:42 +00:00
"time"
"github.com/golang/protobuf/proto"
"github.com/stretchr/testify/suite"
"github.com/status-im/status-go/appdatabase"
"github.com/status-im/status-go/eth-node/crypto"
"github.com/status-im/status-go/protocol/common"
"github.com/status-im/status-go/protocol/protobuf"
"github.com/status-im/status-go/protocol/sqlite"
"github.com/status-im/status-go/t/helpers"
)
2020-07-22 07:41:40 +00:00
const (
testAccessToken = "token"
installationID1 = "installation-id-1"
installationID2 = "installation-id-2"
installationID3 = "installation-id-3"
)
func TestSQLitePersistenceSuite(t *testing.T) {
suite.Run(t, new(SQLitePersistenceSuite))
}
type SQLitePersistenceSuite struct {
suite.Suite
persistence *Persistence
}
func (s *SQLitePersistenceSuite) SetupTest() {
db, err := helpers.SetupTestMemorySQLDB(appdatabase.DbInitializer{})
s.Require().NoError(err)
err = sqlite.Migrate(db)
s.Require().NoError(err)
s.persistence = NewPersistence(db)
}
func (s *SQLitePersistenceSuite) TestSaveAndRetrieveServer() {
key, err := crypto.GenerateKey()
s.Require().NoError(err)
server := &PushNotificationServer{
2020-07-10 07:45:40 +00:00
PublicKey: &key.PublicKey,
Registered: true,
RegisteredAt: 1,
2020-07-22 07:41:40 +00:00
AccessToken: testAccessToken,
}
s.Require().NoError(s.persistence.UpsertServer(server))
retrievedServers, err := s.persistence.GetServers()
s.Require().NoError(err)
s.Require().Len(retrievedServers, 1)
2020-07-10 07:45:40 +00:00
s.Require().True(retrievedServers[0].Registered)
s.Require().Equal(int64(1), retrievedServers[0].RegisteredAt)
s.Require().True(common.IsPubKeyEqual(retrievedServers[0].PublicKey, &key.PublicKey))
2020-07-22 07:41:40 +00:00
s.Require().Equal(testAccessToken, retrievedServers[0].AccessToken)
2020-07-10 07:45:40 +00:00
server.Registered = false
server.RegisteredAt = 2
s.Require().NoError(s.persistence.UpsertServer(server))
retrievedServers, err = s.persistence.GetServers()
s.Require().NoError(err)
s.Require().Len(retrievedServers, 1)
2020-07-10 07:45:40 +00:00
s.Require().False(retrievedServers[0].Registered)
s.Require().Equal(int64(2), retrievedServers[0].RegisteredAt)
s.Require().True(common.IsPubKeyEqual(retrievedServers[0].PublicKey, &key.PublicKey))
}
func (s *SQLitePersistenceSuite) TestSaveAndRetrieveInfo() {
key1, err := crypto.GenerateKey()
s.Require().NoError(err)
key2, err := crypto.GenerateKey()
s.Require().NoError(err)
serverKey, err := crypto.GenerateKey()
s.Require().NoError(err)
infos := []*PushNotificationInfo{
{
PublicKey: &key1.PublicKey,
ServerPublicKey: &serverKey.PublicKey,
RetrievedAt: 1,
2020-07-17 11:41:49 +00:00
Version: 1,
2020-07-22 07:41:40 +00:00
AccessToken: testAccessToken,
InstallationID: installationID1,
},
{
PublicKey: &key1.PublicKey,
ServerPublicKey: &serverKey.PublicKey,
RetrievedAt: 1,
2020-07-17 11:41:49 +00:00
Version: 1,
2020-07-22 07:41:40 +00:00
AccessToken: testAccessToken,
InstallationID: installationID2,
},
{
PublicKey: &key1.PublicKey,
ServerPublicKey: &serverKey.PublicKey,
RetrievedAt: 1,
2020-07-17 11:41:49 +00:00
Version: 1,
2020-07-22 07:41:40 +00:00
AccessToken: testAccessToken,
InstallationID: installationID3,
},
{
PublicKey: &key2.PublicKey,
ServerPublicKey: &serverKey.PublicKey,
RetrievedAt: 1,
2020-07-17 11:41:49 +00:00
Version: 1,
2020-07-22 07:41:40 +00:00
AccessToken: testAccessToken,
InstallationID: installationID1,
},
{
PublicKey: &key2.PublicKey,
ServerPublicKey: &serverKey.PublicKey,
RetrievedAt: 1,
2020-07-17 11:41:49 +00:00
Version: 1,
2020-07-22 07:41:40 +00:00
AccessToken: testAccessToken,
InstallationID: installationID2,
},
{
PublicKey: &key2.PublicKey,
ServerPublicKey: &serverKey.PublicKey,
RetrievedAt: 1,
2020-07-17 11:41:49 +00:00
Version: 1,
2020-07-22 07:41:40 +00:00
AccessToken: testAccessToken,
InstallationID: installationID3,
},
}
s.Require().NoError(s.persistence.SavePushNotificationInfo(infos))
retrievedInfos, err := s.persistence.GetPushNotificationInfo(&key1.PublicKey, []string{installationID1, installationID2})
s.Require().NoError(err)
s.Require().Len(retrievedInfos, 2)
}
2020-07-17 11:41:49 +00:00
func (s *SQLitePersistenceSuite) TestSaveAndRetrieveInfoWithVersion() {
installationID := "installation-id-1"
key, err := crypto.GenerateKey()
s.Require().NoError(err)
serverKey1, err := crypto.GenerateKey()
s.Require().NoError(err)
serverKey2, err := crypto.GenerateKey()
s.Require().NoError(err)
infos := []*PushNotificationInfo{
{
PublicKey: &key.PublicKey,
ServerPublicKey: &serverKey1.PublicKey,
RetrievedAt: 1,
Version: 1,
2020-07-22 07:41:40 +00:00
AccessToken: testAccessToken,
2020-07-17 11:41:49 +00:00
InstallationID: installationID,
},
{
PublicKey: &key.PublicKey,
ServerPublicKey: &serverKey2.PublicKey,
RetrievedAt: 1,
Version: 1,
2020-07-22 07:41:40 +00:00
AccessToken: testAccessToken,
2020-07-17 11:41:49 +00:00
InstallationID: installationID,
},
}
s.Require().NoError(s.persistence.SavePushNotificationInfo(infos))
retrievedInfos, err := s.persistence.GetPushNotificationInfo(&key.PublicKey, []string{installationID})
s.Require().NoError(err)
// We should retrieve both
s.Require().Len(retrievedInfos, 2)
s.Require().Equal(uint64(1), retrievedInfos[0].Version)
// Bump version
infos[0].Version = 2
s.Require().NoError(s.persistence.SavePushNotificationInfo(infos))
retrievedInfos, err = s.persistence.GetPushNotificationInfo(&key.PublicKey, []string{installationID})
s.Require().NoError(err)
// Only one should be retrieved now
s.Require().Len(retrievedInfos, 1)
s.Require().Equal(uint64(2), retrievedInfos[0].Version)
// Lower version
infos[0].Version = 1
s.Require().NoError(s.persistence.SavePushNotificationInfo(infos))
retrievedInfos, err = s.persistence.GetPushNotificationInfo(&key.PublicKey, []string{installationID})
s.Require().NoError(err)
s.Require().Len(retrievedInfos, 1)
s.Require().Equal(uint64(2), retrievedInfos[0].Version)
}
2020-07-20 10:01:42 +00:00
func (s *SQLitePersistenceSuite) TestNotifiedOnAndUpdateNotificationResponse() {
key, err := crypto.GenerateKey()
s.Require().NoError(err)
installationID := "installation-id"
messageID := []byte("message-id")
sentNotification := &SentNotification{
PublicKey: &key.PublicKey,
InstallationID: installationID,
MessageID: messageID,
LastTriedAt: time.Now().Unix(),
2020-07-20 10:01:42 +00:00
}
s.Require().NoError(s.persistence.UpsertSentNotification(sentNotification))
2020-07-20 10:01:42 +00:00
retrievedNotification, err := s.persistence.GetSentNotification(sentNotification.HashedPublicKey(), installationID, messageID)
s.Require().NoError(err)
s.Require().Equal(sentNotification, retrievedNotification)
retriableNotifications, err := s.persistence.GetRetriablePushNotifications()
s.Require().NoError(err)
s.Require().Len(retriableNotifications, 0)
2020-07-20 10:01:42 +00:00
response := &protobuf.PushNotificationReport{
Success: false,
Error: protobuf.PushNotificationReport_WRONG_TOKEN,
PublicKey: sentNotification.HashedPublicKey(),
InstallationId: installationID,
}
s.Require().NoError(s.persistence.UpdateNotificationResponse(messageID, response))
// This notification should be retriable
retriableNotifications, err = s.persistence.GetRetriablePushNotifications()
s.Require().NoError(err)
s.Require().Len(retriableNotifications, 1)
2020-07-20 10:01:42 +00:00
sentNotification.Error = protobuf.PushNotificationReport_WRONG_TOKEN
retrievedNotification, err = s.persistence.GetSentNotification(sentNotification.HashedPublicKey(), installationID, messageID)
s.Require().NoError(err)
s.Require().Equal(sentNotification, retrievedNotification)
// Update with a successful notification
response = &protobuf.PushNotificationReport{
Success: true,
PublicKey: sentNotification.HashedPublicKey(),
InstallationId: installationID,
}
s.Require().NoError(s.persistence.UpdateNotificationResponse(messageID, response))
sentNotification.Success = true
sentNotification.Error = protobuf.PushNotificationReport_UNKNOWN_ERROR_TYPE
retrievedNotification, err = s.persistence.GetSentNotification(sentNotification.HashedPublicKey(), installationID, messageID)
s.Require().NoError(err)
s.Require().Equal(sentNotification, retrievedNotification)
// This notification should not be retriable
retriableNotifications, err = s.persistence.GetRetriablePushNotifications()
s.Require().NoError(err)
s.Require().Len(retriableNotifications, 0)
2020-07-20 10:01:42 +00:00
// Update with a unsuccessful notification, it should be ignored
response = &protobuf.PushNotificationReport{
Success: false,
Error: protobuf.PushNotificationReport_WRONG_TOKEN,
PublicKey: sentNotification.HashedPublicKey(),
InstallationId: installationID,
}
s.Require().NoError(s.persistence.UpdateNotificationResponse(messageID, response))
sentNotification.Success = true
sentNotification.Error = protobuf.PushNotificationReport_UNKNOWN_ERROR_TYPE
retrievedNotification, err = s.persistence.GetSentNotification(sentNotification.HashedPublicKey(), installationID, messageID)
s.Require().NoError(err)
s.Require().Equal(sentNotification, retrievedNotification)
}
func (s *SQLitePersistenceSuite) TestSaveAndRetrieveRegistration() {
// Try with nil first
2020-07-15 08:22:43 +00:00
retrievedRegistration, retrievedContactIDs, err := s.persistence.GetLastPushNotificationRegistration()
s.Require().NoError(err)
s.Require().Nil(retrievedRegistration)
2020-07-15 08:22:43 +00:00
s.Require().Nil(retrievedContactIDs)
// Save & retrieve registration
registration := &protobuf.PushNotificationRegistration{
AccessToken: "test",
Version: 3,
}
2020-07-15 08:22:43 +00:00
key1, err := crypto.GenerateKey()
s.Require().NoError(err)
key2, err := crypto.GenerateKey()
s.Require().NoError(err)
key3, err := crypto.GenerateKey()
s.Require().NoError(err)
publicKeys := []*ecdsa.PublicKey{&key1.PublicKey, &key2.PublicKey}
s.Require().NoError(s.persistence.SaveLastPushNotificationRegistration(registration, publicKeys))
retrievedRegistration, retrievedContactIDs, err = s.persistence.GetLastPushNotificationRegistration()
s.Require().NoError(err)
s.Require().True(proto.Equal(registration, retrievedRegistration))
2020-07-15 08:22:43 +00:00
s.Require().Equal(publicKeys, retrievedContactIDs)
// Override and retrieve
registration.Version = 5
2020-07-15 08:22:43 +00:00
publicKeys = append(publicKeys, &key3.PublicKey)
s.Require().NoError(s.persistence.SaveLastPushNotificationRegistration(registration, publicKeys))
retrievedRegistration, retrievedContactIDs, err = s.persistence.GetLastPushNotificationRegistration()
s.Require().NoError(err)
s.Require().True(proto.Equal(registration, retrievedRegistration))
2020-07-15 08:22:43 +00:00
s.Require().Equal(publicKeys, retrievedContactIDs)
}