🐞 Make integration tests IPv4/IPv6 stack-agnostic

The integration test which worked fine on my dual-stack laptop failed on
my IPv4-only Concourse.

Fixes, when running `ginkgo -r -p .` on an IPv4-only machine:
```
sslip.io-dns-server When it can't bind to a port on loopback [BeforeEach] prints an informative message and continues
  [BeforeEach] /tmp/build/b4e0c68a/sslip.io/src/sslip.io-dns-server/integration_test.go:399
  [It] /tmp/build/b4e0c68a/sslip.io/src/sslip.io-dns-server/integration_test.go:409
  [FAILED] Unexpected error:
      <*net.OpError | 0xc000310d20>:
      listen udp [::1]:1918: socket: address family not supported by protocol
```
This commit is contained in:
Brian Cunnie
2023-09-30 09:01:01 -07:00
parent 4f81fccb7f
commit b09bccdd86

View File

@@ -395,26 +395,22 @@ var _ = Describe("sslip.io-dns-server", func() {
})
})
Describe("When it can't bind to a port on loopback", func() {
var udpConnSquatter *net.UDPConn
var squatter *net.UDPConn
BeforeEach(func() {
port = getFreePort()
// the following won't work on an IPv6-only machine; change to "::1" in that case
udpAddr := net.UDPAddr{
IP: net.ParseIP("::1"),
Port: port,
}
udpConnSquatter, err = net.ListenUDP("udp", &udpAddr)
squatter, err = squatOnUdpLoopbackPort(port)
Expect(err).ToNot(HaveOccurred())
})
It("prints an informative message and continues", func() {
It("prints an informative message and binds to the addresses it can", func() {
Expect(err).ToNot(HaveOccurred())
secondServerCmd := exec.Command(serverPath, "-port", strconv.Itoa(port), "-blocklistURL", "file://../../etc/blocklist.txt")
secondServerSession, err := Start(secondServerCmd, GinkgoWriter, GinkgoWriter)
Expect(err).ToNot(HaveOccurred())
Eventually(secondServerSession.Err, 10).Should(Say(` version \d+\.\d+\.\d+ starting`))
Eventually(secondServerSession.Err, 10).Should(Say(`I couldn't bind via UDP to "\[::\]:\d+" \(INADDR_ANY, all interfaces\), so I'll try to bind to each address individually.`))
Eventually(secondServerSession.Err, 10).Should(Say(`I couldn't bind via UDP to the following IPs:.* "::1"`))
err = udpConnSquatter.Close()
Eventually(secondServerSession.Err, 10).Should(Say(`I couldn't bind via UDP to the following IPs:.* "(::1|127\.0\.0\.1)"`))
err = squatter.Close()
Expect(err).ToNot(HaveOccurred())
Eventually(secondServerSession.Err, 10).Should(Say("Ready to answer queries"))
secondServerSession.Terminate()
@@ -425,6 +421,24 @@ var _ = Describe("sslip.io-dns-server", func() {
var listenPort = 1023 // lowest unprivileged port - 1 (immediately incremented)
func squatOnUdpLoopbackPort(port int) (squatter *net.UDPConn, err error) {
// try IPv6's loopback
udpAddr := net.UDPAddr{
IP: net.ParseIP("::1"),
Port: port,
}
squatter, err = net.ListenUDP("udp", &udpAddr)
if err != nil {
// try IPv4's loopback
udpAddr = net.UDPAddr{
IP: net.ParseIP("127.0.0.1"),
Port: port,
}
squatter, err = net.ListenUDP("udp", &udpAddr)
}
return squatter, err
}
// getFreePort should always succeed unless something awful has happened, e.g. port exhaustion
func getFreePort() int {
// we randomize the start based on the millisecond to avoid collisions in our test