diff --git a/.gometalinter.json b/.gometalinter.json new file mode 100644 index 000000000..c3cce43ce --- /dev/null +++ b/.gometalinter.json @@ -0,0 +1,28 @@ +{ + "Exclude": [ + ".*_mock.go", + "geth/jail/doc.go" + ], + "Skip": ["helpers", "static"], + "Vendor": true, + "Enable": [ + "deadcode", + "errcheck", + "gas", + "goconst", + "gocyclo", + "gofmt", + "golint", + "ineffassign", + "interfacer", + "megacheck", + "misspell", + "structcheck", + "unconvert", + "unparam", + "varcheck", + "vet" + ], + "Cyclo": 16, + "Deadline": "100s" +} diff --git a/Makefile b/Makefile index 5cc7923ea..43d17db4d 100644 --- a/Makefile +++ b/Makefile @@ -4,8 +4,6 @@ help: ##@other Show this help @perl -e '$(HELP_FUN)' $(MAKEFILE_LIST) -include ./static/tools/mk/lint.mk - ifndef GOPATH $(error GOPATH not set. Please set GOPATH and make sure status-go is located at $$GOPATH/src/github.com/status-im/status-go. \ For more information about the GOPATH environment variable, see https://golang.org/doc/code.html#GOPATH) @@ -136,6 +134,14 @@ test-e2e: ##@tests Run e2e tests # e2e_test tag is required to include some files from ./lib without _test suffix go test -timeout 40m -tags e2e_test ./lib -network=$(networkid) +lint-install: + go get -u github.com/alecthomas/gometalinter + gometalinter --install + +lint: + @echo "lint" + @gometalinter ./... + ci: lint mock test-unit test-e2e ##@tests Run all linters and tests at once clean: ##@other Cleanup diff --git a/e2e/whisper/whisper_mailbox_test.go b/e2e/whisper/whisper_mailbox_test.go index 5865f1e16..a520bf73a 100644 --- a/e2e/whisper/whisper_mailbox_test.go +++ b/e2e/whisper/whisper_mailbox_test.go @@ -80,14 +80,14 @@ func (s *WhisperMailboxSuite) TestRequestMessageFromMailboxAsync() { messageFilterID := s.createPrivateChatMessageFilter(rpcClient, keyID, topic.String()) //Threre are no messages at filter - messages := s.getMessagesByMessageFilterId(rpcClient, messageFilterID) + messages := s.getMessagesByMessageFilterID(rpcClient, messageFilterID) s.Require().Equal(0, len(messages)) //Post message s.postMessageToPrivate(rpcClient, pubkey.String(), topic.String(), hexutil.Encode([]byte("Hello world!"))) //There are no messages, because it's a sender filter - messages = s.getMessagesByMessageFilterId(rpcClient, messageFilterID) + messages = s.getMessagesByMessageFilterID(rpcClient, messageFilterID) s.Require().Equal(0, len(messages)) //act @@ -114,11 +114,11 @@ func (s *WhisperMailboxSuite) TestRequestMessageFromMailboxAsync() { //wait to receive message time.Sleep(time.Second) //And we receive message - messages = s.getMessagesByMessageFilterId(rpcClient, messageFilterID) + messages = s.getMessagesByMessageFilterID(rpcClient, messageFilterID) s.Require().Equal(1, len(messages)) //check that there are no messages - messages = s.getMessagesByMessageFilterId(rpcClient, messageFilterID) + messages = s.getMessagesByMessageFilterID(rpcClient, messageFilterID) s.Require().Equal(0, len(messages)) } @@ -158,9 +158,9 @@ func (s *WhisperMailboxSuite) TestRequestMessagesInGroupChat() { charlieWhisperService, err := charlieBackend.NodeManager().WhisperService() s.Require().NoError(err) //get rpc client - aliceRpcClient := aliceBackend.NodeManager().RPCClient() - bobRpcClient := bobBackend.NodeManager().RPCClient() - charlieRpcClient := charlieBackend.NodeManager().RPCClient() + aliceRPCClient := aliceBackend.NodeManager().RPCClient() + bobRPCClient := bobBackend.NodeManager().RPCClient() + charlieRPCClient := charlieBackend.NodeManager().RPCClient() //bob and charlie add mailserver key password := "status-offline-inbox" @@ -196,79 +196,79 @@ func (s *WhisperMailboxSuite) TestRequestMessagesInGroupChat() { charlieAliceKeySendTopic := whisperv5.BytesToTopic([]byte("charlieAliceKeySendTopic ")) //bob and charlie create message filter - bobMessageFilterID := s.createPrivateChatMessageFilter(bobRpcClient, bobKeyID, bobAliceKeySendTopic.String()) - charlieMessageFilterID := s.createPrivateChatMessageFilter(charlieRpcClient, charlieKeyID, charlieAliceKeySendTopic.String()) + bobMessageFilterID := s.createPrivateChatMessageFilter(bobRPCClient, bobKeyID, bobAliceKeySendTopic.String()) + charlieMessageFilterID := s.createPrivateChatMessageFilter(charlieRPCClient, charlieKeyID, charlieAliceKeySendTopic.String()) //Alice send message with symkey and topic to bob and charlie - s.postMessageToPrivate(aliceRpcClient, bobPubkey.String(), bobAliceKeySendTopic.String(), payloadStr) - s.postMessageToPrivate(aliceRpcClient, charliePubkey.String(), charlieAliceKeySendTopic.String(), payloadStr) + s.postMessageToPrivate(aliceRPCClient, bobPubkey.String(), bobAliceKeySendTopic.String(), payloadStr) + s.postMessageToPrivate(aliceRPCClient, charliePubkey.String(), charlieAliceKeySendTopic.String(), payloadStr) //wait to receive time.Sleep(time.Second) //bob receive group chat data and add it to his node //1. bob get group chat details - messages := s.getMessagesByMessageFilterId(bobRpcClient, bobMessageFilterID) + messages := s.getMessagesByMessageFilterID(bobRPCClient, bobMessageFilterID) s.Require().Equal(1, len(messages)) bobGroupChatData := groupChatParams{} bobGroupChatData.Decode(messages[0]["payload"].(string)) s.EqualValues(groupChatPayload, bobGroupChatData) //2. bob add symkey to his node - bobGroupChatSymkeyID := s.addSymKey(bobRpcClient, bobGroupChatData.Key) + bobGroupChatSymkeyID := s.addSymKey(bobRPCClient, bobGroupChatData.Key) s.Require().NotEmpty(bobGroupChatSymkeyID) //3. bob create message filter to node by group chat topic - bobGroupChatMessageFilterID := s.createGroupChatMessageFilter(bobRpcClient, bobGroupChatSymkeyID, bobGroupChatData.Topic) + bobGroupChatMessageFilterID := s.createGroupChatMessageFilter(bobRPCClient, bobGroupChatSymkeyID, bobGroupChatData.Topic) //charlie receive group chat data and add it to his node //1. charlie get group chat details - messages = s.getMessagesByMessageFilterId(charlieRpcClient, charlieMessageFilterID) + messages = s.getMessagesByMessageFilterID(charlieRPCClient, charlieMessageFilterID) s.Require().Equal(1, len(messages)) charlieGroupChatData := groupChatParams{} charlieGroupChatData.Decode(messages[0]["payload"].(string)) s.EqualValues(groupChatPayload, charlieGroupChatData) //2. charlie add symkey to his node - charlieGroupChatSymkeyID := s.addSymKey(charlieRpcClient, charlieGroupChatData.Key) + charlieGroupChatSymkeyID := s.addSymKey(charlieRPCClient, charlieGroupChatData.Key) s.Require().NotEmpty(charlieGroupChatSymkeyID) //3. charlie create message filter to node by group chat topic - charlieGroupChatMessageFilterID := s.createGroupChatMessageFilter(charlieRpcClient, charlieGroupChatSymkeyID, charlieGroupChatData.Topic) + charlieGroupChatMessageFilterID := s.createGroupChatMessageFilter(charlieRPCClient, charlieGroupChatSymkeyID, charlieGroupChatData.Topic) //alice send message to group chat helloWorldMessage := hexutil.Encode([]byte("Hello world!")) - s.postMessageToGroup(aliceRpcClient, groupChatKeyID, groupChatTopic.String(), helloWorldMessage) + s.postMessageToGroup(aliceRPCClient, groupChatKeyID, groupChatTopic.String(), helloWorldMessage) time.Sleep(time.Second) //it need to receive envelopes by bob and charlie nodes //bob receive group chat message - messages = s.getMessagesByMessageFilterId(bobRpcClient, bobGroupChatMessageFilterID) + messages = s.getMessagesByMessageFilterID(bobRPCClient, bobGroupChatMessageFilterID) s.Require().Equal(1, len(messages)) s.Require().Equal(helloWorldMessage, messages[0]["payload"].(string)) //charlie receive group chat message - messages = s.getMessagesByMessageFilterId(charlieRpcClient, charlieGroupChatMessageFilterID) + messages = s.getMessagesByMessageFilterID(charlieRPCClient, charlieGroupChatMessageFilterID) s.Require().Equal(1, len(messages)) s.Require().Equal(helloWorldMessage, messages[0]["payload"].(string)) //check that we don't receive messages each one time - messages = s.getMessagesByMessageFilterId(bobRpcClient, bobGroupChatMessageFilterID) + messages = s.getMessagesByMessageFilterID(bobRPCClient, bobGroupChatMessageFilterID) s.Require().Equal(0, len(messages)) - messages = s.getMessagesByMessageFilterId(charlieRpcClient, charlieGroupChatMessageFilterID) + messages = s.getMessagesByMessageFilterID(charlieRPCClient, charlieGroupChatMessageFilterID) s.Require().Equal(0, len(messages)) //Request each one messages from mailbox using enode - s.requestHistoricMessages(bobRpcClient, mailboxEnode, bobMailServerKeyID, groupChatTopic.String()) - s.requestHistoricMessages(charlieRpcClient, mailboxEnode, charlieMailServerKeyID, groupChatTopic.String()) + s.requestHistoricMessages(bobRPCClient, mailboxEnode, bobMailServerKeyID, groupChatTopic.String()) + s.requestHistoricMessages(charlieRPCClient, mailboxEnode, charlieMailServerKeyID, groupChatTopic.String()) time.Sleep(time.Second) //wait to receive p2p messages //bob receive p2p message from grop chat filter - messages = s.getMessagesByMessageFilterId(bobRpcClient, bobGroupChatMessageFilterID) + messages = s.getMessagesByMessageFilterID(bobRPCClient, bobGroupChatMessageFilterID) s.Require().Equal(1, len(messages)) s.Require().Equal(helloWorldMessage, messages[0]["payload"].(string)) //charlie receive p2p message from grop chat filter - messages = s.getMessagesByMessageFilterId(charlieRpcClient, charlieGroupChatMessageFilterID) + messages = s.getMessagesByMessageFilterID(charlieRPCClient, charlieGroupChatMessageFilterID) s.Require().Equal(1, len(messages)) s.Require().Equal(helloWorldMessage, messages[0]["payload"].(string)) } @@ -434,8 +434,8 @@ func (s *WhisperMailboxSuite) postMessageToGroup(rpcCli *rpc.Client, groupChatKe s.Require().Nil(postResp.Err) } -//getMessagesByMessageFilterId get received messages by messageFilterID -func (s *WhisperMailboxSuite) getMessagesByMessageFilterId(rpcCli *rpc.Client, messageFilterID string) []map[string]interface{} { +//getMessagesByMessageFilterID get received messages by messageFilterID +func (s *WhisperMailboxSuite) getMessagesByMessageFilterID(rpcCli *rpc.Client, messageFilterID string) []map[string]interface{} { resp := rpcCli.CallRaw(`{ "jsonrpc": "2.0", "method": "shh_getFilterMessages", diff --git a/geth/account/accounts_test.go b/geth/account/accounts_test.go index 4e8cf1b34..345eba4bb 100644 --- a/geth/account/accounts_test.go +++ b/geth/account/accounts_test.go @@ -115,9 +115,9 @@ func TestVerifyAccountPasswordWithAccountBeforeEIP55(t *testing.T) { } var ( - testErrWhisper = errors.New("Can't return a whisper service") - testErrKeyStore = errors.New("Can't return a key store") - testErrAccManager = errors.New("Can't return an account manager") + errWhisper = errors.New("Can't return a whisper service") + errKeyStore = errors.New("Can't return a key store") + errAccManager = errors.New("Can't return an account manager") ) func TestManagerTestSuite(t *testing.T) { @@ -198,9 +198,9 @@ func (s *ManagerTestSuite) TestCreateAccount() { _, _, _, err := s.accManager.CreateAccount(s.password) s.NoError(err) - s.nodeManager.EXPECT().AccountKeyStore().Return(nil, testErrKeyStore) + s.nodeManager.EXPECT().AccountKeyStore().Return(nil, errKeyStore) _, _, _, err = s.accManager.CreateAccount(s.password) - s.Equal(testErrKeyStore, err) + s.Equal(errKeyStore, err) } func (s *ManagerTestSuite) TestRecoverAccount() { @@ -210,9 +210,9 @@ func (s *ManagerTestSuite) TestRecoverAccount() { s.Equal(s.address, addr) s.Equal(s.pubKey, pubKey) - s.nodeManager.EXPECT().AccountKeyStore().Return(nil, testErrKeyStore) + s.nodeManager.EXPECT().AccountKeyStore().Return(nil, errKeyStore) _, _, err = s.accManager.RecoverAccount(s.password, s.mnemonic) - s.Equal(testErrKeyStore, err) + s.Equal(errKeyStore, err) } func (s *ManagerTestSuite) TestSelectAccount() { @@ -234,19 +234,19 @@ func (s *ManagerTestSuite) TestSelectAccount() { }, { "fail_keyStore", - []interface{}{nil, testErrKeyStore}, + []interface{}{nil, errKeyStore}, []interface{}{s.shh, nil}, s.address, s.password, - testErrKeyStore, + errKeyStore, }, { "fail_whisperService", []interface{}{s.keyStore, nil}, - []interface{}{nil, testErrWhisper}, + []interface{}{nil, errWhisper}, s.address, s.password, - testErrWhisper, + errWhisper, }, { "fail_wrongAddress", @@ -312,8 +312,8 @@ func (s *ManagerTestSuite) TestCreateChildAccount() { "fail_keyStore", s.address, s.password, - []interface{}{nil, testErrKeyStore}, - testErrKeyStore, + []interface{}{nil, errKeyStore}, + errKeyStore, }, { "fail_wrongAddress", @@ -365,9 +365,9 @@ func (s *ManagerTestSuite) TestSelectedAndReSelectAccount() { s.T().Run("ReSelect_fail_whisper", func(t *testing.T) { s.reinitMock() - s.nodeManager.EXPECT().WhisperService().Return(nil, testErrWhisper).AnyTimes() + s.nodeManager.EXPECT().WhisperService().Return(nil, errWhisper).AnyTimes() err = s.accManager.ReSelectAccount() - s.Equal(testErrWhisper, err) + s.Equal(errWhisper, err) }) s.accManager.selectedAccount = nil @@ -391,9 +391,9 @@ func (s *ManagerTestSuite) TestLogout() { err := s.accManager.Logout() s.NoError(err) - s.nodeManager.EXPECT().WhisperService().Return(nil, testErrWhisper) + s.nodeManager.EXPECT().WhisperService().Return(nil, errWhisper) err = s.accManager.Logout() - s.Equal(testErrWhisper, err) + s.Equal(errWhisper, err) } // TestAccounts tests cases for (*Manager).Accounts. @@ -411,9 +411,9 @@ func (s *ManagerTestSuite) TestAccounts() { s.NotNil(accs) // Can't get an account manager - s.nodeManager.EXPECT().AccountManager().Return(nil, testErrAccManager) + s.nodeManager.EXPECT().AccountManager().Return(nil, errAccManager) _, err = s.accManager.Accounts() - s.Equal(testErrAccManager, err) + s.Equal(errAccManager, err) // Selected account is nil but doesn't fail s.accManager.selectedAccount = nil @@ -440,10 +440,10 @@ func (s *ManagerTestSuite) TestAddressToDecryptedAccount() { }, { "fail_keyStore", - []interface{}{nil, testErrKeyStore}, + []interface{}{nil, errKeyStore}, s.address, s.password, - testErrKeyStore, + errKeyStore, }, { "fail_wrongAddress", diff --git a/geth/common/types.go b/geth/common/types.go index fcf987351..2ceae3718 100644 --- a/geth/common/types.go +++ b/geth/common/types.go @@ -411,7 +411,7 @@ type NotifyResult struct { const passphraseEnvName = "ACCOUNT_PASSWORD" // LoadTestConfig loads test configuration values from disk -func LoadTestConfig(networkId int) (*TestConfig, error) { +func LoadTestConfig(networkID int) (*TestConfig, error) { var testConfig TestConfig configData := static.MustAsset("config/test-data.json") @@ -419,7 +419,7 @@ func LoadTestConfig(networkId int) (*TestConfig, error) { return nil, err } - if networkId == params.StatusChainNetworkID { + if networkID == params.StatusChainNetworkID { accountsData := static.MustAsset("config/status-chain-accounts.json") if err := json.Unmarshal(accountsData, &testConfig); err != nil { return nil, err diff --git a/geth/jail/console/console.go b/geth/jail/console/console.go index bb16ee5f9..e0d935213 100644 --- a/geth/jail/console/console.go +++ b/geth/jail/console/console.go @@ -18,7 +18,7 @@ func Write(fn otto.FunctionCall, w io.Writer, consoleEventName string) otto.Valu }) // Next print out the giving values. - fmt.Fprintf(w, "%s: %s", consoleEventName, formatForConsole(fn.ArgumentList)) // nolint: gas + fmt.Fprintf(w, "%s: %s", consoleEventName, formatForConsole(fn.ArgumentList)) return otto.UndefinedValue() } diff --git a/geth/txqueue/addrlock.go b/geth/txqueue/addrlock.go index b135d7813..dd08c7f43 100644 --- a/geth/txqueue/addrlock.go +++ b/geth/txqueue/addrlock.go @@ -8,6 +8,7 @@ import ( "github.com/ethereum/go-ethereum/common" ) +// AddrLocker provides locks for addresses type AddrLocker struct { mu sync.Mutex locks map[common.Address]*sync.Mutex diff --git a/geth/txqueue/ethtxclient.go b/geth/txqueue/ethtxclient.go index d83d8da94..baf240e96 100644 --- a/geth/txqueue/ethtxclient.go +++ b/geth/txqueue/ethtxclient.go @@ -25,6 +25,7 @@ type EthTxClient struct { c *rpc.Client } +// NewEthTxClient returns a new EthTxClient for client func NewEthTxClient(client *rpc.Client) *EthTxClient { return &EthTxClient{c: client} } diff --git a/geth/txqueue/fake/txservice.go b/geth/txqueue/fake/txservice.go index ee2a8834a..bcf3ac192 100644 --- a/geth/txqueue/fake/txservice.go +++ b/geth/txqueue/fake/txservice.go @@ -10,6 +10,7 @@ import ( "github.com/golang/mock/gomock" ) +// NewTestServer returns a mocked test server func NewTestServer(ctrl *gomock.Controller) (*rpc.Server, *MockFakePublicTransactionPoolAPI) { srv := rpc.NewServer() svc := NewMockFakePublicTransactionPoolAPI(ctrl) @@ -29,10 +30,10 @@ type CallArgs struct { Data hexutil.Bytes `json:"data"` } -// FakePublicTransactionPoolAPI used to generate mock by mockgen util. +// PublicTransactionPoolAPI used to generate mock by mockgen util. // This was done because PublicTransactionPoolAPI is located in internal/ethapi module // and there is no easy way to generate mocks from internal modules. -type FakePublicTransactionPoolAPI interface { +type PublicTransactionPoolAPI interface { GasPrice(ctx context.Context) (*big.Int, error) EstimateGas(ctx context.Context, args CallArgs) (*hexutil.Big, error) GetTransactionCount(ctx context.Context, address common.Address, blockNr rpc.BlockNumber) (*hexutil.Uint64, error) diff --git a/static/tools/mk/lint.mk b/static/tools/mk/lint.mk deleted file mode 100644 index 4a2fd229c..000000000 --- a/static/tools/mk/lint.mk +++ /dev/null @@ -1,64 +0,0 @@ -LINT_EXCLUDE := --exclude='.*_mock.go' --exclude='geth/jail/doc.go' -LINT_FOLDERS := extkeys cmd/... geth/... e2e/... -LINT_FOLDERS_WITHOUT_TESTS := extkeys cmd/... geth/... - -lint-install: - go get -u github.com/alecthomas/gometalinter - gometalinter --install - -lint: lint-vet lint-gofmt lint-deadcode lint-misspell lint-unparam lint-unused lint-gocyclo lint-errcheck lint-ineffassign lint-interfacer lint-unconvert lint-staticcheck lint-goconst lint-gas lint-varcheck lint-structcheck lint-gosimple - -lint-vet: - @echo "lint-vet" - @gometalinter $(LINT_EXCLUDE) --disable-all --enable=vet --deadline=45s $(LINT_FOLDERS) -lint-golint: - @echo "lint-golint" - @gometalinter $(LINT_EXCLUDE) --disable-all --enable=golint --deadline=45s $(LINT_FOLDERS) -lint-gofmt: - @echo "lint-gofmt" - @gometalinter $(LINT_EXCLUDE) --disable-all --enable=gofmt --deadline=45s $(LINT_FOLDERS) -lint-deadcode: - @echo "lint-deadcode" - @gometalinter $(LINT_EXCLUDE) --disable-all --enable=deadcode --deadline=45s $(LINT_FOLDERS) -lint-misspell: - @echo "lint-misspell" - @gometalinter $(LINT_EXCLUDE) --disable-all --enable=misspell --deadline=45s $(LINT_FOLDERS) -lint-unparam: - @echo "lint-unparam" - @gometalinter $(LINT_EXCLUDE) --disable-all --enable=unparam --deadline=45s $(LINT_FOLDERS) -lint-unused: - @echo "lint-unused" - @gometalinter $(LINT_EXCLUDE) --disable-all --enable=unused --deadline=45s $(LINT_FOLDERS) -lint-gocyclo: - @echo "lint-gocyclo" - @gometalinter $(LINT_EXCLUDE) --disable-all --enable=gocyclo --cyclo-over=16 --deadline=45s $(LINT_FOLDERS) -lint-errcheck: - @echo "lint-errcheck" - @gometalinter $(LINT_EXCLUDE) --disable-all --enable=errcheck --deadline=1m $(LINT_FOLDERS) -lint-ineffassign: - @echo "lint-ineffassign" - @gometalinter $(LINT_EXCLUDE) --disable-all --enable=ineffassign --deadline=45s $(LINT_FOLDERS) -lint-interfacer: - @echo "lint-interfacer" - @gometalinter $(LINT_EXCLUDE) --disable-all --enable=interfacer --deadline=45s $(LINT_FOLDERS) -lint-unconvert: - @echo "lint-unconvert" - @gometalinter $(LINT_EXCLUDE) --disable-all --enable=unconvert --deadline=45s $(LINT_FOLDERS) -lint-staticcheck: - @echo "lint-staticcheck" - @gometalinter $(LINT_EXCLUDE) --disable-all --enable=staticcheck --deadline=45s $(LINT_FOLDERS) -lint-goconst: - @echo "lint-goconst" - @gometalinter $(LINT_EXCLUDE) --disable-all --enable=goconst --deadline=45s $(LINT_FOLDERS) -lint-gas: - @echo "lint-gas" - @gometalinter $(LINT_EXCLUDE) --disable-all --enable=gas --deadline=45s $(LINT_FOLDERS) -lint-varcheck: - @echo "lint-varcheck" - @gometalinter $(LINT_EXCLUDE) --disable-all --enable=varcheck --deadline=45s $(LINT_FOLDERS) -lint-structcheck: - @echo "lint-structcheck" - @gometalinter $(LINT_EXCLUDE) --disable-all --enable=structcheck --deadline=45s $(LINT_FOLDERS) -lint-gosimple: - @echo "lint-gosimple" - @gometalinter $(LINT_EXCLUDE) --disable-all --enable=gosimple --deadline=45s $(LINT_FOLDERS) diff --git a/testing/testing.go b/testing/testing.go index 6868c7231..84a60ef5a 100644 --- a/testing/testing.go +++ b/testing/testing.go @@ -194,9 +194,8 @@ func GetNetworkID() int { func GetAccount1PKFile() string { if GetNetworkID() == params.StatusChainNetworkID { return "test-account1-status-chain.pk" - } else { - return "test-account1.pk" } + return "test-account1.pk" } // GetAccount2PKFile returns the filename for Account2 keystore based @@ -205,9 +204,8 @@ func GetAccount1PKFile() string { func GetAccount2PKFile() string { if GetNetworkID() == params.StatusChainNetworkID { return "test-account2-status-chain.pk" - } else { - return "test-account2.pk" } + return "test-account2.pk" } // WaitClosed used to wait on a channel in tests