Skip to content

Commit

Permalink
Expose events emitted from the Blockchain to the test framework
Browse files Browse the repository at this point in the history
  • Loading branch information
m-Peter committed May 23, 2023
1 parent 0cd8fa9 commit 491bf3b
Show file tree
Hide file tree
Showing 3 changed files with 187 additions and 2 deletions.
28 changes: 28 additions & 0 deletions test/emulator_backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -493,3 +493,31 @@ func (e *EmulatorBackend) replaceImports(code string) string {
func (e *EmulatorBackend) StandardLibraryHandler() stdlib.StandardLibraryHandler {
return e.stdlibHandler
}

// GetEvents returns all the emitted events up until the latest block,
// optionally filtered by event type.
func (e *EmulatorBackend) GetEvents(eventType string) []cadence.Event {
latestBlock, err := e.blockchain.GetLatestBlock()
if err != nil {
panic(err)
}

latestBlockHeight := latestBlock.Header.Height
height := uint64(0)
allEvents := make([]cadence.Event, 0)
for height <= latestBlockHeight {
events, err := e.blockchain.GetEventsByHeight(
height,
eventType,
)
if err != nil {
panic(err)
}
for _, event := range events {
allEvents = append(allEvents, event.Value)
}
height += 1
}

return allEvents
}
155 changes: 155 additions & 0 deletions test/test_framework_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/onflow/cadence"
"github.com/onflow/cadence/runtime"
"github.com/onflow/cadence/runtime/common"
"github.com/onflow/cadence/runtime/interpreter"
Expand Down Expand Up @@ -2881,3 +2882,157 @@ func TestCoverageReportForIntegrationTests(t *testing.T) {
coverageReport.String(),
)
}

func TestGetEventsFromIntegrationTests(t *testing.T) {
t.Parallel()

contractCode := `
pub contract FooContract {
pub let specialNumbers: {Int: String}
pub event ContractInitialized()
pub event NumberAdded(n: Int, trait: String)
init() {
self.specialNumbers = {1729: "Harshad"}
emit ContractInitialized()
}
pub fun addSpecialNumber(_ n: Int, _ trait: String) {
self.specialNumbers[n] = trait
emit NumberAdded(n: n, trait: trait)
}
pub fun getIntegerTrait(_ n: Int): String {
if self.specialNumbers.containsKey(n) {
return self.specialNumbers[n]!
}
return "Unknown"
}
}
`

scriptCode := `
import FooContract from "../contracts/FooContract.cdc"
pub fun main(): Bool {
// Act
let trait = FooContract.getIntegerTrait(1729)
// Assert
assert(trait == "Harshad")
return true
}
`

testCode := `
import Test
pub let blockchain = Test.newEmulatorBlockchain()
pub let account = blockchain.createAccount()
pub fun setup() {
let contractCode = Test.readFile("../contracts/FooContract.cdc")
let err = blockchain.deployContract(
name: "FooContract",
code: contractCode,
account: account,
arguments: []
)
if err != nil {
panic(err!.message)
}
blockchain.useConfiguration(Test.Configuration({
"../contracts/FooContract.cdc": account.address
}))
}
pub fun testGetIntegerTrait() {
let script = Test.readFile("../scripts/get_integer_traits.cdc")
let result = blockchain.executeScript(script, [])
if result.status != Test.ResultStatus.succeeded {
panic(result.error!.message)
}
assert(result.returnValue! as! Bool)
}
pub fun testAddSpecialNumber() {
let code = Test.readFile("../transactions/add_special_number.cdc")
let tx = Test.Transaction(
code: code,
authorizers: [account.address],
signers: [account],
arguments: [78557, "Sierpinski"]
)
let result = blockchain.executeTransaction(tx)
assert(result.status == Test.ResultStatus.succeeded)
}
`

transactionCode := `
import FooContract from "../contracts/FooContract.cdc"
transaction(number: Int, trait: String) {
prepare(acct: AuthAccount) {}
execute {
// Act
FooContract.addSpecialNumber(number, trait)
// Assert
assert(trait == FooContract.getIntegerTrait(number))
}
}
`

fileResolver := func(path string) (string, error) {
switch path {
case "../contracts/FooContract.cdc":
return contractCode, nil
case "../scripts/get_integer_traits.cdc":
return scriptCode, nil
case "../transactions/add_special_number.cdc":
return transactionCode, nil
default:
return "", fmt.Errorf("cannot find import location: %s", path)
}
}

runner := NewTestRunner().WithFileResolver(fileResolver)

_, err := runner.RunTests(testCode)
require.NoError(t, err)

events := runner.backend.GetEvents("A.01cf0e2f2f715450.FooContract.RandomEvent")
assert.Equal(t, 0, len(events))

events = runner.backend.GetEvents("A.01cf0e2f2f715450.FooContract.ContractInitialized")
assert.Equal(t, 1, len(events))

events = runner.backend.GetEvents("A.01cf0e2f2f715450.FooContract.NumberAdded")
assert.Equal(t, 1, len(events))

n := cadence.NewInt(78557)
trait, err := cadence.NewString("Sierpinski")
require.NoError(t, err)

event := events[0]
assert.ElementsMatch(
t,
[]cadence.Value{n, trait},
event.Fields,
)
assert.ElementsMatch(
t,
[]cadence.Field{
cadence.NewField("n", cadence.NewIntType()),
cadence.NewField("trait", cadence.NewStringType()),
},
event.EventType.Fields,
)
}
6 changes: 4 additions & 2 deletions test/test_runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ type TestRunner struct {
testRuntime runtime.Runtime

coverageReport *runtime.CoverageReport

backend *EmulatorBackend
}

func NewTestRunner() *TestRunner {
Expand Down Expand Up @@ -362,14 +364,14 @@ func (r *TestRunner) interpreterContractValueHandler(
return contract

case stdlib.TestContractLocation:
testFramework := NewEmulatorBackend(
r.backend = NewEmulatorBackend(
r.fileResolver,
stdlibHandler,
r.coverageReport,
)
contract, err := stdlib.NewTestContract(
inter,
testFramework,
r.backend,
constructorGenerator(common.Address{}),
invocationRange,
)
Expand Down

0 comments on commit 491bf3b

Please sign in to comment.