Skip to content

Commit

Permalink
Merge branch 'master' into issue3502
Browse files Browse the repository at this point in the history
  • Loading branch information
dustinxie committed Jul 6, 2022
2 parents 196b35a + 9347fed commit 6d9ad91
Show file tree
Hide file tree
Showing 5 changed files with 216 additions and 15 deletions.
20 changes: 20 additions & 0 deletions api/grpcserver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,27 @@ import (
)

func TestGrpcServer_GetAccount(t *testing.T) {
require := require.New(t)
ctrl := gomock.NewController(t)
defer ctrl.Finish()
core := mock_apicoreservice.NewMockCoreService(ctrl)
grpcSvr := newGRPCHandler(core)

for _, test := range _getAccountTests {
accountMeta := &iotextypes.AccountMeta{
Address: test.address,
}
blockIdentifier := &iotextypes.BlockIdentifier{}
request := &iotexapi.GetAccountRequest{
Address: test.address,
}

core.EXPECT().Account(gomock.Any()).Return(accountMeta, blockIdentifier, nil)

res, err := grpcSvr.GetAccount(context.Background(), request)
require.NoError(err)
require.Equal(test.address, res.AccountMeta.Address)
}
}

func TestGrpcServer_GetActions(t *testing.T) {
Expand Down
14 changes: 7 additions & 7 deletions ioctl/newcmd/bc/bc.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,21 +100,21 @@ func GetEpochMeta(client ioctl.Client, epochNum uint64) (*iotexapi.GetEpochMetaR
}

// GetProbationList gets probation list
func GetProbationList(client ioctl.Client, epochNum uint64) (*iotexapi.ReadStateResponse, error) {
func GetProbationList(client ioctl.Client, epochNum uint64, epochStartHeight uint64) (*iotexapi.ReadStateResponse, error) {
apiServiceClient, err := client.APIServiceClient()
if err != nil {
return nil, err
}

ctx := context.Background()
jwtMD, err := util.JwtAuth()
if err == nil {
ctx = metautils.NiceMD(jwtMD).ToOutgoing(ctx)
}
request := &iotexapi.ReadStateRequest{
ProtocolID: []byte("poll"),
MethodName: []byte("ProbationListByEpoch"),
Arguments: [][]byte{[]byte(strconv.FormatUint(epochNum, 10))},
Height: strconv.FormatUint(epochStartHeight, 10),
}
ctx := context.Background()
if jwtMD, err := util.JwtAuth(); err == nil {
ctx = metautils.NiceMD(jwtMD).ToOutgoing(ctx)
}

response, err := apiServiceClient.ReadState(ctx, request)
Expand All @@ -123,7 +123,7 @@ func GetProbationList(client ioctl.Client, epochNum uint64) (*iotexapi.ReadState
if ok && sta.Code() == codes.NotFound {
return nil, nil
} else if ok {
return nil, errors.Wrap(nil, sta.Message())
return nil, errors.New(sta.Message())
}
return nil, errors.Wrap(err, "failed to invoke ReadState api")
}
Expand Down
9 changes: 1 addition & 8 deletions ioctl/newcmd/node/nodedelegate.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import (
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"

"github.com/iotexproject/iotex-core/action/protocol/vote"
"github.com/iotexproject/iotex-core/ioctl"
"github.com/iotexproject/iotex-core/ioctl/config"
"github.com/iotexproject/iotex-core/ioctl/newcmd/bc"
Expand Down Expand Up @@ -190,16 +189,10 @@ func NewNodeDelegateCmd(client ioctl.Client) *cobra.Command {
StartBlock: int(epochData.Height),
TotalBlocks: int(response.TotalBlocks),
}
probationListRes, err := bc.GetProbationList(client, epochNum)
probationList, err := getProbationList(client, epochNum, epochData.Height)
if err != nil {
return errors.Wrap(err, "failed to get probation list")
}
probationList := &vote.ProbationList{}
if probationListRes != nil {
if err := probationList.Deserialize(probationListRes.Data); err != nil {
return errors.Wrap(err, "failed to deserialize probation list")
}
}
for rank, bp := range response.BlockProducersInfo {
votes, ok := new(big.Int).SetString(bp.Votes, 10)
if !ok {
Expand Down
94 changes: 94 additions & 0 deletions ioctl/newcmd/node/nodeprobationlist.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// Copyright (c) 2022 IoTeX Foundation
// This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no
// warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent
// permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache
// License 2.0 that can be found in the LICENSE file.

package node

import (
"encoding/json"
"fmt"

"github.com/pkg/errors"
"github.com/spf13/cobra"

"github.com/iotexproject/iotex-core/action/protocol/vote"
"github.com/iotexproject/iotex-core/ioctl"
"github.com/iotexproject/iotex-core/ioctl/config"
"github.com/iotexproject/iotex-core/ioctl/newcmd/bc"
)

// Multi-language support
var (
_probationlistCmdUses = map[config.Language]string{
config.English: "probationlist [-e epoch-num]",
config.Chinese: "probationlist [-e epoch数]",
}
_probationlistCmdShorts = map[config.Language]string{
config.English: "Print probation list at given epoch",
config.Chinese: "打印给定epoch内的试用名单",
}
)

// NewNodeProbationlistCmd represents querying probation list command
func NewNodeProbationlistCmd(client ioctl.Client) *cobra.Command {
var epochNum uint64
use, _ := client.SelectTranslation(_probationlistCmdUses)
short, _ := client.SelectTranslation(_probationlistCmdShorts)
flagEpochNumUsages, _ := client.SelectTranslation(_flagEpochNumUsages)

cmd := &cobra.Command{
Use: use,
Short: short,
Args: cobra.ExactArgs(0),
RunE: func(cmd *cobra.Command, args []string) error {
cmd.SilenceUsage = true
if epochNum == 0 {
chainMeta, err := bc.GetChainMeta(client)
if err != nil {
return errors.Wrap(err, "failed to get chain meta")
}
epochNum = chainMeta.GetEpoch().GetNum()
}
response, err := bc.GetEpochMeta(client, epochNum)
if err != nil {
return errors.Wrap(err, "failed to get epoch meta")
}
probationlist, err := getProbationList(client, epochNum, response.EpochData.Height)
if err != nil {
return errors.Wrap(err, "failed to get probation list")
}
delegateList := make([]string, 0)
for addr := range probationlist.ProbationInfo {
delegateList = append(delegateList, addr)
}
byteAsJSON, err := json.MarshalIndent(delegateList, "", " ")
if err != nil {
return err
}
cmd.Printf("EpochNumber : %d, IntensityRate : %d%%\nProbationList : %s",
epochNum,
probationlist.IntensityRate,
fmt.Sprint(string(byteAsJSON)),
)
return nil
},
}
cmd.PersistentFlags().Uint64VarP(&epochNum, "epoch-num", "e", 0, flagEpochNumUsages)
return cmd
}

func getProbationList(client ioctl.Client, epochNum uint64, epochStartHeight uint64) (*vote.ProbationList, error) {
probationListRes, err := bc.GetProbationList(client, epochNum, epochStartHeight)
if err != nil {
return nil, err
}
probationList := &vote.ProbationList{}
if probationListRes != nil {
if err := probationList.Deserialize(probationListRes.Data); err != nil {
return nil, err
}
}
return probationList, nil
}
94 changes: 94 additions & 0 deletions ioctl/newcmd/node/nodeprobationlist_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// Copyright (c) 2022 IoTeX Foundation
// This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no
// warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent
// permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache
// License 2.0 that can be found in the LICENSE file.

package node

import (
"strconv"
"testing"

"github.com/golang/mock/gomock"
"github.com/iotexproject/iotex-proto/golang/iotexapi"
"github.com/iotexproject/iotex-proto/golang/iotexapi/mock_iotexapi"
"github.com/iotexproject/iotex-proto/golang/iotextypes"
"github.com/pkg/errors"
"github.com/stretchr/testify/require"

"github.com/iotexproject/iotex-core/action/protocol/vote"
"github.com/iotexproject/iotex-core/ioctl/config"
"github.com/iotexproject/iotex-core/ioctl/util"
"github.com/iotexproject/iotex-core/test/mock/mock_ioctlclient"
)

func TestNewNodeProbationlistCmd(t *testing.T) {
require := require.New(t)
ctrl := gomock.NewController(t)
client := mock_ioctlclient.NewMockClient(ctrl)
apiServiceClient := mock_iotexapi.NewMockAPIServiceClient(ctrl)

client.EXPECT().SelectTranslation(gomock.Any()).Return("", config.English).Times(12)
client.EXPECT().APIServiceClient().Return(apiServiceClient, nil).Times(10)

t.Run("failed to get chain meta", func(t *testing.T) {
expectedErr := errors.New("failed to get chain meta")
apiServiceClient.EXPECT().GetChainMeta(gomock.Any(), gomock.Any()).Return(nil, expectedErr).Times(1)

cmd := NewNodeProbationlistCmd(client)
_, err := util.ExecuteCmd(cmd)
require.Contains(err.Error(), "failed to get chain meta")
})

var testBlockProducersInfo = []*iotexapi.BlockProducerInfo{
{Address: "io1kr8c6krd7dhxaaqwdkr6erqgu4z0scug3drgja", Votes: "109510794521770016955545668", Active: true, Production: 30},
{Address: "io13q2am9nedrd3n746lsj6qan4pymcpgm94vvx2c", Votes: "81497052527306018062463878", Active: false, Production: 0},
}

chainMetaResponse := &iotexapi.GetChainMetaResponse{ChainMeta: &iotextypes.ChainMeta{Epoch: &iotextypes.EpochData{Num: 7000}}}
epochMetaResponse := &iotexapi.GetEpochMetaResponse{EpochData: &iotextypes.EpochData{Num: 7000, Height: 3223081}, TotalBlocks: 720, BlockProducersInfo: testBlockProducersInfo}

apiServiceClient.EXPECT().GetChainMeta(gomock.Any(), gomock.Any()).Return(chainMetaResponse, nil).Times(3)
apiServiceClient.EXPECT().GetEpochMeta(gomock.Any(), gomock.Any()).Return(epochMetaResponse, nil).Times(3)

t.Run("query probation list", func(t *testing.T) {
probationList := &iotexapi.ReadStateResponse{}

apiServiceClient.EXPECT().ReadState(gomock.Any(), gomock.Any()).Return(probationList, nil).Times(1)

cmd := NewNodeProbationlistCmd(client)
result, err := util.ExecuteCmd(cmd)
require.NoError(err)
require.Contains(result, "ProbationList : []")
})

t.Run("epochNum > 0", func(t *testing.T) {
d, _ := vote.NewProbationList(1).Serialize()
probationList := &iotexapi.ReadStateResponse{
Data: d,
}

apiServiceClient.EXPECT().ReadState(gomock.Any(), gomock.Any()).Return(probationList, nil).Times(1)

cmd := NewNodeProbationlistCmd(client)
result, err := util.ExecuteCmd(cmd, "-e", "1")
require.NoError(err)
require.Contains(result, "ProbationList : []")
})

t.Run("failed to get probation list", func(t *testing.T) {
apiServiceClient.EXPECT().ReadState(gomock.Any(), &iotexapi.ReadStateRequest{
ProtocolID: []byte("poll"),
MethodName: []byte("ProbationListByEpoch"),
Arguments: [][]byte{[]byte("7000")},
Height: strconv.FormatUint(3223081, 10),
}).Return(&iotexapi.ReadStateResponse{
Data: []byte("0")},
nil)

cmd := NewNodeProbationlistCmd(client)
_, err := util.ExecuteCmd(cmd)
require.Contains(err.Error(), "failed to get probation list")
})
}

0 comments on commit 6d9ad91

Please sign in to comment.