github.com/jonasnick/go-ethereum@v0.7.12-0.20150216215225-22176f05d387/p2p/discover/udp_test.go (about) 1 package discover 2 3 import ( 4 "fmt" 5 logpkg "log" 6 "net" 7 "os" 8 "testing" 9 "time" 10 11 "github.com/jonasnick/go-ethereum/logger" 12 ) 13 14 func init() { 15 logger.AddLogSystem(logger.NewStdLogSystem(os.Stdout, logpkg.LstdFlags, logger.ErrorLevel)) 16 } 17 18 func TestUDP_ping(t *testing.T) { 19 t.Parallel() 20 21 n1, _ := ListenUDP(newkey(), "127.0.0.1:0", nil) 22 n2, _ := ListenUDP(newkey(), "127.0.0.1:0", nil) 23 defer n1.Close() 24 defer n2.Close() 25 26 if err := n1.net.ping(n2.self); err != nil { 27 t.Fatalf("ping error: %v", err) 28 } 29 if find(n2, n1.self.ID) == nil { 30 t.Errorf("node 2 does not contain id of node 1") 31 } 32 if e := find(n1, n2.self.ID); e != nil { 33 t.Errorf("node 1 does contains id of node 2: %v", e) 34 } 35 } 36 37 func find(tab *Table, id NodeID) *Node { 38 for _, b := range tab.buckets { 39 for _, e := range b.entries { 40 if e.ID == id { 41 return e 42 } 43 } 44 } 45 return nil 46 } 47 48 func TestUDP_findnode(t *testing.T) { 49 t.Parallel() 50 51 n1, _ := ListenUDP(newkey(), "127.0.0.1:0", nil) 52 n2, _ := ListenUDP(newkey(), "127.0.0.1:0", nil) 53 defer n1.Close() 54 defer n2.Close() 55 56 // put a few nodes into n2. the exact distribution shouldn't 57 // matter much, altough we need to take care not to overflow 58 // any bucket. 59 target := randomID(n1.self.ID, 100) 60 nodes := &nodesByDistance{target: target} 61 for i := 0; i < bucketSize; i++ { 62 n2.add([]*Node{&Node{ 63 IP: net.IP{1, 2, 3, byte(i)}, 64 DiscPort: i + 2, 65 TCPPort: i + 2, 66 ID: randomID(n2.self.ID, i+2), 67 }}) 68 } 69 n2.add(nodes.entries) 70 n2.bumpOrAdd(n1.self.ID, &net.UDPAddr{IP: n1.self.IP, Port: n1.self.DiscPort}) 71 expected := n2.closest(target, bucketSize) 72 73 err := runUDP(10, func() error { 74 result, _ := n1.net.findnode(n2.self, target) 75 if len(result) != bucketSize { 76 return fmt.Errorf("wrong number of results: got %d, want %d", len(result), bucketSize) 77 } 78 for i := range result { 79 if result[i].ID != expected.entries[i].ID { 80 return fmt.Errorf("result mismatch at %d:\n got: %v\n want: %v", i, result[i], expected.entries[i]) 81 } 82 } 83 return nil 84 }) 85 if err != nil { 86 t.Error(err) 87 } 88 } 89 90 func TestUDP_replytimeout(t *testing.T) { 91 t.Parallel() 92 93 // reserve a port so we don't talk to an existing service by accident 94 addr, _ := net.ResolveUDPAddr("udp", "127.0.0.1:0") 95 fd, err := net.ListenUDP("udp", addr) 96 if err != nil { 97 t.Fatal(err) 98 } 99 defer fd.Close() 100 101 n1, _ := ListenUDP(newkey(), "127.0.0.1:0", nil) 102 defer n1.Close() 103 n2 := n1.bumpOrAdd(randomID(n1.self.ID, 10), fd.LocalAddr().(*net.UDPAddr)) 104 105 if err := n1.net.ping(n2); err != errTimeout { 106 t.Error("expected timeout error, got", err) 107 } 108 109 if result, err := n1.net.findnode(n2, n1.self.ID); err != errTimeout { 110 t.Error("expected timeout error, got", err) 111 } else if len(result) > 0 { 112 t.Error("expected empty result, got", result) 113 } 114 } 115 116 func TestUDP_findnodeMultiReply(t *testing.T) { 117 t.Parallel() 118 119 n1, _ := ListenUDP(newkey(), "127.0.0.1:0", nil) 120 n2, _ := ListenUDP(newkey(), "127.0.0.1:0", nil) 121 udp2 := n2.net.(*udp) 122 defer n1.Close() 123 defer n2.Close() 124 125 err := runUDP(10, func() error { 126 nodes := make([]*Node, bucketSize) 127 for i := range nodes { 128 nodes[i] = &Node{ 129 IP: net.IP{1, 2, 3, 4}, 130 DiscPort: i + 1, 131 TCPPort: i + 1, 132 ID: randomID(n2.self.ID, i+1), 133 } 134 } 135 136 // ask N2 for neighbors. it will send an empty reply back. 137 // the request will wait for up to bucketSize replies. 138 resultc := make(chan []*Node) 139 errc := make(chan error) 140 go func() { 141 ns, err := n1.net.findnode(n2.self, n1.self.ID) 142 if err != nil { 143 errc <- err 144 } else { 145 resultc <- ns 146 } 147 }() 148 149 // send a few more neighbors packets to N1. 150 // it should collect those. 151 for end := 0; end < len(nodes); { 152 off := end 153 if end = end + 5; end > len(nodes) { 154 end = len(nodes) 155 } 156 udp2.send(n1.self, neighborsPacket, neighbors{ 157 Nodes: nodes[off:end], 158 Expiration: uint64(time.Now().Add(10 * time.Second).Unix()), 159 }) 160 } 161 162 // check that they are all returned. we cannot just check for 163 // equality because they might not be returned in the order they 164 // were sent. 165 var result []*Node 166 select { 167 case result = <-resultc: 168 case err := <-errc: 169 return err 170 } 171 if hasDuplicates(result) { 172 return fmt.Errorf("result slice contains duplicates") 173 } 174 if len(result) != len(nodes) { 175 return fmt.Errorf("wrong number of nodes returned: got %d, want %d", len(result), len(nodes)) 176 } 177 matched := make(map[NodeID]bool) 178 for _, n := range result { 179 for _, expn := range nodes { 180 if n.ID == expn.ID { // && bytes.Equal(n.Addr.IP, expn.Addr.IP) && n.Addr.Port == expn.Addr.Port { 181 matched[n.ID] = true 182 } 183 } 184 } 185 if len(matched) != len(nodes) { 186 return fmt.Errorf("wrong number of matching nodes: got %d, want %d", len(matched), len(nodes)) 187 } 188 return nil 189 }) 190 if err != nil { 191 t.Error(err) 192 } 193 } 194 195 // runUDP runs a test n times and returns an error if the test failed 196 // in all n runs. This is necessary because UDP is unreliable even for 197 // connections on the local machine, causing test failures. 198 func runUDP(n int, test func() error) error { 199 errcount := 0 200 errors := "" 201 for i := 0; i < n; i++ { 202 if err := test(); err != nil { 203 errors += fmt.Sprintf("\n#%d: %v", i, err) 204 errcount++ 205 } 206 } 207 if errcount == n { 208 return fmt.Errorf("failed on all %d iterations:%s", n, errors) 209 } 210 return nil 211 }