//nolint:testpackage // white-box tests reach unexported state (approved 2026-07-07) package game import ( "strings" "testing" ) // TestGreeting pins both wordings of main.c's pre-initscr printf byte for // byte. The wizard one carries dnum, which main.c has just assigned to // seed, so it is the seed the player sees. Neither ends in a newline: C // printed, flushed, and handed the display to curses. func TestGreeting(t *testing.T) { t.Parallel() // The account name main.c copies into whoami when ROGUEOPTS does not // name the player itself. const account = "conan" cases := []struct { name string params Params want string }{ { name: "normal", params: Params{Name: account, Seed: 4242}, want: "Hello conan, just a moment while I dig the dungeon...", }, { name: "wizard names the dungeon", params: Params{Name: account, Seed: 4242, Wizard: true}, want: "Hello conan, welcome to dungeon #4242", }, { // parse_opts runs before the printf in main.c, and whoami // falls back to the account name only when ROGUEOPTS left it // empty, so the option is what the player is greeted by. name: "ROGUEOPTS name wins over the account name", params: Params{ Name: account, Seed: 7, RogueOpts: "name=Rodney", }, want: "Hello Rodney, just a moment while I dig the dungeon...", }, { name: "ROGUEOPTS without a name keeps the account name", params: Params{ Name: account, Seed: 7, RogueOpts: "terse,fruit=mango", }, want: "Hello conan, just a moment while I dig the dungeon...", }, { // ParseOpts reaches every option, not just name=, and the // inventory style is matched against a table (options.c // parse_opts, inv_t_name[]) that lives in the game data. A // greeting parsed on a game without those tables faulted on // this ROGUEOPTS before it could print anything at all. name: "ROGUEOPTS inventory style parses without a fault", params: Params{ Name: account, Seed: 7, RogueOpts: "inven=slow,name=Rodney", }, want: "Hello Rodney, just a moment while I dig the dungeon...", }, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { t.Parallel() got := Greeting(tc.params) if got != tc.want { t.Errorf("Greeting() = %q, want %q", got, tc.want) } if strings.HasSuffix(got, "\n") { t.Error("greeting ends in a newline; C's printf did not") } }) } }