diff options
Diffstat (limited to 'ledger/apply/application_test.go')
-rw-r--r-- | ledger/apply/application_test.go | 138 |
1 files changed, 88 insertions, 50 deletions
diff --git a/ledger/apply/application_test.go b/ledger/apply/application_test.go index 3251f0470..124a40936 100644 --- a/ledger/apply/application_test.go +++ b/ledger/apply/application_test.go @@ -114,7 +114,7 @@ type testBalances struct { // logic evaluator control pass bool - delta basics.EvalDelta + delta transactions.EvalDelta err error } @@ -126,6 +126,12 @@ const appIdxError basics.AppIndex = 0x11223344 const appIdxOk basics.AppIndex = 1 func (b *testBalances) Get(addr basics.Address, withPendingRewards bool) (basics.AccountData, error) { + if b.putBalances != nil { + ad, ok := b.putBalances[addr] + if ok { + return ad, nil + } + } ad, ok := b.balances[addr] if !ok { return basics.AccountData{}, fmt.Errorf("mock balance not found") @@ -219,7 +225,7 @@ func (b *testBalances) DeallocateAsset(addr basics.Address, index basics.AssetIn return nil } -func (b *testBalances) StatefulEval(params logic.EvalParams, aidx basics.AppIndex, program []byte) (passed bool, evalDelta basics.EvalDelta, err error) { +func (b *testBalances) StatefulEval(params logic.EvalParams, aidx basics.AppIndex, program []byte) (passed bool, evalDelta transactions.EvalDelta, err error) { return b.pass, b.delta, b.err } @@ -252,7 +258,7 @@ func (b *testBalancesPass) Deallocate(addr basics.Address, aidx basics.AppIndex, return nil } -func (b *testBalancesPass) StatefulEval(params logic.EvalParams, aidx basics.AppIndex, program []byte) (passed bool, evalDelta basics.EvalDelta, err error) { +func (b *testBalancesPass) StatefulEval(params logic.EvalParams, aidx basics.AppIndex, program []byte) (passed bool, evalDelta transactions.EvalDelta, err error) { return true, b.delta, nil } @@ -275,14 +281,14 @@ func (b *testBalances) SetParams(params config.ConsensusParams) { type testEvaluator struct { pass bool - delta basics.EvalDelta + delta transactions.EvalDelta appIdx basics.AppIndex } // Eval for tests that fail on program version > 10 and returns pass/delta from its own state rather than running the program -func (e *testEvaluator) Eval(program []byte) (pass bool, stateDelta basics.EvalDelta, err error) { +func (e *testEvaluator) Eval(program []byte) (pass bool, stateDelta transactions.EvalDelta, err error) { if len(program) < 1 || program[0] > 10 { - return false, basics.EvalDelta{}, fmt.Errorf("mock eval error") + return false, transactions.EvalDelta{}, fmt.Errorf("mock eval error") } return e.pass, e.delta, nil } @@ -515,15 +521,6 @@ func TestAppCallApplyCreate(t *testing.T) { b.ResetWrites() - // now looking up the creator will succeed, but we reset writes, so - // they won't have the app params - err = ApplicationCall(ac, h, &b, ad, &ep, txnCounter) - a.Error(err) - a.Contains(err.Error(), fmt.Sprintf("app %d not found in account", appIdx)) - a.Equal(1, b.put) - - b.ResetWrites() - // now we give the creator the app params again cp := basics.AccountData{} cp.AppParams = cloneAppParams(saved.AppParams) @@ -607,7 +604,7 @@ func TestAppCallApplyCreateOptIn(t *testing.T) { b.appCreators = map[basics.AppIndex]basics.Address{appIdx: creator} gd := map[string]basics.ValueDelta{"uint": {Action: basics.SetUintAction, Uint: 1}} - b.delta = basics.EvalDelta{GlobalDelta: gd} + b.delta = transactions.EvalDelta{GlobalDelta: gd} err := ApplicationCall(ac, h, &b, ad, &ep, txnCounter) a.NoError(err) @@ -690,6 +687,42 @@ func TestAppCallOptIn(t *testing.T) { }, br, ) + + // check max optins + + var optInCountTest = []struct { + proto protocol.ConsensusVersion + }{ + {protocol.ConsensusV29}, + {protocol.ConsensusFuture}, + } + + prevMaxAppsOptedIn := 0 + for _, test := range optInCountTest { + cparams, ok := config.Consensus[test.proto] + a.True(ok) + a.Less(prevMaxAppsOptedIn, cparams.MaxAppsOptedIn) + prevMaxAppsOptedIn = cparams.MaxAppsOptedIn + + b.SetParams(cparams) + aparams := basics.AppParams{ + StateSchemas: basics.StateSchemas{ + LocalStateSchema: basics.StateSchema{NumUint: 1}, + }, + } + sender = getRandomAddress(a) + b.balances = map[basics.Address]basics.AccountData{sender: {}} + var appIdx basics.AppIndex = appIdx + for i := 0; i < cparams.MaxAppsOptedIn; i++ { + appIdx = appIdx + basics.AppIndex(i) + err = optInApplication(&b, sender, appIdx, aparams) + a.NoError(err) + } + appIdx++ + err = optInApplication(&b, sender, appIdx, aparams) + a.Error(err) + a.Contains(err.Error(), "max opted-in apps per acct") + } } func TestAppCallClearState(t *testing.T) { @@ -768,7 +801,7 @@ func TestAppCallClearState(t *testing.T) { br = b.putBalances[sender] a.Equal(0, len(br.AppLocalStates)) a.Equal(basics.StateSchema{}, br.TotalAppSchema) - a.Equal(basics.EvalDelta{}, ad.EvalDelta) + a.Equal(transactions.EvalDelta{}, ad.EvalDelta) b.ResetWrites() @@ -787,7 +820,7 @@ func TestAppCallClearState(t *testing.T) { // one put: to opt out b.pass = false - b.delta = basics.EvalDelta{GlobalDelta: nil} + b.delta = transactions.EvalDelta{GlobalDelta: nil} err = ApplicationCall(ac, h, &b, ad, &ep, txnCounter) a.NoError(err) a.Equal(1, b.put) @@ -801,7 +834,7 @@ func TestAppCallClearState(t *testing.T) { // check existing application with logic err ClearStateProgram. // one to opt out, one deallocate, no error from ApplicationCall b.pass = true - b.delta = basics.EvalDelta{GlobalDelta: nil} + b.delta = transactions.EvalDelta{GlobalDelta: nil} b.err = ledgercore.LogicEvalError{Err: fmt.Errorf("test error")} err = ApplicationCall(ac, h, &b, ad, &ep, txnCounter) a.NoError(err) @@ -816,7 +849,7 @@ func TestAppCallClearState(t *testing.T) { // check existing application with non-logic err ClearStateProgram. // ApplicationCall must fail b.pass = true - b.delta = basics.EvalDelta{GlobalDelta: nil} + b.delta = transactions.EvalDelta{GlobalDelta: nil} b.err = fmt.Errorf("test error") err = ApplicationCall(ac, h, &b, ad, &ep, txnCounter) a.Error(err) @@ -832,23 +865,23 @@ func TestAppCallClearState(t *testing.T) { b.pass = true b.err = nil gd := basics.StateDelta{"uint": {Action: basics.SetUintAction, Uint: 1}} - b.delta = basics.EvalDelta{GlobalDelta: gd} + b.delta = transactions.EvalDelta{GlobalDelta: gd} err = ApplicationCall(ac, h, &b, ad, &ep, txnCounter) a.NoError(err) a.Equal(1, b.put) a.Equal(appIdx, b.deAllocatedAppIdx) a.Equal(0, len(br.AppLocalStates)) a.Equal(basics.StateSchema{}, br.TotalAppSchema) - a.Equal(basics.EvalDelta{GlobalDelta: gd}, ad.EvalDelta) + a.Equal(transactions.EvalDelta{GlobalDelta: gd}, ad.EvalDelta) b.ResetWrites() b.pass = true b.err = nil - logs := []basics.LogItem{{ID: 0, Message: "a"}} - b.delta = basics.EvalDelta{Logs: []basics.LogItem{{ID: 0, Message: "a"}}} + logs := []string{"a"} + b.delta = transactions.EvalDelta{Logs: []string{"a"}} err = ApplicationCall(ac, h, &b, ad, &ep, txnCounter) a.NoError(err) - a.Equal(basics.EvalDelta{Logs: logs}, ad.EvalDelta) + a.Equal(transactions.EvalDelta{Logs: logs}, ad.EvalDelta) } func TestAppCallApplyCloseOut(t *testing.T) { @@ -899,7 +932,7 @@ func TestAppCallApplyCloseOut(t *testing.T) { a.Equal(0, b.put) br := b.balances[creator] a.Equal(cbr, br) - a.Equal(basics.EvalDelta{}, ad.EvalDelta) + a.Equal(transactions.EvalDelta{}, ad.EvalDelta) // check closing on empty sender's balance record b.pass = true @@ -910,13 +943,13 @@ func TestAppCallApplyCloseOut(t *testing.T) { a.Equal(0, b.put) br = b.balances[creator] a.Equal(cbr, br) - a.Equal(basics.EvalDelta{}, ad.EvalDelta) + a.Equal(transactions.EvalDelta{}, ad.EvalDelta) b.ResetWrites() // check a happy case gd := map[string]basics.ValueDelta{"uint": {Action: basics.SetUintAction, Uint: 1}} - b.delta = basics.EvalDelta{GlobalDelta: gd} + b.delta = transactions.EvalDelta{GlobalDelta: gd} b.balances[sender] = basics.AccountData{ AppLocalStates: map[basics.AppIndex]basics.AppLocalState{appIdx: {}}, } @@ -928,14 +961,18 @@ func TestAppCallApplyCloseOut(t *testing.T) { a.Equal(basics.TealKeyValue(nil), br.AppParams[appIdx].GlobalState) br = b.putBalances[sender] a.Equal(0, len(br.AppLocalStates)) - a.Equal(basics.EvalDelta{GlobalDelta: gd}, ad.EvalDelta) + a.Equal(transactions.EvalDelta{GlobalDelta: gd}, ad.EvalDelta) a.Equal(basics.StateSchema{NumUint: 0}, br.TotalAppSchema) - logs := []basics.LogItem{{ID: 0, Message: "a"}} - b.delta = basics.EvalDelta{Logs: []basics.LogItem{{ID: 0, Message: "a"}}} + b.ResetWrites() + logs := []string{"a"} + b.delta = transactions.EvalDelta{Logs: []string{"a"}} + b.balances[sender] = basics.AccountData{ + AppLocalStates: map[basics.AppIndex]basics.AppLocalState{appIdx: {}}, + } err = ApplicationCall(ac, h, &b, ad, &ep, txnCounter) a.NoError(err) - a.Equal(basics.EvalDelta{Logs: logs}, ad.EvalDelta) + a.Equal(transactions.EvalDelta{Logs: logs}, ad.EvalDelta) } func TestAppCallApplyUpdate(t *testing.T) { @@ -988,7 +1025,7 @@ func TestAppCallApplyUpdate(t *testing.T) { a.Equal(0, b.put) br := b.balances[creator] a.Equal(cbr, br) - a.Equal(basics.EvalDelta{}, ad.EvalDelta) + a.Equal(transactions.EvalDelta{}, ad.EvalDelta) // check updating on empty sender's balance record - happy case b.pass = true @@ -1001,7 +1038,7 @@ func TestAppCallApplyUpdate(t *testing.T) { br = b.putBalances[creator] a.Equal([]byte{2}, br.AppParams[appIdx].ApprovalProgram) a.Equal([]byte{2}, br.AppParams[appIdx].ClearStateProgram) - a.Equal(basics.EvalDelta{}, ad.EvalDelta) + a.Equal(transactions.EvalDelta{}, ad.EvalDelta) //check program len check happens in future consensus proto version b.SetProto(protocol.ConsensusFuture) @@ -1030,11 +1067,11 @@ func TestAppCallApplyUpdate(t *testing.T) { b.balances[creator] = cp b.appCreators = map[basics.AppIndex]basics.Address{appIdx: creator} - logs := []basics.LogItem{{ID: 0, Message: "a"}} - b.delta = basics.EvalDelta{Logs: []basics.LogItem{{ID: 0, Message: "a"}}} + logs := []string{"a"} + b.delta = transactions.EvalDelta{Logs: []string{"a"}} err = ApplicationCall(ac, h, &b, ad, &ep, txnCounter) a.NoError(err) - a.Equal(basics.EvalDelta{Logs: logs}, ad.EvalDelta) + a.Equal(transactions.EvalDelta{Logs: logs}, ad.EvalDelta) // check extraProgramPages is used appr := make([]byte, 2*proto.MaxAppProgramLen+1) @@ -1062,6 +1099,7 @@ func TestAppCallApplyUpdate(t *testing.T) { a.Contains(err.Error(), fmt.Sprintf("updateApplication %s program too long", test.name)) } + b.ResetWrites() // check extraProgramPages allows length of proto.MaxAppProgramLen + 1 appr = make([]byte, proto.MaxAppProgramLen+1) appr[0] = 4 @@ -1142,7 +1180,7 @@ func TestAppCallApplyDelete(t *testing.T) { a.Equal(0, b.put) br := b.balances[creator] a.Equal(cbr, br) - a.Equal(basics.EvalDelta{}, ad.EvalDelta) + a.Equal(transactions.EvalDelta{}, ad.EvalDelta) // check calculation on ConsensusV28. TotalExtraAppPages does not change b.SetProto(protocol.ConsensusV28) @@ -1160,7 +1198,7 @@ func TestAppCallApplyDelete(t *testing.T) { br = b.putBalances[creator] a.Equal(basics.AppParams{}, br.AppParams[appIdx]) a.Equal(basics.StateSchema{}, br.TotalAppSchema) - a.Equal(basics.EvalDelta{}, ad.EvalDelta) + a.Equal(transactions.EvalDelta{}, ad.EvalDelta) a.Equal(uint32(1), br.TotalExtraAppPages) b.ResetWrites() @@ -1190,7 +1228,7 @@ func TestAppCallApplyDelete(t *testing.T) { br = b.putBalances[creator] a.Equal(basics.AppParams{}, br.AppParams[appIdx]) a.Equal(basics.StateSchema{}, br.TotalAppSchema) - a.Equal(basics.EvalDelta{}, ad.EvalDelta) + a.Equal(transactions.EvalDelta{}, ad.EvalDelta) if initTotalExtraPages <= params.ExtraProgramPages { a.Equal(uint32(0), br.TotalExtraAppPages) } else { @@ -1198,11 +1236,11 @@ func TestAppCallApplyDelete(t *testing.T) { } b.ResetWrites() } - logs := []basics.LogItem{{ID: 0, Message: "a"}} - b.delta = basics.EvalDelta{Logs: []basics.LogItem{{ID: 0, Message: "a"}}} + logs := []string{"a"} + b.delta = transactions.EvalDelta{Logs: []string{"a"}} err = ApplicationCall(ac, h, &b, ad, &ep, txnCounter) a.NoError(err) - a.Equal(basics.EvalDelta{Logs: logs}, ad.EvalDelta) + a.Equal(transactions.EvalDelta{Logs: logs}, ad.EvalDelta) } func TestAppCallApplyCreateClearState(t *testing.T) { @@ -1238,14 +1276,14 @@ func TestAppCallApplyCreateClearState(t *testing.T) { b.pass = true gd := map[string]basics.ValueDelta{"uint": {Action: basics.SetUintAction, Uint: 1}} - b.delta = basics.EvalDelta{GlobalDelta: gd} + b.delta = transactions.EvalDelta{GlobalDelta: gd} // check creation on empty balance record err := ApplicationCall(ac, h, &b, ad, &ep, txnCounter) a.Error(err) a.Contains(err.Error(), "not currently opted in") a.Equal(appIdx, b.allocatedAppIdx) - a.Equal(basics.EvalDelta{}, ad.EvalDelta) + a.Equal(transactions.EvalDelta{}, ad.EvalDelta) br := b.balances[creator] a.Equal([]byte{1}, br.AppParams[appIdx].ApprovalProgram) a.Equal([]byte{2}, br.AppParams[appIdx].ClearStateProgram) @@ -1288,20 +1326,20 @@ func TestAppCallApplyCreateDelete(t *testing.T) { b.pass = true gd := map[string]basics.ValueDelta{"uint": {Action: basics.SetUintAction, Uint: 1}} - b.delta = basics.EvalDelta{GlobalDelta: gd} + b.delta = transactions.EvalDelta{GlobalDelta: gd} // check creation on empty balance record err := ApplicationCall(ac, h, &b, ad, &ep, txnCounter) a.NoError(err) a.Equal(appIdx, b.allocatedAppIdx) - a.Equal(basics.EvalDelta{GlobalDelta: gd}, ad.EvalDelta) + a.Equal(transactions.EvalDelta{GlobalDelta: gd}, ad.EvalDelta) br := b.balances[creator] a.Equal(basics.AppParams{}, br.AppParams[appIdx]) - logs := []basics.LogItem{{ID: 0, Message: "a"}} - b.delta = basics.EvalDelta{Logs: []basics.LogItem{{ID: 0, Message: "a"}}} + logs := []string{"a"} + b.delta = transactions.EvalDelta{Logs: []string{"a"}} err = ApplicationCall(ac, h, &b, ad, &ep, txnCounter) a.NoError(err) - a.Equal(basics.EvalDelta{Logs: logs}, ad.EvalDelta) + a.Equal(transactions.EvalDelta{Logs: logs}, ad.EvalDelta) } |