| 
									
										
										
										
											2014-10-23 16:57:54 +01:00
										 |  |  | package p2p | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-21 21:48:49 +01:00
										 |  |  | import ( | 
					
						
							| 
									
										
										
										
											2014-11-25 16:01:39 +01:00
										 |  |  | 	"bytes" | 
					
						
							| 
									
										
										
										
											2015-02-05 03:07:58 +01:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2015-02-27 03:06:55 +00:00
										 |  |  | 	"io" | 
					
						
							| 
									
										
										
										
											2014-11-21 21:48:49 +01:00
										 |  |  | 	"net" | 
					
						
							| 
									
										
										
										
											2014-11-26 22:49:40 +01:00
										 |  |  | 	"reflect" | 
					
						
							| 
									
										
										
										
											2014-11-21 21:48:49 +01:00
										 |  |  | 	"testing" | 
					
						
							|  |  |  | 	"time" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var discard = Protocol{ | 
					
						
							|  |  |  | 	Name:   "discard", | 
					
						
							|  |  |  | 	Length: 1, | 
					
						
							|  |  |  | 	Run: func(p *Peer, rw MsgReadWriter) error { | 
					
						
							|  |  |  | 		for { | 
					
						
							|  |  |  | 			msg, err := rw.ReadMsg() | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				return err | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-02-19 01:52:03 +01:00
										 |  |  | 			fmt.Printf("discarding %d\n", msg.Code) | 
					
						
							| 
									
										
										
										
											2014-11-21 21:48:49 +01:00
										 |  |  | 			if err = msg.Discard(); err != nil { | 
					
						
							|  |  |  | 				return err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-27 03:06:55 +00:00
										 |  |  | func testPeer(protos []Protocol) (io.Closer, *conn, *Peer, <-chan DiscReason) { | 
					
						
							|  |  |  | 	fd1, _ := net.Pipe() | 
					
						
							| 
									
										
										
										
											2015-02-19 01:52:03 +01:00
										 |  |  | 	hs1 := &protoHandshake{ID: randomID(), Version: baseProtocolVersion} | 
					
						
							|  |  |  | 	hs2 := &protoHandshake{ID: randomID(), Version: baseProtocolVersion} | 
					
						
							|  |  |  | 	for _, p := range protos { | 
					
						
							|  |  |  | 		hs1.Caps = append(hs1.Caps, p.cap()) | 
					
						
							|  |  |  | 		hs2.Caps = append(hs2.Caps, p.cap()) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-27 03:06:55 +00:00
										 |  |  | 	p1, p2 := MsgPipe() | 
					
						
							|  |  |  | 	peer := newPeer(fd1, &conn{p1, hs1}, protos) | 
					
						
							| 
									
										
										
										
											2015-02-05 03:07:58 +01:00
										 |  |  | 	errc := make(chan DiscReason, 1) | 
					
						
							|  |  |  | 	go func() { errc <- peer.run() }() | 
					
						
							| 
									
										
										
										
											2015-02-19 01:52:03 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-27 03:06:55 +00:00
										 |  |  | 	return p1, &conn{p2, hs2}, peer, errc | 
					
						
							| 
									
										
										
										
											2014-11-21 21:48:49 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestPeerProtoReadMsg(t *testing.T) { | 
					
						
							|  |  |  | 	defer testlog(t).detach() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	done := make(chan struct{}) | 
					
						
							|  |  |  | 	proto := Protocol{ | 
					
						
							|  |  |  | 		Name:   "a", | 
					
						
							|  |  |  | 		Length: 5, | 
					
						
							|  |  |  | 		Run: func(peer *Peer, rw MsgReadWriter) error { | 
					
						
							| 
									
										
										
										
											2015-03-19 15:11:02 +01:00
										 |  |  | 			if err := ExpectMsg(rw, 2, []uint{1}); err != nil { | 
					
						
							| 
									
										
										
										
											2015-02-05 03:07:58 +01:00
										 |  |  | 				t.Error(err) | 
					
						
							| 
									
										
										
										
											2014-11-21 21:48:49 +01:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-03-19 15:11:02 +01:00
										 |  |  | 			if err := ExpectMsg(rw, 3, []uint{2}); err != nil { | 
					
						
							| 
									
										
										
										
											2015-02-05 03:07:58 +01:00
										 |  |  | 				t.Error(err) | 
					
						
							| 
									
										
										
										
											2014-11-21 21:48:49 +01:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-03-19 15:11:02 +01:00
										 |  |  | 			if err := ExpectMsg(rw, 4, []uint{3}); err != nil { | 
					
						
							| 
									
										
										
										
											2015-02-05 03:07:58 +01:00
										 |  |  | 				t.Error(err) | 
					
						
							| 
									
										
										
										
											2014-11-21 21:48:49 +01:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			close(done) | 
					
						
							|  |  |  | 			return nil | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-27 03:06:55 +00:00
										 |  |  | 	closer, rw, _, errc := testPeer([]Protocol{proto}) | 
					
						
							|  |  |  | 	defer closer.Close() | 
					
						
							| 
									
										
										
										
											2014-11-21 21:48:49 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-19 15:11:02 +01:00
										 |  |  | 	Send(rw, baseProtocolLength+2, []uint{1}) | 
					
						
							|  |  |  | 	Send(rw, baseProtocolLength+3, []uint{2}) | 
					
						
							|  |  |  | 	Send(rw, baseProtocolLength+4, []uint{3}) | 
					
						
							| 
									
										
										
										
											2015-02-05 03:07:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-21 21:48:49 +01:00
										 |  |  | 	select { | 
					
						
							|  |  |  | 	case <-done: | 
					
						
							|  |  |  | 	case err := <-errc: | 
					
						
							|  |  |  | 		t.Errorf("peer returned: %v", err) | 
					
						
							|  |  |  | 	case <-time.After(2 * time.Second): | 
					
						
							|  |  |  | 		t.Errorf("receive timeout") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestPeerProtoEncodeMsg(t *testing.T) { | 
					
						
							|  |  |  | 	defer testlog(t).detach() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	proto := Protocol{ | 
					
						
							|  |  |  | 		Name:   "a", | 
					
						
							|  |  |  | 		Length: 2, | 
					
						
							|  |  |  | 		Run: func(peer *Peer, rw MsgReadWriter) error { | 
					
						
							| 
									
										
										
										
											2015-03-19 15:11:02 +01:00
										 |  |  | 			if err := SendItems(rw, 2); err == nil { | 
					
						
							| 
									
										
										
										
											2014-11-21 21:48:49 +01:00
										 |  |  | 				t.Error("expected error for out-of-range msg code, got nil") | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-03-19 15:11:02 +01:00
										 |  |  | 			if err := SendItems(rw, 1, "foo", "bar"); err != nil { | 
					
						
							| 
									
										
										
										
											2014-11-21 21:48:49 +01:00
										 |  |  | 				t.Errorf("write error: %v", err) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			return nil | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-02-27 03:06:55 +00:00
										 |  |  | 	closer, rw, _, _ := testPeer([]Protocol{proto}) | 
					
						
							|  |  |  | 	defer closer.Close() | 
					
						
							| 
									
										
										
										
											2014-11-21 21:48:49 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-19 15:11:02 +01:00
										 |  |  | 	if err := ExpectMsg(rw, 17, []string{"foo", "bar"}); err != nil { | 
					
						
							| 
									
										
										
										
											2015-02-05 03:07:58 +01:00
										 |  |  | 		t.Error(err) | 
					
						
							| 
									
										
										
										
											2015-01-05 17:10:42 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-11-21 21:48:49 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-05 03:07:58 +01:00
										 |  |  | func TestPeerWriteForBroadcast(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2014-11-21 21:48:49 +01:00
										 |  |  | 	defer testlog(t).detach() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-27 03:06:55 +00:00
										 |  |  | 	closer, rw, peer, peerErr := testPeer([]Protocol{discard}) | 
					
						
							|  |  |  | 	defer closer.Close() | 
					
						
							| 
									
										
										
										
											2014-11-21 21:48:49 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-19 15:11:02 +01:00
										 |  |  | 	emptymsg := func(code uint64) Msg { | 
					
						
							|  |  |  | 		return Msg{Code: code, Size: 0, Payload: bytes.NewReader(nil)} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-21 21:48:49 +01:00
										 |  |  | 	// test write errors | 
					
						
							| 
									
										
										
										
											2015-03-19 15:11:02 +01:00
										 |  |  | 	if err := peer.writeProtoMsg("b", emptymsg(3)); err == nil { | 
					
						
							| 
									
										
										
										
											2014-11-21 21:48:49 +01:00
										 |  |  | 		t.Errorf("expected error for unknown protocol, got nil") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-03-19 15:11:02 +01:00
										 |  |  | 	if err := peer.writeProtoMsg("discard", emptymsg(8)); err == nil { | 
					
						
							| 
									
										
										
										
											2014-11-21 21:48:49 +01:00
										 |  |  | 		t.Errorf("expected error for out-of-range msg code, got nil") | 
					
						
							|  |  |  | 	} else if perr, ok := err.(*peerError); !ok || perr.Code != errInvalidMsgCode { | 
					
						
							|  |  |  | 		t.Errorf("wrong error for out-of-range msg code, got %#v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// setup for reading the message on the other end | 
					
						
							|  |  |  | 	read := make(chan struct{}) | 
					
						
							|  |  |  | 	go func() { | 
					
						
							| 
									
										
										
										
											2015-03-19 15:11:02 +01:00
										 |  |  | 		if err := ExpectMsg(rw, 16, nil); err != nil { | 
					
						
							| 
									
										
										
										
											2015-02-19 01:52:03 +01:00
										 |  |  | 			t.Error(err) | 
					
						
							| 
									
										
										
										
											2014-11-21 21:48:49 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		close(read) | 
					
						
							|  |  |  | 	}() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-05 03:07:58 +01:00
										 |  |  | 	// test successful write | 
					
						
							| 
									
										
										
										
											2015-03-19 15:11:02 +01:00
										 |  |  | 	if err := peer.writeProtoMsg("discard", emptymsg(0)); err != nil { | 
					
						
							| 
									
										
										
										
											2014-11-21 21:48:49 +01:00
										 |  |  | 		t.Errorf("expect no error for known protocol: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	select { | 
					
						
							|  |  |  | 	case <-read: | 
					
						
							|  |  |  | 	case err := <-peerErr: | 
					
						
							|  |  |  | 		t.Fatalf("peer stopped: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-05 03:07:58 +01:00
										 |  |  | func TestPeerPing(t *testing.T) { | 
					
						
							|  |  |  | 	defer testlog(t).detach() | 
					
						
							| 
									
										
										
										
											2014-11-21 21:48:49 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-27 03:06:55 +00:00
										 |  |  | 	closer, rw, _, _ := testPeer(nil) | 
					
						
							|  |  |  | 	defer closer.Close() | 
					
						
							| 
									
										
										
										
											2015-03-19 15:11:02 +01:00
										 |  |  | 	if err := SendItems(rw, pingMsg); err != nil { | 
					
						
							| 
									
										
										
										
											2015-02-05 03:07:58 +01:00
										 |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-03-19 15:11:02 +01:00
										 |  |  | 	if err := ExpectMsg(rw, pongMsg, nil); err != nil { | 
					
						
							| 
									
										
										
										
											2015-02-05 03:07:58 +01:00
										 |  |  | 		t.Error(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-11-21 21:48:49 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-05 03:07:58 +01:00
										 |  |  | func TestPeerDisconnect(t *testing.T) { | 
					
						
							|  |  |  | 	defer testlog(t).detach() | 
					
						
							| 
									
										
										
										
											2014-11-21 21:48:49 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-27 03:06:55 +00:00
										 |  |  | 	closer, rw, _, disc := testPeer(nil) | 
					
						
							|  |  |  | 	defer closer.Close() | 
					
						
							| 
									
										
										
										
											2015-03-19 15:11:02 +01:00
										 |  |  | 	if err := SendItems(rw, discMsg, DiscQuitting); err != nil { | 
					
						
							| 
									
										
										
										
											2015-02-05 03:07:58 +01:00
										 |  |  | 		t.Fatal(err) | 
					
						
							| 
									
										
										
										
											2014-11-21 21:48:49 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-03-19 15:11:02 +01:00
										 |  |  | 	if err := ExpectMsg(rw, discMsg, []interface{}{DiscRequested}); err != nil { | 
					
						
							| 
									
										
										
										
											2015-02-05 03:07:58 +01:00
										 |  |  | 		t.Error(err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-02-27 03:06:55 +00:00
										 |  |  | 	closer.Close() // make test end faster | 
					
						
							| 
									
										
										
										
											2015-02-05 03:07:58 +01:00
										 |  |  | 	if reason := <-disc; reason != DiscRequested { | 
					
						
							|  |  |  | 		t.Errorf("run returned wrong reason: got %v, want %v", reason, DiscRequested) | 
					
						
							| 
									
										
										
										
											2014-11-21 21:48:49 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-11-26 22:49:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-05 03:07:58 +01:00
										 |  |  | func TestNewPeer(t *testing.T) { | 
					
						
							|  |  |  | 	name := "nodename" | 
					
						
							|  |  |  | 	caps := []Cap{{"foo", 2}, {"bar", 3}} | 
					
						
							|  |  |  | 	id := randomID() | 
					
						
							|  |  |  | 	p := NewPeer(id, name, caps) | 
					
						
							|  |  |  | 	if p.ID() != id { | 
					
						
							|  |  |  | 		t.Errorf("ID mismatch: got %v, expected %v", p.ID(), id) | 
					
						
							| 
									
										
										
										
											2014-12-12 11:38:42 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-02-05 03:07:58 +01:00
										 |  |  | 	if p.Name() != name { | 
					
						
							|  |  |  | 		t.Errorf("Name mismatch: got %v, expected %v", p.Name(), name) | 
					
						
							| 
									
										
										
										
											2014-12-12 11:38:42 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-02-05 03:07:58 +01:00
										 |  |  | 	if !reflect.DeepEqual(p.Caps(), caps) { | 
					
						
							|  |  |  | 		t.Errorf("Caps mismatch: got %v, expected %v", p.Caps(), caps) | 
					
						
							| 
									
										
										
										
											2014-12-12 11:38:42 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-05 03:07:58 +01:00
										 |  |  | 	p.Disconnect(DiscAlreadyConnected) // Should not hang | 
					
						
							|  |  |  | } |