package main import ( "strings" "testing" ) func TestChosenName(t *testing.T) { for _, ok := range []string{"wan", "lan", "dmz", "guest-wifi", "isp1", "a"} { if why := chosenName(ok); why != "" { t.Errorf("%q refused: %s", ok, why) } } for _, bad := range []string{"", "Wan", "1wan", "wan_1", "eth0", "eth", "wlan0", "enp2s0", "eno1", "ens3", "wlp1s0", "ppp0", "wg0", "veth12", "br0", "lo", "this-name-is-too-long"} { if chosenName(bad) == "" { t.Errorf("%q accepted", bad) } } } func renameSettings(t *testing.T) Settings { t.Helper() s, err := parseSettings([]byte(`{"router": { "wan": {"interface": "enp1s0", "ipv4": {"type": "pppoe", "pppoe": {"vlan": 7}}}, "lans": {"lan": {"interface": "enp2s0"}, "dmz": {"interface": "enp2s0", "vlan": 1002}, "iot": {"interface": "enp3s0", "vlan": 5}}}}`)) if err != nil { t.Fatal(err) } return s } func kernel(mac string) string { return map[string]string{"aa:aa": "enp1s0", "bb:bb": "enp2s0"}[mac] } func TestRenameCard(t *testing.T) { s := renameSettings(t) moved, err := s.rename([]Rename{{Dev: "enp2s0", MAC: "bb:bb", From: "enp2s0", To: "lan"}}, kernel) if err != nil || moved["enp2s0"] != "lan" { t.Fatalf("moved %v, err %v", moved, err) } if s.cardNames()["lan"] != "bb:bb" { t.Errorf("cards = %v", s.cardNames()) } f := s.form() for _, l := range f.LANs { if (l.Name == "lan" || l.Name == "dmz") && !strings.HasPrefix(l.Interface, "lan") { t.Errorf("LAN %s still on %s", l.Name, l.Interface) } if l.Name == "iot" && l.Interface != "enp3s0.5" { t.Errorf("an unrelated LAN moved: %s", l.Interface) } } // The card is now called lan; calling it wan renames the entry, not adds one. if _, err := s.rename([]Rename{{Dev: "lan", MAC: "bb:bb", From: "lan", To: "uplink2"}}, kernel); err != nil { t.Fatal(err) } if got := s.cardNames(); len(got) != 1 || got["uplink2"] != "bb:bb" { t.Errorf("cards = %v", got) } // Clearing the name goes back to the kernel's. if _, err := s.rename([]Rename{{Dev: "uplink2", MAC: "bb:bb", From: "uplink2", To: ""}}, kernel); err != nil { t.Fatal(err) } if _, ok := s["router"].(map[string]any)["interfaces"]; ok { t.Error("an empty interfaces table is kept") } if got := s.form().LANs[0].Interface; got != "enp2s0" && got != "enp2s0.1002" { t.Errorf("LAN back on %s", got) } } func TestRenameRefused(t *testing.T) { for name, row := range map[string]Rename{ "reserved": {Dev: "enp2s0", MAC: "bb:bb", From: "enp2s0", To: "eth5"}, "not there": {Dev: "enp9s0", From: "enp9s0", To: "lan"}, "unused": {Dev: "enp9s0.4", From: "", To: "x"}, } { s := renameSettings(t) if _, err := s.rename([]Rename{row}, kernel); err == nil { t.Errorf("%s accepted", name) } } s := renameSettings(t) _, err := s.rename([]Rename{ {Dev: "enp1s0", MAC: "aa:aa", From: "enp1s0", To: "wan"}, {Dev: "enp2s0", MAC: "bb:bb", From: "enp2s0", To: "wan"}, }, kernel) if err == nil { t.Error("the same name for two cards") } } func TestRenameVLAN(t *testing.T) { s := renameSettings(t) if _, err := s.rename([]Rename{ {Dev: "enp2s0.1002", From: "", To: "dmz"}, {Dev: "enp1s0.7", From: "", To: "isp"}, }, kernel); err != nil { t.Fatal(err) } if got := s.vlanNames(); got["enp2s0.1002"] != "dmz" || got["enp1s0.7"] != "isp" || len(got) != 2 { t.Errorf("vlan names = %v", got) } // The identifier in the form is unchanged. for _, l := range s.form().LANs { if l.Name == "dmz" && l.Interface != "enp2s0.1002" { t.Errorf("form identifier = %s", l.Interface) } } // Saving the network form keeps the names; dropping the VLAN drops its name. f := s.form() if _, err := s.apply(f, "/pw"); err != nil && !strings.Contains(err.Error(), "lans") { _ = err } if s.vlanNames()["enp2s0.1002"] != "dmz" { t.Error("the form dropped the VLAN's name") } for i, l := range f.LANs { if l.Name == "dmz" { f.LANs[i].Interface = "enp2s0" } } _, _ = s.apply(f, "/pw") if s.vlanNames()["enp2s0.1002"] != "" { t.Error("an untagged LAN keeps a VLAN device name") } // A name already used by a card is refused. s = renameSettings(t) if _, err := s.rename([]Rename{{Dev: "enp2s0", MAC: "bb:bb", From: "enp2s0", To: "dmz"}, {Dev: "enp2s0.1002", From: "", To: "dmz"}}, kernel); err == nil { t.Error("a card and a VLAN with the same name") } }