From 5e2a42960d964edb32cf70ba9b8df2f8fb592f26 Mon Sep 17 00:00:00 2001 From: lash Date: Wed, 10 Jan 2018 00:49:53 +0100 Subject: [PATCH] swarm/pss: Omit build of tests using t.Name for go 1.7 --- swarm/pss/handshake_test.go | 2 + swarm/pss/protocol_test.go | 2 + swarm/pss/pss_go18plus_test.go | 465 +++++++++++++++++++++++++++++++++ swarm/pss/pss_test.go | 443 ------------------------------- 4 files changed, 469 insertions(+), 443 deletions(-) create mode 100644 swarm/pss/pss_go18plus_test.go diff --git a/swarm/pss/handshake_test.go b/swarm/pss/handshake_test.go index 25620fb235..6cebdbbd5a 100644 --- a/swarm/pss/handshake_test.go +++ b/swarm/pss/handshake_test.go @@ -1,3 +1,5 @@ +//-build go1.7 + package pss import ( diff --git a/swarm/pss/protocol_test.go b/swarm/pss/protocol_test.go index b30fc0430d..793faa1397 100644 --- a/swarm/pss/protocol_test.go +++ b/swarm/pss/protocol_test.go @@ -1,3 +1,5 @@ +//-build go1.7 + package pss import ( diff --git a/swarm/pss/pss_go18plus_test.go b/swarm/pss/pss_go18plus_test.go new file mode 100644 index 0000000000..54e5b5f386 --- /dev/null +++ b/swarm/pss/pss_go18plus_test.go @@ -0,0 +1,465 @@ +//-build go17 +package pss + +import ( + "bytes" + "context" + "encoding/binary" + "encoding/json" + "fmt" + "io/ioutil" + "math/rand" + "os" + "strconv" + "strings" + "testing" + "time" + + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/p2p/discover" + "github.com/ethereum/go-ethereum/p2p/simulations" + "github.com/ethereum/go-ethereum/p2p/simulations/adapters" + "github.com/ethereum/go-ethereum/rpc" + "github.com/ethereum/go-ethereum/swarm/network" +) + +// send symmetrically encrypted message between two directly connected peers +func TestSymSend(t *testing.T) { + t.Run("32", testSymSend) + t.Run("8", testSymSend) + t.Run("0", testSymSend) +} + +func testSymSend(t *testing.T) { + + // address hint size + var addrsize int64 + var err error + paramstring := strings.Split(t.Name(), "/") + addrsize, _ = strconv.ParseInt(paramstring[1], 10, 0) + log.Info("sym send test", "addrsize", addrsize) + + clients, err := setupNetwork(2) + if err != nil { + t.Fatal(err) + } + + var topic string + err = clients[0].Call(&topic, "pss_stringToTopic", "foo:42") + if err != nil { + t.Fatal(err) + } + + var loaddrhex string + err = clients[0].Call(&loaddrhex, "pss_baseAddr") + if err != nil { + t.Fatalf("rpc get node 1 baseaddr fail: %v", err) + } + loaddrhex = loaddrhex[:2+(addrsize*2)] + var roaddrhex string + err = clients[1].Call(&roaddrhex, "pss_baseAddr") + if err != nil { + t.Fatalf("rpc get node 2 baseaddr fail: %v", err) + } + roaddrhex = roaddrhex[:2+(addrsize*2)] + + // retrieve public key from pss instance + // set this public key reciprocally + var lpubkeyhex string + err = clients[0].Call(&lpubkeyhex, "pss_getPublicKey") + if err != nil { + t.Fatalf("rpc get node 1 pubkey fail: %v", err) + } + var rpubkeyhex string + err = clients[1].Call(&rpubkeyhex, "pss_getPublicKey") + if err != nil { + t.Fatalf("rpc get node 2 pubkey fail: %v", err) + } + + time.Sleep(time.Millisecond * 500) + + // at this point we've verified that symkeys are saved and match on each peer + // now try sending symmetrically encrypted message, both directions + lmsgC := make(chan APIMsg) + lctx, cancel := context.WithTimeout(context.Background(), time.Second*10) + defer cancel() + lsub, err := clients[0].Subscribe(lctx, "pss", lmsgC, "receive", topic) + log.Trace("lsub", "id", lsub) + defer lsub.Unsubscribe() + rmsgC := make(chan APIMsg) + rctx, cancel := context.WithTimeout(context.Background(), time.Second*10) + defer cancel() + rsub, err := clients[1].Subscribe(rctx, "pss", rmsgC, "receive", topic) + log.Trace("rsub", "id", rsub) + defer rsub.Unsubscribe() + + lrecvkey := network.RandomAddr().Over() + rrecvkey := network.RandomAddr().Over() + + var lkeyids [2]string + var rkeyids [2]string + + // manually set reciprocal symkeys + err = clients[0].Call(&lkeyids, "psstest_setSymKeys", rpubkeyhex, lrecvkey, rrecvkey, defaultSymKeySendLimit, topic, roaddrhex) + if err != nil { + t.Fatal(err) + } + err = clients[1].Call(&rkeyids, "psstest_setSymKeys", rpubkeyhex, rrecvkey, lrecvkey, defaultSymKeySendLimit, topic, loaddrhex) + if err != nil { + t.Fatal(err) + } + + // send and verify delivery + lmsg := []byte("plugh") + err = clients[1].Call(nil, "pss_sendSym", rkeyids[1], topic, hexutil.Encode(lmsg)) + if err != nil { + t.Fatal(err) + } + select { + case recvmsg := <-lmsgC: + if !bytes.Equal(recvmsg.Msg, lmsg) { + t.Fatalf("node 1 received payload mismatch: expected %v, got %v", lmsg, recvmsg) + } + case cerr := <-lctx.Done(): + t.Fatalf("test message timed out: %v", cerr) + } + rmsg := []byte("xyzzy") + err = clients[0].Call(nil, "pss_sendSym", lkeyids[1], topic, hexutil.Encode(rmsg)) + if err != nil { + t.Fatal(err) + } + select { + case recvmsg := <-rmsgC: + if !bytes.Equal(recvmsg.Msg, rmsg) { + t.Fatalf("node 2 received payload mismatch: expected %v, got %v", rmsg, recvmsg.Msg) + } + case cerr := <-rctx.Done(): + t.Fatalf("test message timed out: %v", cerr) + } +} + +// send asymmetrically encrypted message between two directly connected peers +func TestAsymSend(t *testing.T) { + t.Run("32", testAsymSend) + t.Run("8", testAsymSend) + t.Run("0", testAsymSend) +} + +func testAsymSend(t *testing.T) { + + // address hint size + var addrsize int64 + var err error + paramstring := strings.Split(t.Name(), "/") + addrsize, _ = strconv.ParseInt(paramstring[1], 10, 0) + log.Info("asym send test", "addrsize", addrsize) + + clients, err := setupNetwork(2) + if err != nil { + t.Fatal(err) + } + + var topic string + err = clients[0].Call(&topic, "pss_stringToTopic", "foo:42") + if err != nil { + t.Fatal(err) + } + + time.Sleep(time.Millisecond * 250) + + var loaddrhex string + err = clients[0].Call(&loaddrhex, "pss_baseAddr") + if err != nil { + t.Fatalf("rpc get node 1 baseaddr fail: %v", err) + } + loaddrhex = loaddrhex[:2+(addrsize*2)] + var roaddrhex string + err = clients[1].Call(&roaddrhex, "pss_baseAddr") + if err != nil { + t.Fatalf("rpc get node 2 baseaddr fail: %v", err) + } + roaddrhex = roaddrhex[:2+(addrsize*2)] + + // retrieve public key from pss instance + // set this public key reciprocally + var lpubkey string + err = clients[0].Call(&lpubkey, "pss_getPublicKey") + if err != nil { + t.Fatalf("rpc get node 1 pubkey fail: %v", err) + } + var rpubkey string + err = clients[1].Call(&rpubkey, "pss_getPublicKey") + if err != nil { + t.Fatalf("rpc get node 2 pubkey fail: %v", err) + } + + time.Sleep(time.Millisecond * 500) // replace with hive healthy code + + lmsgC := make(chan APIMsg) + lctx, cancel := context.WithTimeout(context.Background(), time.Second*10) + defer cancel() + lsub, err := clients[0].Subscribe(lctx, "pss", lmsgC, "receive", topic) + log.Trace("lsub", "id", lsub) + defer lsub.Unsubscribe() + rmsgC := make(chan APIMsg) + rctx, cancel := context.WithTimeout(context.Background(), time.Second*10) + defer cancel() + rsub, err := clients[1].Subscribe(rctx, "pss", rmsgC, "receive", topic) + log.Trace("rsub", "id", rsub) + defer rsub.Unsubscribe() + + // store reciprocal public keys + err = clients[0].Call(nil, "pss_setPeerPublicKey", rpubkey, topic, roaddrhex) + if err != nil { + t.Fatal(err) + } + err = clients[1].Call(nil, "pss_setPeerPublicKey", lpubkey, topic, loaddrhex) + if err != nil { + t.Fatal(err) + } + + // send and verify delivery + rmsg := []byte("xyzzy") + err = clients[0].Call(nil, "pss_sendAsym", rpubkey, topic, hexutil.Encode(rmsg)) + if err != nil { + t.Fatal(err) + } + select { + case recvmsg := <-rmsgC: + if !bytes.Equal(recvmsg.Msg, rmsg) { + t.Fatalf("node 2 received payload mismatch: expected %v, got %v", rmsg, recvmsg.Msg) + } + case cerr := <-rctx.Done(): + t.Fatalf("test message timed out: %v", cerr) + } + lmsg := []byte("plugh") + err = clients[1].Call(nil, "pss_sendAsym", lpubkey, topic, hexutil.Encode(lmsg)) + if err != nil { + t.Fatal(err) + } + select { + case recvmsg := <-lmsgC: + if !bytes.Equal(recvmsg.Msg, lmsg) { + t.Fatalf("node 1 received payload mismatch: expected %v, got %v", lmsg, recvmsg.Msg) + } + case cerr := <-lctx.Done(): + t.Fatalf("test message timed out: %v", cerr) + } +} + +type Job struct { + Msg []byte + SendNode discover.NodeID + RecvNode discover.NodeID +} + +func worker(id int, jobs <-chan Job, rpcs map[discover.NodeID]*rpc.Client, pubkeys map[discover.NodeID]string, topic string) { + for j := range jobs { + rpcs[j.SendNode].Call(nil, "pss_sendAsym", pubkeys[j.RecvNode], topic, hexutil.Encode(j.Msg)) + } +} + +// params in run name: +// nodes/msgs/addrbytes/adaptertype +// if adaptertype is exec uses execadapter, simadapter otherwise +// +// ( some tests are commented out because of resource limitations on Travis) +func TestNetwork(t *testing.T) { + t.Skip("Temporarily deactivated because not all messages can be delivered") + //t.Run("3/2000/4/sock", testNetwork) + //t.Run("4/2000/4/sock", testNetwork) + t.Run("8/2000/4/sock", testNetwork) + t.Run("16/2000/4/sock", testNetwork) + t.Run("8/3000/4/sock", testNetwork) + t.Run("16/3000/4/sock", testNetwork) + //t.Run("32/2000/4/sock", testNetwork) + + t.Run("8/2000/4/sim", testNetwork) + t.Run("16/2000/4/sim", testNetwork) + t.Run("8/3000/4/sim", testNetwork) + t.Run("16/3000/4/sim", testNetwork) + //t.Run("32/2000/4/sim", testNetwork) + // t.Run("64/2000/4/sim", testNetwork) +} + +func testNetwork(t *testing.T) { + type msgnotifyC struct { + id discover.NodeID + msgIdx int + } + + paramstring := strings.Split(t.Name(), "/") + nodecount, _ := strconv.ParseInt(paramstring[1], 10, 0) + msgcount, _ := strconv.ParseInt(paramstring[2], 10, 0) + addrsize, _ := strconv.ParseInt(paramstring[3], 10, 0) + adapter := paramstring[4] + + log.Info("network test", "nodecount", nodecount, "msgcount", msgcount, "addrhintsize", addrsize) + + nodes := make([]discover.NodeID, nodecount) + bzzaddrs := make(map[discover.NodeID]string, nodecount) + rpcs := make(map[discover.NodeID]*rpc.Client, nodecount) + pubkeys := make(map[discover.NodeID]string, nodecount) + + sentmsgs := make([][]byte, msgcount) + recvmsgs := make([]bool, msgcount) + nodemsgcount := make(map[discover.NodeID]int, nodecount) + + trigger := make(chan discover.NodeID) + + var a adapters.NodeAdapter + if adapter == "exec" { + dirname, err := ioutil.TempDir(".", "") + if err != nil { + t.Fatal(err) + } + a = adapters.NewExecAdapter(dirname) + } else if adapter == "sock" { + a = adapters.NewSocketAdapter(services) + } else if adapter == "tcp" { + a = adapters.NewTCPAdapter(services) + } else if adapter == "sim" { + a = adapters.NewSimAdapter(services) + } + net := simulations.NewNetwork(a, &simulations.NetworkConfig{ + ID: "0", + }) + defer net.Shutdown() + + f, err := os.Open(fmt.Sprintf("testdata/snapshot_%d.json", nodecount)) + if err != nil { + t.Fatal(err) + } + jsonbyte, err := ioutil.ReadAll(f) + if err != nil { + t.Fatal(err) + } + var snap simulations.Snapshot + err = json.Unmarshal(jsonbyte, &snap) + if err != nil { + t.Fatal(err) + } + err = net.Load(&snap) + if err != nil { + t.Fatal(err) + } + + triggerChecks := func(trigger chan discover.NodeID, id discover.NodeID, rpcclient *rpc.Client, topic string) error { + msgC := make(chan APIMsg) + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + sub, err := rpcclient.Subscribe(ctx, "pss", msgC, "receive", topic) + if err != nil { + t.Fatal(err) + } + go func() { + defer sub.Unsubscribe() + for { + select { + case recvmsg := <-msgC: + idx, _ := binary.Uvarint(recvmsg.Msg) + if recvmsgs[idx] == false { + log.Debug("msg recv", "idx", idx, "id", id) + recvmsgs[idx] = true + trigger <- id + } + case <-sub.Err(): + return + } + } + }() + return nil + } + + var topic string + for i, nod := range net.GetNodes() { + nodes[i] = nod.ID() + rpcs[nodes[i]], err = nod.Client() + if err != nil { + t.Fatal(err) + } + if topic == "" { + err = rpcs[nodes[i]].Call(&topic, "pss_stringToTopic", "foo:42") + if err != nil { + t.Fatal(err) + } + } + var pubkey string + err = rpcs[nodes[i]].Call(&pubkey, "pss_getPublicKey") + if err != nil { + t.Fatal(err) + } + pubkeys[nod.ID()] = pubkey + var addrhex string + err = rpcs[nodes[i]].Call(&addrhex, "pss_baseAddr") + if err != nil { + t.Fatal(err) + } + bzzaddrs[nodes[i]] = addrhex + err = triggerChecks(trigger, nodes[i], rpcs[nodes[i]], topic) + if err != nil { + t.Fatal(err) + } + } + + // setup workers + jobs := make(chan Job, 10) + for w := 1; w <= 10; w++ { + go worker(w, jobs, rpcs, pubkeys, topic) + } + + for i := 0; i < int(msgcount); i++ { + sendnodeidx := rand.Intn(int(nodecount)) + recvnodeidx := rand.Intn(int(nodecount - 1)) + if recvnodeidx >= sendnodeidx { + recvnodeidx++ + } + nodemsgcount[nodes[recvnodeidx]]++ + sentmsgs[i] = make([]byte, 8) + c := binary.PutUvarint(sentmsgs[i], uint64(i)) + if c == 0 { + t.Fatal("0 byte message") + } + if err != nil { + t.Fatal(err) + } + err = rpcs[nodes[sendnodeidx]].Call(nil, "pss_setPeerPublicKey", pubkeys[nodes[recvnodeidx]], topic, bzzaddrs[nodes[recvnodeidx]]) + if err != nil { + t.Fatal(err) + } + + jobs <- Job{ + Msg: sentmsgs[i], + SendNode: nodes[sendnodeidx], + RecvNode: nodes[recvnodeidx], + } + } + + finalmsgcount := 0 + ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second) + defer cancel() +outer: + for i := 0; i < int(msgcount); i++ { + select { + case id := <-trigger: + nodemsgcount[id]-- + finalmsgcount++ + case <-ctx.Done(): + log.Warn("timeout") + break outer + } + } + + for i, msg := range recvmsgs { + if !msg { + log.Debug("missing message", "idx", i) + } + } + t.Logf("%d of %d messages received", finalmsgcount, msgcount) + + if finalmsgcount != int(msgcount) { + t.Fatalf("%d messages were not received", int(msgcount)-finalmsgcount) + } + +} diff --git a/swarm/pss/pss_test.go b/swarm/pss/pss_test.go index 90e7e3ecb0..d4c11ae74d 100644 --- a/swarm/pss/pss_test.go +++ b/swarm/pss/pss_test.go @@ -4,9 +4,7 @@ import ( "bytes" "context" "crypto/ecdsa" - "encoding/binary" "encoding/hex" - "encoding/json" "flag" "fmt" "io/ioutil" @@ -19,7 +17,6 @@ import ( "time" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/node" @@ -395,446 +392,6 @@ func TestMismatch(t *testing.T) { } -// send symmetrically encrypted message between two directly connected peers -func TestSymSend(t *testing.T) { - t.Run("32", testSymSend) - t.Run("8", testSymSend) - t.Run("0", testSymSend) -} - -func testSymSend(t *testing.T) { - - // address hint size - var addrsize int64 - var err error - paramstring := strings.Split(t.Name(), "/") - addrsize, _ = strconv.ParseInt(paramstring[1], 10, 0) - log.Info("sym send test", "addrsize", addrsize) - - clients, err := setupNetwork(2) - if err != nil { - t.Fatal(err) - } - - var topic string - err = clients[0].Call(&topic, "pss_stringToTopic", "foo:42") - if err != nil { - t.Fatal(err) - } - - var loaddrhex string - err = clients[0].Call(&loaddrhex, "pss_baseAddr") - if err != nil { - t.Fatalf("rpc get node 1 baseaddr fail: %v", err) - } - loaddrhex = loaddrhex[:2+(addrsize*2)] - var roaddrhex string - err = clients[1].Call(&roaddrhex, "pss_baseAddr") - if err != nil { - t.Fatalf("rpc get node 2 baseaddr fail: %v", err) - } - roaddrhex = roaddrhex[:2+(addrsize*2)] - - // retrieve public key from pss instance - // set this public key reciprocally - var lpubkeyhex string - err = clients[0].Call(&lpubkeyhex, "pss_getPublicKey") - if err != nil { - t.Fatalf("rpc get node 1 pubkey fail: %v", err) - } - var rpubkeyhex string - err = clients[1].Call(&rpubkeyhex, "pss_getPublicKey") - if err != nil { - t.Fatalf("rpc get node 2 pubkey fail: %v", err) - } - - time.Sleep(time.Millisecond * 500) - - // at this point we've verified that symkeys are saved and match on each peer - // now try sending symmetrically encrypted message, both directions - lmsgC := make(chan APIMsg) - lctx, cancel := context.WithTimeout(context.Background(), time.Second*10) - defer cancel() - lsub, err := clients[0].Subscribe(lctx, "pss", lmsgC, "receive", topic) - log.Trace("lsub", "id", lsub) - defer lsub.Unsubscribe() - rmsgC := make(chan APIMsg) - rctx, cancel := context.WithTimeout(context.Background(), time.Second*10) - defer cancel() - rsub, err := clients[1].Subscribe(rctx, "pss", rmsgC, "receive", topic) - log.Trace("rsub", "id", rsub) - defer rsub.Unsubscribe() - - lrecvkey := network.RandomAddr().Over() - rrecvkey := network.RandomAddr().Over() - - var lkeyids [2]string - var rkeyids [2]string - - // manually set reciprocal symkeys - err = clients[0].Call(&lkeyids, "psstest_setSymKeys", rpubkeyhex, lrecvkey, rrecvkey, defaultSymKeySendLimit, topic, roaddrhex) - if err != nil { - t.Fatal(err) - } - err = clients[1].Call(&rkeyids, "psstest_setSymKeys", rpubkeyhex, rrecvkey, lrecvkey, defaultSymKeySendLimit, topic, loaddrhex) - if err != nil { - t.Fatal(err) - } - - // send and verify delivery - lmsg := []byte("plugh") - err = clients[1].Call(nil, "pss_sendSym", rkeyids[1], topic, hexutil.Encode(lmsg)) - if err != nil { - t.Fatal(err) - } - select { - case recvmsg := <-lmsgC: - if !bytes.Equal(recvmsg.Msg, lmsg) { - t.Fatalf("node 1 received payload mismatch: expected %v, got %v", lmsg, recvmsg) - } - case cerr := <-lctx.Done(): - t.Fatalf("test message timed out: %v", cerr) - } - rmsg := []byte("xyzzy") - err = clients[0].Call(nil, "pss_sendSym", lkeyids[1], topic, hexutil.Encode(rmsg)) - if err != nil { - t.Fatal(err) - } - select { - case recvmsg := <-rmsgC: - if !bytes.Equal(recvmsg.Msg, rmsg) { - t.Fatalf("node 2 received payload mismatch: expected %v, got %v", rmsg, recvmsg.Msg) - } - case cerr := <-rctx.Done(): - t.Fatalf("test message timed out: %v", cerr) - } -} - -// send asymmetrically encrypted message between two directly connected peers -func TestAsymSend(t *testing.T) { - t.Run("32", testAsymSend) - t.Run("8", testAsymSend) - t.Run("0", testAsymSend) -} - -func testAsymSend(t *testing.T) { - - // address hint size - var addrsize int64 - var err error - paramstring := strings.Split(t.Name(), "/") - addrsize, _ = strconv.ParseInt(paramstring[1], 10, 0) - log.Info("asym send test", "addrsize", addrsize) - - clients, err := setupNetwork(2) - if err != nil { - t.Fatal(err) - } - - var topic string - err = clients[0].Call(&topic, "pss_stringToTopic", "foo:42") - if err != nil { - t.Fatal(err) - } - - time.Sleep(time.Millisecond * 250) - - var loaddrhex string - err = clients[0].Call(&loaddrhex, "pss_baseAddr") - if err != nil { - t.Fatalf("rpc get node 1 baseaddr fail: %v", err) - } - loaddrhex = loaddrhex[:2+(addrsize*2)] - var roaddrhex string - err = clients[1].Call(&roaddrhex, "pss_baseAddr") - if err != nil { - t.Fatalf("rpc get node 2 baseaddr fail: %v", err) - } - roaddrhex = roaddrhex[:2+(addrsize*2)] - - // retrieve public key from pss instance - // set this public key reciprocally - var lpubkey string - err = clients[0].Call(&lpubkey, "pss_getPublicKey") - if err != nil { - t.Fatalf("rpc get node 1 pubkey fail: %v", err) - } - var rpubkey string - err = clients[1].Call(&rpubkey, "pss_getPublicKey") - if err != nil { - t.Fatalf("rpc get node 2 pubkey fail: %v", err) - } - - time.Sleep(time.Millisecond * 500) // replace with hive healthy code - - lmsgC := make(chan APIMsg) - lctx, cancel := context.WithTimeout(context.Background(), time.Second*10) - defer cancel() - lsub, err := clients[0].Subscribe(lctx, "pss", lmsgC, "receive", topic) - log.Trace("lsub", "id", lsub) - defer lsub.Unsubscribe() - rmsgC := make(chan APIMsg) - rctx, cancel := context.WithTimeout(context.Background(), time.Second*10) - defer cancel() - rsub, err := clients[1].Subscribe(rctx, "pss", rmsgC, "receive", topic) - log.Trace("rsub", "id", rsub) - defer rsub.Unsubscribe() - - // store reciprocal public keys - err = clients[0].Call(nil, "pss_setPeerPublicKey", rpubkey, topic, roaddrhex) - if err != nil { - t.Fatal(err) - } - err = clients[1].Call(nil, "pss_setPeerPublicKey", lpubkey, topic, loaddrhex) - if err != nil { - t.Fatal(err) - } - - // send and verify delivery - rmsg := []byte("xyzzy") - err = clients[0].Call(nil, "pss_sendAsym", rpubkey, topic, hexutil.Encode(rmsg)) - if err != nil { - t.Fatal(err) - } - select { - case recvmsg := <-rmsgC: - if !bytes.Equal(recvmsg.Msg, rmsg) { - t.Fatalf("node 2 received payload mismatch: expected %v, got %v", rmsg, recvmsg.Msg) - } - case cerr := <-rctx.Done(): - t.Fatalf("test message timed out: %v", cerr) - } - lmsg := []byte("plugh") - err = clients[1].Call(nil, "pss_sendAsym", lpubkey, topic, hexutil.Encode(lmsg)) - if err != nil { - t.Fatal(err) - } - select { - case recvmsg := <-lmsgC: - if !bytes.Equal(recvmsg.Msg, lmsg) { - t.Fatalf("node 1 received payload mismatch: expected %v, got %v", lmsg, recvmsg.Msg) - } - case cerr := <-lctx.Done(): - t.Fatalf("test message timed out: %v", cerr) - } -} - -type Job struct { - Msg []byte - SendNode discover.NodeID - RecvNode discover.NodeID -} - -func worker(id int, jobs <-chan Job, rpcs map[discover.NodeID]*rpc.Client, pubkeys map[discover.NodeID]string, topic string) { - for j := range jobs { - rpcs[j.SendNode].Call(nil, "pss_sendAsym", pubkeys[j.RecvNode], topic, hexutil.Encode(j.Msg)) - } -} - -// params in run name: -// nodes/msgs/addrbytes/adaptertype -// if adaptertype is exec uses execadapter, simadapter otherwise -// -// ( some tests are commented out because of resource limitations on Travis) -func TestNetwork(t *testing.T) { - t.Skip("Temporarily deactivated because not all messages can be delivered") - //t.Run("3/2000/4/sock", testNetwork) - //t.Run("4/2000/4/sock", testNetwork) - t.Run("8/2000/4/sock", testNetwork) - t.Run("16/2000/4/sock", testNetwork) - t.Run("8/3000/4/sock", testNetwork) - t.Run("16/3000/4/sock", testNetwork) - //t.Run("32/2000/4/sock", testNetwork) - - t.Run("8/2000/4/sim", testNetwork) - t.Run("16/2000/4/sim", testNetwork) - t.Run("8/3000/4/sim", testNetwork) - t.Run("16/3000/4/sim", testNetwork) - //t.Run("32/2000/4/sim", testNetwork) - // t.Run("64/2000/4/sim", testNetwork) -} - -func testNetwork(t *testing.T) { - type msgnotifyC struct { - id discover.NodeID - msgIdx int - } - - paramstring := strings.Split(t.Name(), "/") - nodecount, _ := strconv.ParseInt(paramstring[1], 10, 0) - msgcount, _ := strconv.ParseInt(paramstring[2], 10, 0) - addrsize, _ := strconv.ParseInt(paramstring[3], 10, 0) - adapter := paramstring[4] - - log.Info("network test", "nodecount", nodecount, "msgcount", msgcount, "addrhintsize", addrsize) - - nodes := make([]discover.NodeID, nodecount) - bzzaddrs := make(map[discover.NodeID]string, nodecount) - rpcs := make(map[discover.NodeID]*rpc.Client, nodecount) - pubkeys := make(map[discover.NodeID]string, nodecount) - - sentmsgs := make([][]byte, msgcount) - recvmsgs := make([]bool, msgcount) - nodemsgcount := make(map[discover.NodeID]int, nodecount) - - trigger := make(chan discover.NodeID) - - var a adapters.NodeAdapter - if adapter == "exec" { - dirname, err := ioutil.TempDir(".", "") - if err != nil { - t.Fatal(err) - } - a = adapters.NewExecAdapter(dirname) - } else if adapter == "sock" { - a = adapters.NewSocketAdapter(services) - } else if adapter == "tcp" { - a = adapters.NewTCPAdapter(services) - } else if adapter == "sim" { - a = adapters.NewSimAdapter(services) - } - net := simulations.NewNetwork(a, &simulations.NetworkConfig{ - ID: "0", - }) - defer net.Shutdown() - - f, err := os.Open(fmt.Sprintf("testdata/snapshot_%d.json", nodecount)) - if err != nil { - t.Fatal(err) - } - jsonbyte, err := ioutil.ReadAll(f) - if err != nil { - t.Fatal(err) - } - var snap simulations.Snapshot - err = json.Unmarshal(jsonbyte, &snap) - if err != nil { - t.Fatal(err) - } - err = net.Load(&snap) - if err != nil { - t.Fatal(err) - } - - triggerChecks := func(trigger chan discover.NodeID, id discover.NodeID, rpcclient *rpc.Client, topic string) error { - msgC := make(chan APIMsg) - ctx, cancel := context.WithTimeout(context.Background(), time.Second) - defer cancel() - sub, err := rpcclient.Subscribe(ctx, "pss", msgC, "receive", topic) - if err != nil { - t.Fatal(err) - } - go func() { - defer sub.Unsubscribe() - for { - select { - case recvmsg := <-msgC: - idx, _ := binary.Uvarint(recvmsg.Msg) - if recvmsgs[idx] == false { - log.Debug("msg recv", "idx", idx, "id", id) - recvmsgs[idx] = true - trigger <- id - } - case <-sub.Err(): - return - } - } - }() - return nil - } - - var topic string - for i, nod := range net.GetNodes() { - nodes[i] = nod.ID() - rpcs[nodes[i]], err = nod.Client() - if err != nil { - t.Fatal(err) - } - if topic == "" { - err = rpcs[nodes[i]].Call(&topic, "pss_stringToTopic", "foo:42") - if err != nil { - t.Fatal(err) - } - } - var pubkey string - err = rpcs[nodes[i]].Call(&pubkey, "pss_getPublicKey") - if err != nil { - t.Fatal(err) - } - pubkeys[nod.ID()] = pubkey - var addrhex string - err = rpcs[nodes[i]].Call(&addrhex, "pss_baseAddr") - if err != nil { - t.Fatal(err) - } - bzzaddrs[nodes[i]] = addrhex - err = triggerChecks(trigger, nodes[i], rpcs[nodes[i]], topic) - if err != nil { - t.Fatal(err) - } - } - - // setup workers - jobs := make(chan Job, 10) - for w := 1; w <= 10; w++ { - go worker(w, jobs, rpcs, pubkeys, topic) - } - - for i := 0; i < int(msgcount); i++ { - sendnodeidx := rand.Intn(int(nodecount)) - recvnodeidx := rand.Intn(int(nodecount - 1)) - if recvnodeidx >= sendnodeidx { - recvnodeidx++ - } - nodemsgcount[nodes[recvnodeidx]]++ - sentmsgs[i] = make([]byte, 8) - c := binary.PutUvarint(sentmsgs[i], uint64(i)) - if c == 0 { - t.Fatal("0 byte message") - } - if err != nil { - t.Fatal(err) - } - err = rpcs[nodes[sendnodeidx]].Call(nil, "pss_setPeerPublicKey", pubkeys[nodes[recvnodeidx]], topic, bzzaddrs[nodes[recvnodeidx]]) - if err != nil { - t.Fatal(err) - } - - jobs <- Job{ - Msg: sentmsgs[i], - SendNode: nodes[sendnodeidx], - RecvNode: nodes[recvnodeidx], - } - } - - finalmsgcount := 0 - ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second) - defer cancel() -outer: - for i := 0; i < int(msgcount); i++ { - select { - case id := <-trigger: - nodemsgcount[id]-- - finalmsgcount++ - case <-ctx.Done(): - log.Warn("timeout") - break outer - } - } - - for i, msg := range recvmsgs { - if !msg { - log.Debug("missing message", "idx", i) - } - } - t.Logf("%d of %d messages received", finalmsgcount, msgcount) - - if finalmsgcount != int(msgcount) { - t.Fatalf("%d messages were not received", int(msgcount)-finalmsgcount) - } - -} - // symmetric send performance with varying message sizes func BenchmarkSymkeySend(b *testing.B) { b.Run(fmt.Sprintf("%d", 256), benchmarkSymKeySend)