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

test: testground sanity check with knuu #3194

Closed
wants to merge 50 commits into from
Closed
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
2ff81ab
dummy change to check the CIs
staheri14 Mar 19, 2024
68e4bd4
adds the ability to run txsim as knuu instance and to specify resourc…
staheri14 Mar 19, 2024
de98a06
updates go.mod and go.sum
staheri14 Mar 19, 2024
a678515
resolves linter issues
staheri14 Mar 19, 2024
75f300e
disables plotting
staheri14 Mar 19, 2024
00b4302
modifies skipping info
staheri14 Mar 19, 2024
a1e6382
enables throughput test when namespace equals to test
staheri14 Mar 19, 2024
0a0f9c2
minor edits
staheri14 Mar 19, 2024
dcb94d9
merges multiline codes
staheri14 Mar 19, 2024
fec63bc
shortens multiline func signatures to one line
staheri14 Mar 19, 2024
baf6be9
moves up CreateTxSimAccount func to make diffs more clear
staheri14 Mar 19, 2024
131e021
stop txsim prior to clean up
staheri14 Mar 20, 2024
bfc46fd
Merge branch 'main' into sanaz/testground-sanity-check-with-knuu
staheri14 Mar 20, 2024
343906a
adds the missing parentheses
staheri14 Mar 20, 2024
ba44149
deletes makefile changes
staheri14 Mar 20, 2024
5ec140d
brings back the plotting functionality
staheri14 Mar 20, 2024
9f359db
extracts app version from one of the validators
staheri14 Mar 20, 2024
6684915
read genesis app version
staheri14 Mar 20, 2024
21bd3e4
reverts knuu namespace to test
staheri14 Mar 20, 2024
a2c4f0a
Merge branch 'main' into sanaz/fetch-app-version
staheri14 Mar 20, 2024
c4330b0
resolves a formatting issue found by linter
staheri14 Mar 20, 2024
bd2f8d3
Merge branch 'main' into sanaz/fetch-app-version
staheri14 Mar 20, 2024
d946039
Merge branch 'sanaz/fetch-app-version' into sanaz/testground-sanity-c…
staheri14 Mar 20, 2024
1981c54
checks if the txsim instance is started
staheri14 Mar 21, 2024
5c67ce9
updates grpc endpoint ip address, and increases blob size range
staheri14 Mar 21, 2024
f59b31a
updates unit of block size to KiB and shortens txsim exec time
staheri14 Mar 21, 2024
f5c9f90
deletes plotting utils
staheri14 Mar 21, 2024
f78dfc1
adds RemoteAddressGRPC utility
staheri14 Mar 21, 2024
3d5092e
refactor the code and consolidates txsim setup and creation logics
staheri14 Mar 21, 2024
030d5d5
some formatting correction
staheri14 Mar 21, 2024
299a538
adds more logs
staheri14 Mar 22, 2024
6652192
brings back plotting
staheri14 Mar 22, 2024
424f0af
adds the ability to create and manage multiple txsim nodes
staheri14 Mar 22, 2024
f50c74b
sets the acc name and directory based on the txsim instance name
staheri14 Mar 22, 2024
e4ef082
reduces num of validators
staheri14 Mar 22, 2024
6aa5be9
points to the latest version of txsim
staheri14 Mar 22, 2024
feef734
increases the test duration
staheri14 Mar 22, 2024
6d910da
fixes log messages
staheri14 Mar 22, 2024
44ac423
fixes plots labels
staheri14 Mar 25, 2024
fe2c070
increases num of blobs per PFB
staheri14 Mar 25, 2024
ee4edd6
fixes a godoc
staheri14 Mar 25, 2024
e7463fd
Merge branch 'main' into sanaz/testground-sanity-check-with-knuu
staheri14 Mar 25, 2024
96a1792
changes the txsim version and resouces
staheri14 Mar 25, 2024
75e9841
increases the initial balance
staheri14 Mar 25, 2024
63027a3
uses default resources for txsim, lowers the range of blob sizes, spi…
staheri14 Mar 25, 2024
87a351d
decreases the upper bound to 10K
staheri14 Mar 25, 2024
0d85bd8
this setup works fine
staheri14 Mar 26, 2024
d7aa27e
prints more info for txsim nodes
staheri14 Mar 26, 2024
519ee8c
prints node directory
staheri14 Mar 26, 2024
5100c06
increases resources, blob ranges, and sequences
staheri14 Mar 26, 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
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -212,3 +212,4 @@ prebuilt-binary:
govulncheck:
@go run golang.org/x/vuln/cmd/[email protected] ./...
.PHONY: govulncheck

8 changes: 8 additions & 0 deletions test/e2e/defaults.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package e2e

var defaultResources = Resources{
memoryRequest: "200Mi",
memoryLimit: "200Mi",
cpu: "300m",
volume: "1Gi",
}
13 changes: 11 additions & 2 deletions test/e2e/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const (
secp256k1Type = "secp256k1"
ed25519Type = "ed25519"
remoteRootDir = "/home/celestia/.celestia-app"
txsimRootDir = "/home/celestia"
)

type Node struct {
Expand All @@ -41,12 +42,20 @@ type Node struct {
grpcProxyPort int
}

type Resources struct {
memoryRequest string
memoryLimit string
cpu string
volume string
}

func NewNode(
name, version string,
startHeight, selfDelegation int64,
peers []string,
signerKey, networkKey, accountKey crypto.PrivKey,
upgradeHeight int64,
resources Resources,
) (*Node, error) {
instance, err := knuu.NewInstance(name)
if err != nil {
Expand All @@ -68,11 +77,11 @@ func NewNode(
if err := instance.AddPortUDP(metricsPort); err != nil {
return nil, err
}
err = instance.SetMemory("200Mi", "200Mi")
err = instance.SetMemory(resources.memoryRequest, resources.memoryLimit)
if err != nil {
return nil, err
}
err = instance.SetCPU("300m")
err = instance.SetCPU(resources.cpu)
if err != nil {
return nil, err
}
Expand Down
2 changes: 2 additions & 0 deletions test/e2e/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ func MakeConfig(node *Node) (*config.Config, error) {
cfg.RPC.ListenAddress = "tcp://0.0.0.0:26657"
cfg.P2P.ExternalAddress = fmt.Sprintf("tcp://%v", node.AddressP2P(false))
cfg.P2P.PersistentPeers = strings.Join(node.InitialPeers, ",")
cfg.P2P.SendRate = 5 * 1024 * 1024 // 5MiB/s
cfg.P2P.RecvRate = 5 * 1024 * 1024 // 5MiB/s
cfg.Consensus.TimeoutPropose = time.Second
cfg.Consensus.TimeoutCommit = time.Second
cfg.Instrumentation.Prometheus = true
Expand Down
3 changes: 2 additions & 1 deletion test/e2e/simple_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ func TestE2ESimple(t *testing.T) {
testnet, err := New(t.Name(), seed)
require.NoError(t, err)
t.Cleanup(testnet.Cleanup)
require.NoError(t, testnet.CreateGenesisNodes(4, latestVersion, 10000000, 0))
require.NoError(t, testnet.CreateGenesisNodes(4, latestVersion, 10000000,
0, defaultResources))

kr, err := testnet.CreateAccount("alice", 1e12)
require.NoError(t, err)
Expand Down
80 changes: 74 additions & 6 deletions test/e2e/testnet.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type Testnet struct {
nodes []*Node
genesisAccounts []*Account
keygen *keyGenerator
txSimNode *TxSim
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we want just a single tx sim node? Would that be sufficient to load the testnet?

Maybe it's fine to start with one and not prematurely over-engineer it

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Maybe it's fine to start with one and not prematurely over-engineer it

Indeed, I intended to do it incrementally, first by testing out a single instance of txsim and debugging it, then scaling up if the desired load is not met.

}

func New(name string, seed int64) (*Testnet, error) {
Expand All @@ -34,32 +35,92 @@ func New(name string, seed int64) (*Testnet, error) {
}, nil
}

func (t *Testnet) CreateGenesisNode(version string, selfDelegation, upgradeHeight int64) error {
func (t *Testnet) CreateGenesisNode(version string, selfDelegation, upgradeHeight int64, resources Resources) error {
signerKey := t.keygen.Generate(ed25519Type)
networkKey := t.keygen.Generate(ed25519Type)
accountKey := t.keygen.Generate(secp256k1Type)
node, err := NewNode(fmt.Sprintf("val%d", len(t.nodes)), version, 0, selfDelegation, nil, signerKey, networkKey, accountKey, upgradeHeight)
node, err := NewNode(fmt.Sprintf("val%d", len(t.nodes)), version, 0, selfDelegation, nil, signerKey, networkKey, accountKey, upgradeHeight, resources)
if err != nil {
return err
}
t.nodes = append(t.nodes, node)
return nil
}

func (t *Testnet) CreateGenesisNodes(num int, version string, selfDelegation, upgradeHeight int64) error {
func (t *Testnet) CreateGenesisNodes(num int, version string, selfDelegation, upgradeHeight int64, resources Resources) error {
for i := 0; i < num; i++ {
if err := t.CreateGenesisNode(version, selfDelegation, upgradeHeight); err != nil {
if err := t.CreateGenesisNode(version, selfDelegation, upgradeHeight, resources); err != nil {
return err
}
}
return nil
}

func (t *Testnet) CreateNode(version string, startHeight, upgradeHeight int64) error {
func (t *Testnet) CreateTxSimAccount(name string, tokens int64, rootDir string) (keyring.Keyring, error) {
cdc := encoding.MakeConfig(app.ModuleEncodingRegisters...).Codec
kr, err := keyring.New(app.Name, keyring.BackendTest, rootDir, nil, cdc)
if err != nil {
return nil, err
}
key, _, err := kr.NewMnemonic(name, keyring.English, "", "", hd.Secp256k1)
if err != nil {
return nil, err
}

pk, err := key.GetPubKey()
if err != nil {
return nil, err
}
t.genesisAccounts = append(t.genesisAccounts, &Account{
PubKey: pk,
InitialTokens: tokens,
})
return kr, nil
}

func (t *Testnet) SetupTxsimNode(
name, version string,
endpoint string,
seed int,
sequences int,
blobRange int,
pollTime int,
resources Resources,
volumePath string,
keyringPath string,
) error {
txsim, err := CreateTxSimNode(name, version, endpoint, seed, sequences,
blobRange, pollTime, resources, volumePath)
if err != nil {
return err
}
err = txsim.Instance.AddFolder(keyringPath, volumePath, "10001:10001")
Copy link
Contributor

Choose a reason for hiding this comment

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

I didn't know this was possible. This is useful also for regular consensus nodes

if err != nil {
return err
}

err = txsim.Instance.Commit()
if err != nil {
return err
}

t.txSimNode = txsim
return nil
}

func (t *Testnet) StartTxSimNode() error {
err := t.txSimNode.Instance.Start()
if err != nil {
return err
}
return t.txSimNode.Instance.WaitInstanceIsRunning()
}

func (t *Testnet) CreateNode(version string, startHeight, upgradeHeight int64, resources Resources) error {
signerKey := t.keygen.Generate(ed25519Type)
networkKey := t.keygen.Generate(ed25519Type)
accountKey := t.keygen.Generate(secp256k1Type)
node, err := NewNode(fmt.Sprintf("val%d", len(t.nodes)), version, startHeight, 0, nil, signerKey, networkKey, accountKey, upgradeHeight)
node, err := NewNode(fmt.Sprintf("val%d", len(t.nodes)), version, startHeight, 0, nil, signerKey, networkKey, accountKey, upgradeHeight, resources)
if err != nil {
return err
}
Expand All @@ -74,6 +135,7 @@ func (t *Testnet) CreateAccount(name string, tokens int64) (keyring.Keyring, err
if err != nil {
return nil, err
}

pk, err := key.GetPubKey()
if err != nil {
return nil, err
Expand Down Expand Up @@ -178,6 +240,12 @@ func (t *Testnet) Cleanup() {
log.Err(err).Msg(fmt.Sprintf("node %s failed to cleanup", node.Name))
}
}
if t.txSimNode.Instance != nil {
err := t.txSimNode.Instance.Destroy()
if err != nil {
log.Err(err).Msg(fmt.Sprintf("txsim %s failed to cleanup", t.txSimNode.Name))
}
}
staheri14 marked this conversation as resolved.
Show resolved Hide resolved
}

func (t *Testnet) Node(i int) *Node {
Expand Down
145 changes: 145 additions & 0 deletions test/e2e/throughput_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
package e2e

import (
"context"
"os"
"path/filepath"
"testing"
"time"

v1 "github.com/celestiaorg/celestia-app/pkg/appconsts/v1"
"github.com/celestiaorg/celestia-app/test/util/testnode"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/types"
)

//const seed = 42
//
//var latestVersion = "latest"

func TestE2EThroughput(t *testing.T) {
if os.Getenv("KNUU_NAMESPACE") != "test" {
t.Skip("skipping e2e throughput test")
}

if os.Getenv("E2E_LATEST_VERSION") != "" {
latestVersion = os.Getenv("E2E_LATEST_VERSION")
_, isSemVer := ParseVersion(latestVersion)
switch {
case isSemVer:
case latestVersion == "latest":
case len(latestVersion) == 7:
case len(latestVersion) >= 8:
// assume this is a git commit hash (we need to trim the last digit to match the docker image tag)
latestVersion = latestVersion[:7]
default:
t.Fatalf("unrecognised version: %s", latestVersion)
}
}
t.Log("Running throughput test", "version", latestVersion)

testnet, err := New(t.Name(), seed)
require.NoError(t, err)
t.Cleanup(testnet.Cleanup)
require.NoError(t, testnet.CreateGenesisNodes(4, latestVersion, 10000000,
0, Resources{"200Mi", "200Mi", "300m", "200Mi"}))

// create an account, store it in a temp directory and add the account as genesis account
txsimKeyringDir := filepath.Join(os.TempDir(), "txsim")
_, err = testnet.CreateTxSimAccount("alice", 1e12, txsimKeyringDir)
require.NoError(t, err)

// start the testnet
require.NoError(t, testnet.Setup()) // configs, genesis files, etc.
require.NoError(t, testnet.Start())

t.Log("Starting txsim")
// TODO pull the latest version if possible
// TODO increase blob size range
err = testnet.SetupTxsimNode("txsim", "65c1a8e",
testnet.GRPCEndpoints()[0], seed, 5, 50*1024, 3,
Resources{"200Mi", "200Mi", "300m", "1Gi"},
txsimRootDir, txsimKeyringDir)
require.NoError(t, err)

err = testnet.StartTxSimNode()
require.NoError(t, err)

time.Sleep(30 * time.Second)

blockchain, err := testnode.ReadBlockchain(context.Background(), testnet.Node(0).AddressRPC())
require.NoError(t, err)

blockTimes, blockSizes, thputs := throughput(blockchain)
t.Log("blockTimes", blockTimes)
t.Log("blockSizes", blockSizes)
t.Log("thputs", thputs)
//plotData(blockSizes, "blocksizes.png", "Block Size in bytes", "Height",
// "Block Size")
//plotData(blockTimes, "blockTimes.png", "Block Time in seconds", "Height",
// "Block Time in seconds")
//plotData(thputs, "thputs.png", "Throughput in bytes/second",
// "Height", "Throughput in bytes/second")

totalTxs := 0
for _, block := range blockchain {
require.Equal(t, v1.Version, block.Version.App)
totalTxs += len(block.Data.Txs)
}
require.Greater(t, totalTxs, 10)
}

func throughput(blockchain []*types.Block) ([]float64, []float64, []float64) {
blockTimes := make([]float64, 0, len(blockchain)-1)
blockSizes := make([]float64, 0, len(blockchain)-1)
throughputs := make([]float64, 0, len(blockchain)-1)
// timestamp of the last processed block
lastBlockTs := blockchain[0].Header.Time

for _, block := range blockchain[1:] {
blockTime := float64(block.Header.Time.Sub(lastBlockTs) / 1e9) // Convert time from nanoseconds to seconds
blockSize := float64(block.Size() / (1024 * 1024)) // Convert size from bytes to MiB
thput := blockSize / blockTime

blockTimes = append(blockTimes, blockTime)
blockSizes = append(blockSizes, blockSize)
throughputs = append(throughputs, thput)

lastBlockTs = block.Header.Time // update lastBlockTs for the next block
}
return blockTimes, blockSizes, throughputs
}

//func plotData(data []float64, fileName string, title, xLabel,
// yLabel string,
//) {
// pts := make(plotter.XYs, len(data))
// for i := range data {
// pts[i].X = float64(i)
// pts[i].Y = data[i]
// }
//
// p, err := plot.New()
// if err != nil {
// panic(err)
// }
// p.Title.Text = title
// p.X.Label.Text = xLabel
// p.Y.Label.Text = yLabel
//
// err = plotutil.AddLinePoints(p, yLabel, pts)
// if err != nil {
// panic(err)
// }
//
// // save the plot
// if err := p.Save(10*vg.Inch, 5*vg.Inch, fileName); err != nil {
// panic(err)
// }
//}
//
//func TestPlotBlockSize(_ *testing.T) {
// blockSizes := []float64{100, 200, 300, 400, 500, 600, 700, 800, 900, 1000}
// plotData(blockSizes, "blocksize.png", "Block Size in bytes",
// "Block Height", "Size in bytes")
//}
Loading
Loading