github.com/filecoin-project/specs-actors/v4@v4.0.2/actors/builtin/cron/cron_test.go (about)

     1  package cron_test
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/filecoin-project/go-state-types/abi"
     7  	"github.com/filecoin-project/go-state-types/big"
     8  	"github.com/filecoin-project/go-state-types/exitcode"
     9  	"github.com/stretchr/testify/assert"
    10  
    11  	"github.com/filecoin-project/specs-actors/v4/actors/builtin"
    12  	"github.com/filecoin-project/specs-actors/v4/actors/builtin/cron"
    13  	"github.com/filecoin-project/specs-actors/v4/support/mock"
    14  	tutil "github.com/filecoin-project/specs-actors/v4/support/testing"
    15  )
    16  
    17  func TestExports(t *testing.T) {
    18  	mock.CheckActorExports(t, cron.Actor{})
    19  }
    20  
    21  func TestConstructor(t *testing.T) {
    22  	actor := cronHarness{cron.Actor{}, t}
    23  
    24  	receiver := tutil.NewIDAddr(t, 100)
    25  	builder := mock.NewBuilder(receiver).WithCaller(builtin.SystemActorAddr, builtin.SystemActorCodeID)
    26  
    27  	t.Run("construct with empty entries", func(t *testing.T) {
    28  		rt := builder.Build(t)
    29  
    30  		actor.constructAndVerify(rt)
    31  
    32  		var st cron.State
    33  		rt.GetState(&st)
    34  		var nilCronEntries = []cron.Entry(nil)
    35  		assert.Equal(t, nilCronEntries, st.Entries)
    36  
    37  		actor.checkState(rt)
    38  	})
    39  
    40  	t.Run("construct with non-empty entries", func(t *testing.T) {
    41  		rt := builder.Build(t)
    42  
    43  		var entryParams = []cron.EntryParam{
    44  			{Receiver: tutil.NewIDAddr(t, 1001), MethodNum: abi.MethodNum(1001)},
    45  			{Receiver: tutil.NewIDAddr(t, 1002), MethodNum: abi.MethodNum(1002)},
    46  			{Receiver: tutil.NewIDAddr(t, 1003), MethodNum: abi.MethodNum(1003)},
    47  			{Receiver: tutil.NewIDAddr(t, 1004), MethodNum: abi.MethodNum(1004)},
    48  		}
    49  		actor.constructAndVerify(rt, entryParams...)
    50  
    51  		var st cron.State
    52  		rt.GetState(&st)
    53  		expectedEntries := make([]cron.Entry, len(entryParams))
    54  		for i, e := range entryParams {
    55  			expectedEntries[i] = cron.Entry(e)
    56  		}
    57  		assert.Equal(t, expectedEntries, st.Entries)
    58  
    59  		actor.checkState(rt)
    60  	})
    61  }
    62  
    63  func TestEpochTick(t *testing.T) {
    64  	actor := cronHarness{cron.Actor{}, t}
    65  
    66  	receiver := tutil.NewIDAddr(t, 100)
    67  	builder := mock.NewBuilder(receiver).WithCaller(builtin.SystemActorAddr, builtin.SystemActorCodeID)
    68  
    69  	t.Run("epoch tick with empty entries", func(t *testing.T) {
    70  		rt := builder.Build(t)
    71  
    72  		var nilCronEntries = []cron.EntryParam(nil)
    73  		actor.constructAndVerify(rt, nilCronEntries...)
    74  		actor.epochTickAndVerify(rt)
    75  		actor.checkState(rt)
    76  	})
    77  
    78  	t.Run("epoch tick with non-empty entries", func(t *testing.T) {
    79  		rt := builder.Build(t)
    80  
    81  		entry1 := cron.EntryParam{Receiver: tutil.NewIDAddr(t, 1001), MethodNum: abi.MethodNum(1001)}
    82  		entry2 := cron.EntryParam{Receiver: tutil.NewIDAddr(t, 1002), MethodNum: abi.MethodNum(1002)}
    83  		entry3 := cron.EntryParam{Receiver: tutil.NewIDAddr(t, 1003), MethodNum: abi.MethodNum(1003)}
    84  		entry4 := cron.EntryParam{Receiver: tutil.NewIDAddr(t, 1004), MethodNum: abi.MethodNum(1004)}
    85  
    86  		actor.constructAndVerify(rt, entry1, entry2, entry3, entry4)
    87  		// exit code should not matter
    88  		rt.ExpectSend(entry1.Receiver, entry1.MethodNum, nil, big.Zero(), nil, exitcode.Ok)
    89  		rt.ExpectSend(entry2.Receiver, entry2.MethodNum, nil, big.Zero(), nil, exitcode.ErrIllegalArgument)
    90  		rt.ExpectSend(entry3.Receiver, entry3.MethodNum, nil, big.Zero(), nil, exitcode.ErrInsufficientFunds)
    91  		rt.ExpectSend(entry4.Receiver, entry4.MethodNum, nil, big.Zero(), nil, exitcode.ErrForbidden)
    92  		actor.epochTickAndVerify(rt)
    93  
    94  		actor.checkState(rt)
    95  	})
    96  
    97  	t.Run("built-in entries", func(t *testing.T) {
    98  		bie := cron.BuiltInEntries()
    99  		assert.True(t, len(bie) > 0)
   100  	})
   101  }
   102  
   103  type cronHarness struct {
   104  	cron.Actor
   105  	t testing.TB
   106  }
   107  
   108  func (h *cronHarness) constructAndVerify(rt *mock.Runtime, entries ...cron.EntryParam) {
   109  	params := cron.ConstructorParams{Entries: entries}
   110  	rt.ExpectValidateCallerAddr(builtin.SystemActorAddr)
   111  	ret := rt.Call(h.Constructor, &params)
   112  	assert.Nil(h.t, ret)
   113  	rt.Verify()
   114  }
   115  
   116  func (h *cronHarness) epochTickAndVerify(rt *mock.Runtime) {
   117  	rt.ExpectValidateCallerAddr(builtin.SystemActorAddr)
   118  	ret := rt.Call(h.EpochTick, nil)
   119  	assert.Nil(h.t, ret)
   120  	rt.Verify()
   121  }
   122  
   123  func (h *cronHarness) checkState(rt *mock.Runtime) {
   124  	var st cron.State
   125  	rt.GetState(&st)
   126  	_, msgs := cron.CheckStateInvariants(&st, rt.AdtStore())
   127  	assert.True(h.t, msgs.IsEmpty())
   128  }