2023-11-19 17:29:17 +00:00
|
|
|
package walletconnect
|
|
|
|
|
|
|
|
import (
|
|
|
|
"strconv"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"database/sql"
|
|
|
|
|
2024-05-23 12:19:00 +00:00
|
|
|
"github.com/status-im/status-go/services/wallet/common"
|
2023-11-19 17:29:17 +00:00
|
|
|
"github.com/status-im/status-go/t/helpers"
|
|
|
|
"github.com/status-im/status-go/walletdatabase"
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
)
|
|
|
|
|
|
|
|
func setupTestDB(t *testing.T) (db *sql.DB, close func()) {
|
|
|
|
db, err := helpers.SetupTestMemorySQLDB(walletdatabase.DbInitializer{})
|
|
|
|
require.NoError(t, err)
|
|
|
|
return db, func() {
|
|
|
|
require.NoError(t, db.Close())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-23 12:19:00 +00:00
|
|
|
type urlOverride *string
|
|
|
|
type timestampOverride *int64
|
|
|
|
|
|
|
|
// testSession will override defaults for the fields that are not null
|
|
|
|
type testSession struct {
|
|
|
|
url urlOverride
|
|
|
|
created timestampOverride
|
|
|
|
expiry timestampOverride
|
|
|
|
disconnected *bool
|
|
|
|
testChains *bool
|
|
|
|
}
|
|
|
|
|
|
|
|
const testDappUrl = "https://test.url/"
|
|
|
|
|
2023-12-13 14:05:55 +00:00
|
|
|
// generateTestData generates alternative disconnected and active sessions starting with the active one
|
2024-05-23 12:19:00 +00:00
|
|
|
// timestamps start with 1234567890 and increase by 1 for each session
|
|
|
|
// all sessions will share the same two pairing sessions (roll over after index 1)
|
|
|
|
// testChains is false if not overridden
|
|
|
|
func generateTestData(sessions []testSession) []DBSession {
|
|
|
|
res := make([]DBSession, len(sessions))
|
|
|
|
pairingIdx := 0
|
|
|
|
for i := 0; i < len(res); i++ {
|
2023-11-19 17:29:17 +00:00
|
|
|
strI := strconv.Itoa(i)
|
2024-05-23 12:19:00 +00:00
|
|
|
if i%2 == 0 {
|
|
|
|
pairingIdx++
|
|
|
|
}
|
|
|
|
pairingIdxStr := strconv.Itoa(pairingIdx)
|
|
|
|
|
|
|
|
s := sessions[i]
|
|
|
|
|
|
|
|
url := testDappUrl + strI
|
|
|
|
if s.url != nil {
|
|
|
|
url = *s.url
|
|
|
|
}
|
|
|
|
|
|
|
|
createdTimestamp := 1234567890 + int64(i)
|
|
|
|
if s.created != nil {
|
|
|
|
createdTimestamp = *s.created
|
|
|
|
}
|
|
|
|
|
|
|
|
expiryTimestamp := createdTimestamp + 1000 + int64(i)
|
|
|
|
if s.expiry != nil {
|
|
|
|
expiryTimestamp = *s.expiry
|
|
|
|
}
|
|
|
|
|
|
|
|
disconnected := (i % 2) != 0
|
|
|
|
if s.disconnected != nil {
|
|
|
|
disconnected = *s.disconnected
|
|
|
|
}
|
|
|
|
|
|
|
|
testChains := false
|
|
|
|
if s.testChains != nil {
|
|
|
|
testChains = *s.testChains
|
2023-12-13 14:05:55 +00:00
|
|
|
}
|
2024-05-23 12:19:00 +00:00
|
|
|
|
|
|
|
res[i] = DBSession{
|
|
|
|
Topic: Topic(strI + "aaaaaa1234567890"),
|
|
|
|
Disconnected: disconnected,
|
|
|
|
SessionJSON: "{}",
|
|
|
|
Expiry: expiryTimestamp,
|
|
|
|
CreatedTimestamp: createdTimestamp,
|
|
|
|
PairingTopic: Topic(pairingIdxStr + "bbbbbb1234567890"),
|
|
|
|
TestChains: testChains,
|
|
|
|
DBDApp: DBDApp{
|
|
|
|
URL: url,
|
|
|
|
Name: "TestApp" + strI,
|
|
|
|
IconURL: "https://test.icon" + strI,
|
|
|
|
},
|
2023-11-19 17:29:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return res
|
|
|
|
}
|
|
|
|
|
2024-05-23 12:19:00 +00:00
|
|
|
func insertTestData(t *testing.T, db *sql.DB, entries []DBSession) {
|
2023-11-19 17:29:17 +00:00
|
|
|
for _, entry := range entries {
|
2023-12-13 14:05:55 +00:00
|
|
|
err := UpsertSession(db, entry)
|
2023-11-19 17:29:17 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-13 14:05:55 +00:00
|
|
|
func TestInsertUpdateAndGetSession(t *testing.T) {
|
2023-11-19 17:29:17 +00:00
|
|
|
db, close := setupTestDB(t)
|
|
|
|
defer close()
|
|
|
|
|
2024-05-23 12:19:00 +00:00
|
|
|
entry := generateTestData(make([]testSession, 1))[0]
|
2023-12-13 14:05:55 +00:00
|
|
|
err := UpsertSession(db, entry)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
retrievedSession, err := GetSessionByTopic(db, entry.Topic)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
require.Equal(t, entry, *retrievedSession)
|
|
|
|
|
2024-05-23 12:19:00 +00:00
|
|
|
updatedEntry := entry
|
|
|
|
updatedEntry.Disconnected = true
|
|
|
|
updatedEntry.Expiry = 1111111111
|
|
|
|
err = UpsertSession(db, updatedEntry)
|
2023-12-13 14:05:55 +00:00
|
|
|
|
2023-11-19 17:29:17 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
2024-05-23 12:19:00 +00:00
|
|
|
retrievedSession, err = GetSessionByTopic(db, updatedEntry.Topic)
|
2023-12-13 14:05:55 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
2024-05-23 12:19:00 +00:00
|
|
|
require.Equal(t, updatedEntry, *retrievedSession)
|
2023-12-13 14:05:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestInsertAndGetSessionsByPairingTopic(t *testing.T) {
|
|
|
|
db, close := setupTestDB(t)
|
|
|
|
defer close()
|
|
|
|
|
2024-05-23 12:19:00 +00:00
|
|
|
generatedSessions := generateTestData(make([]testSession, 4))
|
2023-12-13 14:05:55 +00:00
|
|
|
for _, session := range generatedSessions {
|
|
|
|
err := UpsertSession(db, session)
|
|
|
|
require.NoError(t, err)
|
|
|
|
}
|
|
|
|
|
2024-05-23 12:19:00 +00:00
|
|
|
retrievedSessions, err := GetSessionsByPairingTopic(db, generatedSessions[2].Topic)
|
2023-11-19 17:29:17 +00:00
|
|
|
require.NoError(t, err)
|
2023-12-13 14:05:55 +00:00
|
|
|
require.Equal(t, 0, len(retrievedSessions))
|
2023-11-19 17:29:17 +00:00
|
|
|
|
2024-05-23 12:19:00 +00:00
|
|
|
retrievedSessions, err = GetSessionsByPairingTopic(db, generatedSessions[2].PairingTopic)
|
2023-12-13 14:05:55 +00:00
|
|
|
require.NoError(t, err)
|
2024-05-23 12:19:00 +00:00
|
|
|
require.Equal(t, 2, len(retrievedSessions))
|
2023-12-13 14:05:55 +00:00
|
|
|
|
2024-05-23 12:19:00 +00:00
|
|
|
for i := 2; i < 4; i++ {
|
2023-12-13 14:05:55 +00:00
|
|
|
found := false
|
|
|
|
for _, session := range retrievedSessions {
|
|
|
|
if session.Topic == generatedSessions[i].Topic {
|
|
|
|
found = true
|
|
|
|
require.Equal(t, generatedSessions[i], session)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
require.True(t, found)
|
|
|
|
}
|
2023-11-19 17:29:17 +00:00
|
|
|
}
|
|
|
|
|
2024-05-23 12:19:00 +00:00
|
|
|
func TestGet(t *testing.T) {
|
2023-11-26 15:50:12 +00:00
|
|
|
db, close := setupTestDB(t)
|
|
|
|
defer close()
|
|
|
|
|
2024-05-23 12:19:00 +00:00
|
|
|
entries := generateTestData(make([]testSession, 3))
|
|
|
|
insertTestData(t, db, entries)
|
|
|
|
|
|
|
|
retrievedSession, err := GetSessionByTopic(db, entries[1].Topic)
|
2023-11-26 15:50:12 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
2024-05-23 12:19:00 +00:00
|
|
|
require.Equal(t, entries[1], *retrievedSession)
|
|
|
|
|
|
|
|
err = DeleteSession(db, entries[1].Topic)
|
2023-11-26 15:50:12 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
2024-05-23 12:19:00 +00:00
|
|
|
deletedSession, err := GetSessionByTopic(db, entries[1].Topic)
|
|
|
|
require.ErrorIs(t, err, sql.ErrNoRows)
|
|
|
|
require.Nil(t, deletedSession)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestGetActiveSessions(t *testing.T) {
|
|
|
|
db, close := setupTestDB(t)
|
|
|
|
defer close()
|
|
|
|
|
|
|
|
// insert two disconnected and three active sessions
|
|
|
|
entries := generateTestData(make([]testSession, 5))
|
|
|
|
insertTestData(t, db, entries)
|
|
|
|
|
|
|
|
activeSessions, err := GetActiveSessions(db, entries[2].Expiry)
|
2023-11-26 15:50:12 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
2024-05-23 12:19:00 +00:00
|
|
|
require.Equal(t, 2, len(activeSessions))
|
|
|
|
// Expect newest on top
|
|
|
|
require.Equal(t, entries[4], activeSessions[0])
|
|
|
|
require.Equal(t, entries[2], activeSessions[1])
|
2023-11-26 15:50:12 +00:00
|
|
|
}
|
|
|
|
|
2024-05-23 12:19:00 +00:00
|
|
|
func TestDeleteSession(t *testing.T) {
|
2023-11-19 17:29:17 +00:00
|
|
|
db, close := setupTestDB(t)
|
|
|
|
defer close()
|
|
|
|
|
2024-05-23 12:19:00 +00:00
|
|
|
entries := generateTestData(make([]testSession, 3))
|
2023-11-19 17:29:17 +00:00
|
|
|
insertTestData(t, db, entries)
|
|
|
|
|
2024-05-23 12:19:00 +00:00
|
|
|
err := DeleteSession(db, entries[1].Topic)
|
2023-11-19 17:29:17 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
2024-05-23 12:19:00 +00:00
|
|
|
sessions, err := GetSessions(db)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, 2, len(sessions))
|
|
|
|
|
|
|
|
require.Equal(t, entries[0], sessions[1])
|
|
|
|
require.Equal(t, entries[2], sessions[0])
|
|
|
|
|
|
|
|
err = DeleteSession(db, entries[0].Topic)
|
|
|
|
require.NoError(t, err)
|
|
|
|
err = DeleteSession(db, entries[2].Topic)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
sessions, err = GetSessions(db)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, 0, len(sessions))
|
2023-11-19 17:29:17 +00:00
|
|
|
}
|
|
|
|
|
2024-05-23 12:19:00 +00:00
|
|
|
// urlFor prepares a value to be used in testSession
|
|
|
|
func urlFor(i int) urlOverride {
|
|
|
|
return common.NewAndSet(testDappUrl + strconv.Itoa(i))
|
|
|
|
}
|
|
|
|
|
|
|
|
// at prepares a value to be used in testSession
|
|
|
|
func at(i int) timestampOverride {
|
|
|
|
return common.NewAndSet(int64(i))
|
|
|
|
}
|
|
|
|
|
|
|
|
// TestGetActiveDapps_JoinWorksAsExpected also validates that GetActiveDapps returns the dapps in the order of the last first time added
|
|
|
|
func TestGetActiveDapps_JoinWorksAsExpected(t *testing.T) {
|
2023-11-19 17:29:17 +00:00
|
|
|
db, close := setupTestDB(t)
|
|
|
|
defer close()
|
|
|
|
|
2024-05-23 12:19:00 +00:00
|
|
|
not := common.NewAndSet(false)
|
|
|
|
// The first creation date is 1, 2, 3 but the last name update is, respectively, 1, 4, 5
|
|
|
|
entries := generateTestData([]testSession{
|
|
|
|
{url: urlFor(1), created: at(1), disconnected: not},
|
|
|
|
{url: urlFor(1), created: at(2), disconnected: not},
|
|
|
|
{url: urlFor(2), created: at(3), disconnected: not},
|
|
|
|
{url: urlFor(3), created: at(4), disconnected: not},
|
|
|
|
{url: urlFor(2), created: at(5), disconnected: not},
|
|
|
|
{url: urlFor(3), created: at(6), disconnected: not},
|
|
|
|
})
|
2023-11-19 17:29:17 +00:00
|
|
|
insertTestData(t, db, entries)
|
|
|
|
|
2024-05-23 12:19:00 +00:00
|
|
|
getTestnet := false
|
|
|
|
validAtTimestamp := entries[0].Expiry
|
|
|
|
dapps, err := GetActiveDapps(db, validAtTimestamp, getTestnet)
|
2023-11-19 17:29:17 +00:00
|
|
|
require.NoError(t, err)
|
2024-05-23 12:19:00 +00:00
|
|
|
require.Equal(t, 3, len(dapps))
|
2023-11-19 17:29:17 +00:00
|
|
|
|
2024-05-23 12:19:00 +00:00
|
|
|
require.Equal(t, 3, len(dapps))
|
|
|
|
require.Equal(t, entries[5].Name, dapps[0].Name)
|
|
|
|
require.Equal(t, entries[4].Name, dapps[1].Name)
|
|
|
|
require.Equal(t, entries[1].Name, dapps[2].Name)
|
|
|
|
}
|
|
|
|
|
|
|
|
// TestGetActiveDapps_ActiveWorksAsExpected tests the combination of disconnected and expired sessions
|
|
|
|
func TestGetActiveDapps_ActiveWorksAsExpected(t *testing.T) {
|
|
|
|
db, close := setupTestDB(t)
|
|
|
|
defer close()
|
|
|
|
|
|
|
|
not := common.NewAndSet(false)
|
|
|
|
yes := common.NewAndSet(true)
|
|
|
|
timeNow := 4
|
|
|
|
entries := generateTestData([]testSession{
|
|
|
|
{url: urlFor(1), expiry: at(timeNow - 3), disconnected: not},
|
|
|
|
{url: urlFor(1), expiry: at(timeNow - 2), disconnected: yes},
|
|
|
|
{url: urlFor(2), expiry: at(timeNow - 2), disconnected: not},
|
|
|
|
{url: urlFor(3), expiry: at(timeNow - 1), disconnected: yes},
|
|
|
|
// ----- timeNow
|
|
|
|
{url: urlFor(3), expiry: at(timeNow + 1), disconnected: not},
|
|
|
|
{url: urlFor(4), expiry: at(timeNow + 1), disconnected: yes},
|
|
|
|
{url: urlFor(4), expiry: at(timeNow + 2), disconnected: not},
|
|
|
|
{url: urlFor(5), expiry: at(timeNow + 2), disconnected: yes},
|
|
|
|
{url: urlFor(6), expiry: at(timeNow + 3), disconnected: not},
|
|
|
|
})
|
|
|
|
insertTestData(t, db, entries)
|
|
|
|
|
|
|
|
getTestnet := false
|
|
|
|
dapps, err := GetActiveDapps(db, int64(timeNow), getTestnet)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, 3, len(dapps))
|
|
|
|
}
|
|
|
|
|
|
|
|
// TestGetActiveDapps_TestChainsWorksAsExpected tests the combination of disconnected and expired sessions
|
|
|
|
func TestGetActiveDapps_TestChainsWorksAsExpected(t *testing.T) {
|
|
|
|
db, close := setupTestDB(t)
|
|
|
|
defer close()
|
|
|
|
|
|
|
|
not := common.NewAndSet(false)
|
|
|
|
yes := common.NewAndSet(true)
|
|
|
|
timeNow := 4
|
|
|
|
entries := generateTestData([]testSession{
|
|
|
|
{url: urlFor(1), testChains: not, expiry: at(timeNow - 3), disconnected: not},
|
|
|
|
{url: urlFor(2), testChains: yes, expiry: at(timeNow - 2), disconnected: not},
|
|
|
|
{url: urlFor(2), testChains: not, expiry: at(timeNow - 1), disconnected: not},
|
|
|
|
// ----- timeNow
|
|
|
|
{url: urlFor(3), testChains: not, expiry: at(timeNow + 1), disconnected: not},
|
|
|
|
{url: urlFor(4), testChains: not, expiry: at(timeNow + 2), disconnected: not},
|
|
|
|
{url: urlFor(4), testChains: yes, expiry: at(timeNow + 3), disconnected: not},
|
|
|
|
{url: urlFor(5), testChains: yes, expiry: at(timeNow + 4), disconnected: not},
|
|
|
|
})
|
|
|
|
insertTestData(t, db, entries)
|
|
|
|
|
|
|
|
getTestnet := true
|
|
|
|
dapps, err := GetActiveDapps(db, int64(timeNow), getTestnet)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, 2, len(dapps))
|
2023-11-19 17:29:17 +00:00
|
|
|
}
|
|
|
|
|
2024-05-23 12:19:00 +00:00
|
|
|
// TestGetDapps_EmptyDB tests that an empty database will return an empty list
|
|
|
|
func TestGetDapps_EmptyDB(t *testing.T) {
|
|
|
|
db, close := setupTestDB(t)
|
|
|
|
defer close()
|
|
|
|
|
|
|
|
entries := generateTestData([]testSession{})
|
|
|
|
insertTestData(t, db, entries)
|
2023-11-19 17:29:17 +00:00
|
|
|
|
2024-05-23 12:19:00 +00:00
|
|
|
getTestnet := false
|
|
|
|
validAtTimestamp := int64(0)
|
|
|
|
dapps, err := GetActiveDapps(db, validAtTimestamp, getTestnet)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, 0, len(dapps))
|
|
|
|
}
|
2023-11-19 17:29:17 +00:00
|
|
|
|
2024-05-23 12:19:00 +00:00
|
|
|
// TestGetDapps_OrphanDapps tests that missing session will place the dapp at the end
|
|
|
|
func TestGetDapps_OrphanDapps(t *testing.T) {
|
|
|
|
db, close := setupTestDB(t)
|
|
|
|
defer close()
|
2023-11-19 17:29:17 +00:00
|
|
|
|
2024-05-23 12:19:00 +00:00
|
|
|
not := common.NewAndSet(false)
|
|
|
|
entries := generateTestData([]testSession{
|
|
|
|
{url: urlFor(1), disconnected: not},
|
|
|
|
{url: urlFor(2), disconnected: not},
|
|
|
|
{url: urlFor(2), disconnected: not},
|
|
|
|
})
|
|
|
|
insertTestData(t, db, entries)
|
|
|
|
|
|
|
|
err := DeleteSession(db, entries[1].Topic)
|
|
|
|
require.NoError(t, err)
|
|
|
|
err = DeleteSession(db, entries[2].Topic)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
getTestnet := false
|
|
|
|
validAtTimestamp := entries[0].Expiry
|
|
|
|
dapps, err := GetActiveDapps(db, validAtTimestamp, getTestnet)
|
|
|
|
require.NoError(t, err)
|
|
|
|
// The orphan dapp is not considered active
|
|
|
|
require.Equal(t, 1, len(dapps))
|
|
|
|
require.Equal(t, entries[0].Name, dapps[0].Name)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDisconnectSession(t *testing.T) {
|
|
|
|
db, close := setupTestDB(t)
|
|
|
|
defer close()
|
|
|
|
|
|
|
|
not := common.NewAndSet(false)
|
|
|
|
entries := generateTestData([]testSession{
|
|
|
|
{url: urlFor(1), disconnected: not},
|
|
|
|
{url: urlFor(2), disconnected: not},
|
|
|
|
{url: urlFor(2), disconnected: not},
|
|
|
|
})
|
|
|
|
insertTestData(t, db, entries)
|
|
|
|
|
|
|
|
activeSessions, err := GetActiveSessions(db, 0)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, 3, len(activeSessions))
|
|
|
|
|
|
|
|
getTestnet := false
|
|
|
|
validAtTimestamp := entries[0].Expiry
|
|
|
|
dapps, err := GetActiveDapps(db, validAtTimestamp, getTestnet)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, 2, len(dapps))
|
|
|
|
|
|
|
|
err = DisconnectSession(db, entries[1].Topic)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
activeSessions, err = GetActiveSessions(db, 0)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, 2, len(activeSessions))
|
|
|
|
|
|
|
|
err = DisconnectSession(db, entries[2].Topic)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
activeSessions, err = GetActiveSessions(db, 0)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, 1, len(activeSessions))
|
|
|
|
|
|
|
|
dapps, err = GetActiveDapps(db, validAtTimestamp, getTestnet)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, 1, len(dapps))
|
|
|
|
require.Equal(t, entries[0].Name, dapps[0].Name)
|
|
|
|
}
|