cmd/swarm: Merge branch 'master' into multiple-ens-endpoints

Fix a conflict in cmd/swarm envVarsOverride function.
pull/15748/head
Janos Guljas 7 years ago
commit 47a8014559
  1. 2
      accounts/abi/bind/bind.go
  2. 4
      accounts/abi/unpack_test.go
  3. 3
      bmt/bmt.go
  4. 8
      build/ci.go
  5. 2
      cmd/faucet/faucet.go
  6. 1
      cmd/puppeth/module_dashboard.go
  7. 2
      cmd/swarm/config.go
  8. 8
      cmd/swarm/config_test.go
  9. 2
      consensus/clique/clique.go
  10. 14
      console/console_test.go
  11. 5
      core/asm/asm.go
  12. 5
      core/asm/compiler.go
  13. 1
      core/genesis_alloc.go
  14. 1
      ethstats/ethstats.go
  15. 2
      internal/ethapi/api.go
  16. 2
      p2p/discv5/net.go
  17. 8
      p2p/discv5/ntp.go
  18. 4
      p2p/discv5/ticket.go
  19. 35
      p2p/simulations/adapters/state.go
  20. 60
      p2p/simulations/http.go
  21. 192
      p2p/simulations/mocker.go
  22. 171
      p2p/simulations/mocker_test.go
  23. 27
      p2p/simulations/network.go
  24. 8
      rpc/http.go
  25. 12
      rpc/http_test.go
  26. 2
      swarm/api/config_test.go
  27. 10
      swarm/fuse/swarmfs_test.go
  28. 4
      swarm/storage/chunker_test.go
  29. 16
      swarm/storage/pyramid.go
  30. 3
      whisper/whisperv6/whisper_test.go

@ -129,7 +129,7 @@ func Bind(types []string, abis []string, bytecodes []string, pkg string, lang La
return string(code), nil return string(code), nil
} }
// For all others just return as is for now // 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 // 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 { if err != nil {
t.Error(err) t.Error(err)
} else { } else {
if bytes.Compare(p0, p0Exp) != 0 { if !bytes.Equal(p0, p0Exp) {
t.Errorf("unexpected value unpacked: want %x, got %x", p0Exp, p0) 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) 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++ { for d := 1; d <= depth(segmentCount); d++ {
nodes := make([]*Node, count) nodes := make([]*Node, count)
for i := 0; i < len(nodes); i++ { for i := 0; i < len(nodes); i++ {
var parent *Node parent := prevlevel[i/2]
parent = prevlevel[i/2]
t := NewNode(level, i, parent) t := NewNode(level, i, parent)
nodes[i] = t nodes[i] = t
} }

@ -319,8 +319,8 @@ func doLint(cmdline []string) {
packages = flag.CommandLine.Args() packages = flag.CommandLine.Args()
} }
// Get metalinter and install all supported linters // Get metalinter and install all supported linters
build.MustRun(goTool("get", "gopkg.in/alecthomas/gometalinter.v1")) build.MustRun(goTool("get", "gopkg.in/alecthomas/gometalinter.v2"))
build.MustRunCommand(filepath.Join(GOBIN, "gometalinter.v1"), "--install") build.MustRunCommand(filepath.Join(GOBIN, "gometalinter.v2"), "--install")
// Run fast linters batched together // Run fast linters batched together
configs := []string{ configs := []string{
@ -332,12 +332,12 @@ func doLint(cmdline []string) {
"--enable=goconst", "--enable=goconst",
"--min-occurrences=6", // for 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 // Run slow linters one by one
for _, linter := range []string{"unconvert", "gosimple"} { for _, linter := range []string{"unconvert", "gosimple"} {
configs = []string{"--vendor", "--deadline=10m", "--disable-all", "--enable=" + linter} 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 // Send an error if too frequent funding, othewise a success
if !fund { 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) log.Warn("Failed to send funding error to client", "err", err)
return 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 //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, ",") ensAPIs := strings.Split(ensapi, ",")
// Disable ENS resolver if SWARM_ENS_API="" is specified // Disable ENS resolver if SWARM_ENS_API="" is specified
if len(ensAPIs) == 0 { 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) 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") 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) 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") 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) 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") 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) 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") 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 // 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 { if header.Difficulty.Cmp(diffNoTurn) == 0 {
// It's not our turn explicitly to sign, delay it a bit // It's not our turn explicitly to sign, delay it a bit
wiggle := time.Duration(len(snap.Signers)/2+1) * wiggleTime wiggle := time.Duration(len(snap.Signers)/2+1) * wiggleTime

@ -164,7 +164,7 @@ func TestWelcome(t *testing.T) {
tester.console.Welcome() tester.console.Welcome()
output := string(tester.output.Bytes()) output := tester.output.String()
if want := "Welcome"; !strings.Contains(output, want) { if want := "Welcome"; !strings.Contains(output, want) {
t.Fatalf("console output missing welcome message: have\n%s\nwant also %s", 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) defer tester.Close(t)
tester.console.Evaluate("2 + 2") 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") 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): case <-time.After(time.Second):
t.Fatalf("secondary prompt timeout") 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") t.Fatalf("statement evaluation failed: have %s, want %s", output, "4")
} }
} }
@ -230,7 +230,7 @@ func TestPreload(t *testing.T) {
defer tester.Close(t) defer tester.Close(t)
tester.console.Evaluate("preloaded") 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") 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.Execute("exec.js")
tester.console.Evaluate("execed") 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") t.Fatalf("execed variable missing: have %s, want %s", output, "some-executed-string")
} }
} }
@ -275,7 +275,7 @@ func TestPrettyPrint(t *testing.T) {
string: ` + two + ` 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) 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'") tester.console.Evaluate("throw 'hello'")
want := jsre.ErrorColor("hello") + "\n" 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) 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()) fmt.Printf("%06v: %v\n", it.PC(), it.Op())
} }
} }
if err := it.Error(); err != nil { return it.Error()
return err
}
return nil
} }
// Return all disassembled EVM instructions in human-readable format. // 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 // isPush returns whether the string op is either any of
// push(N). // push(N).
func isPush(op string) bool { func isPush(op string) bool {
if op == "push" { return op == "push"
return true
}
return false
} }
// isJump returns whether the string op is jump(i) // 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) close(quitCh)
return
}() }()
// Loop reporting until termination // Loop reporting until termination
for { for {

@ -1071,7 +1071,7 @@ type SendTxArgs struct {
Nonce *hexutil.Uint64 `json:"nonce"` 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 { func (args *SendTxArgs) setDefaults(ctx context.Context, b Backend) error {
if args.Gas == nil { if args.Gas == nil {
args.Gas = (*hexutil.Big)(big.NewInt(defaultGas)) args.Gas = (*hexutil.Big)(big.NewInt(defaultGas))

@ -684,7 +684,7 @@ func (net *Network) refresh(done chan<- struct{}) {
seeds = net.nursery seeds = net.nursery
} }
if len(seeds) == 0 { if len(seeds) == 0 {
log.Trace(fmt.Sprint("no seed nodes found")) log.Trace("no seed nodes found")
close(done) close(done)
return return
} }

@ -54,10 +54,10 @@ func checkClockDrift() {
howtofix := fmt.Sprintf("Please enable network time synchronisation in system settings") howtofix := fmt.Sprintf("Please enable network time synchronisation in system settings")
separator := strings.Repeat("-", len(warning)) separator := strings.Repeat("-", len(warning))
log.Warn(fmt.Sprint(separator)) log.Warn(separator)
log.Warn(fmt.Sprint(warning)) log.Warn(warning)
log.Warn(fmt.Sprint(howtofix)) log.Warn(howtofix)
log.Warn(fmt.Sprint(separator)) log.Warn(separator)
} else { } else {
log.Debug(fmt.Sprintf("Sanity NTP check reported %v drift, all ok", drift)) log.Debug(fmt.Sprintf("Sanity NTP check reported %v drift, all ok", drift))
} }

@ -398,7 +398,8 @@ func (s *ticketStore) nextRegisterableTicket() (t *ticketRef, wait time.Duration
//s.removeExcessTickets(topic) //s.removeExcessTickets(topic)
if len(tickets.buckets) != 0 { if len(tickets.buckets) != 0 {
empty = false empty = false
if list := tickets.buckets[bucket]; list != nil {
list := tickets.buckets[bucket]
for _, ref := range list { 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))) //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() { if nextTicket.t == nil || ref.topicRegTime() < nextTicket.topicRegTime() {
@ -407,7 +408,6 @@ func (s *ticketStore) nextRegisterableTicket() (t *ticketRef, wait time.Duration
} }
} }
} }
}
if empty { if empty {
return nil, 0 return nil, 0
} }

@ -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" "net/http"
"strconv" "strconv"
"strings" "strings"
"sync"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p"
@ -265,6 +266,8 @@ func (c *Client) Send(method, path string, in, out interface{}) error {
type Server struct { type Server struct {
router *httprouter.Router router *httprouter.Router
network *Network 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 // NewServer returns a new simulation API server
@ -278,6 +281,10 @@ func NewServer(network *Network) *Server {
s.GET("/", s.GetNetwork) s.GET("/", s.GetNetwork)
s.POST("/start", s.StartNetwork) s.POST("/start", s.StartNetwork)
s.POST("/stop", s.StopNetwork) 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("/events", s.StreamNetworkEvents)
s.GET("/snapshot", s.CreateSnapshot) s.GET("/snapshot", s.CreateSnapshot)
s.POST("/snapshot", s.LoadSnapshot) s.POST("/snapshot", s.LoadSnapshot)
@ -318,6 +325,59 @@ func (s *Server) StopNetwork(w http.ResponseWriter, req *http.Request) {
w.WriteHeader(http.StatusOK) 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 // StreamNetworkEvents streams network events as a server-sent-events stream
func (s *Server) StreamNetworkEvents(w http.ResponseWriter, req *http.Request) { func (s *Server) StreamNetworkEvents(w http.ResponseWriter, req *http.Request) {
events := make(chan *Event) 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) { func (self *Network) GetNodes() (nodes []*Node) {
self.lock.Lock() self.lock.Lock()
defer self.lock.Unlock() defer self.lock.Unlock()
for _, node := range self.Nodes {
nodes = append(nodes, node) nodes = append(nodes, self.Nodes...)
}
return nodes return nodes
} }
@ -477,7 +476,7 @@ func (self *Network) InitConn(oneID, otherID discover.NodeID) (*Conn, error) {
if err != nil { if err != nil {
return nil, err 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) return nil, fmt.Errorf("connection between %v and %v recently attempted", oneID, otherID)
} }
if conn.Up { if conn.Up {
@ -502,6 +501,20 @@ func (self *Network) Shutdown() {
close(self.quitc) 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 // Node is a wrapper around adapters.Node which is used to track the status
// of a node in the network // of a node in the network
type Node struct { type Node struct {
@ -665,6 +678,12 @@ func (self *Network) Load(snap *Snapshot) error {
} }
} }
for _, conn := range snap.Conns { 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 { if err := self.Connect(conn.One, conn.Other); err != nil {
return err 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. // DialHTTP creates a new RPC clients that connection to an RPC server over HTTP.
func DialHTTP(endpoint string) (*Client, error) { func DialHTTP(endpoint string) (*Client, error) {
req, err := http.NewRequest("POST", endpoint, nil) req, err := http.NewRequest(http.MethodPost, endpoint, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -149,7 +149,7 @@ func NewHTTPServer(cors []string, srv *Server) *http.Server {
// ServeHTTP serves JSON-RPC requests over HTTP. // ServeHTTP serves JSON-RPC requests over HTTP.
func (srv *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (srv *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// Permit dumb empty requests for remote health-checks (AWS) // 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 return
} }
if code, err := validateRequest(r); err != nil { 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 // validateRequest returns a non-zero response code and error message if the
// request is invalid. // request is invalid.
func validateRequest(r *http.Request) (int, error) { 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") return http.StatusMethodNotAllowed, errors.New("method not allowed")
} }
if r.ContentLength > maxHTTPRequestContentLength { if r.ContentLength > maxHTTPRequestContentLength {
@ -192,7 +192,7 @@ func newCorsHandler(srv *Server, allowedOrigins []string) http.Handler {
c := cors.New(cors.Options{ c := cors.New(cors.Options{
AllowedOrigins: allowedOrigins, AllowedOrigins: allowedOrigins,
AllowedMethods: []string{"POST", "GET"}, AllowedMethods: []string{http.MethodPost, http.MethodGet},
MaxAge: 600, MaxAge: 600,
AllowedHeaders: []string{"*"}, AllowedHeaders: []string{"*"},
}) })

@ -24,25 +24,25 @@ import (
) )
func TestHTTPErrorResponseWithDelete(t *testing.T) { func TestHTTPErrorResponseWithDelete(t *testing.T) {
testHTTPErrorResponse(t, "DELETE", contentType, "", http.StatusMethodNotAllowed) testHTTPErrorResponse(t, http.MethodDelete, contentType, "", http.StatusMethodNotAllowed)
} }
func TestHTTPErrorResponseWithPut(t *testing.T) { func TestHTTPErrorResponseWithPut(t *testing.T) {
testHTTPErrorResponse(t, "PUT", contentType, "", http.StatusMethodNotAllowed) testHTTPErrorResponse(t, http.MethodPut, contentType, "", http.StatusMethodNotAllowed)
} }
func TestHTTPErrorResponseWithMaxContentLength(t *testing.T) { func TestHTTPErrorResponseWithMaxContentLength(t *testing.T) {
body := make([]rune, maxHTTPRequestContentLength+1, maxHTTPRequestContentLength+1) body := make([]rune, maxHTTPRequestContentLength+1)
testHTTPErrorResponse(t, testHTTPErrorResponse(t,
"POST", contentType, string(body), http.StatusRequestEntityTooLarge) http.MethodPost, contentType, string(body), http.StatusRequestEntityTooLarge)
} }
func TestHTTPErrorResponseWithEmptyContentType(t *testing.T) { func TestHTTPErrorResponseWithEmptyContentType(t *testing.T) {
testHTTPErrorResponse(t, "POST", "", "", http.StatusUnsupportedMediaType) testHTTPErrorResponse(t, http.MethodPost, "", "", http.StatusUnsupportedMediaType)
} }
func TestHTTPErrorResponseWithValidRequest(t *testing.T) { 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) { func testHTTPErrorResponse(t *testing.T, method, contentType, body string, expected int) {

@ -36,7 +36,7 @@ func TestConfig(t *testing.T) {
one := NewDefaultConfig() one := NewDefaultConfig()
two := 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") 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 // Test listMounts
if found == false { if !found {
t.Fatalf("Error getting mounts information for %v: %v", mountDir, err) t.Fatalf("Error getting mounts information for %v: %v", mountDir, err)
} }
@ -185,10 +185,8 @@ func isDirEmpty(name string) bool {
defer f.Close() defer f.Close()
_, err = f.Readdirnames(1) _, err = f.Readdirnames(1)
if err == io.EOF {
return true return err == io.EOF
}
return false
} }
type testAPI struct { type testAPI struct {
@ -388,7 +386,7 @@ func (ta *testAPI) seekInMultiChunkFile(t *testing.T) {
d.Read(contents) d.Read(contents)
finfo := files["1.txt"] 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") t.Fatalf("File seek contents mismatch")
} }
d.Close() 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) key, err = chunker.Split(data, size, chunkC, swg, nil)
if err != nil && expectedError == 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 { 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) key, err = chunker.Append(rootKey, data, chunkC, swg, nil)
if err != nil && expectedError == 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 { if chunkC != nil {

@ -391,7 +391,7 @@ func (self *PyramidChunker) prepareChunks(isAppend bool, chunkLevel [][]*TreeEnt
parent := NewTreeEntry(self) parent := NewTreeEntry(self)
var unFinishedChunk *Chunk var unFinishedChunk *Chunk
if isAppend == true && len(chunkLevel[0]) != 0 { if isAppend && len(chunkLevel[0]) != 0 {
lastIndex := len(chunkLevel[0]) - 1 lastIndex := len(chunkLevel[0]) - 1
ent := chunkLevel[0][lastIndex] 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 return
} }
@ -522,7 +522,7 @@ func (self *PyramidChunker) buildTree(isAppend bool, chunkLevel [][]*TreeEntry,
for lvl := int64(ent.level); lvl < endLvl; lvl++ { for lvl := int64(ent.level); lvl < endLvl; lvl++ {
lvlCount := int64(len(chunkLevel[lvl])) lvlCount := int64(len(chunkLevel[lvl]))
if lvlCount == 1 && last == true { if lvlCount == 1 && last {
copy(rootKey, chunkLevel[lvl][0].key) copy(rootKey, chunkLevel[lvl][0].key)
return return
} }
@ -540,7 +540,7 @@ func (self *PyramidChunker) buildTree(isAppend bool, chunkLevel [][]*TreeEntry,
nextLvlCount = int64(len(chunkLevel[lvl+1]) - 1) nextLvlCount = int64(len(chunkLevel[lvl+1]) - 1)
tempEntry = chunkLevel[lvl+1][nextLvlCount] tempEntry = chunkLevel[lvl+1][nextLvlCount]
} }
if isAppend == true && tempEntry != nil && tempEntry.updatePending == true { if isAppend && tempEntry != nil && tempEntry.updatePending {
updateEntry := &TreeEntry{ updateEntry := &TreeEntry{
level: int(lvl + 1), level: int(lvl + 1),
branchCount: 0, branchCount: 0,
@ -585,9 +585,9 @@ func (self *PyramidChunker) buildTree(isAppend bool, chunkLevel [][]*TreeEntry,
} }
if isAppend == false { if !isAppend {
chunkWG.Wait() chunkWG.Wait()
if compress == true { if compress {
chunkLevel[lvl] = nil chunkLevel[lvl] = nil
} }
} }
@ -599,7 +599,7 @@ func (self *PyramidChunker) enqueueTreeChunk(chunkLevel [][]*TreeEntry, ent *Tre
if ent != nil { if ent != nil {
// wait for data chunks to get over before processing the tree chunk // wait for data chunks to get over before processing the tree chunk
if last == true { if last {
chunkWG.Wait() 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 // Update or append based on weather it is a new entry or being reused
if ent.updatePending == true { if ent.updatePending {
chunkWG.Wait() chunkWG.Wait()
chunkLevel[ent.level][ent.index] = ent chunkLevel[ent.level][ent.index] = ent
} else { } else {

@ -80,8 +80,7 @@ func TestWhisperBasic(t *testing.T) {
t.Fatalf("failed w.Messages.") 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) { if !validateSymmetricKey(derived) {
t.Fatalf("failed validateSymmetricKey with param = %v.", derived) t.Fatalf("failed validateSymmetricKey with param = %v.", derived)
} }

Loading…
Cancel
Save