cmd/swarm: Merge branch 'master' into multiple-ens-endpoints
Fix a conflict in cmd/swarm envVarsOverride function.
This commit is contained in:
commit
47a8014559
|
@ -129,7 +129,7 @@ func Bind(types []string, abis []string, bytecodes []string, pkg string, lang La
|
|||
return string(code), nil
|
||||
}
|
||||
// For all others just return as is for now
|
||||
return string(buffer.Bytes()), nil
|
||||
return buffer.String(), nil
|
||||
}
|
||||
|
||||
// bindType is a set of type binders that convert Solidity types to some supported
|
||||
|
|
|
@ -368,11 +368,11 @@ func TestUnmarshal(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Error(err)
|
||||
} else {
|
||||
if bytes.Compare(p0, p0Exp) != 0 {
|
||||
if !bytes.Equal(p0, p0Exp) {
|
||||
t.Errorf("unexpected value unpacked: want %x, got %x", p0Exp, p0)
|
||||
}
|
||||
|
||||
if bytes.Compare(p1[:], p1Exp) != 0 {
|
||||
if !bytes.Equal(p1[:], p1Exp) {
|
||||
t.Errorf("unexpected value unpacked: want %x, got %x", p1Exp, p1)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -260,8 +260,7 @@ func NewTree(hasher BaseHasher, segmentSize, segmentCount int) *Tree {
|
|||
for d := 1; d <= depth(segmentCount); d++ {
|
||||
nodes := make([]*Node, count)
|
||||
for i := 0; i < len(nodes); i++ {
|
||||
var parent *Node
|
||||
parent = prevlevel[i/2]
|
||||
parent := prevlevel[i/2]
|
||||
t := NewNode(level, i, parent)
|
||||
nodes[i] = t
|
||||
}
|
||||
|
|
|
@ -319,8 +319,8 @@ func doLint(cmdline []string) {
|
|||
packages = flag.CommandLine.Args()
|
||||
}
|
||||
// Get metalinter and install all supported linters
|
||||
build.MustRun(goTool("get", "gopkg.in/alecthomas/gometalinter.v1"))
|
||||
build.MustRunCommand(filepath.Join(GOBIN, "gometalinter.v1"), "--install")
|
||||
build.MustRun(goTool("get", "gopkg.in/alecthomas/gometalinter.v2"))
|
||||
build.MustRunCommand(filepath.Join(GOBIN, "gometalinter.v2"), "--install")
|
||||
|
||||
// Run fast linters batched together
|
||||
configs := []string{
|
||||
|
@ -332,12 +332,12 @@ func doLint(cmdline []string) {
|
|||
"--enable=goconst",
|
||||
"--min-occurrences=6", // for goconst
|
||||
}
|
||||
build.MustRunCommand(filepath.Join(GOBIN, "gometalinter.v1"), append(configs, packages...)...)
|
||||
build.MustRunCommand(filepath.Join(GOBIN, "gometalinter.v2"), append(configs, packages...)...)
|
||||
|
||||
// Run slow linters one by one
|
||||
for _, linter := range []string{"unconvert", "gosimple"} {
|
||||
configs = []string{"--vendor", "--deadline=10m", "--disable-all", "--enable=" + linter}
|
||||
build.MustRunCommand(filepath.Join(GOBIN, "gometalinter.v1"), append(configs, packages...)...)
|
||||
build.MustRunCommand(filepath.Join(GOBIN, "gometalinter.v2"), append(configs, packages...)...)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -506,7 +506,7 @@ func (f *faucet) apiHandler(conn *websocket.Conn) {
|
|||
|
||||
// Send an error if too frequent funding, othewise a success
|
||||
if !fund {
|
||||
if err = sendError(conn, fmt.Errorf("%s left until next allowance", common.PrettyDuration(timeout.Sub(time.Now())))); err != nil {
|
||||
if err = sendError(conn, fmt.Errorf("%s left until next allowance", common.PrettyDuration(timeout.Sub(time.Now())))); err != nil { // nolint: gosimple
|
||||
log.Warn("Failed to send funding error to client", "err", err)
|
||||
return
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -276,7 +276,7 @@ func envVarsOverride(currentConfig *bzzapi.Config) (config *bzzapi.Config) {
|
|||
}
|
||||
|
||||
//EnsAPIs can be set to "", so can't check for empty string, as it is allowed
|
||||
if ensapi, exists := os.LookupEnv(SWARM_ENV_ENS_API); exists == true {
|
||||
if ensapi, exists := os.LookupEnv(SWARM_ENV_ENS_API); exists {
|
||||
ensAPIs := strings.Split(ensapi, ",")
|
||||
// Disable ENS resolver if SWARM_ENS_API="" is specified
|
||||
if len(ensAPIs) == 0 {
|
||||
|
|
|
@ -124,7 +124,7 @@ func TestCmdLineOverrides(t *testing.T) {
|
|||
t.Fatalf("Expected network ID to be %d, got %d", 42, info.NetworkId)
|
||||
}
|
||||
|
||||
if info.SyncEnabled != true {
|
||||
if !info.SyncEnabled {
|
||||
t.Fatal("Expected Sync to be enabled, but is false")
|
||||
}
|
||||
|
||||
|
@ -219,7 +219,7 @@ func TestFileOverrides(t *testing.T) {
|
|||
t.Fatalf("Expected network ID to be %d, got %d", 54, info.NetworkId)
|
||||
}
|
||||
|
||||
if info.SyncEnabled != true {
|
||||
if !info.SyncEnabled {
|
||||
t.Fatal("Expected Sync to be enabled, but is false")
|
||||
}
|
||||
|
||||
|
@ -334,7 +334,7 @@ func TestEnvVars(t *testing.T) {
|
|||
t.Fatalf("Expected Cors flag to be set to %s, got %s", "*", info.Cors)
|
||||
}
|
||||
|
||||
if info.SyncEnabled != true {
|
||||
if !info.SyncEnabled {
|
||||
t.Fatal("Expected Sync to be enabled, but is false")
|
||||
}
|
||||
|
||||
|
@ -431,7 +431,7 @@ func TestCmdLineOverridesFile(t *testing.T) {
|
|||
t.Fatalf("Expected network ID to be %d, got %d", expectNetworkId, info.NetworkId)
|
||||
}
|
||||
|
||||
if info.SyncEnabled != true {
|
||||
if !info.SyncEnabled {
|
||||
t.Fatal("Expected Sync to be enabled, but is false")
|
||||
}
|
||||
|
||||
|
|
|
@ -630,7 +630,7 @@ func (c *Clique) Seal(chain consensus.ChainReader, block *types.Block, stop <-ch
|
|||
}
|
||||
}
|
||||
// Sweet, the protocol permits us to sign the block, wait for our time
|
||||
delay := time.Unix(header.Time.Int64(), 0).Sub(time.Now())
|
||||
delay := time.Unix(header.Time.Int64(), 0).Sub(time.Now()) // nolint: gosimple
|
||||
if header.Difficulty.Cmp(diffNoTurn) == 0 {
|
||||
// It's not our turn explicitly to sign, delay it a bit
|
||||
wiggle := time.Duration(len(snap.Signers)/2+1) * wiggleTime
|
||||
|
|
|
@ -164,7 +164,7 @@ func TestWelcome(t *testing.T) {
|
|||
|
||||
tester.console.Welcome()
|
||||
|
||||
output := string(tester.output.Bytes())
|
||||
output := tester.output.String()
|
||||
if want := "Welcome"; !strings.Contains(output, want) {
|
||||
t.Fatalf("console output missing welcome message: have\n%s\nwant also %s", output, want)
|
||||
}
|
||||
|
@ -188,7 +188,7 @@ func TestEvaluate(t *testing.T) {
|
|||
defer tester.Close(t)
|
||||
|
||||
tester.console.Evaluate("2 + 2")
|
||||
if output := string(tester.output.Bytes()); !strings.Contains(output, "4") {
|
||||
if output := tester.output.String(); !strings.Contains(output, "4") {
|
||||
t.Fatalf("statement evaluation failed: have %s, want %s", output, "4")
|
||||
}
|
||||
}
|
||||
|
@ -218,7 +218,7 @@ func TestInteractive(t *testing.T) {
|
|||
case <-time.After(time.Second):
|
||||
t.Fatalf("secondary prompt timeout")
|
||||
}
|
||||
if output := string(tester.output.Bytes()); !strings.Contains(output, "4") {
|
||||
if output := tester.output.String(); !strings.Contains(output, "4") {
|
||||
t.Fatalf("statement evaluation failed: have %s, want %s", output, "4")
|
||||
}
|
||||
}
|
||||
|
@ -230,7 +230,7 @@ func TestPreload(t *testing.T) {
|
|||
defer tester.Close(t)
|
||||
|
||||
tester.console.Evaluate("preloaded")
|
||||
if output := string(tester.output.Bytes()); !strings.Contains(output, "some-preloaded-string") {
|
||||
if output := tester.output.String(); !strings.Contains(output, "some-preloaded-string") {
|
||||
t.Fatalf("preloaded variable missing: have %s, want %s", output, "some-preloaded-string")
|
||||
}
|
||||
}
|
||||
|
@ -243,7 +243,7 @@ func TestExecute(t *testing.T) {
|
|||
tester.console.Execute("exec.js")
|
||||
|
||||
tester.console.Evaluate("execed")
|
||||
if output := string(tester.output.Bytes()); !strings.Contains(output, "some-executed-string") {
|
||||
if output := tester.output.String(); !strings.Contains(output, "some-executed-string") {
|
||||
t.Fatalf("execed variable missing: have %s, want %s", output, "some-executed-string")
|
||||
}
|
||||
}
|
||||
|
@ -275,7 +275,7 @@ func TestPrettyPrint(t *testing.T) {
|
|||
string: ` + two + `
|
||||
}
|
||||
`
|
||||
if output := string(tester.output.Bytes()); output != want {
|
||||
if output := tester.output.String(); output != want {
|
||||
t.Fatalf("pretty print mismatch: have %s, want %s", output, want)
|
||||
}
|
||||
}
|
||||
|
@ -287,7 +287,7 @@ func TestPrettyError(t *testing.T) {
|
|||
tester.console.Evaluate("throw 'hello'")
|
||||
|
||||
want := jsre.ErrorColor("hello") + "\n"
|
||||
if output := string(tester.output.Bytes()); output != want {
|
||||
if output := tester.output.String(); output != want {
|
||||
t.Fatalf("pretty error mismatch: have %s, want %s", output, want)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -114,10 +114,7 @@ func PrintDisassembled(code string) error {
|
|||
fmt.Printf("%06v: %v\n", it.PC(), it.Op())
|
||||
}
|
||||
}
|
||||
if err := it.Error(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
return it.Error()
|
||||
}
|
||||
|
||||
// Return all disassembled EVM instructions in human-readable format.
|
||||
|
|
|
@ -237,10 +237,7 @@ func (c *Compiler) pushBin(v interface{}) {
|
|||
// isPush returns whether the string op is either any of
|
||||
// push(N).
|
||||
func isPush(op string) bool {
|
||||
if op == "push" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
return op == "push"
|
||||
}
|
||||
|
||||
// isJump returns whether the string op is jump(i)
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -193,7 +193,6 @@ func (s *Service) loop() {
|
|||
}
|
||||
}
|
||||
close(quitCh)
|
||||
return
|
||||
}()
|
||||
// Loop reporting until termination
|
||||
for {
|
||||
|
|
|
@ -1071,7 +1071,7 @@ type SendTxArgs struct {
|
|||
Nonce *hexutil.Uint64 `json:"nonce"`
|
||||
}
|
||||
|
||||
// prepareSendTxArgs is a helper function that fills in default values for unspecified tx fields.
|
||||
// setDefaults is a helper function that fills in default values for unspecified tx fields.
|
||||
func (args *SendTxArgs) setDefaults(ctx context.Context, b Backend) error {
|
||||
if args.Gas == nil {
|
||||
args.Gas = (*hexutil.Big)(big.NewInt(defaultGas))
|
||||
|
|
|
@ -684,7 +684,7 @@ func (net *Network) refresh(done chan<- struct{}) {
|
|||
seeds = net.nursery
|
||||
}
|
||||
if len(seeds) == 0 {
|
||||
log.Trace(fmt.Sprint("no seed nodes found"))
|
||||
log.Trace("no seed nodes found")
|
||||
close(done)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -54,10 +54,10 @@ func checkClockDrift() {
|
|||
howtofix := fmt.Sprintf("Please enable network time synchronisation in system settings")
|
||||
separator := strings.Repeat("-", len(warning))
|
||||
|
||||
log.Warn(fmt.Sprint(separator))
|
||||
log.Warn(fmt.Sprint(warning))
|
||||
log.Warn(fmt.Sprint(howtofix))
|
||||
log.Warn(fmt.Sprint(separator))
|
||||
log.Warn(separator)
|
||||
log.Warn(warning)
|
||||
log.Warn(howtofix)
|
||||
log.Warn(separator)
|
||||
} else {
|
||||
log.Debug(fmt.Sprintf("Sanity NTP check reported %v drift, all ok", drift))
|
||||
}
|
||||
|
|
|
@ -398,12 +398,12 @@ func (s *ticketStore) nextRegisterableTicket() (t *ticketRef, wait time.Duration
|
|||
//s.removeExcessTickets(topic)
|
||||
if len(tickets.buckets) != 0 {
|
||||
empty = false
|
||||
if list := tickets.buckets[bucket]; list != nil {
|
||||
for _, ref := range list {
|
||||
//debugLog(fmt.Sprintf(" nrt bucket = %d node = %x sn = %v wait = %v", bucket, ref.t.node.ID[:8], ref.t.serial, time.Duration(ref.topicRegTime()-now)))
|
||||
if nextTicket.t == nil || ref.topicRegTime() < nextTicket.topicRegTime() {
|
||||
nextTicket = ref
|
||||
}
|
||||
|
||||
list := tickets.buckets[bucket]
|
||||
for _, ref := range list {
|
||||
//debugLog(fmt.Sprintf(" nrt bucket = %d node = %x sn = %v wait = %v", bucket, ref.t.node.ID[:8], ref.t.serial, time.Duration(ref.topicRegTime()-now)))
|
||||
if nextTicket.t == nil || ref.topicRegTime() < nextTicket.topicRegTime() {
|
||||
nextTicket = ref
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
// Copyright 2017 The go-ethereum Authors
|
||||
// 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 adapters
|
||||
|
||||
type SimStateStore struct {
|
||||
m map[string][]byte
|
||||
}
|
||||
|
||||
func (self *SimStateStore) Load(s string) ([]byte, error) {
|
||||
return self.m[s], nil
|
||||
}
|
||||
|
||||
func (self *SimStateStore) Save(s string, data []byte) error {
|
||||
self.m[s] = data
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewSimStateStore() *SimStateStore {
|
||||
return &SimStateStore{
|
||||
make(map[string][]byte),
|
||||
}
|
||||
}
|
|
@ -27,6 +27,7 @@ import (
|
|||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/ethereum/go-ethereum/event"
|
||||
"github.com/ethereum/go-ethereum/p2p"
|
||||
|
@ -263,8 +264,10 @@ func (c *Client) Send(method, path string, in, out interface{}) error {
|
|||
|
||||
// Server is an HTTP server providing an API to manage a simulation network
|
||||
type Server struct {
|
||||
router *httprouter.Router
|
||||
network *Network
|
||||
router *httprouter.Router
|
||||
network *Network
|
||||
mockerStop chan struct{} // when set, stops the current mocker
|
||||
mockerMtx sync.Mutex // synchronises access to the mockerStop field
|
||||
}
|
||||
|
||||
// NewServer returns a new simulation API server
|
||||
|
@ -278,6 +281,10 @@ func NewServer(network *Network) *Server {
|
|||
s.GET("/", s.GetNetwork)
|
||||
s.POST("/start", s.StartNetwork)
|
||||
s.POST("/stop", s.StopNetwork)
|
||||
s.POST("/mocker/start", s.StartMocker)
|
||||
s.POST("/mocker/stop", s.StopMocker)
|
||||
s.GET("/mocker", s.GetMockers)
|
||||
s.POST("/reset", s.ResetNetwork)
|
||||
s.GET("/events", s.StreamNetworkEvents)
|
||||
s.GET("/snapshot", s.CreateSnapshot)
|
||||
s.POST("/snapshot", s.LoadSnapshot)
|
||||
|
@ -318,6 +325,59 @@ func (s *Server) StopNetwork(w http.ResponseWriter, req *http.Request) {
|
|||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
// StartMocker starts the mocker node simulation
|
||||
func (s *Server) StartMocker(w http.ResponseWriter, req *http.Request) {
|
||||
s.mockerMtx.Lock()
|
||||
defer s.mockerMtx.Unlock()
|
||||
if s.mockerStop != nil {
|
||||
http.Error(w, "mocker already running", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
mockerType := req.FormValue("mocker-type")
|
||||
mockerFn := LookupMocker(mockerType)
|
||||
if mockerFn == nil {
|
||||
http.Error(w, fmt.Sprintf("unknown mocker type %q", mockerType), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
nodeCount, err := strconv.Atoi(req.FormValue("node-count"))
|
||||
if err != nil {
|
||||
http.Error(w, "invalid node-count provided", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
s.mockerStop = make(chan struct{})
|
||||
go mockerFn(s.network, s.mockerStop, nodeCount)
|
||||
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
// StopMocker stops the mocker node simulation
|
||||
func (s *Server) StopMocker(w http.ResponseWriter, req *http.Request) {
|
||||
s.mockerMtx.Lock()
|
||||
defer s.mockerMtx.Unlock()
|
||||
if s.mockerStop == nil {
|
||||
http.Error(w, "stop channel not initialized", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
close(s.mockerStop)
|
||||
s.mockerStop = nil
|
||||
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
// GetMockerList returns a list of available mockers
|
||||
func (s *Server) GetMockers(w http.ResponseWriter, req *http.Request) {
|
||||
|
||||
list := GetMockerList()
|
||||
s.JSON(w, http.StatusOK, list)
|
||||
}
|
||||
|
||||
// ResetNetwork resets all properties of a network to its initial (empty) state
|
||||
func (s *Server) ResetNetwork(w http.ResponseWriter, req *http.Request) {
|
||||
s.network.Reset()
|
||||
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
// StreamNetworkEvents streams network events as a server-sent-events stream
|
||||
func (s *Server) StreamNetworkEvents(w http.ResponseWriter, req *http.Request) {
|
||||
events := make(chan *Event)
|
||||
|
|
|
@ -0,0 +1,192 @@
|
|||
// Copyright 2017 The go-ethereum Authors
|
||||
// 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 simulations simulates p2p networks.
|
||||
// A mocker simulates starting and stopping real nodes in a network.
|
||||
package simulations
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/p2p/discover"
|
||||
)
|
||||
|
||||
//a map of mocker names to its function
|
||||
var mockerList = map[string]func(net *Network, quit chan struct{}, nodeCount int){
|
||||
"startStop": startStop,
|
||||
"probabilistic": probabilistic,
|
||||
"boot": boot,
|
||||
}
|
||||
|
||||
//Lookup a mocker by its name, returns the mockerFn
|
||||
func LookupMocker(mockerType string) func(net *Network, quit chan struct{}, nodeCount int) {
|
||||
return mockerList[mockerType]
|
||||
}
|
||||
|
||||
//Get a list of mockers (keys of the map)
|
||||
//Useful for frontend to build available mocker selection
|
||||
func GetMockerList() []string {
|
||||
list := make([]string, 0, len(mockerList))
|
||||
for k := range mockerList {
|
||||
list = append(list, k)
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
//The boot mockerFn only connects the node in a ring and doesn't do anything else
|
||||
func boot(net *Network, quit chan struct{}, nodeCount int) {
|
||||
_, err := connectNodesInRing(net, nodeCount)
|
||||
if err != nil {
|
||||
panic("Could not startup node network for mocker")
|
||||
}
|
||||
}
|
||||
|
||||
//The startStop mockerFn stops and starts nodes in a defined period (ticker)
|
||||
func startStop(net *Network, quit chan struct{}, nodeCount int) {
|
||||
nodes, err := connectNodesInRing(net, nodeCount)
|
||||
if err != nil {
|
||||
panic("Could not startup node network for mocker")
|
||||
}
|
||||
tick := time.NewTicker(10 * time.Second)
|
||||
defer tick.Stop()
|
||||
for {
|
||||
select {
|
||||
case <-quit:
|
||||
log.Info("Terminating simulation loop")
|
||||
return
|
||||
case <-tick.C:
|
||||
id := nodes[rand.Intn(len(nodes))]
|
||||
log.Info("stopping node", "id", id)
|
||||
if err := net.Stop(id); err != nil {
|
||||
log.Error("error stopping node", "id", id, "err", err)
|
||||
return
|
||||
}
|
||||
|
||||
select {
|
||||
case <-quit:
|
||||
log.Info("Terminating simulation loop")
|
||||
return
|
||||
case <-time.After(3 * time.Second):
|
||||
}
|
||||
|
||||
log.Debug("starting node", "id", id)
|
||||
if err := net.Start(id); err != nil {
|
||||
log.Error("error starting node", "id", id, "err", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//The probabilistic mocker func has a more probabilistic pattern
|
||||
//(the implementation could probably be improved):
|
||||
//nodes are connected in a ring, then a varying number of random nodes is selected,
|
||||
//mocker then stops and starts them in random intervals, and continues the loop
|
||||
func probabilistic(net *Network, quit chan struct{}, nodeCount int) {
|
||||
nodes, err := connectNodesInRing(net, nodeCount)
|
||||
if err != nil {
|
||||
panic("Could not startup node network for mocker")
|
||||
}
|
||||
for {
|
||||
select {
|
||||
case <-quit:
|
||||
log.Info("Terminating simulation loop")
|
||||
return
|
||||
default:
|
||||
}
|
||||
var lowid, highid int
|
||||
var wg sync.WaitGroup
|
||||
randWait := time.Duration(rand.Intn(5000)+1000) * time.Millisecond
|
||||
rand1 := rand.Intn(nodeCount - 1)
|
||||
rand2 := rand.Intn(nodeCount - 1)
|
||||
if rand1 < rand2 {
|
||||
lowid = rand1
|
||||
highid = rand2
|
||||
} else if rand1 > rand2 {
|
||||
highid = rand1
|
||||
lowid = rand2
|
||||
} else {
|
||||
if rand1 == 0 {
|
||||
rand2 = 9
|
||||
} else if rand1 == 9 {
|
||||
rand1 = 0
|
||||
}
|
||||
lowid = rand1
|
||||
highid = rand2
|
||||
}
|
||||
var steps = highid - lowid
|
||||
wg.Add(steps)
|
||||
for i := lowid; i < highid; i++ {
|
||||
select {
|
||||
case <-quit:
|
||||
log.Info("Terminating simulation loop")
|
||||
return
|
||||
case <-time.After(randWait):
|
||||
}
|
||||
log.Debug(fmt.Sprintf("node %v shutting down", nodes[i]))
|
||||
err := net.Stop(nodes[i])
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("Error stopping node %s", nodes[i]))
|
||||
wg.Done()
|
||||
continue
|
||||
}
|
||||
go func(id discover.NodeID) {
|
||||
time.Sleep(randWait)
|
||||
err := net.Start(id)
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("Error starting node %s", id))
|
||||
}
|
||||
wg.Done()
|
||||
}(nodes[i])
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//connect nodeCount number of nodes in a ring
|
||||
func connectNodesInRing(net *Network, nodeCount int) ([]discover.NodeID, error) {
|
||||
ids := make([]discover.NodeID, nodeCount)
|
||||
for i := 0; i < nodeCount; i++ {
|
||||
node, err := net.NewNode()
|
||||
if err != nil {
|
||||
log.Error("Error creating a node! %s", err)
|
||||
return nil, err
|
||||
}
|
||||
ids[i] = node.ID()
|
||||
}
|
||||
|
||||
for _, id := range ids {
|
||||
if err := net.Start(id); err != nil {
|
||||
log.Error("Error starting a node! %s", err)
|
||||
return nil, err
|
||||
}
|
||||
log.Debug(fmt.Sprintf("node %v starting up", id))
|
||||
}
|
||||
for i, id := range ids {
|
||||
peerID := ids[(i+1)%len(ids)]
|
||||
if err := net.Connect(id, peerID); err != nil {
|
||||
log.Error("Error connecting a node to a peer! %s", err)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return ids, nil
|
||||
}
|
|
@ -0,0 +1,171 @@
|
|||
// Copyright 2017 The go-ethereum Authors
|
||||
// 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 simulations simulates p2p networks.
|
||||
// A mokcer simulates starting and stopping real nodes in a network.
|
||||
package simulations
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/p2p/discover"
|
||||
)
|
||||
|
||||
func TestMocker(t *testing.T) {
|
||||
//start the simulation HTTP server
|
||||
_, s := testHTTPServer(t)
|
||||
defer s.Close()
|
||||
|
||||
//create a client
|
||||
client := NewClient(s.URL)
|
||||
|
||||
//start the network
|
||||
err := client.StartNetwork()
|
||||
if err != nil {
|
||||
t.Fatalf("Could not start test network: %s", err)
|
||||
}
|
||||
//stop the network to terminate
|
||||
defer func() {
|
||||
err = client.StopNetwork()
|
||||
if err != nil {
|
||||
t.Fatalf("Could not stop test network: %s", err)
|
||||
}
|
||||
}()
|
||||
|
||||
//get the list of available mocker types
|
||||
resp, err := http.Get(s.URL + "/mocker")
|
||||
if err != nil {
|
||||
t.Fatalf("Could not get mocker list: %s", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
t.Fatalf("Invalid Status Code received, expected 200, got %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
//check the list is at least 1 in size
|
||||
var mockerlist []string
|
||||
err = json.NewDecoder(resp.Body).Decode(&mockerlist)
|
||||
if err != nil {
|
||||
t.Fatalf("Error decoding JSON mockerlist: %s", err)
|
||||
}
|
||||
|
||||
if len(mockerlist) < 1 {
|
||||
t.Fatalf("No mockers available")
|
||||
}
|
||||
|
||||
nodeCount := 10
|
||||
var wg sync.WaitGroup
|
||||
|
||||
events := make(chan *Event, 10)
|
||||
var opts SubscribeOpts
|
||||
sub, err := client.SubscribeNetwork(events, opts)
|
||||
defer sub.Unsubscribe()
|
||||
//wait until all nodes are started and connected
|
||||
//store every node up event in a map (value is irrelevant, mimic Set datatype)
|
||||
nodemap := make(map[discover.NodeID]bool)
|
||||
wg.Add(1)
|
||||
nodesComplete := false
|
||||
connCount := 0
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case event := <-events:
|
||||
//if the event is a node Up event only
|
||||
if event.Node != nil && event.Node.Up {
|
||||
//add the correspondent node ID to the map
|
||||
nodemap[event.Node.Config.ID] = true
|
||||
//this means all nodes got a nodeUp event, so we can continue the test
|
||||
if len(nodemap) == nodeCount {
|
||||
nodesComplete = true
|
||||
//wait for 3s as the mocker will need time to connect the nodes
|
||||
//time.Sleep( 3 *time.Second)
|
||||
}
|
||||
} else if event.Conn != nil && nodesComplete {
|
||||
connCount += 1
|
||||
if connCount == (nodeCount-1)*2 {
|
||||
wg.Done()
|
||||
return
|
||||
}
|
||||
}
|
||||
case <-time.After(30 * time.Second):
|
||||
wg.Done()
|
||||
t.Fatalf("Timeout waiting for nodes being started up!")
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
//take the last element of the mockerlist as the default mocker-type to ensure one is enabled
|
||||
mockertype := mockerlist[len(mockerlist)-1]
|
||||
//still, use hardcoded "probabilistic" one if available ;)
|
||||
for _, m := range mockerlist {
|
||||
if m == "probabilistic" {
|
||||
mockertype = m
|
||||
break
|
||||
}
|
||||
}
|
||||
//start the mocker with nodeCount number of nodes
|
||||
resp, err = http.PostForm(s.URL+"/mocker/start", url.Values{"mocker-type": {mockertype}, "node-count": {strconv.Itoa(nodeCount)}})
|
||||
if err != nil {
|
||||
t.Fatalf("Could not start mocker: %s", err)
|
||||
}
|
||||
if resp.StatusCode != 200 {
|
||||
t.Fatalf("Invalid Status Code received for starting mocker, expected 200, got %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
//check there are nodeCount number of nodes in the network
|
||||
nodes_info, err := client.GetNodes()
|
||||
if err != nil {
|
||||
t.Fatalf("Could not get nodes list: %s", err)
|
||||
}
|
||||
|
||||
if len(nodes_info) != nodeCount {
|
||||
t.Fatalf("Expected %d number of nodes, got: %d", nodeCount, len(nodes_info))
|
||||
}
|
||||
|
||||
//stop the mocker
|
||||
resp, err = http.Post(s.URL+"/mocker/stop", "", nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not stop mocker: %s", err)
|
||||
}
|
||||
if resp.StatusCode != 200 {
|
||||
t.Fatalf("Invalid Status Code received for stopping mocker, expected 200, got %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
//reset the network
|
||||
_, err = http.Post(s.URL+"/reset", "", nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not reset network: %s", err)
|
||||
}
|
||||
|
||||
//now the number of nodes in the network should be zero
|
||||
nodes_info, err = client.GetNodes()
|
||||
if err != nil {
|
||||
t.Fatalf("Could not get nodes list: %s", err)
|
||||
}
|
||||
|
||||
if len(nodes_info) != 0 {
|
||||
t.Fatalf("Expected empty list of nodes, got: %d", len(nodes_info))
|
||||
}
|
||||
}
|
|
@ -403,9 +403,8 @@ func (self *Network) getNodeByName(name string) *Node {
|
|||
func (self *Network) GetNodes() (nodes []*Node) {
|
||||
self.lock.Lock()
|
||||
defer self.lock.Unlock()
|
||||
for _, node := range self.Nodes {
|
||||
nodes = append(nodes, node)
|
||||
}
|
||||
|
||||
nodes = append(nodes, self.Nodes...)
|
||||
return nodes
|
||||
}
|
||||
|
||||
|
@ -477,7 +476,7 @@ func (self *Network) InitConn(oneID, otherID discover.NodeID) (*Conn, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if time.Now().Sub(conn.initiated) < dialBanTimeout {
|
||||
if time.Since(conn.initiated) < dialBanTimeout {
|
||||
return nil, fmt.Errorf("connection between %v and %v recently attempted", oneID, otherID)
|
||||
}
|
||||
if conn.Up {
|
||||
|
@ -502,6 +501,20 @@ func (self *Network) Shutdown() {
|
|||
close(self.quitc)
|
||||
}
|
||||
|
||||
//Reset resets all network properties:
|
||||
//emtpies the nodes and the connection list
|
||||
func (self *Network) Reset() {
|
||||
self.lock.Lock()
|
||||
defer self.lock.Unlock()
|
||||
|
||||
//re-initialize the maps
|
||||
self.connMap = make(map[string]int)
|
||||
self.nodeMap = make(map[discover.NodeID]int)
|
||||
|
||||
self.Nodes = nil
|
||||
self.Conns = nil
|
||||
}
|
||||
|
||||
// Node is a wrapper around adapters.Node which is used to track the status
|
||||
// of a node in the network
|
||||
type Node struct {
|
||||
|
@ -665,6 +678,12 @@ func (self *Network) Load(snap *Snapshot) error {
|
|||
}
|
||||
}
|
||||
for _, conn := range snap.Conns {
|
||||
|
||||
if !self.GetNode(conn.One).Up || !self.GetNode(conn.Other).Up {
|
||||
//in this case, at least one of the nodes of a connection is not up,
|
||||
//so it would result in the snapshot `Load` to fail
|
||||
continue
|
||||
}
|
||||
if err := self.Connect(conn.One, conn.Other); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ func (hc *httpConn) Close() error {
|
|||
|
||||
// DialHTTP creates a new RPC clients that connection to an RPC server over HTTP.
|
||||
func DialHTTP(endpoint string) (*Client, error) {
|
||||
req, err := http.NewRequest("POST", endpoint, nil)
|
||||
req, err := http.NewRequest(http.MethodPost, endpoint, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -149,7 +149,7 @@ func NewHTTPServer(cors []string, srv *Server) *http.Server {
|
|||
// ServeHTTP serves JSON-RPC requests over HTTP.
|
||||
func (srv *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
// Permit dumb empty requests for remote health-checks (AWS)
|
||||
if r.Method == "GET" && r.ContentLength == 0 && r.URL.RawQuery == "" {
|
||||
if r.Method == http.MethodGet && r.ContentLength == 0 && r.URL.RawQuery == "" {
|
||||
return
|
||||
}
|
||||
if code, err := validateRequest(r); err != nil {
|
||||
|
@ -169,7 +169,7 @@ func (srv *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
// validateRequest returns a non-zero response code and error message if the
|
||||
// request is invalid.
|
||||
func validateRequest(r *http.Request) (int, error) {
|
||||
if r.Method == "PUT" || r.Method == "DELETE" {
|
||||
if r.Method == http.MethodPut || r.Method == http.MethodDelete {
|
||||
return http.StatusMethodNotAllowed, errors.New("method not allowed")
|
||||
}
|
||||
if r.ContentLength > maxHTTPRequestContentLength {
|
||||
|
@ -192,7 +192,7 @@ func newCorsHandler(srv *Server, allowedOrigins []string) http.Handler {
|
|||
|
||||
c := cors.New(cors.Options{
|
||||
AllowedOrigins: allowedOrigins,
|
||||
AllowedMethods: []string{"POST", "GET"},
|
||||
AllowedMethods: []string{http.MethodPost, http.MethodGet},
|
||||
MaxAge: 600,
|
||||
AllowedHeaders: []string{"*"},
|
||||
})
|
||||
|
|
|
@ -24,25 +24,25 @@ import (
|
|||
)
|
||||
|
||||
func TestHTTPErrorResponseWithDelete(t *testing.T) {
|
||||
testHTTPErrorResponse(t, "DELETE", contentType, "", http.StatusMethodNotAllowed)
|
||||
testHTTPErrorResponse(t, http.MethodDelete, contentType, "", http.StatusMethodNotAllowed)
|
||||
}
|
||||
|
||||
func TestHTTPErrorResponseWithPut(t *testing.T) {
|
||||
testHTTPErrorResponse(t, "PUT", contentType, "", http.StatusMethodNotAllowed)
|
||||
testHTTPErrorResponse(t, http.MethodPut, contentType, "", http.StatusMethodNotAllowed)
|
||||
}
|
||||
|
||||
func TestHTTPErrorResponseWithMaxContentLength(t *testing.T) {
|
||||
body := make([]rune, maxHTTPRequestContentLength+1, maxHTTPRequestContentLength+1)
|
||||
body := make([]rune, maxHTTPRequestContentLength+1)
|
||||
testHTTPErrorResponse(t,
|
||||
"POST", contentType, string(body), http.StatusRequestEntityTooLarge)
|
||||
http.MethodPost, contentType, string(body), http.StatusRequestEntityTooLarge)
|
||||
}
|
||||
|
||||
func TestHTTPErrorResponseWithEmptyContentType(t *testing.T) {
|
||||
testHTTPErrorResponse(t, "POST", "", "", http.StatusUnsupportedMediaType)
|
||||
testHTTPErrorResponse(t, http.MethodPost, "", "", http.StatusUnsupportedMediaType)
|
||||
}
|
||||
|
||||
func TestHTTPErrorResponseWithValidRequest(t *testing.T) {
|
||||
testHTTPErrorResponse(t, "POST", contentType, "", 0)
|
||||
testHTTPErrorResponse(t, http.MethodPost, contentType, "", 0)
|
||||
}
|
||||
|
||||
func testHTTPErrorResponse(t *testing.T, method, contentType, body string, expected int) {
|
||||
|
|
|
@ -36,7 +36,7 @@ func TestConfig(t *testing.T) {
|
|||
one := NewDefaultConfig()
|
||||
two := NewDefaultConfig()
|
||||
|
||||
if equal := reflect.DeepEqual(one, two); equal == false {
|
||||
if equal := reflect.DeepEqual(one, two); !equal {
|
||||
t.Fatal("Two default configs are not equal")
|
||||
}
|
||||
|
||||
|
|
|
@ -95,7 +95,7 @@ func mountDir(t *testing.T, api *api.Api, files map[string]fileInfo, bzzHash str
|
|||
}
|
||||
|
||||
// Test listMounts
|
||||
if found == false {
|
||||
if !found {
|
||||
t.Fatalf("Error getting mounts information for %v: %v", mountDir, err)
|
||||
}
|
||||
|
||||
|
@ -185,10 +185,8 @@ func isDirEmpty(name string) bool {
|
|||
defer f.Close()
|
||||
|
||||
_, err = f.Readdirnames(1)
|
||||
if err == io.EOF {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
||||
return err == io.EOF
|
||||
}
|
||||
|
||||
type testAPI struct {
|
||||
|
@ -388,7 +386,7 @@ func (ta *testAPI) seekInMultiChunkFile(t *testing.T) {
|
|||
d.Read(contents)
|
||||
finfo := files["1.txt"]
|
||||
|
||||
if bytes.Compare(finfo.contents[:6024][5000:], contents) != 0 {
|
||||
if !bytes.Equal(finfo.contents[:6024][5000:], contents) {
|
||||
t.Fatalf("File seek contents mismatch")
|
||||
}
|
||||
d.Close()
|
||||
|
|
|
@ -77,7 +77,7 @@ func (self *chunkerTester) Split(chunker Splitter, data io.Reader, size int64, c
|
|||
|
||||
key, err = chunker.Split(data, size, chunkC, swg, nil)
|
||||
if err != nil && expectedError == nil {
|
||||
err = errors.New(fmt.Sprintf("Split error: %v", err))
|
||||
err = fmt.Errorf("Split error: %v", err)
|
||||
}
|
||||
|
||||
if chunkC != nil {
|
||||
|
@ -123,7 +123,7 @@ func (self *chunkerTester) Append(chunker Splitter, rootKey Key, data io.Reader,
|
|||
|
||||
key, err = chunker.Append(rootKey, data, chunkC, swg, nil)
|
||||
if err != nil && expectedError == nil {
|
||||
err = errors.New(fmt.Sprintf("Append error: %v", err))
|
||||
err = fmt.Errorf("Append error: %v", err)
|
||||
}
|
||||
|
||||
if chunkC != nil {
|
||||
|
|
|
@ -391,7 +391,7 @@ func (self *PyramidChunker) prepareChunks(isAppend bool, chunkLevel [][]*TreeEnt
|
|||
parent := NewTreeEntry(self)
|
||||
var unFinishedChunk *Chunk
|
||||
|
||||
if isAppend == true && len(chunkLevel[0]) != 0 {
|
||||
if isAppend && len(chunkLevel[0]) != 0 {
|
||||
|
||||
lastIndex := len(chunkLevel[0]) - 1
|
||||
ent := chunkLevel[0][lastIndex]
|
||||
|
@ -512,7 +512,7 @@ func (self *PyramidChunker) buildTree(isAppend bool, chunkLevel [][]*TreeEntry,
|
|||
}
|
||||
}
|
||||
|
||||
if compress == false && last == false {
|
||||
if !compress && !last {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -522,7 +522,7 @@ func (self *PyramidChunker) buildTree(isAppend bool, chunkLevel [][]*TreeEntry,
|
|||
for lvl := int64(ent.level); lvl < endLvl; lvl++ {
|
||||
|
||||
lvlCount := int64(len(chunkLevel[lvl]))
|
||||
if lvlCount == 1 && last == true {
|
||||
if lvlCount == 1 && last {
|
||||
copy(rootKey, chunkLevel[lvl][0].key)
|
||||
return
|
||||
}
|
||||
|
@ -540,7 +540,7 @@ func (self *PyramidChunker) buildTree(isAppend bool, chunkLevel [][]*TreeEntry,
|
|||
nextLvlCount = int64(len(chunkLevel[lvl+1]) - 1)
|
||||
tempEntry = chunkLevel[lvl+1][nextLvlCount]
|
||||
}
|
||||
if isAppend == true && tempEntry != nil && tempEntry.updatePending == true {
|
||||
if isAppend && tempEntry != nil && tempEntry.updatePending {
|
||||
updateEntry := &TreeEntry{
|
||||
level: int(lvl + 1),
|
||||
branchCount: 0,
|
||||
|
@ -585,9 +585,9 @@ func (self *PyramidChunker) buildTree(isAppend bool, chunkLevel [][]*TreeEntry,
|
|||
|
||||
}
|
||||
|
||||
if isAppend == false {
|
||||
if !isAppend {
|
||||
chunkWG.Wait()
|
||||
if compress == true {
|
||||
if compress {
|
||||
chunkLevel[lvl] = nil
|
||||
}
|
||||
}
|
||||
|
@ -599,7 +599,7 @@ func (self *PyramidChunker) enqueueTreeChunk(chunkLevel [][]*TreeEntry, ent *Tre
|
|||
if ent != nil {
|
||||
|
||||
// wait for data chunks to get over before processing the tree chunk
|
||||
if last == true {
|
||||
if last {
|
||||
chunkWG.Wait()
|
||||
}
|
||||
|
||||
|
@ -612,7 +612,7 @@ func (self *PyramidChunker) enqueueTreeChunk(chunkLevel [][]*TreeEntry, ent *Tre
|
|||
}
|
||||
|
||||
// Update or append based on weather it is a new entry or being reused
|
||||
if ent.updatePending == true {
|
||||
if ent.updatePending {
|
||||
chunkWG.Wait()
|
||||
chunkLevel[ent.level][ent.index] = ent
|
||||
} else {
|
||||
|
|
|
@ -80,8 +80,7 @@ func TestWhisperBasic(t *testing.T) {
|
|||
t.Fatalf("failed w.Messages.")
|
||||
}
|
||||
|
||||
var derived []byte
|
||||
derived = pbkdf2.Key([]byte(peerID), nil, 65356, aesKeyLength, sha256.New)
|
||||
derived := pbkdf2.Key([]byte(peerID), nil, 65356, aesKeyLength, sha256.New)
|
||||
if !validateSymmetricKey(derived) {
|
||||
t.Fatalf("failed validateSymmetricKey with param = %v.", derived)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue