Fix every finding surfaced by the canonical .golangci.yml with golangci-lint v2.12.2 (refs #61), behavior-preserving throughout: - err113: dynamic errors replaced with package-level sentinels and %w wrapping; direct comparisons converted to errors.Is - goprintffuncname: printf-style helpers renamed with an f suffix (ui.Writer message methods, cli.ReportErrorf, database.Fatalf, vaultik stdoutf) and all call sites updated - revive: stuttering type names renamed (blob.Handler, blob.WithReader, blob.ChunkPosition, storage.URL, storage.Info), doc comments added, unused parameters blanked, package comments added - contextcheck/noctx: ctx threaded through blob.Packer (AddChunk/Flush/FinalizeBlob/PackChunks) and scanner call sites; context-aware exec and sql variants used - funlen/cyclop/gocognit/nestif/dupl: oversized or duplicated functions split into focused helpers across production and test code - paralleltest/tparallel/thelper/usetesting/testpackage: tests parallelized where safe (global log.Initialize kept in the serial phase), helpers marked, t.TempDir adopted, external test packages where only exported API is used - gosec: integer conversions clamped or justified, header timeouts added, remaining findings suppressed with per-site justifications - mnd/goconst/lll/wsl_v5/nlreturn/noinlineerr/errcheck and other mechanical findings fixed directly Remove the deprecated log.LogOptions alias (callers migrated to log.Options). make check is green.
177 lines
4.3 KiB
Go
177 lines
4.3 KiB
Go
package ui_test
|
|
|
|
import (
|
|
"bytes"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"sneak.berlin/go/vaultik/internal/ui"
|
|
)
|
|
|
|
func newTestWriter(color bool) (*ui.Writer, *bytes.Buffer) {
|
|
buf := &bytes.Buffer{}
|
|
|
|
return ui.NewWithColor(buf, color), buf
|
|
}
|
|
|
|
func TestMessageMethodsPlain(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
method string
|
|
fn func(*ui.Writer)
|
|
want string
|
|
}{
|
|
{"Begin", func(w *ui.Writer) { w.Beginf("starting %s", "thing") },
|
|
"》 starting thing\n"},
|
|
{"Complete", func(w *ui.Writer) { w.Completef("done %s", "thing") },
|
|
"》 done thing\n"},
|
|
{"Info", func(w *ui.Writer) { w.Infof("status") }, "》 status\n"},
|
|
{"Notice", func(w *ui.Writer) { w.Noticef("note") }, "》 note\n"},
|
|
{"Warning", func(w *ui.Writer) { w.Warningf("oops") }, "⚠️ Warning: oops\n"},
|
|
{"Error", func(w *ui.Writer) { w.Errorf("boom") }, "🛑 ERROR: boom\n"},
|
|
{"Progress", func(w *ui.Writer) { w.Progressf("p") }, " 》 p\n"},
|
|
{"Detail", func(w *ui.Writer) { w.Detailf("d") }, " 》 d\n"},
|
|
{"Banner", func(w *ui.Writer) { w.Bannerf("hello") }, "hello\n"}, // plain, no bold
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.method, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
w, buf := newTestWriter(false)
|
|
tt.fn(w)
|
|
|
|
if got := buf.String(); got != tt.want {
|
|
t.Errorf("got %q, want %q", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestWarningErrorCounters(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
w, _ := newTestWriter(false)
|
|
if w.WarningCount() != 0 || w.ErrorCount() != 0 {
|
|
t.Fatalf("expected fresh writer to have zero counts")
|
|
}
|
|
|
|
w.Infof("normal")
|
|
w.Warningf("first warn")
|
|
w.Warningf("second warn")
|
|
w.Errorf("only error")
|
|
|
|
if got, want := w.WarningCount(), 2; got != want {
|
|
t.Errorf("WarningCount: got %d, want %d", got, want)
|
|
}
|
|
|
|
if got, want := w.ErrorCount(), 1; got != want {
|
|
t.Errorf("ErrorCount: got %d, want %d", got, want)
|
|
}
|
|
}
|
|
|
|
func TestColorOutputContainsANSI(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
w, buf := newTestWriter(true)
|
|
w.Errorf("boom")
|
|
|
|
out := buf.String()
|
|
if !strings.Contains(out, "\033[") {
|
|
t.Errorf("expected ANSI escapes in color output, got %q", out)
|
|
}
|
|
|
|
if !strings.Contains(out, "ERROR: ") {
|
|
t.Errorf("expected 'ERROR: ' text in output, got %q", out)
|
|
}
|
|
}
|
|
|
|
func TestBannerBoldWhenColor(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
w, buf := newTestWriter(true)
|
|
w.Bannerf("hello")
|
|
|
|
out := buf.String()
|
|
if !strings.Contains(out, "\033[1m") {
|
|
t.Errorf("expected bold ANSI escape in colored Banner output, got %q", out)
|
|
}
|
|
}
|
|
|
|
func TestValueFormattersPlain(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
w, _ := newTestWriter(false)
|
|
|
|
if got := w.Hex("0123456789abcdef0123"); got != "0123456789ab..." {
|
|
t.Errorf("Hex long: got %q", got)
|
|
}
|
|
|
|
if got := w.Hex("short"); got != "short" {
|
|
t.Errorf("Hex short: got %q", got)
|
|
}
|
|
|
|
if got := w.Size(1024); got != "1.0 kB" {
|
|
t.Errorf("Size: got %q", got)
|
|
}
|
|
|
|
if got := w.Duration(90 * time.Second); got != "1m30s" {
|
|
t.Errorf("Duration: got %q", got)
|
|
}
|
|
|
|
if got := w.Count(12345); got != "12,345" {
|
|
t.Errorf("Count: got %q", got)
|
|
}
|
|
|
|
if got := w.Percent(12.34); got != "12.3%" {
|
|
t.Errorf("Percent: got %q", got)
|
|
}
|
|
|
|
// Speed: input is bytes/sec, output is bits/sec.
|
|
if got := w.Speed(0); got != "N/A" {
|
|
t.Errorf("Speed(0): got %q, want N/A", got)
|
|
}
|
|
|
|
if got := w.Speed(125_000_000); got != "1.0 Gbit/sec" { // 1 Gbit/s = 125 MB/s
|
|
t.Errorf("Speed(125e6): got %q", got)
|
|
}
|
|
|
|
if got := w.Speed(125_000); got != "1 Mbit/sec" {
|
|
t.Errorf("Speed(125e3): got %q", got)
|
|
}
|
|
|
|
// Time format: today → HH:MM:SS, other day → YYYY-MM-DD HH:MM:SS.
|
|
// These construct local-zone times on purpose: Writer.Time displays
|
|
// in the process's local zone.
|
|
now := time.Now()
|
|
|
|
today := time.Date(now.Year(), now.Month(), now.Day(),
|
|
14, 30, 45, 0, time.Local) //nolint:gosmopolitan // local display
|
|
if got := w.Time(today); got != "14:30:45" {
|
|
t.Errorf("Time today: got %q, want 14:30:45", got)
|
|
}
|
|
|
|
other := time.Date(2030, 1, 2, 3, 4, 5, 0,
|
|
time.Local) //nolint:gosmopolitan // local display
|
|
if got := w.Time(other); got != "2030-01-02 03:04:05" {
|
|
t.Errorf("Time other day: got %q", got)
|
|
}
|
|
}
|
|
|
|
func TestValueFormattersColored(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
w, _ := newTestWriter(true)
|
|
|
|
hex := w.Hex("0123456789abcdef0123")
|
|
if !strings.Contains(hex, "\033[") {
|
|
t.Errorf("expected ANSI in colored Hex output, got %q", hex)
|
|
}
|
|
|
|
if !strings.Contains(hex, "0123456789ab") {
|
|
t.Errorf("expected hex content in output, got %q", hex)
|
|
}
|
|
}
|