external_test.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. // Copyright 2009 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. //go:build !js
  5. package net
  6. import (
  7. "fmt"
  8. "internal/testenv"
  9. "io"
  10. "strings"
  11. "testing"
  12. )
  13. func TestResolveGoogle(t *testing.T) {
  14. testenv.MustHaveExternalNetwork(t)
  15. if !supportsIPv4() || !supportsIPv6() || !*testIPv4 || !*testIPv6 {
  16. t.Skip("both IPv4 and IPv6 are required")
  17. }
  18. for _, network := range []string{"tcp", "tcp4", "tcp6"} {
  19. addr, err := ResolveTCPAddr(network, "www.google.com:http")
  20. if err != nil {
  21. t.Error(err)
  22. continue
  23. }
  24. switch {
  25. case network == "tcp" && addr.IP.To4() == nil:
  26. fallthrough
  27. case network == "tcp4" && addr.IP.To4() == nil:
  28. t.Errorf("got %v; want an IPv4 address on %s", addr, network)
  29. case network == "tcp6" && (addr.IP.To16() == nil || addr.IP.To4() != nil):
  30. t.Errorf("got %v; want an IPv6 address on %s", addr, network)
  31. }
  32. }
  33. }
  34. var dialGoogleTests = []struct {
  35. dial func(string, string) (Conn, error)
  36. unreachableNetwork string
  37. networks []string
  38. addrs []string
  39. }{
  40. {
  41. dial: (&Dialer{DualStack: true}).Dial,
  42. networks: []string{"tcp", "tcp4", "tcp6"},
  43. addrs: []string{"www.google.com:http"},
  44. },
  45. {
  46. dial: Dial,
  47. unreachableNetwork: "tcp6",
  48. networks: []string{"tcp", "tcp4"},
  49. },
  50. {
  51. dial: Dial,
  52. unreachableNetwork: "tcp4",
  53. networks: []string{"tcp", "tcp6"},
  54. },
  55. }
  56. func TestDialGoogle(t *testing.T) {
  57. testenv.MustHaveExternalNetwork(t)
  58. if !supportsIPv4() || !supportsIPv6() || !*testIPv4 || !*testIPv6 {
  59. t.Skip("both IPv4 and IPv6 are required")
  60. }
  61. var err error
  62. dialGoogleTests[1].addrs, dialGoogleTests[2].addrs, err = googleLiteralAddrs()
  63. if err != nil {
  64. t.Error(err)
  65. }
  66. for _, tt := range dialGoogleTests {
  67. for _, network := range tt.networks {
  68. disableSocketConnect(tt.unreachableNetwork)
  69. for _, addr := range tt.addrs {
  70. if err := fetchGoogle(tt.dial, network, addr); err != nil {
  71. t.Error(err)
  72. }
  73. }
  74. enableSocketConnect()
  75. }
  76. }
  77. }
  78. var (
  79. literalAddrs4 = [...]string{
  80. "%d.%d.%d.%d:80",
  81. "www.google.com:80",
  82. "%d.%d.%d.%d:http",
  83. "www.google.com:http",
  84. "%03d.%03d.%03d.%03d:0080",
  85. "[::ffff:%d.%d.%d.%d]:80",
  86. "[::ffff:%02x%02x:%02x%02x]:80",
  87. "[0:0:0:0:0000:ffff:%d.%d.%d.%d]:80",
  88. "[0:0:0:0:000000:ffff:%d.%d.%d.%d]:80",
  89. "[0:0:0:0::ffff:%d.%d.%d.%d]:80",
  90. }
  91. literalAddrs6 = [...]string{
  92. "[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:80",
  93. "ipv6.google.com:80",
  94. "[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:http",
  95. "ipv6.google.com:http",
  96. }
  97. )
  98. func googleLiteralAddrs() (lits4, lits6 []string, err error) {
  99. ips, err := LookupIP("www.google.com")
  100. if err != nil {
  101. return nil, nil, err
  102. }
  103. if len(ips) == 0 {
  104. return nil, nil, nil
  105. }
  106. var ip4, ip6 IP
  107. for _, ip := range ips {
  108. if ip4 == nil && ip.To4() != nil {
  109. ip4 = ip.To4()
  110. }
  111. if ip6 == nil && ip.To16() != nil && ip.To4() == nil {
  112. ip6 = ip.To16()
  113. }
  114. if ip4 != nil && ip6 != nil {
  115. break
  116. }
  117. }
  118. if ip4 != nil {
  119. for i, lit4 := range literalAddrs4 {
  120. if strings.Contains(lit4, "%") {
  121. literalAddrs4[i] = fmt.Sprintf(lit4, ip4[0], ip4[1], ip4[2], ip4[3])
  122. }
  123. }
  124. lits4 = literalAddrs4[:]
  125. }
  126. if ip6 != nil {
  127. for i, lit6 := range literalAddrs6 {
  128. if strings.Contains(lit6, "%") {
  129. literalAddrs6[i] = fmt.Sprintf(lit6, ip6[0], ip6[1], ip6[2], ip6[3], ip6[4], ip6[5], ip6[6], ip6[7], ip6[8], ip6[9], ip6[10], ip6[11], ip6[12], ip6[13], ip6[14], ip6[15])
  130. }
  131. }
  132. lits6 = literalAddrs6[:]
  133. }
  134. return
  135. }
  136. func fetchGoogle(dial func(string, string) (Conn, error), network, address string) error {
  137. c, err := dial(network, address)
  138. if err != nil {
  139. return err
  140. }
  141. defer c.Close()
  142. req := []byte("GET /robots.txt HTTP/1.0\r\nHost: www.google.com\r\n\r\n")
  143. if _, err := c.Write(req); err != nil {
  144. return err
  145. }
  146. b := make([]byte, 1000)
  147. n, err := io.ReadFull(c, b)
  148. if err != nil {
  149. return err
  150. }
  151. if n < 1000 {
  152. return fmt.Errorf("short read from %s:%s->%s", network, c.RemoteAddr(), c.LocalAddr())
  153. }
  154. return nil
  155. }