status-go/multiaccounts/accounts/database_test.go

348 lines
10 KiB
Go
Raw Normal View History

package accounts
import (
"database/sql"
"testing"
2020-01-02 09:10:19 +00:00
"github.com/stretchr/testify/require"
2019-07-25 05:35:09 +00:00
"github.com/status-im/status-go/appdatabase"
2019-12-11 13:59:37 +00:00
"github.com/status-im/status-go/eth-node/types"
Sync Settings (#2478) * Sync Settings * Added valueHandlers and Database singleton Some issues remain, need a way to comparing incoming sql.DB to check if the connection is to a different file or not. Maybe make singleton instance per filename * Added functionality to check the sqlite filename * Refactor of Database.SaveSyncSettings to be used as a handler * Implemented inteface for setting sync protobuf factories * Refactored and completed adhoc send setting sync * Tidying up * Immutability refactor * Refactor settings into dedicated package * Breakout structs * Tidy up * Refactor of bulk settings sync * Bug fixes * Addressing feedback * Fix code dropped during rebase * Fix for db closed * Fix for node config related crashes * Provisional fix for type assertion - issue 2 * Adding robust type assertion checks * Partial fix for null literal db storage and json encoding * Fix for passively handling nil sql.DB, and checking if elem has len and if len is 0 * Added test for preferred name behaviour * Adding saved sync settings to MessengerResponse * Completed granular initial sync and clock from network on save * add Settings to isEmpty * Refactor of protobufs, partially done * Added syncSetting receiver handling, some bug fixes * Fix for sticker packs * Implement inactive flag on sync protobuf factory * Refactor of types and structs * Added SettingField.CanSync functionality * Addressing rebase artifact * Refactor of Setting SELECT queries * Refactor of string return queries * VERSION bump and migration index bump * Deactiveate Sync Settings * Deactiveated preferred_name and send_status_updates Co-authored-by: Andrea Maria Piana <andrea.maria.piana@gmail.com>
2022-03-23 18:47:00 +00:00
"github.com/status-im/status-go/multiaccounts/errors"
"github.com/status-im/status-go/multiaccounts/keypairs"
)
func setupTestDB(t *testing.T) (*Database, func()) {
Sync Settings (#2478) * Sync Settings * Added valueHandlers and Database singleton Some issues remain, need a way to comparing incoming sql.DB to check if the connection is to a different file or not. Maybe make singleton instance per filename * Added functionality to check the sqlite filename * Refactor of Database.SaveSyncSettings to be used as a handler * Implemented inteface for setting sync protobuf factories * Refactored and completed adhoc send setting sync * Tidying up * Immutability refactor * Refactor settings into dedicated package * Breakout structs * Tidy up * Refactor of bulk settings sync * Bug fixes * Addressing feedback * Fix code dropped during rebase * Fix for db closed * Fix for node config related crashes * Provisional fix for type assertion - issue 2 * Adding robust type assertion checks * Partial fix for null literal db storage and json encoding * Fix for passively handling nil sql.DB, and checking if elem has len and if len is 0 * Added test for preferred name behaviour * Adding saved sync settings to MessengerResponse * Completed granular initial sync and clock from network on save * add Settings to isEmpty * Refactor of protobufs, partially done * Added syncSetting receiver handling, some bug fixes * Fix for sticker packs * Implement inactive flag on sync protobuf factory * Refactor of types and structs * Added SettingField.CanSync functionality * Addressing rebase artifact * Refactor of Setting SELECT queries * Refactor of string return queries * VERSION bump and migration index bump * Deactiveate Sync Settings * Deactiveated preferred_name and send_status_updates Co-authored-by: Andrea Maria Piana <andrea.maria.piana@gmail.com>
2022-03-23 18:47:00 +00:00
db, stop, err := appdatabase.SetupTestSQLDB("settings-tests-")
if err != nil {
require.NoError(t, stop())
}
require.NoError(t, err)
Sync Settings (#2478) * Sync Settings * Added valueHandlers and Database singleton Some issues remain, need a way to comparing incoming sql.DB to check if the connection is to a different file or not. Maybe make singleton instance per filename * Added functionality to check the sqlite filename * Refactor of Database.SaveSyncSettings to be used as a handler * Implemented inteface for setting sync protobuf factories * Refactored and completed adhoc send setting sync * Tidying up * Immutability refactor * Refactor settings into dedicated package * Breakout structs * Tidy up * Refactor of bulk settings sync * Bug fixes * Addressing feedback * Fix code dropped during rebase * Fix for db closed * Fix for node config related crashes * Provisional fix for type assertion - issue 2 * Adding robust type assertion checks * Partial fix for null literal db storage and json encoding * Fix for passively handling nil sql.DB, and checking if elem has len and if len is 0 * Added test for preferred name behaviour * Adding saved sync settings to MessengerResponse * Completed granular initial sync and clock from network on save * add Settings to isEmpty * Refactor of protobufs, partially done * Added syncSetting receiver handling, some bug fixes * Fix for sticker packs * Implement inactive flag on sync protobuf factory * Refactor of types and structs * Added SettingField.CanSync functionality * Addressing rebase artifact * Refactor of Setting SELECT queries * Refactor of string return queries * VERSION bump and migration index bump * Deactiveate Sync Settings * Deactiveated preferred_name and send_status_updates Co-authored-by: Andrea Maria Piana <andrea.maria.piana@gmail.com>
2022-03-23 18:47:00 +00:00
d, err := NewDB(db)
if err != nil {
require.NoError(t, stop())
}
require.NoError(t, err)
Sync Settings (#2478) * Sync Settings * Added valueHandlers and Database singleton Some issues remain, need a way to comparing incoming sql.DB to check if the connection is to a different file or not. Maybe make singleton instance per filename * Added functionality to check the sqlite filename * Refactor of Database.SaveSyncSettings to be used as a handler * Implemented inteface for setting sync protobuf factories * Refactored and completed adhoc send setting sync * Tidying up * Immutability refactor * Refactor settings into dedicated package * Breakout structs * Tidy up * Refactor of bulk settings sync * Bug fixes * Addressing feedback * Fix code dropped during rebase * Fix for db closed * Fix for node config related crashes * Provisional fix for type assertion - issue 2 * Adding robust type assertion checks * Partial fix for null literal db storage and json encoding * Fix for passively handling nil sql.DB, and checking if elem has len and if len is 0 * Added test for preferred name behaviour * Adding saved sync settings to MessengerResponse * Completed granular initial sync and clock from network on save * add Settings to isEmpty * Refactor of protobufs, partially done * Added syncSetting receiver handling, some bug fixes * Fix for sticker packs * Implement inactive flag on sync protobuf factory * Refactor of types and structs * Added SettingField.CanSync functionality * Addressing rebase artifact * Refactor of Setting SELECT queries * Refactor of string return queries * VERSION bump and migration index bump * Deactiveate Sync Settings * Deactiveated preferred_name and send_status_updates Co-authored-by: Andrea Maria Piana <andrea.maria.piana@gmail.com>
2022-03-23 18:47:00 +00:00
return d, func() {
require.NoError(t, stop())
}
}
func TestSaveAccounts(t *testing.T) {
type testCase struct {
description string
2022-05-18 10:42:51 +00:00
accounts []*Account
err error
}
for _, tc := range []testCase{
{
description: "NoError",
2022-05-18 10:42:51 +00:00
accounts: []*Account{
2019-12-11 13:59:37 +00:00
{Address: types.Address{0x01}, Chat: true, Wallet: true},
{Address: types.Address{0x02}},
},
},
{
description: "UniqueChat",
2022-05-18 10:42:51 +00:00
accounts: []*Account{
2019-12-11 13:59:37 +00:00
{Address: types.Address{0x01}, Chat: true},
{Address: types.Address{0x02}, Chat: true},
},
Sync Settings (#2478) * Sync Settings * Added valueHandlers and Database singleton Some issues remain, need a way to comparing incoming sql.DB to check if the connection is to a different file or not. Maybe make singleton instance per filename * Added functionality to check the sqlite filename * Refactor of Database.SaveSyncSettings to be used as a handler * Implemented inteface for setting sync protobuf factories * Refactored and completed adhoc send setting sync * Tidying up * Immutability refactor * Refactor settings into dedicated package * Breakout structs * Tidy up * Refactor of bulk settings sync * Bug fixes * Addressing feedback * Fix code dropped during rebase * Fix for db closed * Fix for node config related crashes * Provisional fix for type assertion - issue 2 * Adding robust type assertion checks * Partial fix for null literal db storage and json encoding * Fix for passively handling nil sql.DB, and checking if elem has len and if len is 0 * Added test for preferred name behaviour * Adding saved sync settings to MessengerResponse * Completed granular initial sync and clock from network on save * add Settings to isEmpty * Refactor of protobufs, partially done * Added syncSetting receiver handling, some bug fixes * Fix for sticker packs * Implement inactive flag on sync protobuf factory * Refactor of types and structs * Added SettingField.CanSync functionality * Addressing rebase artifact * Refactor of Setting SELECT queries * Refactor of string return queries * VERSION bump and migration index bump * Deactiveate Sync Settings * Deactiveated preferred_name and send_status_updates Co-authored-by: Andrea Maria Piana <andrea.maria.piana@gmail.com>
2022-03-23 18:47:00 +00:00
err: errors.ErrChatNotUnique,
},
{
description: "UniqueWallet",
2022-05-18 10:42:51 +00:00
accounts: []*Account{
2019-12-11 13:59:37 +00:00
{Address: types.Address{0x01}, Wallet: true},
{Address: types.Address{0x02}, Wallet: true},
},
Sync Settings (#2478) * Sync Settings * Added valueHandlers and Database singleton Some issues remain, need a way to comparing incoming sql.DB to check if the connection is to a different file or not. Maybe make singleton instance per filename * Added functionality to check the sqlite filename * Refactor of Database.SaveSyncSettings to be used as a handler * Implemented inteface for setting sync protobuf factories * Refactored and completed adhoc send setting sync * Tidying up * Immutability refactor * Refactor settings into dedicated package * Breakout structs * Tidy up * Refactor of bulk settings sync * Bug fixes * Addressing feedback * Fix code dropped during rebase * Fix for db closed * Fix for node config related crashes * Provisional fix for type assertion - issue 2 * Adding robust type assertion checks * Partial fix for null literal db storage and json encoding * Fix for passively handling nil sql.DB, and checking if elem has len and if len is 0 * Added test for preferred name behaviour * Adding saved sync settings to MessengerResponse * Completed granular initial sync and clock from network on save * add Settings to isEmpty * Refactor of protobufs, partially done * Added syncSetting receiver handling, some bug fixes * Fix for sticker packs * Implement inactive flag on sync protobuf factory * Refactor of types and structs * Added SettingField.CanSync functionality * Addressing rebase artifact * Refactor of Setting SELECT queries * Refactor of string return queries * VERSION bump and migration index bump * Deactiveate Sync Settings * Deactiveated preferred_name and send_status_updates Co-authored-by: Andrea Maria Piana <andrea.maria.piana@gmail.com>
2022-03-23 18:47:00 +00:00
err: errors.ErrWalletNotUnique,
},
} {
t.Run(tc.description, func(t *testing.T) {
db, stop := setupTestDB(t)
defer stop()
require.Equal(t, tc.err, db.SaveAccounts(tc.accounts))
})
}
}
func TestUpdateAccounts(t *testing.T) {
db, stop := setupTestDB(t)
defer stop()
2022-05-18 10:42:51 +00:00
accounts := []*Account{
2019-12-11 13:59:37 +00:00
{Address: types.Address{0x01}, Chat: true, Wallet: true},
{Address: types.Address{0x02}},
}
require.NoError(t, db.SaveAccounts(accounts))
accounts[0].Chat = false
accounts[1].Chat = true
require.NoError(t, db.SaveAccounts(accounts))
rst, err := db.GetAccounts()
require.NoError(t, err)
require.Equal(t, accounts, rst)
}
func TestDeleteAccount(t *testing.T) {
db, stop := setupTestDB(t)
defer stop()
2022-05-18 10:42:51 +00:00
accounts := []*Account{
2019-12-11 13:59:37 +00:00
{Address: types.Address{0x01}, Chat: true, Wallet: true},
}
require.NoError(t, db.SaveAccounts(accounts))
rst, err := db.GetAccounts()
require.NoError(t, err)
require.Equal(t, 1, len(rst))
2019-12-11 13:59:37 +00:00
require.NoError(t, db.DeleteAccount(types.Address{0x01}))
rst2, err := db.GetAccounts()
require.NoError(t, err)
require.Equal(t, 0, len(rst2))
}
func TestGetAddresses(t *testing.T) {
db, stop := setupTestDB(t)
defer stop()
2022-05-18 10:42:51 +00:00
accounts := []*Account{
2019-12-11 13:59:37 +00:00
{Address: types.Address{0x01}, Chat: true, Wallet: true},
{Address: types.Address{0x02}},
}
require.NoError(t, db.SaveAccounts(accounts))
addresses, err := db.GetAddresses()
require.NoError(t, err)
2019-12-11 13:59:37 +00:00
require.Equal(t, []types.Address{{0x01}, {0x02}}, addresses)
}
func TestGetWalletAddress(t *testing.T) {
db, stop := setupTestDB(t)
defer stop()
2019-12-11 13:59:37 +00:00
address := types.Address{0x01}
_, err := db.GetWalletAddress()
require.Equal(t, err, sql.ErrNoRows)
2022-05-18 10:42:51 +00:00
require.NoError(t, db.SaveAccounts([]*Account{{Address: address, Wallet: true}}))
wallet, err := db.GetWalletAddress()
require.NoError(t, err)
require.Equal(t, address, wallet)
}
func TestGetChatAddress(t *testing.T) {
db, stop := setupTestDB(t)
defer stop()
2019-12-11 13:59:37 +00:00
address := types.Address{0x01}
_, err := db.GetChatAddress()
require.Equal(t, err, sql.ErrNoRows)
2022-05-18 10:42:51 +00:00
require.NoError(t, db.SaveAccounts([]*Account{{Address: address, Chat: true}}))
chat, err := db.GetChatAddress()
require.NoError(t, err)
require.Equal(t, address, chat)
}
func TestGetAccounts(t *testing.T) {
db, stop := setupTestDB(t)
defer stop()
2022-05-18 10:42:51 +00:00
accounts := []*Account{
2019-12-11 13:59:37 +00:00
{Address: types.Address{0x01}, Chat: true, Wallet: true},
{Address: types.Address{0x02}, PublicKey: types.HexBytes{0x01, 0x02}},
{Address: types.Address{0x03}, PublicKey: types.HexBytes{0x02, 0x03}},
}
require.NoError(t, db.SaveAccounts(accounts))
rst, err := db.GetAccounts()
require.NoError(t, err)
require.Equal(t, accounts, rst)
}
func TestGetAccountByAddress(t *testing.T) {
db, stop := setupTestDB(t)
defer stop()
address := types.Address{0x01}
2022-05-18 10:42:51 +00:00
account := &Account{Address: address, Chat: true, Wallet: true}
dilute := []*Account{
{Address: types.Address{0x02}, PublicKey: types.HexBytes{0x01, 0x02}},
{Address: types.Address{0x03}, PublicKey: types.HexBytes{0x02, 0x03}},
}
accounts := append(dilute, account)
require.NoError(t, db.SaveAccounts(accounts))
rst, err := db.GetAccountByAddress(address)
require.NoError(t, err)
2022-05-18 10:42:51 +00:00
require.Equal(t, account, rst)
}
func TestAddressExists(t *testing.T) {
db, stop := setupTestDB(t)
defer stop()
2022-05-18 10:42:51 +00:00
accounts := []*Account{
2019-12-11 13:59:37 +00:00
{Address: types.Address{0x01}, Chat: true, Wallet: true},
}
require.NoError(t, db.SaveAccounts(accounts))
exists, err := db.AddressExists(accounts[0].Address)
require.NoError(t, err)
require.True(t, exists)
}
func TestAddressDoesntExist(t *testing.T) {
db, stop := setupTestDB(t)
defer stop()
2019-12-11 13:59:37 +00:00
exists, err := db.AddressExists(types.Address{1, 1, 1})
require.NoError(t, err)
require.False(t, exists)
}
func TestKeypairs(t *testing.T) {
db, stop := setupTestDB(t)
defer stop()
keycardUID := "00000000000000000000000000000000"
keyPair1 := keypairs.KeyPair{
KeycardUID: "00000000000000000000000000000001",
KeycardName: "Card01",
KeycardLocked: false,
AccountsAddresses: []types.Address{{0x01}, {0x02}, {0x03}, {0x04}},
KeyUID: "0000000000000000000000000000000000000000000000000000000000000001",
}
keyPair2 := keypairs.KeyPair{
KeycardUID: "00000000000000000000000000000002",
KeycardName: "Card02",
KeycardLocked: false,
AccountsAddresses: []types.Address{{0x01}, {0x02}},
KeyUID: "0000000000000000000000000000000000000000000000000000000000000002",
}
keyPair3 := keypairs.KeyPair{
KeycardUID: "00000000000000000000000000000003",
KeycardName: "Card02 Copy",
KeycardLocked: false,
AccountsAddresses: []types.Address{{0x01}, {0x02}},
KeyUID: "0000000000000000000000000000000000000000000000000000000000000002",
}
// Test adding key pairs
err := db.AddMigratedKeyPair(keyPair1.KeycardUID, keyPair1.KeycardName, keyPair1.KeyUID, keyPair1.AccountsAddresses)
require.NoError(t, err)
err = db.AddMigratedKeyPair(keyPair2.KeycardUID, keyPair2.KeycardName, keyPair2.KeyUID, keyPair2.AccountsAddresses)
require.NoError(t, err)
err = db.AddMigratedKeyPair(keyPair3.KeycardUID, keyPair3.KeycardName, keyPair3.KeyUID, keyPair3.AccountsAddresses)
require.NoError(t, err)
// Test reading migrated key pairs
rows, err := db.GetAllMigratedKeyPairs()
require.NoError(t, err)
require.Equal(t, 2, len(rows))
for _, kp := range rows {
if kp.KeyUID == keyPair1.KeyUID {
require.Equal(t, keyPair1.KeycardUID, kp.KeycardUID)
require.Equal(t, keyPair1.KeycardName, kp.KeycardName)
require.Equal(t, keyPair1.KeycardLocked, kp.KeycardLocked)
require.Equal(t, len(keyPair1.AccountsAddresses), len(kp.AccountsAddresses))
} else {
require.Equal(t, keyPair2.KeycardUID, kp.KeycardUID)
require.Equal(t, keyPair2.KeycardName, kp.KeycardName)
require.Equal(t, keyPair2.KeycardLocked, kp.KeycardLocked)
require.Equal(t, len(keyPair2.AccountsAddresses), len(kp.AccountsAddresses))
}
}
rows, err = db.GetMigratedKeyPairByKeyUID(keyPair1.KeyUID)
require.NoError(t, err)
require.Equal(t, 1, len(rows))
require.Equal(t, keyPair1.KeyUID, rows[0].KeyUID)
require.Equal(t, keyPair1.KeycardUID, rows[0].KeycardUID)
require.Equal(t, keyPair1.KeycardName, rows[0].KeycardName)
require.Equal(t, keyPair1.KeycardLocked, rows[0].KeycardLocked)
require.Equal(t, len(keyPair1.AccountsAddresses), len(rows[0].AccountsAddresses))
rows, err = db.GetAllKnownKeycards()
require.NoError(t, err)
require.Equal(t, 3, len(rows))
for _, kp := range rows {
if kp.KeycardUID == keyPair1.KeycardUID {
require.Equal(t, keyPair1.KeycardUID, kp.KeycardUID)
require.Equal(t, keyPair1.KeycardName, kp.KeycardName)
require.Equal(t, keyPair1.KeycardLocked, kp.KeycardLocked)
require.Equal(t, len(keyPair1.AccountsAddresses), len(kp.AccountsAddresses))
} else if kp.KeycardUID == keyPair2.KeycardUID {
require.Equal(t, keyPair2.KeycardUID, kp.KeycardUID)
require.Equal(t, keyPair2.KeycardName, kp.KeycardName)
require.Equal(t, keyPair2.KeycardLocked, kp.KeycardLocked)
require.Equal(t, len(keyPair2.AccountsAddresses), len(kp.AccountsAddresses))
} else {
require.Equal(t, keyPair3.KeycardUID, kp.KeycardUID)
require.Equal(t, keyPair3.KeycardName, kp.KeycardName)
require.Equal(t, keyPair3.KeycardLocked, kp.KeycardLocked)
require.Equal(t, len(keyPair3.AccountsAddresses), len(kp.AccountsAddresses))
}
}
// Test seting a new keycard name
err = db.SetKeycardName(keyPair1.KeycardUID, "Card101")
require.NoError(t, err)
rows, err = db.GetAllMigratedKeyPairs()
require.NoError(t, err)
newKeycardName := ""
for _, kp := range rows {
if kp.KeyUID == keyPair1.KeyUID {
newKeycardName = kp.KeycardName
}
}
require.Equal(t, "Card101", newKeycardName)
// Test locking a keycard
err = db.KeycardLocked(keyPair1.KeycardUID)
require.NoError(t, err)
rows, err = db.GetAllMigratedKeyPairs()
require.NoError(t, err)
locked := false
for _, kp := range rows {
if kp.KeyUID == keyPair1.KeyUID {
locked = kp.KeycardLocked
}
}
require.Equal(t, true, locked)
// Test detleting accounts (addresses) for a certain keycard
const numOfAccountsToRemove = 2
require.Greater(t, len(keyPair1.AccountsAddresses), numOfAccountsToRemove)
accountsToRemove := keyPair1.AccountsAddresses[:numOfAccountsToRemove]
err = db.RemoveMigratedAccountsForKeycard(keyPair1.KeycardUID, accountsToRemove)
require.NoError(t, err)
rows, err = db.GetMigratedKeyPairByKeyUID(keyPair1.KeyUID)
require.NoError(t, err)
require.Equal(t, 1, len(rows))
require.Equal(t, len(keyPair1.AccountsAddresses)-numOfAccountsToRemove, len(rows[0].AccountsAddresses))
// Test update keycard uid
err = db.UpdateKeycardUID(keyPair1.KeycardUID, keycardUID)
require.NoError(t, err)
// Test unlocking a locked keycard
err = db.KeycardUnlocked(keycardUID)
require.NoError(t, err)
rows, err = db.GetAllMigratedKeyPairs()
require.NoError(t, err)
locked = true
for _, kp := range rows {
if kp.KeyUID == keyPair1.KeyUID {
locked = kp.KeycardLocked
}
}
require.Equal(t, false, locked)
// Test detleting a keycard
err = db.DeleteKeycard(keycardUID)
require.NoError(t, err)
rows, err = db.GetAllMigratedKeyPairs()
require.NoError(t, err)
require.Equal(t, 1, len(rows))
// Test if correct keycard is deleted
deletedKeyPair1 := true
for _, kp := range rows {
if kp.KeyUID == keyPair1.KeyUID {
deletedKeyPair1 = false
}
}
require.Equal(t, true, deletedKeyPair1)
}