Add tests for the API to change addresses being watched in direct indexing

This commit is contained in:
Prathamesh Musale 2022-02-01 15:32:39 +05:30
parent 381c61c517
commit 19aff30d61
6 changed files with 754 additions and 16 deletions

View File

@ -90,8 +90,10 @@ func loadWatchedAddresses(db *postgres.DB) error {
return fmt.Errorf("error loading watched addresses: %v", err)
}
var watchedAddresses []common.Address
var watchedStorageSlots []common.Hash
var (
watchedAddresses = []common.Address{}
watchedStorageSlots = []common.Hash{}
)
for _, entry := range watched {
switch entry.Kind {
case types.WatchedAddress.Int():

View File

@ -109,8 +109,6 @@ type IService interface {
WriteLoop(chainEventCh chan core.ChainEvent)
// Method to change the addresses being watched in write loop params
WatchAddress(operation OperationType, args []WatchAddressArg) error
// Method to get currently watched addresses from write loop params
GetWatchedAddresses() []common.Address
}
// Wraps consructor parameters
@ -825,7 +823,7 @@ func (sds *Service) WatchAddress(operation OperationType, args []WatchAddressArg
}
// update in-memory params
writeLoopParams.WatchedAddresses = nil
writeLoopParams.WatchedAddresses = []common.Address{}
case AddStorageSlots:
// filter out args having an already watched storage slot with a warning
@ -902,7 +900,7 @@ func (sds *Service) WatchAddress(operation OperationType, args []WatchAddressArg
return err
}
writeLoopParams.WatchedStorageSlots = nil
writeLoopParams.WatchedStorageSlots = []common.Hash{}
default:
return fmt.Errorf("Unexpected operation %s", operation)
@ -910,8 +908,3 @@ func (sds *Service) WatchAddress(operation OperationType, args []WatchAddressArg
return nil
}
// Gets currently watched addresses from the in-memory write loop params
func (sds *Service) GetWatchedAddresses() []common.Address {
return writeLoopParams.WatchedAddresses
}

View File

@ -39,6 +39,7 @@ type BlockChain struct {
Receipts map[common.Hash]types.Receipts
TDByHash map[common.Hash]*big.Int
TDByNum map[uint64]*big.Int
currentBlock *types.Block
}
// SetBlocksForHashes mock method
@ -128,9 +129,14 @@ func (bc *BlockChain) GetTd(hash common.Hash, blockNum uint64) *big.Int {
return nil
}
// SetCurrentBlock test method
func (bc *BlockChain) SetCurrentBlock(block *types.Block) {
bc.currentBlock = block
}
// CurrentBlock mock method
func (bc *BlockChain) CurrentBlock() *types.Block {
return nil
return bc.currentBlock
}
func (bc *BlockChain) SetTd(hash common.Hash, blockNum uint64, td *big.Int) {

View File

@ -0,0 +1,59 @@
// Copyright 2022 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package mocks
import (
"math/big"
"time"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/statediff/indexer"
sdtypes "github.com/ethereum/go-ethereum/statediff/types"
)
// Indexer is a mock state diff indexer
type Indexer struct{}
func (sdi *Indexer) PushBlock(block *types.Block, receipts types.Receipts, totalDifficulty *big.Int) (*indexer.BlockTx, error) {
return nil, nil
}
func (sdi *Indexer) PushStateNode(tx *indexer.BlockTx, stateNode sdtypes.StateNode) error {
return nil
}
func (sdi *Indexer) PushCodeAndCodeHash(tx *indexer.BlockTx, codeAndCodeHash sdtypes.CodeAndCodeHash) error {
return nil
}
func (sdi *Indexer) ReportDBMetrics(delay time.Duration, quit <-chan bool) {}
func (sdi *Indexer) InsertWatchedAddresses(addresses []sdtypes.WatchAddressArg, currentBlock *big.Int, kind sdtypes.WatchedAddressType) error {
return nil
}
func (sdi *Indexer) RemoveWatchedAddresses(addresses []sdtypes.WatchAddressArg, kind sdtypes.WatchedAddressType) error {
return nil
}
func (sdi *Indexer) SetWatchedAddresses(args []sdtypes.WatchAddressArg, currentBlockNumber *big.Int, kind sdtypes.WatchedAddressType) error {
return nil
}
func (sdi *Indexer) ClearWatchedAddresses(kind sdtypes.WatchedAddressType) error {
return nil
}

View File

@ -25,6 +25,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rlp"
"github.com/thoas/go-funk"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
@ -32,9 +33,12 @@ import (
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/statediff"
ind "github.com/ethereum/go-ethereum/statediff/indexer"
sdtypes "github.com/ethereum/go-ethereum/statediff/types"
)
var typeAssertionFailed = "type assertion failed"
// MockStateDiffService is a mock state diff service
type MockStateDiffService struct {
sync.Mutex
@ -47,6 +51,8 @@ type MockStateDiffService struct {
QuitChan chan bool
Subscriptions map[common.Hash]map[rpc.ID]statediff.Subscription
SubscriptionTypes map[common.Hash]statediff.Params
Indexer ind.Indexer
writeLoopParams statediff.ParamsWithMutex
}
// Protocols mock method
@ -333,10 +339,175 @@ func sendNonBlockingQuit(id rpc.ID, sub statediff.Subscription) {
}
}
// WatchAddress mock method
func (sds *MockStateDiffService) WatchAddress(operation statediff.OperationType, args []sdtypes.WatchAddressArg) error {
// lock writeLoopParams for a write
sds.writeLoopParams.Lock()
defer sds.writeLoopParams.Unlock()
// get the current block number
currentBlockNumber := sds.BlockChain.CurrentBlock().Number()
switch operation {
case statediff.AddAddresses:
// filter out args having an already watched address with a warning
filteredArgs, ok := funk.Filter(args, func(arg sdtypes.WatchAddressArg) bool {
if funk.Contains(sds.writeLoopParams.WatchedAddresses, common.HexToAddress(arg.Address)) {
log.Warn("Address already being watched", "address", arg.Address)
return false
}
return true
}).([]sdtypes.WatchAddressArg)
if !ok {
return fmt.Errorf("AddAddresses: filtered args %s", typeAssertionFailed)
}
// get addresses from the filtered args
filteredAddresses, ok := funk.Map(filteredArgs, func(arg sdtypes.WatchAddressArg) common.Address {
return common.HexToAddress(arg.Address)
}).([]common.Address)
if !ok {
return fmt.Errorf("AddAddresses: filtered addresses %s", typeAssertionFailed)
}
// update the db
err := sds.Indexer.InsertWatchedAddresses(filteredArgs, currentBlockNumber, sdtypes.WatchedAddress)
if err != nil {
return err
}
// update in-memory params
sds.writeLoopParams.WatchedAddresses = append(sds.writeLoopParams.WatchedAddresses, filteredAddresses...)
case statediff.RemoveAddresses:
// get addresses from args
argAddresses, ok := funk.Map(args, func(arg sdtypes.WatchAddressArg) common.Address {
return common.HexToAddress(arg.Address)
}).([]common.Address)
if !ok {
return fmt.Errorf("RemoveAddresses: mapped addresses %s", typeAssertionFailed)
}
// remove the provided addresses from currently watched addresses
addresses, ok := funk.Subtract(sds.writeLoopParams.WatchedAddresses, argAddresses).([]common.Address)
if !ok {
return fmt.Errorf("RemoveAddresses: filtered addresses %s", typeAssertionFailed)
}
// update the db
err := sds.Indexer.RemoveWatchedAddresses(args, sdtypes.WatchedAddress)
if err != nil {
return err
}
// update in-memory params
sds.writeLoopParams.WatchedAddresses = addresses
case statediff.SetAddresses:
// get addresses from args
argAddresses, ok := funk.Map(args, func(arg sdtypes.WatchAddressArg) common.Address {
return common.HexToAddress(arg.Address)
}).([]common.Address)
if !ok {
return fmt.Errorf("SetAddresses: mapped addresses %s", typeAssertionFailed)
}
// update the db
err := sds.Indexer.SetWatchedAddresses(args, currentBlockNumber, sdtypes.WatchedAddress)
if err != nil {
return err
}
// update in-memory params
sds.writeLoopParams.WatchedAddresses = argAddresses
case statediff.ClearAddresses:
// update the db
err := sds.Indexer.ClearWatchedAddresses(sdtypes.WatchedAddress)
if err != nil {
return err
}
// update in-memory params
sds.writeLoopParams.WatchedAddresses = []common.Address{}
case statediff.AddStorageSlots:
// filter out args having an already watched storage slot with a warning
filteredArgs, ok := funk.Filter(args, func(arg sdtypes.WatchAddressArg) bool {
if funk.Contains(sds.writeLoopParams.WatchedStorageSlots, common.HexToHash(arg.Address)) {
log.Warn("StorageSlot already being watched", "address", arg.Address)
return false
}
return true
}).([]sdtypes.WatchAddressArg)
if !ok {
return fmt.Errorf("AddStorageSlots: filtered args %s", typeAssertionFailed)
}
// get storage slots from the filtered args
filteredStorageSlots, ok := funk.Map(filteredArgs, func(arg sdtypes.WatchAddressArg) common.Hash {
return common.HexToHash(arg.Address)
}).([]common.Hash)
if !ok {
return fmt.Errorf("AddStorageSlots: filtered storage slots %s", typeAssertionFailed)
}
// update the db
err := sds.Indexer.InsertWatchedAddresses(filteredArgs, currentBlockNumber, sdtypes.WatchedStorageSlot)
if err != nil {
return err
}
// update in-memory params
sds.writeLoopParams.WatchedStorageSlots = append(sds.writeLoopParams.WatchedStorageSlots, filteredStorageSlots...)
case statediff.RemoveStorageSlots:
// get storage slots from args
argStorageSlots, ok := funk.Map(args, func(arg sdtypes.WatchAddressArg) common.Hash {
return common.HexToHash(arg.Address)
}).([]common.Hash)
if !ok {
return fmt.Errorf("RemoveStorageSlots: mapped storage slots %s", typeAssertionFailed)
}
// remove the provided storage slots from currently watched storage slots
storageSlots, ok := funk.Subtract(sds.writeLoopParams.WatchedStorageSlots, argStorageSlots).([]common.Hash)
if !ok {
return fmt.Errorf("RemoveStorageSlots: filtered storage slots %s", typeAssertionFailed)
}
// update the db
err := sds.Indexer.RemoveWatchedAddresses(args, sdtypes.WatchedStorageSlot)
if err != nil {
return err
}
// update in-memory params
sds.writeLoopParams.WatchedStorageSlots = storageSlots
case statediff.SetStorageSlots:
// get storage slots from args
argStorageSlots, ok := funk.Map(args, func(arg sdtypes.WatchAddressArg) common.Hash {
return common.HexToHash(arg.Address)
}).([]common.Hash)
if !ok {
return fmt.Errorf("SetStorageSlots: mapped storage slots %s", typeAssertionFailed)
}
// update the db
err := sds.Indexer.SetWatchedAddresses(args, currentBlockNumber, sdtypes.WatchedStorageSlot)
if err != nil {
return err
}
// update in-memory params
sds.writeLoopParams.WatchedStorageSlots = argStorageSlots
case statediff.ClearStorageSlots:
err := sds.Indexer.ClearWatchedAddresses(sdtypes.WatchedStorageSlot)
if err != nil {
return err
}
sds.writeLoopParams.WatchedStorageSlots = []common.Hash{}
default:
return fmt.Errorf("Unexpected operation %s", operation)
}
return nil
}
func (sds *MockStateDiffService) GetWatchedAddresses() []common.Address {
return []common.Address{}
}

View File

@ -21,12 +21,14 @@ import (
"fmt"
"math/big"
"os"
"reflect"
"sort"
"sync"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/statediff"
@ -87,6 +89,7 @@ func init() {
func TestAPI(t *testing.T) {
testSubscriptionAPI(t)
testHTTPAPI(t)
testWatchAddressAPI(t)
}
func testSubscriptionAPI(t *testing.T) {
@ -246,3 +249,507 @@ func testHTTPAPI(t *testing.T) {
t.Errorf("paylaod does not have the expected total difficulty\r\nactual td: %d\r\nexpected td: %d", payload.TotalDifficulty.Int64(), mockTotalDifficulty.Int64())
}
}
func testWatchAddressAPI(t *testing.T) {
blocks, chain := testhelpers.MakeChain(6, testhelpers.Genesis, testhelpers.TestChainGen)
defer chain.Stop()
block6 := blocks[5]
mockBlockChain := &BlockChain{}
mockBlockChain.SetCurrentBlock(block6)
mockIndexer := Indexer{}
mockService := MockStateDiffService{
BlockChain: mockBlockChain,
Indexer: &mockIndexer,
}
var (
contract1Address = "0x5d663F5269090bD2A7DC2390c911dF6083D7b28F"
contract2Address = "0x6Eb7e5C66DB8af2E96159AC440cbc8CDB7fbD26B"
contract3Address = "0xcfeB164C328CA13EFd3C77E1980d94975aDfedfc"
contract4Address = "0x0Edf0c4f393a628DE4828B228C48175b3EA297fc"
contract1CreatedAt = uint64(1)
contract2CreatedAt = uint64(2)
contract3CreatedAt = uint64(3)
contract4CreatedAt = uint64(4)
slot1 = common.HexToHash("1")
slot2 = common.HexToHash("2")
slot3 = common.HexToHash("3")
slot4 = common.HexToHash("4")
slot1StorageKey = crypto.Keccak256Hash(slot1.Bytes())
slot2StorageKey = crypto.Keccak256Hash(slot2.Bytes())
slot3StorageKey = crypto.Keccak256Hash(slot3.Bytes())
slot4StorageKey = crypto.Keccak256Hash(slot4.Bytes())
slot1StorageKeyHex = crypto.Keccak256Hash(slot1.Bytes()).Hex()
slot2StorageKeyHex = crypto.Keccak256Hash(slot2.Bytes()).Hex()
slot3StorageKeyHex = crypto.Keccak256Hash(slot3.Bytes()).Hex()
slot4StorageKeyHex = crypto.Keccak256Hash(slot4.Bytes()).Hex()
slot1CreatedAt = uint64(1)
slot2CreatedAt = uint64(2)
slot3CreatedAt = uint64(3)
slot4CreatedAt = uint64(4)
args1 = []sdtypes.WatchAddressArg{
{
Address: contract1Address,
CreatedAt: contract1CreatedAt,
},
{
Address: contract2Address,
CreatedAt: contract2CreatedAt,
},
}
startingParams1 = statediff.Params{
WatchedAddresses: []common.Address{},
}
expectedParams1 = statediff.Params{
WatchedAddresses: []common.Address{
common.HexToAddress(contract1Address),
common.HexToAddress(contract2Address),
},
}
args2 = []sdtypes.WatchAddressArg{
{
Address: contract3Address,
CreatedAt: contract3CreatedAt,
},
{
Address: contract2Address,
CreatedAt: contract2CreatedAt,
},
}
startingParams2 = expectedParams1
expectedParams2 = statediff.Params{
WatchedAddresses: []common.Address{
common.HexToAddress(contract1Address),
common.HexToAddress(contract2Address),
common.HexToAddress(contract3Address),
},
}
args3 = []sdtypes.WatchAddressArg{
{
Address: contract3Address,
CreatedAt: contract3CreatedAt,
},
{
Address: contract2Address,
CreatedAt: contract2CreatedAt,
},
}
startingParams3 = expectedParams2
expectedParams3 = statediff.Params{
WatchedAddresses: []common.Address{
common.HexToAddress(contract1Address),
},
}
args4 = []sdtypes.WatchAddressArg{
{
Address: contract1Address,
CreatedAt: contract1CreatedAt,
},
{
Address: contract2Address,
CreatedAt: contract2CreatedAt,
},
}
startingParams4 = expectedParams3
expectedParams4 = statediff.Params{
WatchedAddresses: []common.Address{},
}
args5 = []sdtypes.WatchAddressArg{
{
Address: contract1Address,
CreatedAt: contract1CreatedAt,
},
{
Address: contract2Address,
CreatedAt: contract2CreatedAt,
},
{
Address: contract3Address,
CreatedAt: contract3CreatedAt,
},
}
startingParams5 = expectedParams4
expectedParams5 = statediff.Params{
WatchedAddresses: []common.Address{
common.HexToAddress(contract1Address),
common.HexToAddress(contract2Address),
common.HexToAddress(contract3Address),
},
}
args6 = []sdtypes.WatchAddressArg{
{
Address: contract4Address,
CreatedAt: contract4CreatedAt,
},
{
Address: contract2Address,
CreatedAt: contract2CreatedAt,
},
{
Address: contract3Address,
CreatedAt: contract3CreatedAt,
},
}
startingParams6 = expectedParams5
expectedParams6 = statediff.Params{
WatchedAddresses: []common.Address{
common.HexToAddress(contract4Address),
common.HexToAddress(contract2Address),
common.HexToAddress(contract3Address),
},
}
args7 = []sdtypes.WatchAddressArg{}
startingParams7 = expectedParams6
expectedParams7 = statediff.Params{
WatchedAddresses: []common.Address{},
}
args8 = []sdtypes.WatchAddressArg{}
startingParams8 = expectedParams6
expectedParams8 = statediff.Params{
WatchedAddresses: []common.Address{},
}
args9 = []sdtypes.WatchAddressArg{}
startingParams9 = expectedParams8
expectedParams9 = statediff.Params{
WatchedAddresses: []common.Address{},
}
args10 = []sdtypes.WatchAddressArg{
{
Address: slot1StorageKeyHex,
CreatedAt: slot1CreatedAt,
},
{
Address: slot2StorageKeyHex,
CreatedAt: slot2CreatedAt,
},
}
startingParams10 = statediff.Params{
WatchedStorageSlots: []common.Hash{},
}
expectedParams10 = statediff.Params{
WatchedStorageSlots: []common.Hash{
slot1StorageKey,
slot2StorageKey,
},
}
args11 = []sdtypes.WatchAddressArg{
{
Address: slot3StorageKeyHex,
CreatedAt: slot3CreatedAt,
},
{
Address: slot2StorageKeyHex,
CreatedAt: slot2CreatedAt,
},
}
startingParams11 = expectedParams10
expectedParams11 = statediff.Params{
WatchedStorageSlots: []common.Hash{
slot1StorageKey,
slot2StorageKey,
slot3StorageKey,
},
}
args12 = []sdtypes.WatchAddressArg{
{
Address: slot3StorageKeyHex,
CreatedAt: slot3CreatedAt,
},
{
Address: slot2StorageKeyHex,
CreatedAt: slot2CreatedAt,
},
}
startingParams12 = expectedParams11
expectedParams12 = statediff.Params{
WatchedStorageSlots: []common.Hash{
slot1StorageKey,
},
}
args13 = []sdtypes.WatchAddressArg{
{
Address: slot1StorageKeyHex,
CreatedAt: slot1CreatedAt,
},
{
Address: slot2StorageKeyHex,
CreatedAt: slot2CreatedAt,
},
}
startingParams13 = expectedParams12
expectedParams13 = statediff.Params{
WatchedStorageSlots: []common.Hash{},
}
args14 = []sdtypes.WatchAddressArg{
{
Address: slot1StorageKeyHex,
CreatedAt: slot1CreatedAt,
},
{
Address: slot2StorageKeyHex,
CreatedAt: slot2CreatedAt,
},
{
Address: slot3StorageKeyHex,
CreatedAt: slot3CreatedAt,
},
}
startingParams14 = expectedParams13
expectedParams14 = statediff.Params{
WatchedStorageSlots: []common.Hash{
slot1StorageKey,
slot2StorageKey,
slot3StorageKey,
},
}
args15 = []sdtypes.WatchAddressArg{
{
Address: slot4StorageKeyHex,
CreatedAt: slot4CreatedAt,
},
{
Address: slot2StorageKeyHex,
CreatedAt: slot2CreatedAt,
},
{
Address: slot3StorageKeyHex,
CreatedAt: slot3CreatedAt,
},
}
startingParams15 = expectedParams14
expectedParams15 = statediff.Params{
WatchedStorageSlots: []common.Hash{
slot4StorageKey,
slot2StorageKey,
slot3StorageKey,
},
}
args16 = []sdtypes.WatchAddressArg{}
startingParams16 = expectedParams15
expectedParams16 = statediff.Params{
WatchedStorageSlots: []common.Hash{},
}
args17 = []sdtypes.WatchAddressArg{}
startingParams17 = expectedParams15
expectedParams17 = statediff.Params{
WatchedStorageSlots: []common.Hash{},
}
args18 = []sdtypes.WatchAddressArg{}
startingParams18 = expectedParams17
expectedParams18 = statediff.Params{
WatchedStorageSlots: []common.Hash{},
}
)
tests := []struct {
name string
operation statediff.OperationType
args []sdtypes.WatchAddressArg
startingParams statediff.Params
expectedParams statediff.Params
expectedErr error
}{
// addresses tests
{
"testAddAddresses",
statediff.AddAddresses,
args1,
startingParams1,
expectedParams1,
nil,
},
{
"testAddAddressesSomeWatched",
statediff.AddAddresses,
args2,
startingParams2,
expectedParams2,
nil,
},
{
"testRemoveAddresses",
statediff.RemoveAddresses,
args3,
startingParams3,
expectedParams3,
nil,
},
{
"testRemoveAddressesSomeWatched",
statediff.RemoveAddresses,
args4,
startingParams4,
expectedParams4,
nil,
},
{
"testSetAddresses",
statediff.SetAddresses,
args5,
startingParams5,
expectedParams5,
nil,
},
{
"testSetAddressesSomeWatched",
statediff.SetAddresses,
args6,
startingParams6,
expectedParams6,
nil,
},
{
"testSetAddressesEmtpyArgs",
statediff.SetAddresses,
args7,
startingParams7,
expectedParams7,
nil,
},
{
"testClearAddresses",
statediff.ClearAddresses,
args8,
startingParams8,
expectedParams8,
nil,
},
{
"testClearAddressesEmpty",
statediff.ClearAddresses,
args9,
startingParams9,
expectedParams9,
nil,
},
// storage slots tests
{
"testAddStorageSlots",
statediff.AddStorageSlots,
args10,
startingParams10,
expectedParams10,
nil,
},
{
"testAddStorageSlotsSomeWatched",
statediff.AddStorageSlots,
args11,
startingParams11,
expectedParams11,
nil,
},
{
"testRemoveStorageSlots",
statediff.RemoveStorageSlots,
args12,
startingParams12,
expectedParams12,
nil,
},
{
"testRemoveStorageSlotsSomeWatched",
statediff.RemoveStorageSlots,
args13,
startingParams13,
expectedParams13,
nil,
},
{
"testSetStorageSlots",
statediff.SetStorageSlots,
args14,
startingParams14,
expectedParams14,
nil,
},
{
"testSetStorageSlotsSomeWatched",
statediff.SetStorageSlots,
args15,
startingParams15,
expectedParams15,
nil,
},
{
"testSetStorageSlotsEmtpyArgs",
statediff.SetStorageSlots,
args16,
startingParams16,
expectedParams16,
nil,
},
{
"testClearStorageSlots",
statediff.ClearStorageSlots,
args17,
startingParams17,
expectedParams17,
nil,
},
{
"testClearStorageSlotsEmpty",
statediff.ClearStorageSlots,
args18,
startingParams18,
expectedParams18,
nil,
},
// invalid args
{
"testInvalidOperation",
"WrongOp",
args18,
startingParams18,
statediff.Params{},
fmt.Errorf("Unexpected operation WrongOp"),
},
}
for _, test := range tests {
mockService.writeLoopParams = statediff.ParamsWithMutex{
Params: test.startingParams,
}
err := mockService.WatchAddress(test.operation, test.args)
if test.expectedErr != nil {
if err.Error() != test.expectedErr.Error() {
t.Logf("Test failed: %s", test.name)
t.Errorf("actual err: %+v\nexpected err: %+v", err, test.expectedErr)
}
continue
}
if err != nil {
t.Error(err)
}
updatedParams := mockService.writeLoopParams.Params
if !reflect.DeepEqual(updatedParams, test.expectedParams) {
t.Logf("Test failed: %s", test.name)
t.Errorf("actual params: %+v\nexpected params: %+v", updatedParams, test.expectedParams)
}
}
}