package bootstrap import ( "strings" "testing" ) func quietly(string) {} // A flag answers, and answers wrongly is refused naming what would have worked. func TestAFlagAnswersAndAWrongOneIsRefused(t *testing.T) { filter := Choice{Name: "packet-filter", Options: []string{"nftables", "ufw"}} got, err := decide(filter, "ufw", nil, quietly) if err != nil || got != "ufw" { t.Fatalf("an explicit answer was not taken: %q, %v", got, err) } _, err = decide(filter, "iptables", nil, quietly) if err == nil { t.Fatal("an answer nothing offers was accepted") } if !strings.Contains(err.Error(), "nftables") || !strings.Contains(err.Error(), "ufw") { t.Fatalf("the refusal does not say what would have worked: %v", err) } } // A lone option answers itself — and says so, because "it chose for me" and "there was nothing to // choose" read identically afterwards unless one of them speaks. func TestALoneOptionAnswersItselfAloud(t *testing.T) { var said []string got, err := decide(Choice{Name: "private-network", Options: []string{"wireguard"}}, "", nil, func(line string) { said = append(said, line) }) if err != nil || got != "wireguard" { t.Fatalf("the only option was not taken: %q, %v", got, err) } if len(said) == 0 || !strings.Contains(said[0], "only option") { t.Fatalf("choosing silently: %v", said) } } // A terminal is asked; an empty answer takes the default when there is one. func TestATerminalIsAskedAndEmptyTakesTheDefault(t *testing.T) { asked := 0 prompt := func(c Choice) (string, error) { asked++; return "", nil } got, err := decide(Choice{Name: "extras", Default: "none"}, "", prompt, quietly) if err != nil || got != "none" || asked != 1 { t.Fatalf("empty answer at a prompt did not take the default: %q asked=%d %v", got, asked, err) } } // **Unattended and required is a refusal, not a guess.** The lab and any machine without a // terminal must be answerable by flags — and a required choice with no flag has to stop the run // naming the flag, because a guessed packet filter is a machine somebody else configured. func TestUnattendedAndRequiredRefusesNamingTheFlag(t *testing.T) { _, err := decide(Choice{Name: "packet-filter", Options: []string{"nftables", "ufw"}}, "", nil, quietly) if err == nil { t.Fatal("a required choice was guessed for an unattended run") } if !strings.Contains(err.Error(), "--packet-filter") { t.Fatalf("the refusal does not name the flag that answers it: %v", err) } }