github.com/ebceco/ebc@v1.8.19-0.20190309150932-8cb0b9e06484/p2p/enode/urlv4_test.go (about) 1 // Copyright 2018 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package enode 18 19 import ( 20 "bytes" 21 "crypto/ecdsa" 22 "math/big" 23 "net" 24 "reflect" 25 "strings" 26 "testing" 27 "testing/quick" 28 ) 29 30 var parseNodeTests = []struct { 31 rawurl string 32 wantError string 33 wantResult *Node 34 }{ 35 { 36 rawurl: "http://foobar", 37 wantError: `invalid URL scheme, want "enode"`, 38 }, 39 { 40 rawurl: "enode://01010101@123.124.125.126:3", 41 wantError: `invalid node ID (wrong length, want 128 hex chars)`, 42 }, 43 // Complete nodes with IP address. 44 { 45 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@hostname:3", 46 wantError: `invalid IP address`, 47 }, 48 { 49 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:foo", 50 wantError: `invalid port`, 51 }, 52 { 53 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:3?discport=foo", 54 wantError: `invalid discport in query`, 55 }, 56 { 57 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:52150", 58 wantResult: NewV4( 59 hexPubkey("1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 60 net.IP{0x7f, 0x0, 0x0, 0x1}, 61 52150, 62 52150, 63 ), 64 }, 65 { 66 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@[::]:52150", 67 wantResult: NewV4( 68 hexPubkey("1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 69 net.ParseIP("::"), 70 52150, 71 52150, 72 ), 73 }, 74 { 75 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@[2001:db8:3c4d:15::abcd:ef12]:52150", 76 wantResult: NewV4( 77 hexPubkey("1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 78 net.ParseIP("2001:db8:3c4d:15::abcd:ef12"), 79 52150, 80 52150, 81 ), 82 }, 83 { 84 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:52150?discport=22334", 85 wantResult: NewV4( 86 hexPubkey("1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 87 net.IP{0x7f, 0x0, 0x0, 0x1}, 88 52150, 89 22334, 90 ), 91 }, 92 // Incomplete nodes with no address. 93 { 94 rawurl: "1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439", 95 wantResult: NewV4( 96 hexPubkey("1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 97 nil, 0, 0, 98 ), 99 }, 100 { 101 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439", 102 wantResult: NewV4( 103 hexPubkey("1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 104 nil, 0, 0, 105 ), 106 }, 107 // Invalid URLs 108 { 109 rawurl: "01010101", 110 wantError: `invalid node ID (wrong length, want 128 hex chars)`, 111 }, 112 { 113 rawurl: "enode://01010101", 114 wantError: `invalid node ID (wrong length, want 128 hex chars)`, 115 }, 116 { 117 // This test checks that errors from url.Parse are handled. 118 rawurl: "://foo", 119 wantError: `parse ://foo: missing protocol scheme`, 120 }, 121 } 122 123 func hexPubkey(h string) *ecdsa.PublicKey { 124 k, err := parsePubkey(h) 125 if err != nil { 126 panic(err) 127 } 128 return k 129 } 130 131 func TestParseNode(t *testing.T) { 132 for _, test := range parseNodeTests { 133 n, err := ParseV4(test.rawurl) 134 if test.wantError != "" { 135 if err == nil { 136 t.Errorf("test %q:\n got nil error, expected %#q", test.rawurl, test.wantError) 137 continue 138 } else if err.Error() != test.wantError { 139 t.Errorf("test %q:\n got error %#q, expected %#q", test.rawurl, err.Error(), test.wantError) 140 continue 141 } 142 } else { 143 if err != nil { 144 t.Errorf("test %q:\n unexpected error: %v", test.rawurl, err) 145 continue 146 } 147 if !reflect.DeepEqual(n, test.wantResult) { 148 t.Errorf("test %q:\n result mismatch:\ngot: %#v\nwant: %#v", test.rawurl, n, test.wantResult) 149 } 150 } 151 } 152 } 153 154 func TestNodeString(t *testing.T) { 155 for i, test := range parseNodeTests { 156 if test.wantError == "" && strings.HasPrefix(test.rawurl, "enode://") { 157 str := test.wantResult.String() 158 if str != test.rawurl { 159 t.Errorf("test %d: Node.String() mismatch:\ngot: %s\nwant: %s", i, str, test.rawurl) 160 } 161 } 162 } 163 } 164 165 func TestHexID(t *testing.T) { 166 ref := ID{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} 167 id1 := HexID("0x00000000000000806ad9b61fa5ae014307ebdc964253adcd9f2c0a392aa11abc") 168 id2 := HexID("00000000000000806ad9b61fa5ae014307ebdc964253adcd9f2c0a392aa11abc") 169 170 if id1 != ref { 171 t.Errorf("wrong id1\ngot %v\nwant %v", id1[:], ref[:]) 172 } 173 if id2 != ref { 174 t.Errorf("wrong id2\ngot %v\nwant %v", id2[:], ref[:]) 175 } 176 } 177 178 func TestID_textEncoding(t *testing.T) { 179 ref := ID{ 180 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 181 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20, 182 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x30, 183 0x31, 0x32, 184 } 185 hex := "0102030405060708091011121314151617181920212223242526272829303132" 186 187 text, err := ref.MarshalText() 188 if err != nil { 189 t.Fatal(err) 190 } 191 if !bytes.Equal(text, []byte(hex)) { 192 t.Fatalf("text encoding did not match\nexpected: %s\ngot: %s", hex, text) 193 } 194 195 id := new(ID) 196 if err := id.UnmarshalText(text); err != nil { 197 t.Fatal(err) 198 } 199 if *id != ref { 200 t.Fatalf("text decoding did not match\nexpected: %s\ngot: %s", ref, id) 201 } 202 } 203 204 func TestNodeID_distcmp(t *testing.T) { 205 distcmpBig := func(target, a, b ID) int { 206 tbig := new(big.Int).SetBytes(target[:]) 207 abig := new(big.Int).SetBytes(a[:]) 208 bbig := new(big.Int).SetBytes(b[:]) 209 return new(big.Int).Xor(tbig, abig).Cmp(new(big.Int).Xor(tbig, bbig)) 210 } 211 if err := quick.CheckEqual(DistCmp, distcmpBig, nil); err != nil { 212 t.Error(err) 213 } 214 } 215 216 // The random tests is likely to miss the case where a and b are equal, 217 // this test checks it explicitly. 218 func TestNodeID_distcmpEqual(t *testing.T) { 219 base := ID{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} 220 x := ID{15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0} 221 if DistCmp(base, x, x) != 0 { 222 t.Errorf("DistCmp(base, x, x) != 0") 223 } 224 } 225 226 func TestNodeID_logdist(t *testing.T) { 227 logdistBig := func(a, b ID) int { 228 abig, bbig := new(big.Int).SetBytes(a[:]), new(big.Int).SetBytes(b[:]) 229 return new(big.Int).Xor(abig, bbig).BitLen() 230 } 231 if err := quick.CheckEqual(LogDist, logdistBig, nil); err != nil { 232 t.Error(err) 233 } 234 } 235 236 // The random tests is likely to miss the case where a and b are equal, 237 // this test checks it explicitly. 238 func TestNodeID_logdistEqual(t *testing.T) { 239 x := ID{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} 240 if LogDist(x, x) != 0 { 241 t.Errorf("LogDist(x, x) != 0") 242 } 243 }