Skip to content

Commit 2387b18

Browse files
committed
add tests
1 parent ae5a635 commit 2387b18

File tree

2 files changed

+127
-5
lines changed

2 files changed

+127
-5
lines changed

api/api_errors.go

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ var (
5757
_ error = (*ErrExecutionReverted)(nil)
5858
_ jsonrpc.RPCErrorCodec = (*ErrExecutionReverted)(nil)
5959
_ error = (*ErrNullRound)(nil)
60+
_ jsonrpc.RPCErrorCodec = (*ErrNullRound)(nil)
6061
)
6162

6263
func init() {
@@ -166,17 +167,40 @@ func NewErrExecutionReverted(reason string) *ErrExecutionReverted {
166167
}
167168

168169
type ErrNullRound struct {
169-
Epoch int64
170+
Epoch int64
171+
Message string
170172
}
171173

172174
func NewErrNullRound(epoch int64) *ErrNullRound {
173-
return &ErrNullRound{Epoch: epoch}
175+
return &ErrNullRound{
176+
Epoch: epoch,
177+
Message: fmt.Sprintf("requested epoch was a null round (%d)", epoch),
178+
}
174179
}
175180

176181
func (e *ErrNullRound) Error() string {
177-
return fmt.Sprintf("requested epoch was a null round (%d)", e.Epoch)
182+
return e.Message
178183
}
179184

180-
func init() {
181-
RPCErrors.Register(ENullRound, new(*ErrNullRound))
185+
func (e *ErrNullRound) FromJSONRPCError(jerr jsonrpc.JSONRPCError) error {
186+
if jerr.Code != ENullRound {
187+
return fmt.Errorf("unexpected error code: %d", jerr.Code)
188+
}
189+
190+
epoch, ok := jerr.Data.(float64)
191+
if !ok {
192+
return fmt.Errorf("expected number data in null round error, got %T", jerr.Data)
193+
}
194+
195+
e.Epoch = int64(epoch)
196+
e.Message = jerr.Message
197+
return nil
198+
}
199+
200+
func (e *ErrNullRound) ToJSONRPCError() (jsonrpc.JSONRPCError, error) {
201+
return jsonrpc.JSONRPCError{
202+
Code: ENullRound,
203+
Message: e.Message,
204+
Data: e.Epoch,
205+
}, nil
182206
}

itests/fevm_test.go

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"encoding/binary"
88
"encoding/hex"
99
"encoding/json"
10+
"errors"
1011
"fmt"
1112
"os"
1213
"testing"
@@ -1659,3 +1660,100 @@ func TestEthEstimateGas(t *testing.T) {
16591660
})
16601661
}
16611662
}
1663+
1664+
func TestEthNullRoundHandling(t *testing.T) {
1665+
blockTime := 100 * time.Millisecond
1666+
client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC())
1667+
1668+
bms := ens.InterconnectAll().BeginMining(blockTime)
1669+
1670+
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
1671+
defer cancel()
1672+
1673+
bms[0].InjectNulls(10)
1674+
1675+
tctx, cancel := context.WithTimeout(ctx, 30*time.Second)
1676+
defer cancel()
1677+
ch, err := client.ChainNotify(tctx)
1678+
require.NoError(t, err)
1679+
<-ch
1680+
hc := <-ch
1681+
require.Equal(t, store.HCApply, hc[0].Type)
1682+
1683+
afterNullHeight := hc[0].Val.Height()
1684+
1685+
nullHeight := afterNullHeight - 1
1686+
for nullHeight > 0 {
1687+
ts, err := client.ChainGetTipSetByHeight(ctx, nullHeight, types.EmptyTSK)
1688+
require.NoError(t, err)
1689+
if ts.Height() == nullHeight {
1690+
nullHeight--
1691+
} else {
1692+
break
1693+
}
1694+
}
1695+
1696+
nullBlockHex := fmt.Sprintf("0x%x", nullHeight)
1697+
1698+
testCases := []struct {
1699+
name string
1700+
testFunc func() error
1701+
}{
1702+
{
1703+
name: "EthGetBlockByNumber",
1704+
testFunc: func() error {
1705+
_, err := client.EthGetBlockByNumber(ctx, nullBlockHex, true)
1706+
if err == nil {
1707+
return errors.New("expected error for null round")
1708+
}
1709+
return err
1710+
},
1711+
},
1712+
{
1713+
name: "EthFeeHistory",
1714+
testFunc: func() error {
1715+
params, err := json.Marshal([]interface{}{1, nullBlockHex})
1716+
if err != nil {
1717+
return err
1718+
}
1719+
_, err = client.EthFeeHistory(ctx, params)
1720+
return err
1721+
},
1722+
},
1723+
{
1724+
name: "EthTraceBlock",
1725+
testFunc: func() error {
1726+
_, err := client.EthTraceBlock(ctx, nullBlockHex)
1727+
return err
1728+
},
1729+
},
1730+
{
1731+
name: "EthTraceReplayBlockTransactions",
1732+
testFunc: func() error {
1733+
_, err := client.EthTraceReplayBlockTransactions(ctx, nullBlockHex, []string{"trace"})
1734+
return err
1735+
},
1736+
},
1737+
}
1738+
1739+
for _, tc := range testCases {
1740+
t.Run(tc.name, func(t *testing.T) {
1741+
err := tc.testFunc()
1742+
t.Logf("error: %v", err)
1743+
require.Error(t, err)
1744+
1745+
// Test errors.Is
1746+
require.True(t, errors.Is(err, new(api.ErrNullRound)),
1747+
"error should be or wrap ErrNullRound")
1748+
1749+
// Test errors.As and verify message
1750+
var nullRoundErr *api.ErrNullRound
1751+
require.True(t, errors.As(err, &nullRoundErr),
1752+
"error should be convertible to ErrNullRound")
1753+
1754+
expectedMsg := fmt.Sprintf("block number %s was a null round", nullBlockHex)
1755+
require.Equal(t, expectedMsg, nullRoundErr.Error())
1756+
require.Equal(t, nullHeight, nullRoundErr.Epoch)
1757+
})
1758+
}
1759+
}

0 commit comments

Comments
 (0)