diff --git a/docs/doc-site/project/maintainers/ROADMAP.md b/docs/doc-site/project/maintainers/ROADMAP.md index 59eece511..55c50512a 100644 --- a/docs/doc-site/project/maintainers/ROADMAP.md +++ b/docs/doc-site/project/maintainers/ROADMAP.md @@ -56,8 +56,8 @@ timeline ### Adoption timeline at go-openapi -1. [x] Jan 2026: all go-openapi projects adopts the forked testify -2. [ ] Feb 2026: all go-openapi projects transition to generics +1. [x] Jan 2026: all go-openapi projects adopts the forked testify +2. [x] Feb 2026: all go-openapi projects transition to generics 3. [x] Mar 2026: go-swagger transitions to the forked testify ### What won't come anytime soon diff --git a/tools/difflib/difflib.go b/tools/difflib/difflib.go new file mode 100644 index 000000000..458695628 --- /dev/null +++ b/tools/difflib/difflib.go @@ -0,0 +1,49 @@ +// SPDX-FileCopyrightText: Copyright 2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +// Package difflib provides a unified diff for sequences of strings. +// +// It exposes the unified diff formatter used internally by [github.com/go-openapi/testify/v2]. +package difflib + +import ( + "io" + + idifflib "github.com/go-openapi/testify/v2/internal/difflib" +) + +// SplitLines splits a string on "\n" while preserving them. The output can be used +// as input for the [UnifiedDiff] structure. +func SplitLines(s string) []string { + return idifflib.SplitLines(s) +} + +// UnifiedDiff holds the unified diff parameters. +type UnifiedDiff = idifflib.UnifiedDiff + +// Options to fine-tune the rendering of the diff output. +type Options = idifflib.Options + +// Formatter is a formatting function like [fmt.Printf]. +type Formatter = idifflib.Formatter + +// Printer outputs a formatted string, e.g. to some underlying writer. +type Printer idifflib.Printer + +// FormatterBuilder is a function that builds a [Formatter] given a buffered [bufio.Writer]. +type FormatterBuilder = idifflib.FormatterBuilder + +// PrinterBuilder is a function that builds a [Printer] given a buffered [bufio.Writer]. +type PrinterBuilder = idifflib.PrinterBuilder + +// GetUnifiedDiffString is like [WriteUnifiedDiff] but returns the diff as a string instead of writing to an [io.Writer]. +func GetUnifiedDiffString(diff UnifiedDiff) (string, error) { + return idifflib.GetUnifiedDiffString(diff) +} + +// WriteUnifiedDiff writes the comparison between two sequences of lines. +// +// It generates the delta as a unified diff. +func WriteUnifiedDiff(writer io.Writer, diff UnifiedDiff) error { + return idifflib.WriteUnifiedDiff(writer, diff) +} diff --git a/tools/difflib/difflib_test.go b/tools/difflib/difflib_test.go new file mode 100644 index 000000000..4559c93cb --- /dev/null +++ b/tools/difflib/difflib_test.go @@ -0,0 +1,91 @@ +// SPDX-FileCopyrightText: Copyright 2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package difflib + +import ( + "bytes" + "strings" + "testing" +) + +func TestSplitLines(t *testing.T) { + lines := SplitLines("a\nb\nc\n") + if len(lines) != 4 { + t.Fatalf("expected 4 lines, got %d: %q", len(lines), lines) + } + if lines[0] != "a\n" || lines[1] != "b\n" || lines[2] != "c\n" { + t.Errorf("unexpected split result: %q", lines) + } +} + +func TestSplitLinesEmpty(t *testing.T) { + lines := SplitLines("") + if len(lines) != 1 { + t.Errorf("expected 1 line for empty string, got %d: %q", len(lines), lines) + } +} + +func TestGetUnifiedDiffString(t *testing.T) { + diff := UnifiedDiff{ + A: SplitLines("a\nb\nc\n"), + B: SplitLines("a\nB\nc\n"), + FromFile: "original", + ToFile: "modified", + Context: 1, + } + + result, err := GetUnifiedDiffString(diff) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if !strings.Contains(result, "---") { + t.Errorf("expected unified diff header, got: %s", result) + } + if !strings.Contains(result, "-b") { + t.Errorf("expected removed line '-b', got: %s", result) + } + if !strings.Contains(result, "+B") { + t.Errorf("expected added line '+B', got: %s", result) + } +} + +func TestGetUnifiedDiffStringIdentical(t *testing.T) { + lines := SplitLines("a\nb\nc\n") + diff := UnifiedDiff{ + A: lines, + B: lines, + } + + result, err := GetUnifiedDiffString(diff) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if result != "" { + t.Errorf("expected empty diff for identical inputs, got: %s", result) + } +} + +func TestWriteUnifiedDiff(t *testing.T) { + diff := UnifiedDiff{ + A: SplitLines("a\nb\nc\n"), + B: SplitLines("a\nB\nc\n"), + FromFile: "original", + ToFile: "modified", + Context: 1, + } + + var buf bytes.Buffer + err := WriteUnifiedDiff(&buf, diff) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + result := buf.String() + if !strings.Contains(result, "-b") { + t.Errorf("expected removed line '-b', got: %s", result) + } + if !strings.Contains(result, "+B") { + t.Errorf("expected added line '+B', got: %s", result) + } +} diff --git a/tools/spew/spew.go b/tools/spew/spew.go new file mode 100644 index 000000000..88e6ccfcb --- /dev/null +++ b/tools/spew/spew.go @@ -0,0 +1,50 @@ +// SPDX-FileCopyrightText: Copyright 2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +// Package spew implements a deep pretty printer for Go data structures to aid in +// debugging. +// +// It exposes the pretty-printer used internally by [github.com/go-openapi/testify/v2]. +// +// This a modernized version of the well-known [github.com/davecgh/go-spew]. +// +// The original software is Copyright: 2012-2016 Dave Collins, under an ISC license. +package spew + +import ( + "io" + + ispew "github.com/go-openapi/testify/v2/internal/spew" +) + +// ConfigState houses the configuration options used by spew to format and +// display values. +type ConfigState = ispew.ConfigState + +// Config is the active configuration of the top-level functions. +// +// This is an independent copy that does not affect the internal testify configuration. +// The configuration can be changed by modifying the contents of [spew.Config]. +var Config = ConfigState{ //nolint:gochecknoglobals + Indent: " ", + EnableTimeStringer: true, +} + +// Dump displays the passed parameters to standard out with newlines, customizable +// indentation, and additional debug information such as complete types and all +// pointer addresses used to indirect to the final value. +func Dump(a ...any) { + Config.Dump(a...) +} + +// Fdump formats and displays the passed arguments to [io.Writer] w. It formats +// exactly the same as [Dump]. +func Fdump(w io.Writer, a ...any) { + Config.Fdump(w, a...) +} + +// Sdump returns a string with the passed arguments formatted exactly the same +// as [Dump]. +func Sdump(a ...any) string { + return Config.Sdump(a...) +} diff --git a/tools/spew/spew_test.go b/tools/spew/spew_test.go new file mode 100644 index 000000000..cf8637109 --- /dev/null +++ b/tools/spew/spew_test.go @@ -0,0 +1,45 @@ +// SPDX-FileCopyrightText: Copyright 2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package spew + +import ( + "bytes" + "strings" + "testing" +) + +func TestDump(_ *testing.T) { + // Smoke test: Dump should not panic. + Dump("hello", 42, []int{1, 2, 3}) +} + +func TestFdump(t *testing.T) { + var buf bytes.Buffer + Fdump(&buf, "hello", 42) + + out := buf.String() + if !strings.Contains(out, "hello") { + t.Errorf("Fdump output should contain %q, got: %s", "hello", out) + } + if !strings.Contains(out, "42") { + t.Errorf("Fdump output should contain %q, got: %s", "42", out) + } +} + +func TestSdump(t *testing.T) { + out := Sdump("hello", 42) + + if !strings.Contains(out, "hello") { + t.Errorf("Sdump output should contain %q, got: %s", "hello", out) + } + if !strings.Contains(out, "42") { + t.Errorf("Sdump output should contain %q, got: %s", "42", out) + } +} + +func TestConfig(t *testing.T) { + if Config.Indent != " " { + t.Errorf("expected default Indent to be a single space, got %q", Config.Indent) + } +}