a76480d454
- unwrap the {"catalog": ...} envelope, still accepting a bare catalog
- report an environment-less response as a protocol mismatch, not an ENC problem
- make Resource.Line a pointer and Resource.Params() map absent onto empty
- render a missing manifest location as "(source unknown)"
- retry compile failures caused by the compiler's PuppetDB query
- stop retrying manifest errors the compiler returns as HTTP 500
- add a trimmed real-server response fixture and tests for each shape
175 lines
5.4 KiB
Go
175 lines
5.4 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())
|
|
}
|
|
}
|
|
|
|
func TestRenderTextMarksMissingSourceUnknown(t *testing.T) {
|
|
changes := []Change{
|
|
{DiffType: DiffAdded, Type: "Class", Title: "Settings", Severity: SeverityNormal},
|
|
{DiffType: DiffRemoved, Type: "File", Title: "/etc/motd", OldFile: "site.pp", OldLine: intPtr(9), Severity: SeverityCritical},
|
|
}
|
|
var buf bytes.Buffer
|
|
if err := RenderText(&buf, NewReport("host.example.net", "develop", "benvin_test", changes), RenderOptions{SourceFileLine: true}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
out := buf.String()
|
|
if !strings.Contains(out, "Class[Settings] added (source unknown)") {
|
|
t.Errorf("a resource with no manifest location must render as unknown:\n%s", out)
|
|
}
|
|
if strings.Contains(out, ":0)") {
|
|
t.Errorf("an absent line must never render as line 0:\n%s", out)
|
|
}
|
|
if !strings.Contains(out, "(site.pp:9)") {
|
|
t.Errorf("a real location must still render:\n%s", out)
|
|
}
|
|
}
|
|
|
|
func TestRenderJSONOmitsAbsentSource(t *testing.T) {
|
|
changes := []Change{{DiffType: DiffAdded, Type: "Class", Title: "Settings", Severity: SeverityNormal}}
|
|
var buf bytes.Buffer
|
|
if err := RenderJSON(&buf, NewReport("host.example.net", "develop", "benvin_test", changes)); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, key := range []string{"new_file", "new_line", "old_file", "old_line"} {
|
|
if strings.Contains(buf.String(), key) {
|
|
t.Errorf("%s must be omitted when the compiler gave no location:\n%s", key, buf.String())
|
|
}
|
|
}
|
|
}
|