github.com/jonasnick/go-ethereum@v0.7.12-0.20150216215225-22176f05d387/p2p/discover/node_test.go (about)

     1  package discover
     2  
     3  import (
     4  	"math/big"
     5  	"math/rand"
     6  	"net"
     7  	"reflect"
     8  	"testing"
     9  	"testing/quick"
    10  	"time"
    11  
    12  	"github.com/jonasnick/go-ethereum/crypto"
    13  )
    14  
    15  var (
    16  	quickrand = rand.New(rand.NewSource(time.Now().Unix()))
    17  	quickcfg  = &quick.Config{MaxCount: 5000, Rand: quickrand}
    18  )
    19  
    20  var parseNodeTests = []struct {
    21  	rawurl     string
    22  	wantError  string
    23  	wantResult *Node
    24  }{
    25  	{
    26  		rawurl:    "http://foobar",
    27  		wantError: `invalid URL scheme, want "enode"`,
    28  	},
    29  	{
    30  		rawurl:    "enode://foobar",
    31  		wantError: `does not contain node ID`,
    32  	},
    33  	{
    34  		rawurl:    "enode://01010101@123.124.125.126:3",
    35  		wantError: `invalid node ID (wrong length, need 64 hex bytes)`,
    36  	},
    37  	{
    38  		rawurl:    "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@hostname:3",
    39  		wantError: `invalid IP address`,
    40  	},
    41  	{
    42  		rawurl:    "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:foo",
    43  		wantError: `invalid port`,
    44  	},
    45  	{
    46  		rawurl:    "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:3?discport=foo",
    47  		wantError: `invalid discport in query`,
    48  	},
    49  	{
    50  		rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:52150",
    51  		wantResult: &Node{
    52  			ID:       MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"),
    53  			IP:       net.ParseIP("127.0.0.1"),
    54  			DiscPort: 52150,
    55  			TCPPort:  52150,
    56  		},
    57  	},
    58  	{
    59  		rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@[::]:52150",
    60  		wantResult: &Node{
    61  			ID:       MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"),
    62  			IP:       net.ParseIP("::"),
    63  			DiscPort: 52150,
    64  			TCPPort:  52150,
    65  		},
    66  	},
    67  	{
    68  		rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:52150?discport=223344",
    69  		wantResult: &Node{
    70  			ID:       MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"),
    71  			IP:       net.ParseIP("127.0.0.1"),
    72  			DiscPort: 223344,
    73  			TCPPort:  52150,
    74  		},
    75  	},
    76  }
    77  
    78  func TestParseNode(t *testing.T) {
    79  	for i, test := range parseNodeTests {
    80  		n, err := ParseNode(test.rawurl)
    81  		if err == nil && test.wantError != "" {
    82  			t.Errorf("test %d: got nil error, expected %#q", i, test.wantError)
    83  			continue
    84  		}
    85  		if err != nil && err.Error() != test.wantError {
    86  			t.Errorf("test %d: got error %#q, expected %#q", i, err.Error(), test.wantError)
    87  			continue
    88  		}
    89  		if !reflect.DeepEqual(n, test.wantResult) {
    90  			t.Errorf("test %d: result mismatch:\ngot:  %#v, want: %#v", i, n, test.wantResult)
    91  		}
    92  	}
    93  }
    94  
    95  func TestNodeString(t *testing.T) {
    96  	for i, test := range parseNodeTests {
    97  		if test.wantError != "" {
    98  			continue
    99  		}
   100  		str := test.wantResult.String()
   101  		if str != test.rawurl {
   102  			t.Errorf("test %d: Node.String() mismatch:\ngot:  %s\nwant: %s", i, str, test.rawurl)
   103  		}
   104  	}
   105  }
   106  
   107  func TestHexID(t *testing.T) {
   108  	ref := NodeID{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 106, 217, 182, 31, 165, 174, 1, 67, 7, 235, 220, 150, 66, 83, 173, 205, 159, 44, 10, 57, 42, 161, 26, 188}
   109  	id1 := MustHexID("0x000000000000000000000000000000000000000000000000000000000000000000000000000000806ad9b61fa5ae014307ebdc964253adcd9f2c0a392aa11abc")
   110  	id2 := MustHexID("000000000000000000000000000000000000000000000000000000000000000000000000000000806ad9b61fa5ae014307ebdc964253adcd9f2c0a392aa11abc")
   111  
   112  	if id1 != ref {
   113  		t.Errorf("wrong id1\ngot  %v\nwant %v", id1[:], ref[:])
   114  	}
   115  	if id2 != ref {
   116  		t.Errorf("wrong id2\ngot  %v\nwant %v", id2[:], ref[:])
   117  	}
   118  }
   119  
   120  func TestNodeID_recover(t *testing.T) {
   121  	prv := newkey()
   122  	hash := make([]byte, 32)
   123  	sig, err := crypto.Sign(hash, prv)
   124  	if err != nil {
   125  		t.Fatalf("signing error: %v", err)
   126  	}
   127  
   128  	pub := PubkeyID(&prv.PublicKey)
   129  	recpub, err := recoverNodeID(hash, sig)
   130  	if err != nil {
   131  		t.Fatalf("recovery error: %v", err)
   132  	}
   133  	if pub != recpub {
   134  		t.Errorf("recovered wrong pubkey:\ngot:  %v\nwant: %v", recpub, pub)
   135  	}
   136  }
   137  
   138  func TestNodeID_distcmp(t *testing.T) {
   139  	distcmpBig := func(target, a, b NodeID) int {
   140  		tbig := new(big.Int).SetBytes(target[:])
   141  		abig := new(big.Int).SetBytes(a[:])
   142  		bbig := new(big.Int).SetBytes(b[:])
   143  		return new(big.Int).Xor(tbig, abig).Cmp(new(big.Int).Xor(tbig, bbig))
   144  	}
   145  	if err := quick.CheckEqual(distcmp, distcmpBig, quickcfg); err != nil {
   146  		t.Error(err)
   147  	}
   148  }
   149  
   150  // the random tests is likely to miss the case where they're equal.
   151  func TestNodeID_distcmpEqual(t *testing.T) {
   152  	base := NodeID{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
   153  	x := NodeID{15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}
   154  	if distcmp(base, x, x) != 0 {
   155  		t.Errorf("distcmp(base, x, x) != 0")
   156  	}
   157  }
   158  
   159  func TestNodeID_logdist(t *testing.T) {
   160  	logdistBig := func(a, b NodeID) int {
   161  		abig, bbig := new(big.Int).SetBytes(a[:]), new(big.Int).SetBytes(b[:])
   162  		return new(big.Int).Xor(abig, bbig).BitLen()
   163  	}
   164  	if err := quick.CheckEqual(logdist, logdistBig, quickcfg); err != nil {
   165  		t.Error(err)
   166  	}
   167  }
   168  
   169  // the random tests is likely to miss the case where they're equal.
   170  func TestNodeID_logdistEqual(t *testing.T) {
   171  	x := NodeID{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
   172  	if logdist(x, x) != 0 {
   173  		t.Errorf("logdist(x, x) != 0")
   174  	}
   175  }
   176  
   177  func TestNodeID_randomID(t *testing.T) {
   178  	// we don't use quick.Check here because its output isn't
   179  	// very helpful when the test fails.
   180  	for i := 0; i < quickcfg.MaxCount; i++ {
   181  		a := gen(NodeID{}, quickrand).(NodeID)
   182  		dist := quickrand.Intn(len(NodeID{}) * 8)
   183  		result := randomID(a, dist)
   184  		actualdist := logdist(result, a)
   185  
   186  		if dist != actualdist {
   187  			t.Log("a:     ", a)
   188  			t.Log("result:", result)
   189  			t.Fatalf("#%d: distance of result is %d, want %d", i, actualdist, dist)
   190  		}
   191  	}
   192  }
   193  
   194  func (NodeID) Generate(rand *rand.Rand, size int) reflect.Value {
   195  	var id NodeID
   196  	m := rand.Intn(len(id))
   197  	for i := len(id) - 1; i > m; i-- {
   198  		id[i] = byte(rand.Uint32())
   199  	}
   200  	return reflect.ValueOf(id)
   201  }