Skip to content

Commit

Permalink
More comprehensive testing of global opcode
Browse files Browse the repository at this point in the history
  • Loading branch information
jannotti committed Apr 16, 2024
1 parent fcf5bfe commit c6ae176
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 13 deletions.
2 changes: 1 addition & 1 deletion data/transactions/logic/eval.go
Original file line number Diff line number Diff line change
Expand Up @@ -3741,7 +3741,7 @@ func (cx *EvalContext) globalFieldToValue(fs globalFieldSpec) (sv stackValue, er
return sv, fmt.Errorf("invalid global field %s", fs.field)
}

if fs.ftype.AVMType != sv.avmType() {
if err == nil && fs.ftype.AVMType != sv.avmType() {
return sv, fmt.Errorf("%s expected field type is %s but got %s", fs.field, fs.ftype, sv.avmType())
}

Expand Down
9 changes: 9 additions & 0 deletions data/transactions/logic/evalStateful_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,9 @@ func testApp(t *testing.T, program string, ep *EvalParams, problems ...string) (
return testAppBytes(t, ops.Program, ep, problems...)
}

// testAppCreator is the creator of the 888 app that is inserted when testing an app call
const testAppCreator = "47YPQTIGQEO7T4Y4RWDYWEKV6RTR2UNBQXBABEEGM72ESWDQNCQ52OPASU"

func testAppBytes(t *testing.T, program []byte, ep *EvalParams, problems ...string) (transactions.EvalDelta, error) {
t.Helper()
if ep == nil {
Expand All @@ -499,6 +502,12 @@ func testAppBytes(t *testing.T, program []byte, ep *EvalParams, problems ...stri
aid := ep.TxnGroup[0].Txn.ApplicationID
if aid == 0 {
aid = basics.AppIndex(888)
// we're testing an app call without the caller specifying details about
// the app, so conjure up buring app params to make the `global
// AppCreator` work.
addr, err := basics.UnmarshalChecksumAddress(testAppCreator)
require.NoError(t, err)
ep.Ledger.(*Ledger).NewApp(addr, 888, basics.AppParams{})
}
return testAppFull(t, program, 0, aid, ep, problems...)
}
Expand Down
13 changes: 3 additions & 10 deletions data/transactions/logic/eval_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1160,8 +1160,6 @@ int 1
&&
`

const testAddr = "47YPQTIGQEO7T4Y4RWDYWEKV6RTR2UNBQXBABEEGM72ESWDQNCQ52OPASU"

const globalV2TestProgram = globalV1TestProgram + `
global LogicSigVersion
int 1
Expand All @@ -1182,7 +1180,7 @@ int 888
`
const globalV3TestProgram = globalV2TestProgram + `
global CreatorAddress
addr ` + testAddr + `
addr ` + testAppCreator + `
==
&&
`
Expand Down Expand Up @@ -1239,10 +1237,10 @@ const globalV11TestProgram = globalV10TestProgram + `
// No new globals in v11
`

func TestGlobal(t *testing.T) {
func TestAllGlobals(t *testing.T) {
partitiontest.PartitionTest(t)

t.Parallel()

type desc struct {
lastField GlobalField
program string
Expand Down Expand Up @@ -1270,10 +1268,6 @@ func TestGlobal(t *testing.T) {
require.Equal(t, tests[AssemblerMaxVersion].lastField, invalidGlobalField-1,
"did you add a new global field?")

ledger := NewLedger(nil)
addr, err := basics.UnmarshalChecksumAddress(testAddr)
require.NoError(t, err)
ledger.NewApp(addr, 888, basics.AppParams{})
for v := uint64(1); v <= AssemblerMaxVersion; v++ {
_, ok := tests[v]
require.True(t, ok)
Expand All @@ -1294,7 +1288,6 @@ func TestGlobal(t *testing.T) {
appcall.Txn.Group = crypto.Digest{0x07, 0x06}

ep := defaultAppParams(appcall)
ep.Ledger = ledger
testApp(t, tests[v].program, ep)
})
}
Expand Down
31 changes: 29 additions & 2 deletions data/transactions/logic/fields_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ import (

// ensure v2+ fields fail in TEAL assembler and evaluator on a version before they introduced
// ensure v2+ fields error in v1 program
func TestGlobalFieldsVersions(t *testing.T) {
// ensure the types of the returned values are correct
func TestGlobalVersionsAndTypes(t *testing.T) {
partitiontest.PartitionTest(t)
t.Parallel()

Expand All @@ -42,14 +43,40 @@ func TestGlobalFieldsVersions(t *testing.T) {
require.Greater(t, len(fields), 1)

for _, field := range fields {
text := fmt.Sprintf("global %s", field.field.String())
text := "global " + field.field.String()
// check assembler fails if version before introduction
testLine(t, text, assemblerNoVersion, "...was introduced in...")
for v := uint64(0); v < field.version; v++ {
testLine(t, text, v, "...was introduced in...")
}
testLine(t, text, field.version, "")

// tack on a type check, and return a value (`int` gets compiled
// differently in different versions, so use intc_0 explicitly
switch field.ftype.AVMType {
case avmUint64: // ensure the return type is uint64 by using !
text = "intcblock 1;" + text + "; !; pop; intc_0"
case avmBytes: // ensure the return type is bytes by using len
text = "intcblock 1;" + text + "; len; pop; intc_0"
case avmAny:
text = "intcblock 1;" + text + "; pop; intc_0"
}

// check success in AssemblerMaxVersion and fs.version
for _, ver := range []uint64{AssemblerMaxVersion, field.version} {
ops := testProg(t, text, ver)
switch field.mode {
case ModeSig:
testLogicBytes(t, ops.Program, defaultSigParamsWithVersion(ver))
case ModeApp:
testAppBytes(t, ops.Program, defaultAppParamsWithVersion(ver))
case modeAny:
testLogicBytes(t, ops.Program, defaultSigParamsWithVersion(ver))
testAppBytes(t, ops.Program, defaultAppParamsWithVersion(ver))
default:
t.Fail()
}
}
ops := testProg(t, text, AssemblerMaxVersion)

// check on a version before the field version
Expand Down

0 comments on commit c6ae176

Please sign in to comment.