Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tests: Improve address unit test infrastructure #1047

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
185 changes: 107 additions & 78 deletions addr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,123 +20,152 @@ func TestAddrReplace(t *testing.T) {
DoTestAddr(t, AddrReplace)
}

type addrTest struct {
name string
addr *Addr
expected *Addr
canFail bool
t *testing.T
}

func (at *addrTest) Fatal(a interface{}) {
at.t.Helper()
if !at.canFail {
at.t.Fatal(a)
return
}
at.t.Skipf("Non-fatal: %v", a)
}

func (at *addrTest) Fatalf(fmt string, a ...interface{}) {
at.t.Helper()
if !at.canFail {
at.t.Fatalf(fmt, a...)
return
}
at.t.Skipf("Non-fatal: "+fmt, a...)
}

func DoTestAddr(t *testing.T, FunctionUndertest func(Link, *Addr) error) {
if os.Getenv("CI") == "true" {
t.Skipf("Fails in CI with: addr_test.go:*: Address flags not set properly, got=128, expected=132")
}

// TODO: IFA_F_PERMANENT does not seem to be set by default on older kernels?
// TODO: IFA_F_OPTIMISTIC failing in CI. should we just skip that one check?
var address = &net.IPNet{IP: net.IPv4(127, 0, 0, 2), Mask: net.CIDRMask(32, 32)}
var peer = &net.IPNet{IP: net.IPv4(127, 0, 0, 3), Mask: net.CIDRMask(24, 32)}
var addrTests = []struct {
addr *Addr
expected *Addr
}{
var addrTests = []addrTest{
{
&Addr{IPNet: address},
&Addr{IPNet: address, Label: "lo", Scope: unix.RT_SCOPE_UNIVERSE, Flags: unix.IFA_F_PERMANENT},
name: "lo_uni_perm", addr: &Addr{IPNet: address},
expected: &Addr{IPNet: address, Label: "lo", Scope: unix.RT_SCOPE_UNIVERSE, Flags: unix.IFA_F_PERMANENT},
},
{
&Addr{IPNet: address, Label: "local"},
&Addr{IPNet: address, Label: "local", Scope: unix.RT_SCOPE_UNIVERSE, Flags: unix.IFA_F_PERMANENT},
name: "local_uni_perm", addr: &Addr{IPNet: address, Label: "local"},
expected: &Addr{IPNet: address, Label: "local", Scope: unix.RT_SCOPE_UNIVERSE, Flags: unix.IFA_F_PERMANENT},
},
{
&Addr{IPNet: address, Flags: unix.IFA_F_OPTIMISTIC},
&Addr{IPNet: address, Label: "lo", Flags: unix.IFA_F_OPTIMISTIC | unix.IFA_F_PERMANENT, Scope: unix.RT_SCOPE_UNIVERSE},
name: "lo_uni_optimistic_perm", addr: &Addr{IPNet: address, Flags: unix.IFA_F_OPTIMISTIC}, canFail: true,
expected: &Addr{IPNet: address, Label: "lo", Flags: unix.IFA_F_OPTIMISTIC | unix.IFA_F_PERMANENT, Scope: unix.RT_SCOPE_UNIVERSE},
},
{
&Addr{IPNet: address, Flags: unix.IFA_F_OPTIMISTIC | unix.IFA_F_DADFAILED},
&Addr{IPNet: address, Label: "lo", Flags: unix.IFA_F_OPTIMISTIC | unix.IFA_F_DADFAILED | unix.IFA_F_PERMANENT, Scope: unix.RT_SCOPE_UNIVERSE},
// Is this a valid scenario for IPv4?
name: "lo_uni_optimistic_perm_dupe", addr: &Addr{IPNet: address, Flags: unix.IFA_F_OPTIMISTIC | unix.IFA_F_DADFAILED}, canFail: true,
expected: &Addr{IPNet: address, Label: "lo", Flags: unix.IFA_F_OPTIMISTIC | unix.IFA_F_DADFAILED | unix.IFA_F_PERMANENT, Scope: unix.RT_SCOPE_UNIVERSE},
},
{
&Addr{IPNet: address, Scope: unix.RT_SCOPE_NOWHERE},
&Addr{IPNet: address, Label: "lo", Flags: unix.IFA_F_PERMANENT, Scope: unix.RT_SCOPE_NOWHERE},
name: "lo_nullroute_perm", addr: &Addr{IPNet: address, Scope: unix.RT_SCOPE_NOWHERE},
expected: &Addr{IPNet: address, Label: "lo", Flags: unix.IFA_F_PERMANENT, Scope: unix.RT_SCOPE_NOWHERE},
},
{
&Addr{IPNet: address, Peer: peer},
&Addr{IPNet: address, Peer: peer, Label: "lo", Scope: unix.RT_SCOPE_UNIVERSE, Flags: unix.IFA_F_PERMANENT},
name: "lo_uni_perm_with_peer", addr: &Addr{IPNet: address, Peer: peer},
expected: &Addr{IPNet: address, Peer: peer, Label: "lo", Scope: unix.RT_SCOPE_UNIVERSE, Flags: unix.IFA_F_PERMANENT},
},
}

tearDown := setUpNetlinkTest(t)
defer tearDown()
for _, tt := range addrTests {
t.Run(tt.name, func(t *testing.T) {
tt.t = t

link, err := LinkByName("lo")
if err != nil {
t.Fatal(err)
}
tearDown := setUpNetlinkTest(t)
defer tearDown()

for _, tt := range addrTests {
if err = FunctionUndertest(link, tt.addr); err != nil {
t.Fatal(err)
}
link, err := LinkByName("lo")
if err != nil {
tt.Fatal(err)
}

addrs, err := AddrList(link, FAMILY_ALL)
if err != nil {
t.Fatal(err)
}
if err = FunctionUndertest(link, tt.addr); err != nil {
tt.Fatal(err)
}

if len(addrs) != 1 {
t.Fatal("Address not added properly")
}
addrs, err := AddrList(link, FAMILY_ALL)
if err != nil {
tt.Fatal(err)
}

if !addrs[0].Equal(*tt.expected) {
t.Fatalf("Address ip no set properly, got=%s, expected=%s", addrs[0], tt.expected)
}
if len(addrs) != 1 {
tt.Fatal("Address not added properly")
}

if addrs[0].Label != tt.expected.Label {
t.Fatalf("Address label not set properly, got=%s, expected=%s", addrs[0].Label, tt.expected.Label)
}
if !addrs[0].Equal(*tt.expected) {
tt.Fatalf("Address ip not set properly, got=%s, expected=%s", addrs[0], tt.expected)
}

if addrs[0].Flags != tt.expected.Flags {
t.Fatalf("Address flags not set properly, got=%d, expected=%d", addrs[0].Flags, tt.expected.Flags)
}
if addrs[0].Label != tt.expected.Label {
tt.Fatalf("Address label not set properly, got=%s, expected=%s", addrs[0].Label, tt.expected.Label)
}

if addrs[0].Scope != tt.expected.Scope {
t.Fatalf("Address scope not set properly, got=%d, expected=%d", addrs[0].Scope, tt.expected.Scope)
}
if addrs[0].Flags != tt.expected.Flags {
tt.Fatalf("Address flags not set properly, got=%d, expected=%d", addrs[0].Flags, tt.expected.Flags)
}

if ifindex := link.Attrs().Index; ifindex != addrs[0].LinkIndex {
t.Fatalf("Address ifindex not set properly, got=%d, expected=%d", addrs[0].LinkIndex, ifindex)
}
if addrs[0].Scope != tt.expected.Scope {
tt.Fatalf("Address scope not set properly, got=%d, expected=%d", addrs[0].Scope, tt.expected.Scope)
}

if tt.expected.Peer != nil {
if !addrs[0].PeerEqual(*tt.expected) {
t.Fatalf("Peer Address ip no set properly, got=%s, expected=%s", addrs[0].Peer, tt.expected.Peer)
if ifindex := link.Attrs().Index; ifindex != addrs[0].LinkIndex {
tt.Fatalf("Address ifindex not set properly, got=%d, expected=%d", addrs[0].LinkIndex, ifindex)
}
}

// Pass FAMILY_V4, we should get the same results as FAMILY_ALL
addrs, err = AddrList(link, FAMILY_V4)
if err != nil {
t.Fatal(err)
}
if len(addrs) != 1 {
t.Fatal("Address not added properly")
}
if tt.expected.Peer != nil {
if !addrs[0].PeerEqual(*tt.expected) {
tt.Fatalf("Peer Address ip not set properly, got=%s, expected=%s", addrs[0].Peer, tt.expected.Peer)
}
}

// Pass a wrong family number, we should get nil list
addrs, err = AddrList(link, 0x8)
if err != nil {
t.Fatal(err)
}
// Pass FAMILY_V4, we should get the same results as FAMILY_ALL
addrs, err = AddrList(link, FAMILY_V4)
if err != nil {
tt.Fatal(err)
}
if len(addrs) != 1 {
tt.Fatal("Address not added properly")
}

if len(addrs) != 0 {
t.Fatal("Address not expected")
}
// Pass a wrong family number, we should get nil list
addrs, err = AddrList(link, 0x8)
if err != nil {
tt.Fatal(err)
}

if err = AddrDel(link, tt.addr); err != nil {
t.Fatal(err)
}
if len(addrs) != 0 {
tt.Fatal("Address not expected")
}

addrs, err = AddrList(link, FAMILY_ALL)
if err != nil {
t.Fatal(err)
}
if err = AddrDel(link, tt.addr); err != nil {
tt.Fatal(err)
}

if len(addrs) != 0 {
t.Fatal("Address not removed properly")
}
addrs, err = AddrList(link, FAMILY_ALL)
if err != nil {
tt.Fatal(err)
}

if len(addrs) != 0 {
tt.Fatal("Address not removed properly")
}
})
}

}
Expand Down
Loading