diff --git a/link_test.go b/link_test.go index bb994ad..7910f2e 100644 --- a/link_test.go +++ b/link_test.go @@ -3,7 +3,9 @@ package netlink import ( "bytes" "net" + "syscall" "testing" + "time" "github.com/vishvananda/netns" ) @@ -662,3 +664,54 @@ func TestLinkSet(t *testing.T) { t.Fatalf("hardware address not changed!") } } + +func expectLinkUpdate(ch <-chan LinkUpdate, ifaceName string, up bool) bool { + for { + timeout := time.After(time.Minute) + select { + case update := <-ch: + if ifaceName == update.Link.Attrs().Name && (update.IfInfomsg.Flags&syscall.IFF_UP != 0) == up { + return true + } + case <-timeout: + return false + } + } +} + +func TestLinkSubscribe(t *testing.T) { + tearDown := setUpNetlinkTest(t) + defer tearDown() + + ch := make(chan LinkUpdate) + done := make(chan struct{}) + defer close(done) + if err := LinkSubscribe(ch, done); err != nil { + t.Fatal(err) + } + + link := &Veth{LinkAttrs{Name: "foo", TxQLen: testTxQLen, MTU: 1400}, "bar"} + if err := LinkAdd(link); err != nil { + t.Fatal(err) + } + + if !expectLinkUpdate(ch, "foo", false) { + t.Fatal("Add update not received as expected") + } + + if err := LinkSetUp(link); err != nil { + t.Fatal(err) + } + + if !expectLinkUpdate(ch, "foo", true) { + t.Fatal("Link Up update not received as expected") + } + + if err := LinkDel(link); err != nil { + t.Fatal(err) + } + + if !expectLinkUpdate(ch, "foo", false) { + t.Fatal("Del update not received as expected") + } +} diff --git a/route_test.go b/route_test.go index f02bef8..3d170cc 100644 --- a/route_test.go +++ b/route_test.go @@ -2,7 +2,9 @@ package netlink import ( "net" + "syscall" "testing" + "time" ) func TestRouteAddDel(t *testing.T) { @@ -82,3 +84,63 @@ func TestRouteAddIncomplete(t *testing.T) { t.Fatal("Adding incomplete route should fail") } } + +func expectRouteUpdate(ch <-chan RouteUpdate, t uint16, dst net.IP) bool { + for { + timeout := time.After(time.Minute) + select { + case update := <-ch: + if update.Type == t && update.Route.Dst.IP.Equal(dst) { + return true + } + case <-timeout: + return false + } + } +} + +func TestRouteSubscribe(t *testing.T) { + tearDown := setUpNetlinkTest(t) + defer tearDown() + + ch := make(chan RouteUpdate) + done := make(chan struct{}) + defer close(done) + if err := RouteSubscribe(ch, done); err != nil { + t.Fatal(err) + } + + // get loopback interface + link, err := LinkByName("lo") + if err != nil { + t.Fatal(err) + } + + // bring the interface up + if err = LinkSetUp(link); err != nil { + t.Fatal(err) + } + + // add a gateway route + _, dst, err := net.ParseCIDR("192.168.0.0/24") + + ip := net.ParseIP("127.1.1.1") + route := Route{LinkIndex: link.Attrs().Index, Dst: dst, Src: ip} + err = RouteAdd(&route) + if err != nil { + t.Fatal(err) + } + + if !expectRouteUpdate(ch, syscall.RTM_NEWROUTE, dst.IP) { + t.Fatal("Add update not received as expected") + } + + err = RouteDel(&route) + if err != nil { + t.Fatal(err) + } + + if !expectRouteUpdate(ch, syscall.RTM_DELROUTE, dst.IP) { + t.Fatal("Del update not received as expected") + } +}