package main import ( "strings" "testing" "time" ) func TestParseFields(t *testing.T) { m, err := parseFields([]string{"a=1", "b=x=y"}) if err != nil { t.Fatal(err) } if m["a"] != "1" || m["b"] != "x=y" { t.Errorf("m = %v", m) } for _, bad := range []string{"noequals", "=v"} { if _, err := parseFields([]string{bad}); err == nil { t.Errorf("%q: expected error", bad) } } if m, _ := parseFields(nil); m != nil { t.Error("nil input should give nil map") } } func TestCommonFlagsFilterDefaults(t *testing.T) { cf := &commonFlags{since: "1h", format: "text"} now := time.Date(2026, 8, 23, 12, 0, 0, 0, time.UTC) f, err := cf.filter(now) if err != nil { t.Fatal(err) } if !f.Since.Equal(now.Add(-time.Hour)) { t.Errorf("since = %s", f.Since) } if !f.Until.Equal(now) { t.Errorf("until = %s", f.Until) } } func TestGrepGuardBlocksWideUnfilteredSearch(t *testing.T) { cmd := newGrepCmd("chgrep") cmd.SetArgs([]string{"--since", "24h", "needle"}) var out strings.Builder cmd.SetOut(&out) cmd.SetErr(&out) err := cmd.Execute() if err == nil || !strings.Contains(err.Error(), "--force") { t.Fatalf("expected guard error mentioning --force, got %v", err) } } func TestGrepGuardAllowsFilteredSearch(t *testing.T) { // A namespace filter disables the guard; the query then fails on the // unreachable server rather than the guard, proving the guard passed. t.Setenv("CH_URL", "http://127.0.0.1:1") cmd := newGrepCmd("chgrep") cmd.SetArgs([]string{"--since", "24h", "--namespace", "logging", "needle"}) var out strings.Builder cmd.SetOut(&out) cmd.SetErr(&out) err := cmd.Execute() if err == nil { t.Fatal("expected connection error") } if strings.Contains(err.Error(), "--force") { t.Fatalf("guard should not trigger with a namespace filter: %v", err) } } func TestGrepGuardAllowsShortWindow(t *testing.T) { t.Setenv("CH_URL", "http://127.0.0.1:1") cmd := newGrepCmd("chgrep") cmd.SetArgs([]string{"--since", "1h", "needle"}) err := cmd.Execute() if err == nil { t.Fatal("expected connection error") } if strings.Contains(err.Error(), "--force") { t.Fatalf("guard should not trigger for 1h window: %v", err) } } func TestEntrypointDispatch(t *testing.T) { root := newRootCmd() names := map[string]bool{} for _, c := range root.Commands() { names[c.Name()] = true } for _, want := range []string{"cat", "tail", "grep"} { if !names[want] { t.Errorf("chlog missing subcommand %q", want) } } }