Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support procedural test style for VM-defined workloads #1667

Merged
merged 43 commits into from
Nov 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
6f2fc50
initial revision.
tsachiherman Oct 16, 2024
1833c3f
lint
tsachiherman Oct 17, 2024
a4f51a1
update
tsachiherman Oct 17, 2024
8e22542
merge
tsachiherman Oct 17, 2024
fe528f5
update
tsachiherman Oct 17, 2024
baf90fd
update
tsachiherman Oct 17, 2024
ee7974c
lint
tsachiherman Oct 17, 2024
0b935bb
update
tsachiherman Oct 17, 2024
83afa8d
update
tsachiherman Oct 18, 2024
2523292
Merge branch 'main' into tsachi/proc-testing
tsachiherman Oct 23, 2024
1716ecf
Merge branch 'main' into tsachi/proc-testing
tsachiherman Oct 24, 2024
b681a95
stage
tsachiherman Oct 24, 2024
9fcc4dc
update
tsachiherman Oct 24, 2024
62048d7
update
tsachiherman Oct 24, 2024
3f7f35c
lint
tsachiherman Oct 24, 2024
bb6ca7b
Merge branch 'main' into tsachi/proc-testing
tsachiherman Oct 24, 2024
b27c3e7
try to fix chainid
tsachiherman Oct 24, 2024
c55e886
move test registry instance to be created at the vm level.
tsachiherman Oct 25, 2024
53d05e2
lint
tsachiherman Oct 25, 2024
848a8b9
update
tsachiherman Oct 25, 2024
32b6cff
update
tsachiherman Oct 25, 2024
69625eb
lint
tsachiherman Oct 25, 2024
f06bcf8
update
tsachiherman Oct 25, 2024
834bf53
Merge branch 'main' into tsachi/proc-testing
tsachiherman Oct 25, 2024
128d5fc
lint
tsachiherman Oct 25, 2024
93541c0
Merge branch 'main' into tsachi/proc-testing
tsachiherman Oct 27, 2024
c4621d6
update per CR
tsachiherman Oct 27, 2024
bb12aa7
sync e2e tests
tsachiherman Oct 27, 2024
473a08d
Update tests/workload/network.go
tsachiherman Oct 28, 2024
66d5493
update per CR
tsachiherman Oct 28, 2024
4c55dc3
Merge branch 'tsachi/proc-testing' of github.com:ava-labs/hypersdk in…
tsachiherman Oct 28, 2024
83231c7
update per CR
tsachiherman Oct 29, 2024
4bc7424
use ginkgo.Serial instead of mutex'ing.
tsachiherman Oct 29, 2024
f087929
lint
tsachiherman Oct 29, 2024
23f5b79
Merge branch 'main' into tsachi/proc-testing
tsachiherman Oct 29, 2024
782f4b2
Merge branch 'main' into tsachi/proc-testing
tsachiherman Oct 30, 2024
920c45a
avoid re-calc of txid
tsachiherman Oct 31, 2024
e5bb823
Merge branch 'tsachi/proc-testing' of github.com:ava-labs/hypersdk in…
tsachiherman Oct 31, 2024
5471cac
update per CR
tsachiherman Nov 1, 2024
2e7261f
Merge branch 'main' into tsachi/proc-testing
tsachiherman Nov 1, 2024
4021021
fix lint
tsachiherman Nov 1, 2024
a346111
fix comment per lint
tsachiherman Nov 1, 2024
3b5d436
update per CR
tsachiherman Nov 1, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 10 additions & 12 deletions examples/morpheusvm/tests/e2e/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@
package e2e_test

import (
"encoding/json"
"testing"
"time"

"github.com/ava-labs/avalanchego/tests/fixture/e2e"
"github.com/stretchr/testify/require"

_ "github.com/ava-labs/hypersdk/examples/morpheusvm/tests" // include the tests that are shared between the integration and e2e

"github.com/ava-labs/hypersdk/abi"
"github.com/ava-labs/hypersdk/auth"
"github.com/ava-labs/hypersdk/examples/morpheusvm/consts"
Expand Down Expand Up @@ -39,14 +40,10 @@ func init() {
var _ = ginkgo.SynchronizedBeforeSuite(func() []byte {
require := require.New(ginkgo.GinkgoT())

keys := workload.NewDefaultKeys()
genesis := workload.NewGenesis(keys, 100*time.Millisecond)
genesisBytes, err := json.Marshal(genesis)
require.NoError(err)
expectedABI, err := abi.NewABI(vm.ActionParser.GetRegisteredTypes(), vm.OutputParser.GetRegisteredTypes())
testingNetworkConfig, err := workload.NewTestNetworkConfig(100 * time.Millisecond)
require.NoError(err)

parser, err := vm.CreateParser(genesisBytes)
expectedABI, err := abi.NewABI(vm.ActionParser.GetRegisteredTypes(), vm.OutputParser.GetRegisteredTypes())
require.NoError(err)

// Import HyperSDK e2e test coverage and inject MorpheusVM name
Expand All @@ -55,15 +52,16 @@ var _ = ginkgo.SynchronizedBeforeSuite(func() []byte {
KeyType: auth.ED25519Key,
}

generator := workload.NewTxGenerator(keys[0])
firstKey := testingNetworkConfig.Keys()[0]
generator := workload.NewTxGenerator(firstKey)
spamKey := &auth.PrivateKey{
Address: auth.NewED25519Address(keys[0].PublicKey()),
Bytes: keys[0][:],
Address: auth.NewED25519Address(firstKey.PublicKey()),
Bytes: firstKey[:],
}
tc := e2e.NewTestContext()
he2e.SetWorkload(consts.Name, generator, expectedABI, parser, &spamHelper, spamKey)
he2e.SetWorkload(testingNetworkConfig, generator, expectedABI, &spamHelper, spamKey)

return fixture.NewTestEnvironment(tc, flagVars, owner, consts.Name, consts.ID, genesisBytes).Marshal()
return fixture.NewTestEnvironment(tc, flagVars, owner, testingNetworkConfig, consts.ID).Marshal()
}, func(envBytes []byte) {
// Run in every ginkgo process

Expand Down
12 changes: 5 additions & 7 deletions examples/morpheusvm/tests/integration/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@
package integration_test

import (
"encoding/json"
"testing"

"github.com/stretchr/testify/require"

_ "github.com/ava-labs/hypersdk/examples/morpheusvm/tests" // include the tests that are shared between the integration and e2e

"github.com/ava-labs/hypersdk/auth"
"github.com/ava-labs/hypersdk/crypto/ed25519"
"github.com/ava-labs/hypersdk/examples/morpheusvm/tests/workload"
Expand All @@ -26,23 +27,20 @@ func TestIntegration(t *testing.T) {
var _ = ginkgo.BeforeSuite(func() {
require := require.New(ginkgo.GinkgoT())

keys := workload.NewDefaultKeys()
genesis := workload.NewGenesis(keys, 0)
genesisBytes, err := json.Marshal(genesis)
testingNetworkConfig, err := workload.NewTestNetworkConfig(0)
require.NoError(err)

randomEd25519Priv, err := ed25519.GeneratePrivateKey()
require.NoError(err)

randomEd25519AuthFactory := auth.NewED25519Factory(randomEd25519Priv)

generator := workload.NewTxGenerator(keys[0])
generator := workload.NewTxGenerator(testingNetworkConfig.Keys()[0])
// Setup imports the integration test coverage
integration.Setup(
vm.New,
genesisBytes,
testingNetworkConfig,
lconsts.ID,
vm.CreateParser,
generator,
randomEd25519AuthFactory,
)
Expand Down
49 changes: 49 additions & 0 deletions examples/morpheusvm/tests/transfer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright (C) 2024, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package tests

import (
"context"
"time"

"github.com/stretchr/testify/require"

"github.com/ava-labs/hypersdk/auth"
"github.com/ava-labs/hypersdk/chain"
"github.com/ava-labs/hypersdk/crypto/ed25519"
"github.com/ava-labs/hypersdk/examples/morpheusvm/actions"
"github.com/ava-labs/hypersdk/examples/morpheusvm/tests/workload"
"github.com/ava-labs/hypersdk/tests/registry"

tworkload "github.com/ava-labs/hypersdk/tests/workload"
ginkgo "github.com/onsi/ginkgo/v2"
)

// TestsRegistry initialized during init to ensure tests are identical during ginkgo
// suite construction and test execution
// ref https://onsi.github.io/ginkgo/#mental-model-how-ginkgo-traverses-the-spec-hierarchy
var TestsRegistry = &registry.Registry{}

var _ = registry.Register(TestsRegistry, "Transfer Transaction", func(t ginkgo.FullGinkgoTInterface, tn tworkload.TestNetwork) {
require := require.New(t)
other, err := ed25519.GeneratePrivateKey()
require.NoError(err)
toAddress := auth.NewED25519Address(other.PublicKey())

networkConfig := tn.Configuration().(*workload.NetworkConfiguration)
spendingKey := networkConfig.Keys()[0]

tx, err := tn.GenerateTx(context.Background(), []chain.Action{&actions.Transfer{
To: toAddress,
Value: 1,
}},
auth.NewED25519Factory(spendingKey),
)
require.NoError(err)

timeoutCtx, timeoutCtxFnc := context.WithDeadline(context.Background(), time.Now().Add(2*time.Second))
defer timeoutCtxFnc()

require.NoError(tn.ConfirmTxs(timeoutCtx, []*chain.Transaction{tx}))
})
40 changes: 38 additions & 2 deletions examples/morpheusvm/tests/workload/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,36 @@
package workload

import (
"encoding/json"
"math"
"time"

"github.com/ava-labs/avalanchego/ids"

"github.com/ava-labs/hypersdk/auth"
"github.com/ava-labs/hypersdk/codec"
"github.com/ava-labs/hypersdk/crypto/ed25519"
"github.com/ava-labs/hypersdk/examples/morpheusvm/consts"
"github.com/ava-labs/hypersdk/examples/morpheusvm/vm"
"github.com/ava-labs/hypersdk/fees"
"github.com/ava-labs/hypersdk/genesis"
"github.com/ava-labs/hypersdk/tests/workload"
)

const (
// default initial balance for each address
InitialBalance uint64 = 10_000_000_000_000
)

var _ workload.TestNetworkConfiguration = &NetworkConfiguration{}

// hardcoded initial set of ed25519 keys. Each will be initialized with InitialBalance
var ed25519HexKeys = []string{
"323b1d8f4eed5f0da9da93071b034f2dce9d2d22692c172f3cb252a64ddfafd01b057de320297c29ad0c1f589ea216869cf1938d88c9fbd70d6748323dbf2fa7", //nolint:lll
"8a7be2e0c9a2d09ac2861c34326d6fe5a461d920ba9c2b345ae28e603d517df148735063f8d5d8ba79ea4668358943e5c80bc09e9b2b9a15b5b15db6c1862e88", //nolint:lll
}

func NewGenesis(keys []ed25519.PrivateKey, minBlockGap time.Duration) *genesis.DefaultGenesis {
func newGenesis(keys []ed25519.PrivateKey, minBlockGap time.Duration) *genesis.DefaultGenesis {
// allocate the initial balance to the addresses
customAllocs := make([]*genesis.CustomAllocation, 0, len(keys))
for _, key := range keys {
Expand All @@ -45,10 +53,13 @@ func NewGenesis(keys []ed25519.PrivateKey, minBlockGap time.Duration) *genesis.D
genesis.Rules.MaxBlockUnits = fees.Dimensions{1800000, math.MaxUint64, math.MaxUint64, math.MaxUint64, math.MaxUint64}
genesis.Rules.MinBlockGap = minBlockGap.Milliseconds()

genesis.Rules.NetworkID = uint32(1)
genesis.Rules.ChainID = ids.GenerateTestID()

return genesis
}

func NewDefaultKeys() []ed25519.PrivateKey {
func newDefaultKeys() []ed25519.PrivateKey {
testKeys := make([]ed25519.PrivateKey, len(ed25519HexKeys))
for i, keyHex := range ed25519HexKeys {
bytes, err := codec.LoadHex(keyHex, ed25519.PrivateKeyLen)
Expand All @@ -60,3 +71,28 @@ func NewDefaultKeys() []ed25519.PrivateKey {

return testKeys
}

type NetworkConfiguration struct {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: we should add a type check for NetworkConfiguration

var _ TestNetworkConfiguration = &NetworkConfiguration{}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

workload.DefaultTestNetworkConfiguration
keys []ed25519.PrivateKey
}

func (n *NetworkConfiguration) Keys() []ed25519.PrivateKey {
return n.keys
}

func NewTestNetworkConfig(minBlockGap time.Duration) (*NetworkConfiguration, error) {
keys := newDefaultKeys()
genesis := newGenesis(keys, minBlockGap)
genesisBytes, err := json.Marshal(genesis)
if err != nil {
return nil, err
}
return &NetworkConfiguration{
DefaultTestNetworkConfiguration: workload.NewDefaultTestNetworkConfiguration(
genesisBytes,
consts.Name,
vm.NewParser(genesis)),
keys: keys,
}, nil
}
57 changes: 34 additions & 23 deletions tests/e2e/e2e.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import (
"github.com/ava-labs/hypersdk/api/jsonrpc"
"github.com/ava-labs/hypersdk/api/state"
"github.com/ava-labs/hypersdk/auth"
"github.com/ava-labs/hypersdk/chain"
"github.com/ava-labs/hypersdk/tests/registry"
"github.com/ava-labs/hypersdk/tests/workload"
"github.com/ava-labs/hypersdk/throughput"
"github.com/ava-labs/hypersdk/utils"
Expand All @@ -28,20 +28,18 @@ import (
)

var (
vmName string
txWorkload workload.TxWorkload
parser chain.Parser
expectedABI abi.ABI
spamKey *auth.PrivateKey
spamHelper throughput.SpamHelper
networkConfig workload.TestNetworkConfiguration
txWorkload workload.TxWorkload
expectedABI abi.ABI
spamKey *auth.PrivateKey
spamHelper throughput.SpamHelper
)

func SetWorkload(name string, generator workload.TxGenerator, abi abi.ABI, chainParser chain.Parser, sh throughput.SpamHelper, key *auth.PrivateKey) {
vmName = name
func SetWorkload(networkConfigImpl workload.TestNetworkConfiguration, generator workload.TxGenerator, abi abi.ABI, sh throughput.SpamHelper, key *auth.PrivateKey) {
networkConfig = networkConfigImpl
txWorkload = workload.TxWorkload{
Generator: generator,
}
parser = chainParser
expectedABI = abi
spamHelper = sh
spamKey = key
Expand All @@ -52,23 +50,23 @@ var _ = ginkgo.Describe("[HyperSDK APIs]", func() {
require := require.New(tc)

ginkgo.It("Ping", func() {
expectedBlockchainID := e2e.GetEnv(tc).GetNetwork().GetSubnet(vmName).Chains[0].ChainID
expectedBlockchainID := e2e.GetEnv(tc).GetNetwork().GetSubnet(networkConfig.Name()).Chains[0].ChainID
workload.Ping(tc.DefaultContext(), require, getE2EURIs(tc, expectedBlockchainID))
})

ginkgo.It("StableNetworkIdentity", func() {
hardcodedHostPort := "http://localhost:9650"
fixedNodeURL := hardcodedHostPort + "/ext/bc/" + vmName
fixedNodeURL := hardcodedHostPort + "/ext/bc/" + networkConfig.Name()

c := jsonrpc.NewJSONRPCClient(fixedNodeURL)
_, _, chainIDFromRPC, err := c.Network(tc.DefaultContext())
require.NoError(err)
expectedBlockchainID := e2e.GetEnv(tc).GetNetwork().GetSubnet(vmName).Chains[0].ChainID
expectedBlockchainID := e2e.GetEnv(tc).GetNetwork().GetSubnet(networkConfig.Name()).Chains[0].ChainID
require.Equal(expectedBlockchainID, chainIDFromRPC)
})

ginkgo.It("GetNetwork", func() {
expectedBlockchainID := e2e.GetEnv(tc).GetNetwork().GetSubnet(vmName).Chains[0].ChainID
expectedBlockchainID := e2e.GetEnv(tc).GetNetwork().GetSubnet(networkConfig.Name()).Chains[0].ChainID
baseURIs := getE2EBaseURIs(tc)
baseURI := baseURIs[0]
client := info.NewClient(baseURI)
Expand All @@ -78,12 +76,12 @@ var _ = ginkgo.Describe("[HyperSDK APIs]", func() {
})

ginkgo.It("GetABI", func() {
expectedBlockchainID := e2e.GetEnv(tc).GetNetwork().GetSubnet(vmName).Chains[0].ChainID
expectedBlockchainID := e2e.GetEnv(tc).GetNetwork().GetSubnet(networkConfig.Name()).Chains[0].ChainID
workload.GetABI(tc.DefaultContext(), require, getE2EURIs(tc, expectedBlockchainID), expectedABI)
})

ginkgo.It("ReadState", func() {
blockchainID := e2e.GetEnv(tc).GetNetwork().GetSubnet(vmName).Chains[0].ChainID
blockchainID := e2e.GetEnv(tc).GetNetwork().GetSubnet(networkConfig.Name()).Chains[0].ChainID
ctx := tc.DefaultContext()
for _, uri := range getE2EURIs(tc, blockchainID) {
client := state.NewJSONRPCStateClient(uri)
Expand All @@ -97,31 +95,31 @@ var _ = ginkgo.Describe("[HyperSDK APIs]", func() {
})
})

var _ = ginkgo.Describe("[HyperSDK Tx Workloads]", func() {
var _ = ginkgo.Describe("[HyperSDK Tx Workloads]", ginkgo.Serial, func() {
ginkgo.It("Basic Tx Workload", func() {
tc := e2e.NewTestContext()
require := require.New(tc)
blockchainID := e2e.GetEnv(tc).GetNetwork().GetSubnet(vmName).Chains[0].ChainID
blockchainID := e2e.GetEnv(tc).GetNetwork().GetSubnet(networkConfig.Name()).Chains[0].ChainID

ginkgo.By("Tx workloads", func() {
txWorkload.GenerateBlocks(tc.DefaultContext(), require, getE2EURIs(tc, blockchainID), 1)
})

ginkgo.By("Confirm accepted blocks indexed", func() {
workload.GetBlocks(tc.DefaultContext(), require, parser, getE2EURIs(tc, blockchainID))
workload.GetBlocks(tc.DefaultContext(), require, networkConfig.Parser(), getE2EURIs(tc, blockchainID))
})
})
})

var _ = ginkgo.Describe("[HyperSDK Spam Workloads]", func() {
var _ = ginkgo.Describe("[HyperSDK Spam Workloads]", ginkgo.Serial, func() {
ginkgo.It("Spam Workload", func() {
if spamKey == nil || spamHelper == nil {
return
}

tc := e2e.NewTestContext()
require := require.New(tc)
blockchainID := e2e.GetEnv(tc).GetNetwork().GetSubnet(vmName).Chains[0].ChainID
blockchainID := e2e.GetEnv(tc).GetNetwork().GetSubnet(networkConfig.Name()).Chains[0].ChainID
uris := getE2EURIs(tc, blockchainID)
key := spamKey

Expand All @@ -137,11 +135,11 @@ var _ = ginkgo.Describe("[HyperSDK Spam Workloads]", func() {
})
})

var _ = ginkgo.Describe("[HyperSDK Syncing]", func() {
var _ = ginkgo.Describe("[HyperSDK Syncing]", ginkgo.Serial, func() {
ginkgo.It("[Sync]", func() {
tc := e2e.NewTestContext()
require := require.New(tc)
blockchainID := e2e.GetEnv(tc).GetNetwork().GetSubnet(vmName).Chains[0].ChainID
blockchainID := e2e.GetEnv(tc).GetNetwork().GetSubnet(networkConfig.Name()).Chains[0].ChainID

uris := getE2EURIs(tc, blockchainID)
ginkgo.By("Generate 128 blocks", func() {
Expand Down Expand Up @@ -244,6 +242,19 @@ var _ = ginkgo.Describe("[HyperSDK Syncing]", func() {
})
})

var _ = ginkgo.Describe("[Custom VM Tests]", ginkgo.Serial, func() {
tc := e2e.NewTestContext()

for testRegistry := range registry.GetTestsRegistries() {
for _, test := range testRegistry.List() {
ginkgo.It(test.Name, func() {
testNetwork := NewNetwork(tc)
test.Fnc(ginkgo.GinkgoT(), testNetwork)
})
}
}
})

func getE2EURIs(tc tests.TestContext, blockchainID ids.ID) []string {
nodeURIs := e2e.GetEnv(tc).GetNetwork().GetNodeURIs()
uris := make([]string, 0, len(nodeURIs))
Expand Down
Loading
Loading