package ipstack import ( "fmt" ipv4header "github.com/brown-csci1680/iptcp-headers" "net" "net/netip" "testing" "time" ) func TestInitialize(t *testing.T) { lnxFilePath := "../../doc-example/r2.lnx" err := Initialize(lnxFilePath) if err != nil { t.Error(err) } fmt.Printf("Interfaces:\n%s\n\n", SprintInterfaces()) fmt.Printf("Neighbors:\n%s\n", SprintNeighbors()) fmt.Printf("RoutingTable:\n%s\n", SprintRoutingTable()) fmt.Println("TestInitialize successful") t.Cleanup(func() { CleanUp() }) } func TestInterfaceUpThenDown(t *testing.T) { lnxFilePath := "../../doc-example/r2.lnx" err := Initialize(lnxFilePath) if err != nil { t.Error(err) } iface, err := GetInterfaceByName("if0") if err != nil { t.Error(err) } InterfaceUp(iface) if iface.State == false { t.Error("iface state should be true") } fmt.Printf("Interfaces:\n%s\n", SprintInterfaces()) time.Sleep(5 * time.Millisecond) // allow time to print InterfaceDown(iface) if iface.State == true { t.Error("iface state should be false") } time.Sleep(5 * time.Millisecond) // allow time to print fmt.Printf("Interfaces:\n%s\n", SprintInterfaces()) fmt.Println("TestInterfaceUpThenDown successful") t.Cleanup(func() { CleanUp() }) } func TestInterfaceUpThenDownTwice(t *testing.T) { lnxFilePath := "../../doc-example/r2.lnx" err := Initialize(lnxFilePath) if err != nil { t.Error(err) } iface, err := GetInterfaceByName("if0") if err != nil { t.Error(err) } InterfaceUp(iface) if iface.State == false { t.Error("iface state should be true") } fmt.Printf("Interfaces:\n%s\n", SprintInterfaces()) time.Sleep(5 * time.Millisecond) // allow time to print fmt.Println("putting interface down") InterfaceDown(iface) if iface.State == true { t.Error("iface state should be false") } time.Sleep(3 * time.Millisecond) fmt.Println("putting interface back up for 3 iterations") InterfaceUp(iface) if iface.State == false { t.Error("iface state should be true") } time.Sleep(3 * time.Millisecond) // allow time to print fmt.Println("putting interface down") InterfaceDown(iface) if iface.State == true { t.Error("iface state should be false") } time.Sleep(5 * time.Millisecond) // allow time to print fmt.Printf("Interfaces:\n%s\n", SprintInterfaces()) fmt.Println("TestInterfaceUpThenDownTwice successful") t.Cleanup(func() { CleanUp() }) } func TestSendIPToNeighbor(t *testing.T) { lnxFilePath := "../../doc-example/r2.lnx" err := Initialize(lnxFilePath) if err != nil { t.Error(err) } // get the first neighbor of this interface iface, err := GetInterfaceByName("if0") if err != nil { t.Error(err) } neighbors, err := GetNeighborsToInterface("if0") if err != nil { t.Error(err) } // setup a neighbor listener socket testNeighbor := neighbors[0] // close the socket so we can listen on it err = testNeighbor.SendSocket.Close() if err != nil { t.Error(err) } fmt.Printf("Interfaces:\n%s\n", SprintInterfaces()) fmt.Printf("Neighbors:\n%s\n", SprintNeighbors()) listenString := testNeighbor.UdpAddr.String() fmt.Println("listening on " + listenString) listenAddr, err := net.ResolveUDPAddr("udp4", listenString) if err != nil { t.Error(err) } recvSocket, err := net.ListenUDP("udp4", listenAddr) if err != nil { t.Error(err) } testNeighbor.SendSocket = *recvSocket sent := false go func() { buffer := make([]byte, MAX_IP_PACKET_SIZE) fmt.Println("wating to read from UDP socket") _, sourceAddr, err := recvSocket.ReadFromUDP(buffer) if err != nil { t.Error(err) } fmt.Println("read from UDP socket") hdr, err := ipv4header.ParseHeader(buffer) if err != nil { t.Error(err) } headerSize := hdr.Len headerBytes := buffer[:headerSize] checksumFromHeader := uint16(hdr.Checksum) computedChecksum := ValidateChecksum(headerBytes, checksumFromHeader) var checksumState string if computedChecksum == checksumFromHeader { checksumState = "OK" } else { checksumState = "FAIL" } message := buffer[headerSize:] fmt.Printf("Received IP packet from %s\nHeader: %v\nChecksum: %s\nMessage: %s\n", sourceAddr.String(), hdr, checksumState, string(message)) if err != nil { t.Error(err) } sent = true }() time.Sleep(10 * time.Millisecond) // send a message to the neighbor fmt.Printf("sending message to neighbor\t%t\n", sent) err = SendIP(*iface, *testNeighbor, 0, []byte("You are my firest neighbor!")) if err != nil { t.Error(err) } fmt.Printf("SENT message to neighbor\t%t\n", sent) // give a little time for the message to be sent time.Sleep(1000 * time.Millisecond) if !sent { t.Error("Message not sent") t.Fail() } fmt.Println("TestSendIPToNeighbor successful") t.Cleanup(func() { CleanUp() }) } func TestRecvIP(t *testing.T) { lnxFilePath := "../../doc-example/r2.lnx" err := Initialize(lnxFilePath) if err != nil { t.Error(err) } // get the first neighbor of this interface to RecvIP from iface, err := GetInterfaceByName("if0") if err != nil { t.Error(err) } InterfaceUp(iface) // setup a random socket to send an ip packet from listenAddr, err := net.ResolveUDPAddr("udp4", "127.0.0.1:6969") sendSocket, err := net.ListenUDP("udp4", listenAddr) // send a message to the neighbor ifaceAsNeighbor := Neighbor{ VipAddr: iface.IpPrefix.Addr(), UdpAddr: iface.UdpAddr, SendSocket: iface.RecvSocket, SocketChannel: iface.SocketChannel, } fakeIface := Interface{ Name: "if69", IpPrefix: netip.MustParsePrefix("10.69.0.1/24"), UdpAddr: netip.MustParseAddrPort("127.0.0.1:6969"), RecvSocket: net.UDPConn{}, SocketChannel: nil, State: true, } err = SendIP(fakeIface, ifaceAsNeighbor, 0, []byte("hello")) if err != nil { return } time.Sleep(10 * time.Millisecond) // TODO: potenially make this a channel, so it actually checks values. // For now, you must read the message from the console. err = sendSocket.Close() if err != nil { t.Error(err) } t.Cleanup(func() { CleanUp() }) }