Skip to content

Commit

Permalink
Add stake module tests (#207)
Browse files Browse the repository at this point in the history
* Init stake test tool

* Add module test

* Add handle instruction tests

* Add stake module tests

* Fix system module tests
  • Loading branch information
dadamu authored Apr 18, 2022
1 parent 03d0c53 commit a1c1b9b
Show file tree
Hide file tree
Showing 9 changed files with 537 additions and 61 deletions.
83 changes: 83 additions & 0 deletions modules/stake/commen_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package stake_test

import (
"testing"

"github.com/stretchr/testify/suite"

"github.com/forbole/soljuno/db"
dbtypes "github.com/forbole/soljuno/db/types"
"github.com/forbole/soljuno/modules/stake"
clienttypes "github.com/forbole/soljuno/solana/client/types"
)

var _ db.StakeDb = &MockDb{}

type MockDb struct {
isLatest bool
}

func NewDefaultMockDb() *MockDb {
return &MockDb{isLatest: true}
}

func (db *MockDb) SaveStakeAccount(account dbtypes.StakeAccountRow) error { return nil }
func (db *MockDb) DeleteStakeAccount(address string) error { return nil }
func (db *MockDb) SaveStakeDelegation(delegation dbtypes.StakeDelegationRow) error { return nil }
func (db *MockDb) SaveStakeLockup(lockup dbtypes.StakeLockupRow) error { return nil }
func (db *MockDb) DeleteStakeDelegation(address string) error { return nil }

func (db *MockDb) CheckStakeAccountLatest(address string, currentSlot uint64) bool {
return db.isLatest
}

func (m MockDb) GetCached() MockDb {
return m
}

func (m *MockDb) WithLatest(isLatest bool) {
m.isLatest = isLatest
}

// ----------------------------------------------------------------

var _ stake.ClientProxy = &MockClient{}

type MockClient struct {
account clienttypes.AccountInfo
}

func NewDefaultMockClient() *MockClient {
return &MockClient{}
}

func (m MockClient) GetCached() MockClient {
return m
}

func (m *MockClient) WithAccount(account clienttypes.AccountInfo) {
m.account = account
}

func (m *MockClient) GetAccountInfo(address string) (clienttypes.AccountInfo, error) {
return m.account, nil
}

// ----------------------------------------------------------------

type ModuleTestSuite struct {
suite.Suite
module *stake.Module
db *MockDb
client *MockClient
}

func TestModuleTestSuite(t *testing.T) {
suite.Run(t, new(ModuleTestSuite))
}

func (suite *ModuleTestSuite) SetupTest() {
suite.module = stake.NewModule(NewDefaultMockDb(), NewDefaultMockClient())
suite.db = NewDefaultMockDb()
suite.client = NewDefaultMockClient()
}
87 changes: 43 additions & 44 deletions modules/stake/handle_instruction.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,190 +5,189 @@ import (

"github.com/forbole/soljuno/db"
dbtypes "github.com/forbole/soljuno/db/types"
"github.com/forbole/soljuno/solana/client"
"github.com/forbole/soljuno/solana/program/stake"
"github.com/forbole/soljuno/types"
)

// HandleInstruction allows to handle different instructions types for the stake module
func HandleInstruction(instruction types.Instruction, tx types.Tx, db db.StakeDb, client client.ClientProxy) error {
func HandleInstruction(instruction types.Instruction, db db.StakeDb, client ClientProxy) error {
switch instruction.Parsed.Type {
case "initialize":
return handleInitialize(instruction, tx, db)
return handleInitialize(instruction, db)
case "authorize":
return handleAuthorize(instruction, tx, db, client)
return handleAuthorize(instruction, db, client)
case "delegate":
return handleDelegate(instruction, tx, db, client)
return handleDelegate(instruction, db, client)
case "split":
return handleSplit(instruction, tx, db, client)
return handleSplit(instruction, db, client)
case "withdraw":
return handleWithdraw(instruction, tx, db, client)
return handleWithdraw(instruction, db, client)
case "deactivate":
return handleDeactivate(instruction, tx, db, client)
return handleDeactivate(instruction, db, client)
case "setLockup":
return handleSetLockup(instruction, tx, db, client)
return handleSetLockup(instruction, db, client)
case "merge":
return handleMerge(instruction, tx, db, client)
return handleMerge(instruction, db, client)
case "authorizeWithSeed":
return handleAuthorizeWithSeed(instruction, tx, db, client)
return handleAuthorizeWithSeed(instruction, db, client)
case "initializeChecked":
return handleInitializeChecked(instruction, tx, db, client)
return handleInitializeChecked(instruction, db, client)
case "authorizeChecked":
return handleAuthorizeChecked(instruction, tx, db, client)
return handleAuthorizeChecked(instruction, db, client)
case "authorizeCheckedWithSeed":
return handleAuthorizeCheckedWithSeed(instruction, tx, db, client)
return handleAuthorizeCheckedWithSeed(instruction, db, client)
case "setLockupChecked":
return handleSetLockupChecked(instruction, tx, db, client)
return handleSetLockupChecked(instruction, db, client)
}
return nil
}

// handleInitialize handles a instruction of Initialize
func handleInitialize(instruction types.Instruction, tx types.Tx, db db.StakeDb) error {
func handleInitialize(instruction types.Instruction, db db.StakeDb) error {
parsed, ok := instruction.Parsed.Value.(stake.ParsedInitialize)
if !ok {
return fmt.Errorf("instruction does not match %s type: %s", "initialize", instruction.Parsed.Type)

}
err := db.SaveStakeAccount(
dbtypes.NewStakeAccountRow(
parsed.StakeAccount, tx.Slot, parsed.Authorized.Staker, parsed.Authorized.Withdrawer,
parsed.StakeAccount, instruction.Slot, parsed.Authorized.Staker, parsed.Authorized.Withdrawer,
),
)
if err != nil {
return err
}
return db.SaveStakeLockup(
dbtypes.NewStakeLockupRow(
parsed.StakeAccount, tx.Slot, parsed.Lockup.Custodian, parsed.Lockup.Epoch, parsed.Lockup.UnixTimestamp,
parsed.StakeAccount, instruction.Slot, parsed.Lockup.Custodian, parsed.Lockup.Epoch, parsed.Lockup.UnixTimestamp,
),
)
}

// handleAuthorize handles a instruction of Authorize
func handleAuthorize(instruction types.Instruction, tx types.Tx, db db.StakeDb, client client.ClientProxy) error {
func handleAuthorize(instruction types.Instruction, db db.StakeDb, client ClientProxy) error {
parsed, ok := instruction.Parsed.Value.(stake.ParsedAuthorize)
if !ok {
return fmt.Errorf("instruction does not match %s type: %s", "authorize", instruction.Parsed.Type)

}
return updateStakeAccount(parsed.StakeAccount, tx.Slot, db, client)
return UpdateStakeAccount(parsed.StakeAccount, instruction.Slot, db, client)
}

// handleDelegate handles a instruction of Delegate
func handleDelegate(instruction types.Instruction, tx types.Tx, db db.StakeDb, client client.ClientProxy) error {
func handleDelegate(instruction types.Instruction, db db.StakeDb, client ClientProxy) error {
parsed, ok := instruction.Parsed.Value.(stake.ParsedDelegateStake)
if !ok {
return fmt.Errorf("instruction does not match %s type: %s", "delegate", instruction.Parsed.Type)

}
return updateStakeAccount(parsed.StakeAccount, tx.Slot, db, client)
return UpdateStakeAccount(parsed.StakeAccount, instruction.Slot, db, client)
}

// handleSplit handles a instruction of Split
func handleSplit(instruction types.Instruction, tx types.Tx, db db.StakeDb, client client.ClientProxy) error {
func handleSplit(instruction types.Instruction, db db.StakeDb, client ClientProxy) error {
parsed, ok := instruction.Parsed.Value.(stake.ParsedSplit)
if !ok {
return fmt.Errorf("instruction does not match %s type: %s", "split", instruction.Parsed.Type)

}
err := updateStakeAccount(parsed.StakeAccount, tx.Slot, db, client)
err := UpdateStakeAccount(parsed.StakeAccount, instruction.Slot, db, client)
if err != nil {
return nil
}
return updateStakeAccount(parsed.NewSplitAccount, tx.Slot, db, client)
return UpdateStakeAccount(parsed.NewSplitAccount, instruction.Slot, db, client)
}

// handleWithdraw handles a instruction of Withdraw
func handleWithdraw(instruction types.Instruction, tx types.Tx, db db.StakeDb, client client.ClientProxy) error {
func handleWithdraw(instruction types.Instruction, db db.StakeDb, client ClientProxy) error {
parsed, ok := instruction.Parsed.Value.(stake.ParsedWithdraw)
if !ok {
return fmt.Errorf("instruction does not match %s type: %s", "withdraw", instruction.Parsed.Type)

}
return updateStakeAccount(parsed.StakeAccount, tx.Slot, db, client)
return UpdateStakeAccount(parsed.StakeAccount, instruction.Slot, db, client)
}

// handleDeactivate handles a instruction of Deactivate
func handleDeactivate(instruction types.Instruction, tx types.Tx, db db.StakeDb, client client.ClientProxy) error {
func handleDeactivate(instruction types.Instruction, db db.StakeDb, client ClientProxy) error {
parsed, ok := instruction.Parsed.Value.(stake.ParsedDeactivate)
if !ok {
return fmt.Errorf("instruction does not match %s type: %s", "deactivate", instruction.Parsed.Type)

}
return updateStakeAccount(parsed.StakeAccount, tx.Slot, db, client)
return UpdateStakeAccount(parsed.StakeAccount, instruction.Slot, db, client)
}

// handleSetLockup handles a instruction of SetLockup
func handleSetLockup(instruction types.Instruction, tx types.Tx, db db.StakeDb, client client.ClientProxy) error {
func handleSetLockup(instruction types.Instruction, db db.StakeDb, client ClientProxy) error {
parsed, ok := instruction.Parsed.Value.(stake.ParsedSetLockup)
if !ok {
return fmt.Errorf("instruction does not match %s type: %s", "setLockup", instruction.Parsed.Type)

}
return updateStakeAccount(parsed.StakeAccount, tx.Slot, db, client)
return UpdateStakeAccount(parsed.StakeAccount, instruction.Slot, db, client)
}

// handleMerge handles a instruction of Merge
func handleMerge(instruction types.Instruction, tx types.Tx, db db.StakeDb, client client.ClientProxy) error {
func handleMerge(instruction types.Instruction, db db.StakeDb, client ClientProxy) error {
parsed, ok := instruction.Parsed.Value.(stake.ParsedMerge)
if !ok {
return fmt.Errorf("instruction does not match %s type: %s", "merge", instruction.Parsed.Type)

}
err := updateStakeAccount(parsed.Source, tx.Slot, db, client)
err := UpdateStakeAccount(parsed.Source, instruction.Slot, db, client)
if err != nil {
return err
}
return updateStakeAccount(parsed.Destination, tx.Slot, db, client)
return UpdateStakeAccount(parsed.Destination, instruction.Slot, db, client)
}

// handleAuthorizeWithSeed handles a instruction of AuthorizeWithSeed
func handleAuthorizeWithSeed(instruction types.Instruction, tx types.Tx, db db.StakeDb, client client.ClientProxy) error {
func handleAuthorizeWithSeed(instruction types.Instruction, db db.StakeDb, client ClientProxy) error {
parsed, ok := instruction.Parsed.Value.(stake.ParsedAuthorizeWithSeed)
if !ok {
return fmt.Errorf("instruction does not match %s type: %s", "authorizeWithSeed", instruction.Parsed.Type)

}
return updateStakeAccount(parsed.StakeAccount, tx.Slot, db, client)
return UpdateStakeAccount(parsed.StakeAccount, instruction.Slot, db, client)
}

// handleInitializeChecked handles a instruction of InitializeChecked
func handleInitializeChecked(instruction types.Instruction, tx types.Tx, db db.StakeDb, client client.ClientProxy) error {
func handleInitializeChecked(instruction types.Instruction, db db.StakeDb, client ClientProxy) error {
parsed, ok := instruction.Parsed.Value.(stake.ParsedInitializeChecked)
if !ok {
return fmt.Errorf("instruction does not match %s type: %s", "initializeChecked", instruction.Parsed.Type)

}
return updateStakeAccount(parsed.StakeAccount, tx.Slot, db, client)
return UpdateStakeAccount(parsed.StakeAccount, instruction.Slot, db, client)
}

// handleAuthorizeChecked handles a instruction of AuthorizeChecked
func handleAuthorizeChecked(instruction types.Instruction, tx types.Tx, db db.StakeDb, client client.ClientProxy) error {
func handleAuthorizeChecked(instruction types.Instruction, db db.StakeDb, client ClientProxy) error {
parsed, ok := instruction.Parsed.Value.(stake.ParsedAuthorizeChecked)
if !ok {
return fmt.Errorf("instruction does not match %s type: %s", "authorizeChecked", instruction.Parsed.Type)

}
return updateStakeAccount(parsed.StakeAccount, tx.Slot, db, client)
return UpdateStakeAccount(parsed.StakeAccount, instruction.Slot, db, client)
}

// handleAuthorizeCheckedWithSeed handles a instruction of AuthorizeCheckedWithSeed
func handleAuthorizeCheckedWithSeed(instruction types.Instruction, tx types.Tx, db db.StakeDb, client client.ClientProxy) error {
func handleAuthorizeCheckedWithSeed(instruction types.Instruction, db db.StakeDb, client ClientProxy) error {
parsed, ok := instruction.Parsed.Value.(stake.ParsedAuthorizeCheckedWithSeed)
if !ok {
return fmt.Errorf("instruction does not match %s type: %s", "authorizeCheckedWithSeed", instruction.Parsed.Type)

}
return updateStakeAccount(parsed.StakeAccount, tx.Slot, db, client)
return UpdateStakeAccount(parsed.StakeAccount, instruction.Slot, db, client)
}

// handleSetLockupChecked handles a instruction of SetLockupChecked
func handleSetLockupChecked(instruction types.Instruction, tx types.Tx, db db.StakeDb, client client.ClientProxy) error {
func handleSetLockupChecked(instruction types.Instruction, db db.StakeDb, client ClientProxy) error {
parsed, ok := instruction.Parsed.Value.(stake.ParsedSetLockupChecked)
if !ok {
return fmt.Errorf("instruction does not match %s type: %s", "setLockupChecked", instruction.Parsed.Type)

}
return updateStakeAccount(parsed.StakeAccount, tx.Slot, db, client)
return UpdateStakeAccount(parsed.StakeAccount, instruction.Slot, db, client)
}
Loading

0 comments on commit a1c1b9b

Please sign in to comment.