mirror of
https://github.com/hashicorp/terraform.git
synced 2026-03-21 10:00:09 -04:00
300 lines
8 KiB
Go
300 lines
8 KiB
Go
// Copyright IBM Corp. 2014, 2026
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
package tfdiags
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/hashicorp/hcl/v2"
|
|
)
|
|
|
|
// testDiagWithExtra is a test helper that creates a diagnostic with extra info
|
|
type testDiagWithExtra struct {
|
|
severity Severity
|
|
summary string
|
|
detail string
|
|
subject *SourceRange
|
|
extra interface{}
|
|
}
|
|
|
|
var _ Diagnostic = testDiagWithExtra{}
|
|
var _ ComparableDiagnostic = testDiagWithExtra{}
|
|
|
|
func (d testDiagWithExtra) Severity() Severity {
|
|
return d.severity
|
|
}
|
|
|
|
func (d testDiagWithExtra) Description() Description {
|
|
return Description{
|
|
Summary: d.summary,
|
|
Detail: d.detail,
|
|
}
|
|
}
|
|
|
|
func (d testDiagWithExtra) Source() Source {
|
|
return Source{
|
|
Subject: d.subject,
|
|
}
|
|
}
|
|
|
|
func (d testDiagWithExtra) FromExpr() *FromExpr {
|
|
return nil
|
|
}
|
|
|
|
func (d testDiagWithExtra) ExtraInfo() interface{} {
|
|
return d.extra
|
|
}
|
|
|
|
func (d testDiagWithExtra) Equals(other ComparableDiagnostic) bool {
|
|
od, ok := other.(testDiagWithExtra)
|
|
if !ok {
|
|
return false
|
|
}
|
|
return d.severity == od.severity && d.summary == od.summary && d.detail == od.detail
|
|
}
|
|
|
|
// These tests are to ensure that the normalisation of the diagnostics' concrete
|
|
// types doesn't impact how the diagnostics are compared.
|
|
//
|
|
// Full tests of the comparison logic in DiagnosticComparer and
|
|
// DiagnosticComparerWithSource are in compare_test.go
|
|
|
|
func Test_assertDiagnosticMatch_differentConcreteTypes(t *testing.T) {
|
|
baseError := hcl.Diagnostic{
|
|
Severity: hcl.DiagError,
|
|
Summary: "error",
|
|
Detail: "this is an error",
|
|
}
|
|
|
|
cases := map[string]struct {
|
|
diag1 Diagnostic
|
|
diag2 Diagnostic
|
|
expectDiff bool
|
|
}{
|
|
"diagnostics match but are different concrete types": {
|
|
expectDiff: false,
|
|
diag1: hclDiagnostic{&baseError},
|
|
diag2: makeRPCFriendlyDiag(hclDiagnostic{&baseError}),
|
|
},
|
|
"diagnostics don't match and are different concrete types": {
|
|
expectDiff: true,
|
|
diag1: hclDiagnostic{&baseError},
|
|
diag2: func() Diagnostic {
|
|
d := baseError
|
|
d.Severity = hcl.DiagWarning // Altered severity level
|
|
return makeRPCFriendlyDiag(hclDiagnostic{&d})
|
|
}(),
|
|
},
|
|
}
|
|
for tn, tc := range cases {
|
|
t.Run(tn, func(t *testing.T) {
|
|
// This should show no diff as, internally, the two diags are transformed into the same
|
|
// concrete type
|
|
diff := assertDiagnosticMatch(tc.diag1, tc.diag2)
|
|
|
|
if !tc.expectDiff && len(diff) > 0 {
|
|
t.Fatalf("unexpected diff:\n%s", diff)
|
|
}
|
|
if tc.expectDiff && len(diff) == 0 {
|
|
t.Fatalf("expected a diff but got none")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_assertDiagnosticsAndExtrasMatch(t *testing.T) {
|
|
baseError := hcl.Diagnostic{
|
|
Severity: hcl.DiagError,
|
|
Summary: "error",
|
|
Detail: "this is an error",
|
|
}
|
|
|
|
cases := map[string]struct {
|
|
diags1 Diagnostics
|
|
diags2 Diagnostics
|
|
expectDiff bool
|
|
}{
|
|
"both empty": {
|
|
expectDiff: false,
|
|
diags1: Diagnostics{},
|
|
diags2: Diagnostics{},
|
|
},
|
|
"diagnostics match with no extras": {
|
|
expectDiff: false,
|
|
diags1: Diagnostics{hclDiagnostic{&baseError}},
|
|
diags2: Diagnostics{makeRPCFriendlyDiag(hclDiagnostic{&baseError})},
|
|
},
|
|
"diagnostics match with same deprecation extra": {
|
|
expectDiff: false,
|
|
diags1: Diagnostics{testDiagWithExtra{
|
|
severity: Error,
|
|
summary: "error",
|
|
detail: "this is an error",
|
|
extra: &DeprecationOriginDiagnosticExtra{OriginDescription: "test origin"},
|
|
}},
|
|
diags2: Diagnostics{testDiagWithExtra{
|
|
severity: Error,
|
|
summary: "error",
|
|
detail: "this is an error",
|
|
extra: &DeprecationOriginDiagnosticExtra{OriginDescription: "test origin"},
|
|
}},
|
|
},
|
|
"diagnostics match but different deprecation extras": {
|
|
expectDiff: true,
|
|
diags1: Diagnostics{testDiagWithExtra{
|
|
severity: Error,
|
|
summary: "error",
|
|
detail: "this is an error",
|
|
extra: &DeprecationOriginDiagnosticExtra{OriginDescription: "origin 1"},
|
|
}},
|
|
diags2: Diagnostics{testDiagWithExtra{
|
|
severity: Error,
|
|
summary: "error",
|
|
detail: "this is an error",
|
|
extra: &DeprecationOriginDiagnosticExtra{OriginDescription: "origin 2"},
|
|
}},
|
|
},
|
|
"diagnostics match but one has extra and one doesn't": {
|
|
expectDiff: true,
|
|
diags1: Diagnostics{testDiagWithExtra{
|
|
severity: Error,
|
|
summary: "error",
|
|
detail: "this is an error",
|
|
extra: &DeprecationOriginDiagnosticExtra{OriginDescription: "test origin"},
|
|
}},
|
|
diags2: Diagnostics{testDiagWithExtra{
|
|
severity: Error,
|
|
summary: "error",
|
|
detail: "this is an error",
|
|
extra: nil,
|
|
}},
|
|
},
|
|
"diagnostics don't match - fails on base comparison": {
|
|
expectDiff: true,
|
|
diags1: Diagnostics{hclDiagnostic{&baseError}},
|
|
diags2: func() Diagnostics {
|
|
d := baseError
|
|
d.Severity = hcl.DiagWarning
|
|
return Diagnostics{hclDiagnostic{&d}}
|
|
}(),
|
|
},
|
|
"multiple diagnostics with matching extras": {
|
|
expectDiff: false,
|
|
diags1: Diagnostics{
|
|
testDiagWithExtra{
|
|
severity: Warning,
|
|
summary: "warning 1",
|
|
detail: "detail 1",
|
|
extra: &DeprecationOriginDiagnosticExtra{OriginDescription: "origin 1"},
|
|
},
|
|
testDiagWithExtra{
|
|
severity: Error,
|
|
summary: "error 1",
|
|
detail: "detail 2",
|
|
extra: &DeprecationOriginDiagnosticExtra{OriginDescription: "origin 2"},
|
|
},
|
|
},
|
|
diags2: Diagnostics{
|
|
testDiagWithExtra{
|
|
severity: Warning,
|
|
summary: "warning 1",
|
|
detail: "detail 1",
|
|
extra: &DeprecationOriginDiagnosticExtra{OriginDescription: "origin 1"},
|
|
},
|
|
testDiagWithExtra{
|
|
severity: Error,
|
|
summary: "error 1",
|
|
detail: "detail 2",
|
|
extra: &DeprecationOriginDiagnosticExtra{OriginDescription: "origin 2"},
|
|
},
|
|
},
|
|
},
|
|
"multiple diagnostics with one mismatched extra": {
|
|
expectDiff: true,
|
|
diags1: Diagnostics{
|
|
testDiagWithExtra{
|
|
severity: Warning,
|
|
summary: "warning 1",
|
|
detail: "detail 1",
|
|
extra: &DeprecationOriginDiagnosticExtra{OriginDescription: "origin 1"},
|
|
},
|
|
testDiagWithExtra{
|
|
severity: Error,
|
|
summary: "error 1",
|
|
detail: "detail 2",
|
|
extra: &DeprecationOriginDiagnosticExtra{OriginDescription: "origin 2"},
|
|
},
|
|
},
|
|
diags2: Diagnostics{
|
|
testDiagWithExtra{
|
|
severity: Warning,
|
|
summary: "warning 1",
|
|
detail: "detail 1",
|
|
extra: &DeprecationOriginDiagnosticExtra{OriginDescription: "origin 1"},
|
|
},
|
|
testDiagWithExtra{
|
|
severity: Error,
|
|
summary: "error 1",
|
|
detail: "detail 2",
|
|
extra: &DeprecationOriginDiagnosticExtra{OriginDescription: "different origin"},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
for tn, tc := range cases {
|
|
t.Run(tn, func(t *testing.T) {
|
|
diff := assertDiagnosticsAndExtrasMatch(tc.diags1, tc.diags2)
|
|
|
|
if !tc.expectDiff && len(diff) > 0 {
|
|
t.Fatalf("unexpected diff:\n%s", diff)
|
|
}
|
|
if tc.expectDiff && len(diff) == 0 {
|
|
t.Fatalf("expected a diff but got none")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_assertDiagnosticsMatch_differentConcreteTypes(t *testing.T) {
|
|
baseError := hcl.Diagnostic{
|
|
Severity: hcl.DiagError,
|
|
Summary: "error",
|
|
Detail: "this is an error",
|
|
}
|
|
|
|
cases := map[string]struct {
|
|
diags1 Diagnostics
|
|
diags2 Diagnostics
|
|
expectDiff bool
|
|
}{
|
|
"diagnostics match but are different concrete types": {
|
|
expectDiff: false,
|
|
diags1: Diagnostics{hclDiagnostic{&baseError}},
|
|
diags2: Diagnostics{makeRPCFriendlyDiag(hclDiagnostic{&baseError})},
|
|
},
|
|
"diagnostics don't match and are different concrete types": {
|
|
expectDiff: true,
|
|
diags1: Diagnostics{hclDiagnostic{&baseError}},
|
|
diags2: func() Diagnostics {
|
|
d := baseError
|
|
d.Severity = hcl.DiagWarning // Altered severity level
|
|
return Diagnostics{makeRPCFriendlyDiag(hclDiagnostic{&d})}
|
|
}(),
|
|
},
|
|
}
|
|
for tn, tc := range cases {
|
|
t.Run(tn, func(t *testing.T) {
|
|
// This should show no diff as, internally, the two diags are transformed into the same
|
|
// concrete type
|
|
diff := assertDiagnosticsMatch(tc.diags1, tc.diags2)
|
|
|
|
if !tc.expectDiff && len(diff) > 0 {
|
|
t.Fatalf("unexpected diff:\n%s", diff)
|
|
}
|
|
if tc.expectDiff && len(diff) == 0 {
|
|
t.Fatalf("expected a diff but got none")
|
|
}
|
|
})
|
|
}
|
|
}
|