Read iproute2 names from /usr/share, rt_tables.d and any whitespace, no panic on short lines

This commit is contained in:
2026-10-20 21:17:17 +00:00
parent 74f0a2f5ab
commit 925d266ab4
3 changed files with 225 additions and 32 deletions
+143
View File
@@ -1 +1,144 @@
package iproute2mapping
import (
"maps"
"os"
"path/filepath"
"strings"
"testing"
)
func TestGetMappingFromText(t *testing.T) {
tests := []struct {
name string
text string
wantId int
wantName string
wantErr bool
}{
{name: "tab", text: "254\tmain", wantId: 254, wantName: "main"},
{name: "space", text: "254 main", wantId: 254, wantName: "main"},
{name: "many spaces", text: "254 main", wantId: 254, wantName: "main"},
{name: "mixed whitespace", text: "254 \t main", wantId: 254, wantName: "main"},
{name: "trailing comment", text: "100 mytable # my table", wantId: 100, wantName: "mytable"},
{name: "hex", text: "0x10 hextable", wantId: 16, wantName: "hextable"},
{name: "leading zeros are decimal", text: "010 oct", wantId: 10, wantName: "oct"},
{name: "only a number", text: "254", wantErr: true},
{name: "only a name", text: "main", wantErr: true},
{name: "name before number", text: "main 254", wantErr: true},
{name: "negative", text: "-1 neg", wantErr: true},
{name: "too large", text: "99999999999 big", wantErr: true},
{name: "empty hex", text: "0x hex", wantErr: true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
id, name, err := getMappingFromText(tt.text)
if (err != nil) != tt.wantErr {
t.Fatalf("error = %v, wantErr %v", err, tt.wantErr)
}
if err == nil && (id != tt.wantId || name != tt.wantName) {
t.Errorf("got (%d, %q), want (%d, %q)", id, name, tt.wantId, tt.wantName)
}
})
}
}
func writeFile(t *testing.T, path, content string) {
t.Helper()
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(path, []byte(content), 0o644); err != nil {
t.Fatal(err)
}
}
func TestLoad(t *testing.T) {
usr, etc := t.TempDir(), t.TempDir()
writeFile(t, filepath.Join(usr, "rt_tables"),
"# comment\n\n255\tlocal\n254 main\n253 default\n0\tunspec\n")
writeFile(t, filepath.Join(usr, "rt_tables.d", "extra.conf"), "200 extra\n")
writeFile(t, filepath.Join(usr, "rt_tables.d", "ignored.txt"), "201 ignored\n")
// etc overrides usr
writeFile(t, filepath.Join(etc, "rt_tables"), " 100 custom \n254 mainoverride\n")
writeFile(t, filepath.Join(etc, "rt_tables.d", "more.conf"), "101 more\n")
m := load([]string{usr, etc}, "rt_tables")
if len(m.errs) != 0 {
t.Errorf("unexpected errors: %v", m.errs)
}
wantByName := map[string]int{
"local": 255, "main": 254, "default": 253, "unspec": 0,
"extra": 200, "custom": 100, "mainoverride": 254, "more": 101,
}
if !maps.Equal(m.byName, wantByName) {
t.Errorf("byName = %v, want %v", m.byName, wantByName)
}
if m.byId[254] != "mainoverride" || m.byId[100] != "custom" || m.byId[200] != "extra" {
t.Errorf("byId = %v", m.byId)
}
}
func TestLoadMissingRootIsFine(t *testing.T) {
usr := t.TempDir()
writeFile(t, filepath.Join(usr, "rt_protos"), "2 kernel\n")
m := load([]string{usr, filepath.Join(usr, "does-not-exist")}, "rt_protos")
if len(m.errs) != 0 {
t.Errorf("unexpected errors: %v", m.errs)
}
if m.byName["kernel"] != 2 {
t.Errorf("byName = %v", m.byName)
}
}
func TestLoadNothingFound(t *testing.T) {
m := load([]string{filepath.Join(t.TempDir(), "a"), filepath.Join(t.TempDir(), "b")}, "rt_tables")
if len(m.errs) != 1 || !strings.Contains(m.errs[0].Error(), "no mapping-file") {
t.Errorf("errs = %v", m.errs)
}
}
func TestLoadMalformedLinesAreSkipped(t *testing.T) {
dir := t.TempDir()
writeFile(t, filepath.Join(dir, "rt_tables"), "254\nfoo bar\n100 ok\n300\n")
m := load([]string{dir}, "rt_tables")
if len(m.errs) != 3 {
t.Errorf("want 3 errors, got %v", m.errs)
}
if !maps.Equal(m.byName, map[string]int{"ok": 100}) {
t.Errorf("byName = %v", m.byName)
}
}
func TestTryGetId(t *testing.T) {
origByName := ByName
t.Cleanup(func() { ByName = origByName })
ByName = map[int]map[string]int{TABLE: {"main": 254}}
tests := []struct {
name string
input string
want int
wantErr bool
}{
{name: "name", input: "main", want: 254},
{name: "number", input: "100", want: 100},
{name: "negative number", input: "-1", want: -1},
{name: "unknown name", input: "nope", wantErr: true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := TryGetId(TABLE, tt.input)
if (err != nil) != tt.wantErr {
t.Fatalf("error = %v, wantErr %v", err, tt.wantErr)
}
if err == nil && got != tt.want {
t.Errorf("got %d, want %d", got, tt.want)
}
})
}
}