mirror of
https://github.com/hashicorp/terraform.git
synced 2026-03-21 10:00:09 -04:00
171 lines
5.4 KiB
Go
171 lines
5.4 KiB
Go
// Copyright IBM Corp. 2014, 2026
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
package tfdiags
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
|
|
"github.com/google/go-cmp/cmp"
|
|
)
|
|
|
|
// AssertDiagnosticsMatch fails the test in progress (using t.Fatal) if the
|
|
// two sets of diagnostics don't match after being normalized using the
|
|
// "ForRPC" processing step, which eliminates the specific type information
|
|
// and HCL expression information of each diagnostic.
|
|
//
|
|
// AssertDiagnosticsMatch sorts the two sets of diagnostics in the usual way
|
|
// before comparing them, though diagnostics only have a partial order so that
|
|
// will not totally normalize the ordering of all diagnostics sets.
|
|
func AssertDiagnosticsMatch(t *testing.T, got, want Diagnostics) {
|
|
t.Helper()
|
|
|
|
if diff := assertDiagnosticsMatch(got, want); diff != "" {
|
|
t.Fatalf("unexpected diagnostics difference:\n%s", diff)
|
|
}
|
|
}
|
|
|
|
func assertDiagnosticsMatch(got, want Diagnostics) string {
|
|
got = got.ForRPC()
|
|
want = want.ForRPC()
|
|
|
|
got.Sort()
|
|
want.Sort()
|
|
|
|
return cmp.Diff(want, got, DiagnosticComparer)
|
|
}
|
|
|
|
// AssertDiagnosticMatch fails the test in progress (using t.Fatal) if the
|
|
// two (singular) diagnostics don't match after being normalized to an
|
|
// "RPC-friendly" diagnostic, which eliminates the specific type information
|
|
// and HCL expression information of each diagnostic.
|
|
func AssertDiagnosticMatch(t *testing.T, got, want Diagnostic) {
|
|
t.Helper()
|
|
|
|
if diff := assertDiagnosticMatch(want, got); diff != "" {
|
|
t.Fatalf("unexpected diagnostics difference:\n%s", diff)
|
|
}
|
|
}
|
|
|
|
func assertDiagnosticMatch(got, want Diagnostic) string {
|
|
|
|
got = makeRPCFriendlyDiag(got)
|
|
want = makeRPCFriendlyDiag(want)
|
|
|
|
return cmp.Diff(want, got, DiagnosticComparer)
|
|
}
|
|
|
|
// AssertDiagnosticsAndExtrasMatch fails the test in progress (using t.Fatal) if the
|
|
// two sets of diagnostics don't match after being normalized using the
|
|
// "ForRPC" processing step, AND also checks that the extra information on each
|
|
// diagnostic matches.
|
|
//
|
|
// This is similar to AssertDiagnosticsMatch but additionally verifies that the
|
|
// extra information (ExtraInfo) on diagnostics is equal, using DiagnosticExtrasEqual.
|
|
//
|
|
// AssertDiagnosticsAndExtrasMatch sorts the two sets of diagnostics in the usual way
|
|
// before comparing them, though diagnostics only have a partial order so that
|
|
// will not totally normalize the ordering of all diagnostics sets.
|
|
func AssertDiagnosticsAndExtrasMatch(t *testing.T, got, want Diagnostics) {
|
|
t.Helper()
|
|
|
|
if diff := assertDiagnosticsAndExtrasMatch(got, want); diff != "" {
|
|
t.Fatalf("unexpected diagnostics difference:\n%s", diff)
|
|
}
|
|
}
|
|
|
|
func assertDiagnosticsAndExtrasMatch(got, want Diagnostics) string {
|
|
// First check that the basic diagnostic info matches
|
|
if diff := assertDiagnosticsMatch(got, want); diff != "" {
|
|
return diff
|
|
}
|
|
|
|
// Now check extras - we need to compare the original diagnostics
|
|
// since ForRPC discards extra info
|
|
gotSorted := make(Diagnostics, len(got))
|
|
copy(gotSorted, got)
|
|
gotSorted.Sort()
|
|
|
|
wantSorted := make(Diagnostics, len(want))
|
|
copy(wantSorted, want)
|
|
wantSorted.Sort()
|
|
|
|
// Length should already match if assertDiagnosticsMatch passed
|
|
for i := range gotSorted {
|
|
if !DiagnosticExtrasEqual(gotSorted[i], wantSorted[i]) {
|
|
return fmt.Sprintf("diagnostic[%d] extras do not match:\n got extra: %#v\n want extra: %#v",
|
|
i, gotSorted[i].ExtraInfo(), wantSorted[i].ExtraInfo())
|
|
}
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
// AssertNoDiagnostics will fail a test if any diagnostics are present.
|
|
// If diagnostics are present, they will each be logged.
|
|
func AssertNoDiagnostics(t *testing.T, diags Diagnostics) {
|
|
t.Helper()
|
|
AssertDiagnosticCount(t, diags, 0)
|
|
}
|
|
|
|
// AssertDiagnosticCount will fail a test if the number of diagnostics present
|
|
// doesn't match the expected number.
|
|
// If an incorrect number of diagnostics are present, they will each be logged.
|
|
func AssertDiagnosticCount(t *testing.T, diags Diagnostics, want int) {
|
|
t.Helper()
|
|
if len(diags) != want {
|
|
t.Errorf("wrong number of diagnostics %d; want %d", len(diags), want)
|
|
for _, diag := range diags {
|
|
t.Logf("- [%s] %s: %s", diag.Severity(), diag.Description().Summary, diag.Description().Detail)
|
|
}
|
|
t.FailNow()
|
|
}
|
|
}
|
|
|
|
// tfdiags.AssertNoDiagnostics fails the test in progress (using t.FailNow) if the given
|
|
// diagnostics has any errors.
|
|
func AssertNoErrors(t *testing.T, diags Diagnostics) {
|
|
t.Helper()
|
|
if !diags.HasErrors() {
|
|
return
|
|
}
|
|
LogDiagnostics(t, diags)
|
|
t.FailNow()
|
|
}
|
|
|
|
// LogDiagnostics is a test helper that logs the given diagnostics to to the
|
|
// given testing.T using t.Log, in a way that is hopefully useful in debugging
|
|
// a test. It does not generate any errors or fail the test. See
|
|
// tfdiags.AssertNoDiagnostics and tfdiags.AssertNoErrors for more specific helpers that can
|
|
// also fail the test.
|
|
func LogDiagnostics(t *testing.T, diags Diagnostics) {
|
|
t.Helper()
|
|
for _, diag := range diags {
|
|
desc := diag.Description()
|
|
rng := diag.Source()
|
|
|
|
var severity string
|
|
switch diag.Severity() {
|
|
case Error:
|
|
severity = "ERROR"
|
|
case Warning:
|
|
severity = "WARN"
|
|
default:
|
|
severity = "???" // should never happen
|
|
}
|
|
|
|
if subj := rng.Subject; subj != nil {
|
|
if desc.Detail == "" {
|
|
t.Logf("[%s@%s] %s", severity, subj.StartString(), desc.Summary)
|
|
} else {
|
|
t.Logf("[%s@%s] %s: %s", severity, subj.StartString(), desc.Summary, desc.Detail)
|
|
}
|
|
} else {
|
|
if desc.Detail == "" {
|
|
t.Logf("[%s] %s", severity, desc.Summary)
|
|
} else {
|
|
t.Logf("[%s] %s: %s", severity, desc.Summary, desc.Detail)
|
|
}
|
|
}
|
|
}
|
|
}
|