internal/names/names_test.go
Ref: Size: 3.3 KiB History
package names
import (
"os"
"path/filepath"
"strings"
"testing"
)
// TestIsNetworkName exercises the network-name grammar's boundaries directly
// against the implementation: the length limits, the leading/trailing-hyphen
// rule, the reserved "nat" word, and the lowercase-alnum-and-hyphen charset.
func TestIsNetworkName(t *testing.T) {
valid := []string{"lan", "lab-2", "a", strings.Repeat("x", 32)}
invalid := []string{"", "nat", "LAN", "l_n", "-lan", "lan-", strings.Repeat("x", 33), "br0.7"}
for _, s := range valid {
if !IsNetworkName(s) {
t.Errorf("IsNetworkName(%q) = false, want true", s)
}
}
for _, s := range invalid {
if IsNetworkName(s) {
t.Errorf("IsNetworkName(%q) = true, want false", s)
}
}
}
// TestDocsMatchNetworkNameGrammar is the docs-match tripwire for the network-
// name grammar. IsNetworkName is the one home for the rule (see its doc
// comment), but the agent's flag parser (internal/agent/run/cli.go) and
// docs/networking.md both restate it in prose for a human reader, in a form
// that cannot import the Go function. This test reads the quickstart prose
// and fails if its load-bearing fragments go missing, and separately proves
// the stated bounds still match IsNetworkName's behavior — so a change to
// the grammar cannot silently leave the docs describing the old rule.
func TestDocsMatchNetworkNameGrammar(t *testing.T) {
quickstart := readRepoFile(t, "docs/networking.md")
for _, want := range []string{
"1–32 of `[a-z0-9-]`",
"no leading",
"or trailing hyphen",
"`nat` is reserved",
} {
if !strings.Contains(quickstart, want) {
t.Errorf("docs/networking.md is missing %q — the network-name grammar prose drifted from IsNetworkName", want)
}
}
// Behavioral half: the bounds the prose claims (1-32 chars, no
// leading/trailing hyphen, "nat" reserved) must match what the code
// actually accepts. TestIsNetworkName already covers this in depth;
// these three checks pin the specific numbers the doc sentence quotes.
if !IsNetworkName(strings.Repeat("x", 32)) {
t.Error("IsNetworkName rejects a 32-char name — docs/networking.md's \"1–32\" would be wrong")
}
if IsNetworkName(strings.Repeat("x", 33)) {
t.Error("IsNetworkName accepts a 33-char name — docs/networking.md's \"1–32\" would be wrong")
}
if IsNetworkName("nat") {
t.Error("IsNetworkName accepts \"nat\" — docs/networking.md's \"nat is reserved\" would be wrong")
}
}
// TestOSServesNamedNetworks pins the one platform this fact is true for today
// and confirms it is a real comparison, not a stub that always answers true.
func TestOSServesNamedNetworks(t *testing.T) {
if !OSServesNamedNetworks("linux") {
t.Error("OSServesNamedNetworks(\"linux\") = false, want true")
}
for _, goos := range []string{"darwin", "windows", ""} {
if OSServesNamedNetworks(goos) {
t.Errorf("OSServesNamedNetworks(%q) = true, want false", goos)
}
}
}
// readRepoFile reads a repo-root-relative path, locating the root by walking
// up from this test file's own location so the result does not depend on the
// working directory the test is run from.
func readRepoFile(t *testing.T, rel string) string {
t.Helper()
b, err := os.ReadFile(filepath.Join("..", "..", rel))
if err != nil {
t.Fatalf("reading %s: %v", rel, err)
}
return string(b)
}