ipsock_test.go 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. // Copyright 2013 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package net
  5. import (
  6. "reflect"
  7. "testing"
  8. )
  9. var testInetaddr = func(ip IPAddr) Addr { return &TCPAddr{IP: ip.IP, Port: 5682, Zone: ip.Zone} }
  10. var addrListTests = []struct {
  11. filter func(IPAddr) bool
  12. ips []IPAddr
  13. inetaddr func(IPAddr) Addr
  14. first Addr
  15. primaries addrList
  16. fallbacks addrList
  17. err error
  18. }{
  19. {
  20. nil,
  21. []IPAddr{
  22. {IP: IPv4(127, 0, 0, 1)},
  23. {IP: IPv6loopback},
  24. },
  25. testInetaddr,
  26. &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
  27. addrList{&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682}},
  28. addrList{&TCPAddr{IP: IPv6loopback, Port: 5682}},
  29. nil,
  30. },
  31. {
  32. nil,
  33. []IPAddr{
  34. {IP: IPv6loopback},
  35. {IP: IPv4(127, 0, 0, 1)},
  36. },
  37. testInetaddr,
  38. &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
  39. addrList{&TCPAddr{IP: IPv6loopback, Port: 5682}},
  40. addrList{&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682}},
  41. nil,
  42. },
  43. {
  44. nil,
  45. []IPAddr{
  46. {IP: IPv4(127, 0, 0, 1)},
  47. {IP: IPv4(192, 168, 0, 1)},
  48. },
  49. testInetaddr,
  50. &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
  51. addrList{
  52. &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
  53. &TCPAddr{IP: IPv4(192, 168, 0, 1), Port: 5682},
  54. },
  55. nil,
  56. nil,
  57. },
  58. {
  59. nil,
  60. []IPAddr{
  61. {IP: IPv6loopback},
  62. {IP: ParseIP("fe80::1"), Zone: "eth0"},
  63. },
  64. testInetaddr,
  65. &TCPAddr{IP: IPv6loopback, Port: 5682},
  66. addrList{
  67. &TCPAddr{IP: IPv6loopback, Port: 5682},
  68. &TCPAddr{IP: ParseIP("fe80::1"), Port: 5682, Zone: "eth0"},
  69. },
  70. nil,
  71. nil,
  72. },
  73. {
  74. nil,
  75. []IPAddr{
  76. {IP: IPv4(127, 0, 0, 1)},
  77. {IP: IPv4(192, 168, 0, 1)},
  78. {IP: IPv6loopback},
  79. {IP: ParseIP("fe80::1"), Zone: "eth0"},
  80. },
  81. testInetaddr,
  82. &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
  83. addrList{
  84. &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
  85. &TCPAddr{IP: IPv4(192, 168, 0, 1), Port: 5682},
  86. },
  87. addrList{
  88. &TCPAddr{IP: IPv6loopback, Port: 5682},
  89. &TCPAddr{IP: ParseIP("fe80::1"), Port: 5682, Zone: "eth0"},
  90. },
  91. nil,
  92. },
  93. {
  94. nil,
  95. []IPAddr{
  96. {IP: IPv6loopback},
  97. {IP: ParseIP("fe80::1"), Zone: "eth0"},
  98. {IP: IPv4(127, 0, 0, 1)},
  99. {IP: IPv4(192, 168, 0, 1)},
  100. },
  101. testInetaddr,
  102. &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
  103. addrList{
  104. &TCPAddr{IP: IPv6loopback, Port: 5682},
  105. &TCPAddr{IP: ParseIP("fe80::1"), Port: 5682, Zone: "eth0"},
  106. },
  107. addrList{
  108. &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
  109. &TCPAddr{IP: IPv4(192, 168, 0, 1), Port: 5682},
  110. },
  111. nil,
  112. },
  113. {
  114. nil,
  115. []IPAddr{
  116. {IP: IPv4(127, 0, 0, 1)},
  117. {IP: IPv6loopback},
  118. {IP: IPv4(192, 168, 0, 1)},
  119. {IP: ParseIP("fe80::1"), Zone: "eth0"},
  120. },
  121. testInetaddr,
  122. &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
  123. addrList{
  124. &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
  125. &TCPAddr{IP: IPv4(192, 168, 0, 1), Port: 5682},
  126. },
  127. addrList{
  128. &TCPAddr{IP: IPv6loopback, Port: 5682},
  129. &TCPAddr{IP: ParseIP("fe80::1"), Port: 5682, Zone: "eth0"},
  130. },
  131. nil,
  132. },
  133. {
  134. nil,
  135. []IPAddr{
  136. {IP: IPv6loopback},
  137. {IP: IPv4(127, 0, 0, 1)},
  138. {IP: ParseIP("fe80::1"), Zone: "eth0"},
  139. {IP: IPv4(192, 168, 0, 1)},
  140. },
  141. testInetaddr,
  142. &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
  143. addrList{
  144. &TCPAddr{IP: IPv6loopback, Port: 5682},
  145. &TCPAddr{IP: ParseIP("fe80::1"), Port: 5682, Zone: "eth0"},
  146. },
  147. addrList{
  148. &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
  149. &TCPAddr{IP: IPv4(192, 168, 0, 1), Port: 5682},
  150. },
  151. nil,
  152. },
  153. {
  154. ipv4only,
  155. []IPAddr{
  156. {IP: IPv4(127, 0, 0, 1)},
  157. {IP: IPv6loopback},
  158. },
  159. testInetaddr,
  160. &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
  161. addrList{&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682}},
  162. nil,
  163. nil,
  164. },
  165. {
  166. ipv4only,
  167. []IPAddr{
  168. {IP: IPv6loopback},
  169. {IP: IPv4(127, 0, 0, 1)},
  170. },
  171. testInetaddr,
  172. &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
  173. addrList{&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682}},
  174. nil,
  175. nil,
  176. },
  177. {
  178. ipv6only,
  179. []IPAddr{
  180. {IP: IPv4(127, 0, 0, 1)},
  181. {IP: IPv6loopback},
  182. },
  183. testInetaddr,
  184. &TCPAddr{IP: IPv6loopback, Port: 5682},
  185. addrList{&TCPAddr{IP: IPv6loopback, Port: 5682}},
  186. nil,
  187. nil,
  188. },
  189. {
  190. ipv6only,
  191. []IPAddr{
  192. {IP: IPv6loopback},
  193. {IP: IPv4(127, 0, 0, 1)},
  194. },
  195. testInetaddr,
  196. &TCPAddr{IP: IPv6loopback, Port: 5682},
  197. addrList{&TCPAddr{IP: IPv6loopback, Port: 5682}},
  198. nil,
  199. nil,
  200. },
  201. {nil, nil, testInetaddr, nil, nil, nil, &AddrError{errNoSuitableAddress.Error(), "ADDR"}},
  202. {ipv4only, nil, testInetaddr, nil, nil, nil, &AddrError{errNoSuitableAddress.Error(), "ADDR"}},
  203. {ipv4only, []IPAddr{{IP: IPv6loopback}}, testInetaddr, nil, nil, nil, &AddrError{errNoSuitableAddress.Error(), "ADDR"}},
  204. {ipv6only, nil, testInetaddr, nil, nil, nil, &AddrError{errNoSuitableAddress.Error(), "ADDR"}},
  205. {ipv6only, []IPAddr{{IP: IPv4(127, 0, 0, 1)}}, testInetaddr, nil, nil, nil, &AddrError{errNoSuitableAddress.Error(), "ADDR"}},
  206. }
  207. func TestAddrList(t *testing.T) {
  208. if !supportsIPv4() || !supportsIPv6() {
  209. t.Skip("both IPv4 and IPv6 are required")
  210. }
  211. for i, tt := range addrListTests {
  212. addrs, err := filterAddrList(tt.filter, tt.ips, tt.inetaddr, "ADDR")
  213. if !reflect.DeepEqual(err, tt.err) {
  214. t.Errorf("#%v: got %v; want %v", i, err, tt.err)
  215. }
  216. if tt.err != nil {
  217. if len(addrs) != 0 {
  218. t.Errorf("#%v: got %v; want 0", i, len(addrs))
  219. }
  220. continue
  221. }
  222. first := addrs.first(isIPv4)
  223. if !reflect.DeepEqual(first, tt.first) {
  224. t.Errorf("#%v: got %v; want %v", i, first, tt.first)
  225. }
  226. primaries, fallbacks := addrs.partition(isIPv4)
  227. if !reflect.DeepEqual(primaries, tt.primaries) {
  228. t.Errorf("#%v: got %v; want %v", i, primaries, tt.primaries)
  229. }
  230. if !reflect.DeepEqual(fallbacks, tt.fallbacks) {
  231. t.Errorf("#%v: got %v; want %v", i, fallbacks, tt.fallbacks)
  232. }
  233. expectedLen := len(primaries) + len(fallbacks)
  234. if len(addrs) != expectedLen {
  235. t.Errorf("#%v: got %v; want %v", i, len(addrs), expectedLen)
  236. }
  237. }
  238. }
  239. func TestAddrListPartition(t *testing.T) {
  240. addrs := addrList{
  241. &IPAddr{IP: ParseIP("fe80::"), Zone: "eth0"},
  242. &IPAddr{IP: ParseIP("fe80::1"), Zone: "eth0"},
  243. &IPAddr{IP: ParseIP("fe80::2"), Zone: "eth0"},
  244. }
  245. cases := []struct {
  246. lastByte byte
  247. primaries addrList
  248. fallbacks addrList
  249. }{
  250. {0, addrList{addrs[0]}, addrList{addrs[1], addrs[2]}},
  251. {1, addrList{addrs[0], addrs[2]}, addrList{addrs[1]}},
  252. {2, addrList{addrs[0], addrs[1]}, addrList{addrs[2]}},
  253. {3, addrList{addrs[0], addrs[1], addrs[2]}, nil},
  254. }
  255. for i, tt := range cases {
  256. // Inverting the function's output should not affect the outcome.
  257. for _, invert := range []bool{false, true} {
  258. primaries, fallbacks := addrs.partition(func(a Addr) bool {
  259. ip := a.(*IPAddr).IP
  260. return (ip[len(ip)-1] == tt.lastByte) != invert
  261. })
  262. if !reflect.DeepEqual(primaries, tt.primaries) {
  263. t.Errorf("#%v: got %v; want %v", i, primaries, tt.primaries)
  264. }
  265. if !reflect.DeepEqual(fallbacks, tt.fallbacks) {
  266. t.Errorf("#%v: got %v; want %v", i, fallbacks, tt.fallbacks)
  267. }
  268. }
  269. }
  270. }