Merge pull request #54 from getamis/feature/load-test-skeleton

tests: load test skeleton
This commit is contained in:
Alan Chen 2017-09-08 11:22:55 +08:00 committed by GitHub
commit de7b73ea4d
18 changed files with 795 additions and 106 deletions

View File

@ -1,4 +1,5 @@
GOBIN = build/bin
CURDIR = $(shell pwd)
GOBIN = $(CURDIR)/build/bin
GO ?= latest
istanbul:
@ -6,5 +7,9 @@ istanbul:
@echo "Done building."
@echo "Run \"$(GOBIN)/istanbul\" to launch istanbul."
load-testing:
@echo "Run load testing"
@CURDIR=$(CURDIR) go test -v github.com/getamis/istanbul-tools/tests/load/... --timeout 1h
clean:
rm -rf build/bin/
rm -rf build/bin/

View File

@ -177,7 +177,7 @@ spec:
- --maxpeers
- "100"
- --verbosity
- "4"
- "{{ .Values.ethereum.verbosity }}"
- --syncmode
- "full"
ports:
@ -232,6 +232,10 @@ spec:
- name: nodekey
mountPath: "{{ .Values.ethereum.nodekey.mountPath }}"
volumes:
{{- if .Values.testing.enabled }}
- name: data
emptyDir: {}
{{- end }}
- name: genesis
configMap:
name: {{ .Values.genesis.config }}
@ -244,6 +248,8 @@ spec:
- name: static-nodes
configMap:
name: {{ .Values.ethereum.staticNodes.config }}
{{- if .Values.testing.enabled }}
{{- else }}
volumeClaimTemplates:
- metadata:
name: data
@ -253,3 +259,4 @@ spec:
resources:
requests:
storage: {{ .Values.volumes.chaindir.size }}
{{- end }}

View File

@ -2,6 +2,9 @@
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
testing:
enabled: true
# service.yaml
service:
type: ClusterIP
@ -12,8 +15,8 @@ service:
# statefulset.yaml
replicaCount: 1
image:
repository: quay.io/maicoin/ottoman_geth
tag: latest
repository: quay.io/amis/geth
tag: istanbul_develop
pullPolicy: Always
ethereum:
@ -27,26 +30,26 @@ ethereum:
enabled: true
path: ""
rpc:
enabled: true
addr: 0.0.0.0
port: 8545
api: "eth,net,web3,personal"
corsdomain: "*"
ws:
enabled: false
addr: 0.0.0.0
port: 8545
api: "eth,net,web3,personal,miner,admin"
corsdomain: "*"
ws:
enabled: true
addr: 0.0.0.0
port: 8546
api: "eth,net,web3,personal"
api: "eth,net,web3,personal,miner,admin"
origins: "*"
mining:
enabled: true
enabled: false
threads: 1
etherbase: "1a9afb711302c5f83b5902843d1c007a1a137632"
staticNodes:
config: static-nodes
mountPath: "/staticNodes"
ethstats:
enabled: true
enabled: false
addr: ws://eth-netstats
port: 3000
secret: bb98a0b6442386d0cdf8a31b267892c1
@ -58,11 +61,12 @@ ethereum:
address: "1a9afb711302c5f83b5902843d1c007a1a137632"
data: '{"address":"1a9afb711302c5f83b5902843d1c007a1a137632","Crypto":{"cipher":"aes-128-ctr","ciphertext":"132b50d7c8944a115824de7c00911c40a90f84f27c614b7a3ef05ee8fd414312","cipherparams":{"iv":"0f745599d1b3303988ce210fb82b8c7f"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"bce940bac232b4a9c5a2d50e5be51fde5cecfa7da9d49d8f650f91167bebf0de"},"mac":"36d515070b797aec58a574a3e04ea109498ee7674b15d7f952322cda7dcb68e3"},"id":"5d212b4c-3dd0-4c52-a32f-e42bf1b41133","version":3}'
mountPath: "/keystore"
verbosity: 3
volumes:
chaindir:
name: chaindir
size: 1000Gi
size: 10Gi
mountPath: "/data"
storageClass: ""

View File

@ -14,33 +14,17 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package genesis
package charts
import (
"fmt"
"log"
"os"
"path/filepath"
uuid "github.com/satori/go.uuid"
)
const (
defaultLocalDir = "/tmp/gdata"
clientIdentifier = "genesis"
var (
chartBasePath string
)
func generateRandomDir() (string, error) {
err := os.MkdirAll(filepath.Join(defaultLocalDir), 0700)
if err != nil {
log.Fatal(err)
}
instanceDir := filepath.Join(defaultLocalDir, fmt.Sprintf("%s-%s", clientIdentifier, uuid.NewV4().String()))
if err := os.MkdirAll(instanceDir, 0700); err != nil {
log.Println(fmt.Sprintf("Failed to create instance dir: %v", err))
return "", err
}
return instanceDir, nil
func init() {
chartBasePath = filepath.Join(os.Getenv("CURDIR"), "benchmark/kubernetes")
}

80
charts/genesis.go Normal file
View File

@ -0,0 +1,80 @@
// Copyright 2017 AMIS Technologies
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package charts
import (
"fmt"
"log"
"os"
"path/filepath"
"strings"
"github.com/ethereum/go-ethereum/common"
"github.com/getamis/istanbul-tools/genesis"
)
type GenesisChart struct {
name string
chartPath string
genesisFile string
args []string
}
func NewGenesisChart(addrs []common.Address, gasLimit uint64) *GenesisChart {
chartPath := filepath.Join(chartBasePath, "genesis-block")
genesisPath := filepath.Join(chartPath, ".genesis")
err := os.MkdirAll(genesisPath, 0700)
if err != nil {
log.Fatal(err)
}
chart := &GenesisChart{
name: "genesis-block",
chartPath: chartPath,
genesisFile: genesis.NewFileAt(
genesisPath,
false,
genesis.Validators(addrs...),
genesis.GasLimit(gasLimit),
),
}
relPath := strings.Replace(chart.genesisFile, chartPath+"/", "", 1)
chart.Override("genesisFileName", relPath)
return chart
}
func (chart *GenesisChart) Override(key, value string) {
chart.args = append(chart.args, fmt.Sprintf("%s=%s", key, value))
}
func (chart *GenesisChart) Install(debug bool) error {
defer os.RemoveAll(filepath.Dir(chart.genesisFile))
return installRelease(
chart.name,
chart.args,
chart.chartPath,
debug,
)
}
func (chart *GenesisChart) Uninstall() error {
return uninstallRelease(chart.name)
}

78
charts/static_nodes.go Normal file
View File

@ -0,0 +1,78 @@
// Copyright 2017 AMIS Technologies
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package charts
import (
"fmt"
"log"
"os"
"path/filepath"
"strings"
"github.com/getamis/istanbul-tools/common"
)
type StaticNodesChart struct {
name string
chartPath string
staticNodesFile string
args []string
}
func NewStaticNodesChart(nodekeys []string, ipAddrs []string) *StaticNodesChart {
chartPath := filepath.Join(chartBasePath, "static-nodes")
staticNodesPath := filepath.Join(chartPath, ".static-nodes")
err := os.MkdirAll(staticNodesPath, 0700)
if err != nil {
log.Fatal(err)
}
if len(nodekeys) != len(ipAddrs) {
log.Println("The number of nodekeys and the number of IP address should be equal")
return nil
}
chart := &StaticNodesChart{
name: "static-nodes",
chartPath: chartPath,
staticNodesFile: common.GenerateStaticNodesAt(staticNodesPath, nodekeys, ipAddrs),
}
relPath := strings.Replace(chart.staticNodesFile, chartPath+"/", "", 1)
chart.Override("fileName", relPath)
return chart
}
func (chart *StaticNodesChart) Override(key, value string) {
chart.args = append(chart.args, fmt.Sprintf("%s=%s", key, value))
}
func (chart *StaticNodesChart) Install(debug bool) error {
defer os.RemoveAll(filepath.Dir(chart.staticNodesFile))
return installRelease(
chart.name,
chart.args,
chart.chartPath,
debug,
)
}
func (chart *StaticNodesChart) Uninstall() error {
return uninstallRelease(chart.name)
}

98
charts/utils.go Normal file
View File

@ -0,0 +1,98 @@
// Copyright 2017 AMIS Technologies
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package charts
import (
"errors"
"fmt"
"os/exec"
"strings"
)
func newInstallCommand() *exec.Cmd {
return exec.Command("helm", "install")
}
func newUninstallCommand() *exec.Cmd {
return exec.Command("helm", "delete", "--purge")
}
func installRelease(name string, args []string, path string, debug bool) error {
cmd := newInstallCommand()
if name != "" {
cmd.Args = append(cmd.Args, "--name")
cmd.Args = append(cmd.Args, name)
}
if len(args) > 0 {
cmd.Args = append(cmd.Args, "--set")
cmd.Args = append(cmd.Args, strings.Join(args, ","))
}
cmd.Args = append(cmd.Args, path)
if debug {
cmd.Args = append(cmd.Args, "--dry-run")
cmd.Args = append(cmd.Args, "--debug")
}
cmd.Args = append(cmd.Args, "--wait")
if debug {
fmt.Println(cmd.Args)
}
output, err := cmd.CombinedOutput()
if err != nil {
fmt.Println(err, string(output))
return err
}
fmt.Println(string(output))
return nil
}
func uninstallRelease(release string) error {
cmd := newUninstallCommand()
if release != "" {
cmd.Args = append(cmd.Args, release)
} else {
return errors.New("Unknown release name")
}
output, err := cmd.CombinedOutput()
if err != nil {
fmt.Println(err)
return err
}
fmt.Println(string(output))
return nil
}
func ListCharts() {
cmd := exec.Command("helm", "list")
output, err := cmd.Output()
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(output))
}

61
charts/validator.go Normal file
View File

@ -0,0 +1,61 @@
// Copyright 2017 AMIS Technologies
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package charts
import (
"fmt"
"path/filepath"
)
type ValidatorChart struct {
name string
chartPath string
args []string
}
func NewValidatorChart(name string, args []string) *ValidatorChart {
chartPath := filepath.Join(chartBasePath, "validator")
chart := &ValidatorChart{
name: "validator-" + name,
args: args,
chartPath: chartPath,
}
return chart
}
func (chart *ValidatorChart) Override(key, value string) {
chart.args = append(chart.args, fmt.Sprintf("%s=%s", key, value))
}
func (chart *ValidatorChart) Install(debug bool) error {
return installRelease(
chart.name,
chart.args,
chart.chartPath,
debug,
)
}
func (chart *ValidatorChart) Uninstall() error {
return uninstallRelease(chart.name)
}
func (chart *ValidatorChart) Name() string {
return chart.name
}

149
common/utils.go Normal file
View File

@ -0,0 +1,149 @@
// Copyright 2017 AMIS Technologies
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package common
import (
"crypto/ecdsa"
"crypto/rand"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net"
"os"
"path/filepath"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/getamis/go-ethereum/p2p/discover"
uuid "github.com/satori/go.uuid"
)
const (
defaultLocalDir = "/tmp/gdata"
clientIdentifier = "geth"
nodekeyFileName = "nodekey"
)
func GenerateIPs(num int) (ips []string) {
for i := 0; i < num; i++ {
ips = append(ips, fmt.Sprintf("10.1.1.%d", i+2))
}
return ips
}
func GenerateRandomDir() (string, error) {
err := os.MkdirAll(filepath.Join(defaultLocalDir), 0700)
if err != nil {
log.Fatal(err)
}
instanceDir := filepath.Join(defaultLocalDir, fmt.Sprintf("%s-%s", clientIdentifier, uuid.NewV4().String()))
if err := os.MkdirAll(instanceDir, 0700); err != nil {
log.Println(fmt.Sprintf("Failed to create instance dir: %v", err))
return "", err
}
return instanceDir, nil
}
func GenerateKeys(num int) (keys []*ecdsa.PrivateKey, nodekeys []string, addrs []common.Address) {
for i := 0; i < num; i++ {
nodekey := RandomHex()[2:]
nodekeys = append(nodekeys, nodekey)
key, err := crypto.HexToECDSA(nodekey)
if err != nil {
log.Fatalf("couldn't generate key: " + err.Error())
}
keys = append(keys, key)
addr := crypto.PubkeyToAddress(key.PublicKey)
addrs = append(addrs, addr)
}
return keys, nodekeys, addrs
}
func SaveNodeKey(key *ecdsa.PrivateKey, dataDir string) error {
keyDir := filepath.Join(dataDir, clientIdentifier)
if err := os.MkdirAll(keyDir, 0700); err != nil {
log.Println(fmt.Sprintf("Failed to create key dir: %v", err))
return err
}
keyfile := filepath.Join(keyDir, nodekeyFileName)
if err := crypto.SaveECDSA(keyfile, key); err != nil {
log.Println(fmt.Sprintf("Failed to persist node key: %v", err))
return err
}
return nil
}
func GenerateStaticNodesAt(dir string, nodekeys []string, ipAddrs []string) (filename string) {
var nodes []string
for i, nodekey := range nodekeys {
key, err := crypto.HexToECDSA(nodekey)
if err != nil {
log.Printf("Failed to create key, err: %v\n", err)
return ""
}
node := discover.NewNode(
discover.PubkeyID(&key.PublicKey),
net.ParseIP(ipAddrs[i]),
0,
uint16(30303))
nodes = append(nodes, node.String())
}
filename = filepath.Join(dir, "static-nodes.json")
bytes, _ := json.Marshal(nodes)
if err := ioutil.WriteFile(filename, bytes, 0644); err != nil {
log.Printf("Failed to write '%s', err: %v\n", filename, err)
return ""
}
return filename
}
func GenerateStaticNodes(nodekeys []string, ipAddrs []string) (filename string) {
dir, err := GenerateRandomDir()
if err != nil {
log.Printf("Failed to generate directory, err: %v\n", err)
return ""
}
return GenerateStaticNodesAt(dir, nodekeys, ipAddrs)
}
func RandomHex() string {
b, _ := RandomBytes(32)
return common.BytesToHash(b).Hex()
}
func RandomBytes(len int) ([]byte, error) {
b := make([]byte, len)
_, err := rand.Read(b)
if err != nil {
log.Fatalln(err)
}
return b, nil
}

View File

@ -30,6 +30,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/phayes/freeport"
istcommon "github.com/getamis/istanbul-tools/common"
"github.com/getamis/istanbul-tools/genesis"
)
@ -137,7 +138,7 @@ func NewDefaultBlockchainWithFaulty(network *DockerNetwork, numOfNormal int, num
log.Fatalf("Failed to get free ip addresses, err: %v", err)
}
keys, addrs := generateKeys(totalNodes)
keys, _, addrs := istcommon.GenerateKeys(totalNodes)
bc.setupGenesis(addrs)
// Create normal validators
bc.opts = normalOpts
@ -319,7 +320,7 @@ func (bc *blockchain) CreateNodes(num int, options ...Option) (nodes []Ethereum,
opts = append(opts, options...)
// Host data directory
dataDir, err := generateRandomDir()
dataDir, err := istcommon.GenerateRandomDir()
if err != nil {
log.Println("Failed to create data dir", err)
return nil, err
@ -353,7 +354,7 @@ func (bc *blockchain) addValidators(numOfValidators int) error {
if err != nil {
return err
}
keys, addrs := generateKeys(numOfValidators)
keys, _, addrs := istcommon.GenerateKeys(numOfValidators)
bc.setupGenesis(addrs)
bc.setupValidators(ips, keys, bc.opts...)
@ -394,7 +395,7 @@ func (bc *blockchain) setupValidators(ips []net.IP, keys []*ecdsa.PrivateKey, op
opts = append(opts, options...)
// Host data directory
dataDir, err := generateRandomDir()
dataDir, err := istcommon.GenerateRandomDir()
if err != nil {
log.Fatal("Failed to create data dir", err)
}

View File

@ -33,6 +33,8 @@ import (
"github.com/docker/docker/api/types/network"
"github.com/docker/docker/client"
"github.com/docker/go-connections/nat"
istcommon "github.com/getamis/istanbul-tools/common"
)
//TODO: refactor this with ethereum options?
@ -192,7 +194,7 @@ func (ct *constellation) Image() string {
func (ct *constellation) GenerateKey() (localWorkDir string, err error) {
// Generate empty password file
ct.localWorkDir, err = generateRandomDir()
ct.localWorkDir, err = istcommon.GenerateRandomDir()
if err != nil {
log.Printf("Failed to generate working dir, err: :%v\n", err)
return "", err

View File

@ -43,6 +43,7 @@ import (
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/p2p/discover"
istcommon "github.com/getamis/istanbul-tools/common"
"github.com/getamis/istanbul-tools/genesis"
"github.com/getamis/istanbul-tools/istclient"
)
@ -146,7 +147,7 @@ type ethereum struct {
}
func (eth *ethereum) Init(genesisFile string) error {
if err := saveNodeKey(eth.key, eth.dataDir); err != nil {
if err := istcommon.SaveNodeKey(eth.key, eth.dataDir); err != nil {
log.Fatal("Failed to save nodekey", err)
return err
}

View File

@ -17,74 +17,15 @@
package container
import (
"crypto/ecdsa"
"fmt"
"log"
"os"
"path/filepath"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/istanbul"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/sha3"
"github.com/ethereum/go-ethereum/rlp"
uuid "github.com/satori/go.uuid"
"github.com/getamis/istanbul-tools/cmd/istanbul/extra"
)
const (
defaultLocalDir = "/tmp/gdata"
clientIdentifier = "geth"
nodekeyFileName = "nodekey"
)
func generateRandomDir() (string, error) {
err := os.MkdirAll(filepath.Join(defaultLocalDir), 0700)
if err != nil {
log.Fatal(err)
}
instanceDir := filepath.Join(defaultLocalDir, fmt.Sprintf("%s-%s", clientIdentifier, uuid.NewV4().String()))
if err := os.MkdirAll(instanceDir, 0700); err != nil {
log.Println(fmt.Sprintf("Failed to create instance dir: %v", err))
return "", err
}
return instanceDir, nil
}
func generateKeys(num int) (keys []*ecdsa.PrivateKey, addrs []common.Address) {
for i := 0; i < num; i++ {
key, err := crypto.GenerateKey()
if err != nil {
log.Fatalf("couldn't generate key: " + err.Error())
}
keys = append(keys, key)
addr := crypto.PubkeyToAddress(key.PublicKey)
addrs = append(addrs, addr)
}
return keys, addrs
}
func saveNodeKey(key *ecdsa.PrivateKey, dataDir string) error {
keyDir := filepath.Join(dataDir, clientIdentifier)
if err := os.MkdirAll(keyDir, 0700); err != nil {
log.Println(fmt.Sprintf("Failed to create key dir: %v", err))
return err
}
keyfile := filepath.Join(keyDir, nodekeyFileName)
if err := crypto.SaveECDSA(keyfile, key); err != nil {
log.Println(fmt.Sprintf("Failed to persist node key: %v", err))
return err
}
return nil
}
func sigHash(header *types.Header) (hash common.Hash) {
hasher := sha3.NewKeccak256()

View File

@ -30,6 +30,8 @@ import (
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
"github.com/getamis/istanbul-tools/common"
)
const (
@ -64,11 +66,7 @@ func New(options ...Option) *core.Genesis {
return genesis
}
func NewFile(isQuorum bool, options ...Option) string {
dir, err := generateRandomDir()
if err != nil {
log.Fatalf("Failed to create random directory, err: %v", err)
}
func NewFileAt(dir string, isQuorum bool, options ...Option) string {
genesis := New(options...)
if err := Save(dir, genesis, isQuorum); err != nil {
log.Fatalf("Failed to save genesis to '%s', err: %v", dir, err)
@ -77,6 +75,14 @@ func NewFile(isQuorum bool, options ...Option) string {
return filepath.Join(dir, FileName)
}
func NewFile(isQuorum bool, options ...Option) string {
dir, err := common.GenerateRandomDir()
if err != nil {
log.Fatalf("Failed to create random directory, err: %v", err)
}
return NewFileAt(dir, isQuorum, options...)
}
func Save(dataDir string, genesis *core.Genesis, isQuorum bool) error {
filePath := filepath.Join(dataDir, FileName)

22
tests/chart_installer.go Normal file
View File

@ -0,0 +1,22 @@
// Copyright 2017 AMIS Technologies
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package tests
type ChartInstaller interface {
Install(bool) error
Uninstall() error
}

85
tests/load/load_test.go Normal file
View File

@ -0,0 +1,85 @@
// Copyright 2017 AMIS Technologies
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package load
import (
"testing"
"github.com/getamis/istanbul-tools/charts"
"github.com/getamis/istanbul-tools/common"
"github.com/getamis/istanbul-tools/tests"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("TPS-01: Large amount of transactions", func() {
tests.CaseTable("with number of validators",
func(numberOfValidators int) {
tests.CaseTable("with gas limit",
func(gaslimit int) {
tests.CaseTable("with txpool size",
func(txpoolSize int) {
runTests(numberOfValidators, gaslimit, txpoolSize)
},
tests.Case("2048", 2048),
tests.Case("10240", 10240),
)
},
tests.Case("21000*1000", 21000*1000),
tests.Case("21000*3000", 21000*3000),
)
},
tests.Case("4 validators", 4),
tests.Case("7 validators", 7),
tests.Case("10 validators", 10),
)
})
func runTests(numberOfValidators int, gaslimit int, txpoolSize int) {
Describe("", func() {
var (
genesisChart tests.ChartInstaller
staticNodesChart tests.ChartInstaller
)
BeforeEach(func() {
_, nodekeys, addrs := common.GenerateKeys(numberOfValidators)
genesisChart = charts.NewGenesisChart(addrs, uint64(gaslimit))
Expect(genesisChart.Install(false)).To(BeNil())
staticNodesChart = charts.NewStaticNodesChart(nodekeys, common.GenerateIPs(len(nodekeys)))
Expect(staticNodesChart.Install(false)).To(BeNil())
})
AfterEach(func() {
Expect(genesisChart.Uninstall()).To(BeNil())
Expect(staticNodesChart.Uninstall()).To(BeNil())
})
It("", func() {
})
})
}
func IstanbulLoadTest(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Istanbul Load Test Suite")
}

80
tests/table.go Normal file
View File

@ -0,0 +1,80 @@
// Copyright 2017 AMIS Technologies
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package tests
import (
"fmt"
"reflect"
"github.com/onsi/ginkgo"
)
func CaseTable(description string, itBody interface{}, entries ...tableEntry) bool {
caseTable(description, itBody, entries, false, false)
return true
}
/*
You can focus a table with `FCaseTable`.
*/
func FCaseTable(description string, itBody interface{}, entries ...tableEntry) bool {
caseTable(description, itBody, entries, false, true)
return true
}
/*
You can mark a table as pending with `PCaseTable`.
*/
func PCaseTable(description string, itBody interface{}, entries ...tableEntry) bool {
caseTable(description, itBody, entries, true, false)
return true
}
/*
You can mark a table as pending with `XCaseTable`.
*/
func XCaseTable(description string, itBody interface{}, entries ...tableEntry) bool {
caseTable(description, itBody, entries, true, false)
return true
}
func caseTable(description string, itBody interface{}, entries []tableEntry, pending bool, focused bool) {
itBodyValue := reflect.ValueOf(itBody)
if itBodyValue.Kind() != reflect.Func {
panic(fmt.Sprintf("DescribeTable expects a function, got %#v", itBody))
}
if pending {
ginkgo.PDescribe(description, func() {
for _, entry := range entries {
entry.generate(itBodyValue, entries, pending, focused)
}
})
} else if focused {
ginkgo.FDescribe(description, func() {
for _, entry := range entries {
entry.generate(itBodyValue, entries, pending, focused)
}
})
} else {
ginkgo.Describe(description, func() {
for _, entry := range entries {
entry.generate(itBodyValue, entries, pending, focused)
}
})
}
}

85
tests/table_entry.go Normal file
View File

@ -0,0 +1,85 @@
package tests
import (
"reflect"
"github.com/onsi/ginkgo"
)
/*
TableEntry represents an entry in a table test. You generally use the `Entry` constructor.
*/
type tableEntry struct {
Description string
Parameters []interface{}
Pending bool
Focused bool
}
func (t tableEntry) generate(itBody reflect.Value, entries []tableEntry, pending bool, focused bool) {
if t.Pending {
ginkgo.PDescribe(t.Description, func() {
for _, entry := range entries {
entry.generate(itBody, entries, pending, focused)
}
})
return
}
values := []reflect.Value{}
for i, param := range t.Parameters {
var value reflect.Value
if param == nil {
inType := itBody.Type().In(i)
value = reflect.Zero(inType)
} else {
value = reflect.ValueOf(param)
}
values = append(values, value)
}
body := func() {
itBody.Call(values)
}
if t.Focused {
ginkgo.FDescribe(t.Description, body)
} else {
ginkgo.Describe(t.Description, body)
}
}
/*
Entry constructs a tableEntry.
The first argument is a required description (this becomes the content of the generated Ginkgo `It`).
Subsequent parameters are saved off and sent to the callback passed in to `DescribeTable`.
Each Entry ends up generating an individual Ginkgo It.
*/
func Case(description string, parameters ...interface{}) tableEntry {
return tableEntry{description, parameters, false, false}
}
/*
You can focus a particular entry with FEntry. This is equivalent to FIt.
*/
func FCase(description string, parameters ...interface{}) tableEntry {
return tableEntry{description, parameters, false, true}
}
/*
You can mark a particular entry as pending with PEntry. This is equivalent to PIt.
*/
func PCase(description string, parameters ...interface{}) tableEntry {
return tableEntry{description, parameters, true, false}
}
/*
You can mark a particular entry as pending with XEntry. This is equivalent to XIt.
*/
func XCase(description string, parameters ...interface{}) tableEntry {
return tableEntry{description, parameters, true, false}
}