From 209b0ff3644331036aaf676a61450d1d3f88a945 Mon Sep 17 00:00:00 2001 From: user Date: Fri, 4 Sep 2026 05:34:33 +0000 Subject: [PATCH] test(ircserver): cover VERSION/ADMIN/TIME under the default empty SERVER_NAME Both wire test environments hardcoded ServerName: "test.irc", so no test exercised the shipped default and the empty server-name parameter went unnoticed for five rework rounds. Parameterize the env's server name and add a wire test that runs with it empty, asserting the numerics name "neoirc" and contain no empty parameter. Verified to fail against the pre-fix handlers. --- internal/ircserver/integration_test.go | 77 ++++++++++++++++++++++++++ internal/ircserver/server_test.go | 16 +++++- 2 files changed, 92 insertions(+), 1 deletion(-) diff --git a/internal/ircserver/integration_test.go b/internal/ircserver/integration_test.go index 9cef876..f7b35a2 100644 --- a/internal/ircserver/integration_test.go +++ b/internal/ircserver/integration_test.go @@ -1241,3 +1241,80 @@ func TestIntegrationThirdClientObserver(t *testing.T) { "carol receives trio message", ) } + +// assertNoEmptyParam fails if any line contains a doubled +// space, which is what FormatMessage emits for an empty +// non-trailing parameter. A numeric whose server-name +// parameter came out empty is malformed on the wire even +// though it still contains the numeric code, so the other +// assertions in this file would not catch it. +func assertNoEmptyParam( + t *testing.T, + lines []string, + context string, +) { + t.Helper() + + for _, line := range lines { + if strings.Contains(line, " ") { + t.Errorf( + "%s: empty parameter in wire line: %q", + context, line, + ) + } + } +} + +// TestIntegrationDefaultServerNameFallback runs the wire +// server with SERVER_NAME unset, which is the shipped +// default from config.go, and verifies that VERSION, ADMIN +// and TIME fall back to "neoirc" exactly as the HTTP path +// does instead of emitting an empty server-name parameter. +// +// Every other wire test hardcodes ServerName: "test.irc", +// so none of them exercise the default configuration. +func TestIntegrationDefaultServerNameFallback(t *testing.T) { + t.Parallel() + + env := newTestEnvWithServerName(t, "") + + alice := env.dial(t) + alice.register("alice") + + alice.send("VERSION") + + versionReply := alice.readUntil(func(l string) bool { + return strings.Contains(l, " 351 ") + }) + assertNoEmptyParam(t, versionReply, "VERSION") + assertContains( + t, versionReply, "neoirc", + "VERSION falls back to default server name", + ) + + alice.send("ADMIN") + + adminReply := alice.readUntil(func(l string) bool { + return strings.Contains(l, " 259 ") + }) + assertNoEmptyParam(t, adminReply, "ADMIN") + assertContains( + t, adminReply, " 256 alice neoirc ", + "RPL_ADMINME names the default server", + ) + assertContains( + t, adminReply, "admin@neoirc", + "RPL_ADMINEMAIL is a well-formed address", + ) + + alice.send("TIME") + + timeReply := alice.readUntil(func(l string) bool { + return strings.Contains(l, " 391 ") + }) + assertNoEmptyParam(t, timeReply, "TIME") + assertContains( + t, timeReply, " 391 alice neoirc ", + "RPL_TIME names the default server", + ) +} diff --git a/internal/ircserver/server_test.go b/internal/ircserver/server_test.go index 9797656..6f8c738 100644 --- a/internal/ircserver/server_test.go +++ b/internal/ircserver/server_test.go @@ -38,6 +38,20 @@ type testEnv struct { func newTestEnv(t *testing.T) *testEnv { t.Helper() + return newTestEnvWithServerName(t, "test.irc") +} + +// newTestEnvWithServerName creates a test environment with +// an explicit SERVER_NAME. Passing "" exercises the shipped +// default from config.go, under which the server must fall +// back to "neoirc" rather than emitting an empty +// server-name parameter. +func newTestEnvWithServerName( + t *testing.T, + serverName string, +) *testEnv { + t.Helper() + dsn := fmt.Sprintf( "file:%s?mode=memory&cache=shared&_journal_mode=WAL", t.Name(), @@ -67,7 +81,7 @@ func newTestEnv(t *testing.T) *testEnv { brk := broker.New() cfg := &config.Config{ //nolint:exhaustruct - ServerName: "test.irc", + ServerName: serverName, MOTD: "Welcome to test IRC", }