diff options
Diffstat (limited to 'dhcpv6/async/client_test.go')
-rw-r--r-- | dhcpv6/async/client_test.go | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/dhcpv6/async/client_test.go b/dhcpv6/async/client_test.go new file mode 100644 index 0000000..0bc3a87 --- /dev/null +++ b/dhcpv6/async/client_test.go @@ -0,0 +1,153 @@ +package async + +import ( + "context" + "net" + "testing" + "time" + + "github.com/insomniacslk/dhcp/dhcpv6" + "github.com/insomniacslk/dhcp/iana" + "github.com/stretchr/testify/require" +) + +const retries = 5 + +// solicit creates new solicit based on the mac address +func solicit(input string) (dhcpv6.DHCPv6, error) { + mac, err := net.ParseMAC(input) + if err != nil { + return nil, err + } + duid := dhcpv6.Duid{ + Type: dhcpv6.DUID_LLT, + HwType: iana.HwTypeEthernet, + Time: dhcpv6.GetTime(), + LinkLayerAddr: mac, + } + return dhcpv6.NewSolicitWithCID(duid) +} + +// server creates a server which responds with a predefined response +func serve(ctx context.Context, addr *net.UDPAddr, response dhcpv6.DHCPv6) error { + conn, err := net.ListenUDP("udp6", addr) + if err != nil { + return err + } + go func() { + defer conn.Close() + oobdata := []byte{} + buffer := make([]byte, dhcpv6.MaxUDPReceivedPacketSize) + for { + select { + case <-ctx.Done(): + return + default: + conn.SetReadDeadline(time.Now().Add(1 * time.Second)) + n, _, _, src, err := conn.ReadMsgUDP(buffer, oobdata) + if err != nil { + continue + } + _, err = dhcpv6.FromBytes(buffer[:n]) + if err != nil { + continue + } + conn.SetWriteDeadline(time.Now().Add(1 * time.Second)) + _, err = conn.WriteTo(response.ToBytes(), src) + if err != nil { + continue + } + } + } + }() + return nil +} + +func TestNewClient(t *testing.T) { + c := NewClient() + require.NotNil(t, c) + require.Equal(t, c.ReadTimeout, dhcpv6.DefaultReadTimeout) + require.Equal(t, c.ReadTimeout, dhcpv6.DefaultWriteTimeout) +} + +func TestOpenInvalidAddrFailes(t *testing.T) { + c := NewClient() + err := c.Open(512) + require.Error(t, err) +} + +// This test uses port 15438 so please make sure its not used before running +func TestOpenClose(t *testing.T) { + c := NewClient() + addr, err := net.ResolveUDPAddr("udp6", ":15438") + require.NoError(t, err) + c.LocalAddr = addr + err = c.Open(512) + require.NoError(t, err) + defer c.Close() +} + +// This test uses ports 15438 and 15439 so please make sure they are not used +// before running +func TestSendTimeout(t *testing.T) { + c := NewClient() + addr, err := net.ResolveUDPAddr("udp6", ":15438") + require.NoError(t, err) + remote, err := net.ResolveUDPAddr("udp6", ":15439") + require.NoError(t, err) + c.ReadTimeout = 50 * time.Millisecond + c.WriteTimeout = 50 * time.Millisecond + c.LocalAddr = addr + c.RemoteAddr = remote + err = c.Open(512) + require.NoError(t, err) + defer c.Close() + m, err := dhcpv6.NewMessage() + require.NoError(t, err) + _, err, timeout := c.Send(m).GetOrTimeout(200) + require.NoError(t, err) + require.True(t, timeout) +} + +// This test uses ports 15438 and 15439 so please make sure they are not used +// before running +func TestSend(t *testing.T) { + s, err := solicit("c8:6c:2c:47:96:fd") + require.NoError(t, err) + require.NotNil(t, s) + + a, err := dhcpv6.NewAdvertiseFromSolicit(s) + require.NoError(t, err) + require.NotNil(t, a) + + c := NewClient() + addr, err := net.ResolveUDPAddr("udp6", ":15438") + require.NoError(t, err) + remote, err := net.ResolveUDPAddr("udp6", ":15439") + require.NoError(t, err) + c.LocalAddr = addr + c.RemoteAddr = remote + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + err = serve(ctx, remote, a) + require.NoError(t, err) + + err = c.Open(16) + require.NoError(t, err) + defer c.Close() + + f := c.Send(s) + + var passed bool + for i := 0; i < retries; i++ { + response, err, timeout := f.GetOrTimeout(1000) + if timeout { + continue + } + passed = true + require.NoError(t, err) + require.Equal(t, a, response) + } + require.True(t, passed, "All attempts to TestSend timed out") +} |