Files
puppet-catalog-tools/internal/catalog/report_test.go
T
unkin-agent 53007a9257
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was canceled
ci/woodpecker/pr/test Pipeline was canceled
add repo scaffold and the catalog-diff CLI
Compile a host's catalog in a base and a test environment over the
puppetserver API, then diff the two.

- add catalog-diff CLI with cobra flags, config precedence and exit codes
- add puppetserver mTLS client for POST /puppet/v4/catalog
- add pdbmux fact client
- add catalog normalisation, diff engine and text/JSON renderers
- add Makefile, nfpm RPM packaging and woodpecker pipelines
2026-09-12 15:54:25 +10:00

141 lines
4.0 KiB
Go

package catalog
import (
"bytes"
"flag"
"os"
"path/filepath"
"strings"
"testing"
)
var update = flag.Bool("update", false, "rewrite the golden files")
func golden(t *testing.T, name string, got []byte) {
t.Helper()
path := filepath.Join("testdata", name)
if *update {
if err := os.WriteFile(path, got, 0o644); err != nil {
t.Fatalf("writing golden %s: %v", path, err)
}
return
}
want, err := os.ReadFile(path)
if err != nil {
t.Fatalf("reading golden %s: %v (run go test -update)", path, err)
}
if !bytes.Equal(want, got) {
t.Errorf("output does not match %s\n--- want ---\n%s\n--- got ---\n%s", path, want, got)
}
}
func testReport(t *testing.T) Report {
t.Helper()
return NewReport("host.example.net", "develop", "benvin_test", changeSet(t))
}
func TestRenderTextGolden(t *testing.T) {
var buf bytes.Buffer
if err := RenderText(&buf, testReport(t), RenderOptions{SourceFileLine: true}); err != nil {
t.Fatalf("RenderText: %v", err)
}
golden(t, "report.txt", buf.Bytes())
}
func TestRenderJSONGolden(t *testing.T) {
var buf bytes.Buffer
if err := RenderJSON(&buf, testReport(t)); err != nil {
t.Fatalf("RenderJSON: %v", err)
}
golden(t, "report.json", buf.Bytes())
}
func TestRenderTextNoChanges(t *testing.T) {
var buf bytes.Buffer
if err := RenderText(&buf, NewReport("host.example.net", "develop", "benvin_test", nil), RenderOptions{}); err != nil {
t.Fatalf("RenderText: %v", err)
}
if !strings.Contains(buf.String(), "No differences between environments.") {
t.Errorf("unexpected empty-diff output:\n%s", buf.String())
}
}
func TestRenderTextColourOnlyWhenAsked(t *testing.T) {
var plain, coloured bytes.Buffer
report := testReport(t)
if err := RenderText(&plain, report, RenderOptions{}); err != nil {
t.Fatal(err)
}
if err := RenderText(&coloured, report, RenderOptions{Colour: true}); err != nil {
t.Fatal(err)
}
if strings.Contains(plain.String(), "\033[") {
t.Error("plain output contains ANSI escapes")
}
if !strings.Contains(coloured.String(), "\033[") {
t.Error("coloured output contains no ANSI escapes")
}
}
func TestRenderTextGroupsCriticalFirst(t *testing.T) {
var buf bytes.Buffer
if err := RenderText(&buf, testReport(t), RenderOptions{SourceFileLine: true}); err != nil {
t.Fatal(err)
}
out := buf.String()
crit, other := strings.Index(out, "CRITICAL"), strings.Index(out, "OTHER")
if crit < 0 || other < 0 || crit > other {
t.Errorf("critical changes not listed first:\n%s", out)
}
}
func TestRenderJSONEmptyChangesIsArray(t *testing.T) {
var buf bytes.Buffer
if err := RenderJSON(&buf, NewReport("host.example.net", "develop", "benvin_test", nil)); err != nil {
t.Fatal(err)
}
if !strings.Contains(buf.String(), `"changes": []`) {
t.Errorf("empty change list must render as [], got:\n%s", buf.String())
}
}
func TestRenderTextCollapsesAddedResources(t *testing.T) {
report := testReport(t)
var collapsed bytes.Buffer
if err := RenderText(&collapsed, report, RenderOptions{}); err != nil {
t.Fatal(err)
}
if strings.Contains(collapsed.String(), "message: hi") {
t.Errorf("added resource expanded without --display-detail-add:\n%s", collapsed.String())
}
var detailed bytes.Buffer
if err := RenderText(&detailed, report, RenderOptions{DetailAdd: true}); err != nil {
t.Fatal(err)
}
if !strings.Contains(detailed.String(), "message: hi") {
t.Errorf("--display-detail-add did not expand the added resource:\n%s", detailed.String())
}
}
func TestRenderTextSourceFileLineIsOptional(t *testing.T) {
report := testReport(t)
var plain bytes.Buffer
if err := RenderText(&plain, report, RenderOptions{}); err != nil {
t.Fatal(err)
}
if strings.Contains(plain.String(), "site.pp") {
t.Errorf("file:line printed without --display-source-file-line:\n%s", plain.String())
}
var located bytes.Buffer
if err := RenderText(&located, report, RenderOptions{SourceFileLine: true}); err != nil {
t.Fatal(err)
}
if !strings.Contains(located.String(), "site.pp:19") {
t.Errorf("--display-source-file-line did not print the source:\n%s", located.String())
}
}