github.com/opentofu/opentofu@v1.7.1/internal/tfdiags/consolidate_warnings_test.go (about)

     1  // Copyright (c) The OpenTofu Authors
     2  // SPDX-License-Identifier: MPL-2.0
     3  // Copyright (c) 2023 HashiCorp, Inc.
     4  // SPDX-License-Identifier: MPL-2.0
     5  
     6  package tfdiags
     7  
     8  import (
     9  	"fmt"
    10  	"testing"
    11  
    12  	"github.com/google/go-cmp/cmp"
    13  	"github.com/hashicorp/hcl/v2"
    14  )
    15  
    16  func TestConsolidateWarnings(t *testing.T) {
    17  	var diags Diagnostics
    18  
    19  	for i := 0; i < 4; i++ {
    20  		diags = diags.Append(&hcl.Diagnostic{
    21  			Severity: hcl.DiagWarning,
    22  			Summary:  "Warning 1",
    23  			Detail:   fmt.Sprintf("This one has a subject %d", i),
    24  			Subject: &hcl.Range{
    25  				Filename: "foo.tf",
    26  				Start:    hcl.Pos{Line: 1, Column: 1, Byte: 0},
    27  				End:      hcl.Pos{Line: 1, Column: 1, Byte: 0},
    28  			},
    29  		})
    30  		diags = diags.Append(&hcl.Diagnostic{
    31  			Severity: hcl.DiagError,
    32  			Summary:  "Error 1",
    33  			Detail:   fmt.Sprintf("This one has a subject %d", i),
    34  			Subject: &hcl.Range{
    35  				Filename: "foo.tf",
    36  				Start:    hcl.Pos{Line: 1, Column: 1, Byte: 0},
    37  				End:      hcl.Pos{Line: 1, Column: 1, Byte: 0},
    38  			},
    39  		})
    40  		diags = diags.Append(Sourceless(
    41  			Warning,
    42  			"Warning 2",
    43  			fmt.Sprintf("This one is sourceless %d", i),
    44  		))
    45  		diags = diags.Append(SimpleWarning("Warning 3"))
    46  	}
    47  
    48  	diags = diags.Append(&hcl.Diagnostic{
    49  		Severity: hcl.DiagWarning,
    50  		Summary:  "Warning 4",
    51  		Detail:   "Only one of this one",
    52  		Subject: &hcl.Range{
    53  			Filename: "foo.tf",
    54  			Start:    hcl.Pos{Line: 1, Column: 1, Byte: 0},
    55  			End:      hcl.Pos{Line: 1, Column: 1, Byte: 0},
    56  		},
    57  	})
    58  
    59  	// Finally, we'll just add a set of diags that should not be consolidated.
    60  
    61  	diags = diags.Append(&hcl.Diagnostic{
    62  		Severity: hcl.DiagWarning,
    63  		Summary:  "do not consolidate",
    64  		Detail:   "warning 1, I should not have been consolidated",
    65  		Subject: &hcl.Range{
    66  			Filename: "bar.tf",
    67  			Start:    hcl.Pos{Line: 1, Column: 1, Byte: 0},
    68  			End:      hcl.Pos{Line: 1, Column: 1, Byte: 0},
    69  		},
    70  		Extra: doNotConsolidate(true),
    71  	})
    72  
    73  	diags = diags.Append(&hcl.Diagnostic{
    74  		Severity: hcl.DiagWarning,
    75  		Summary:  "do not consolidate",
    76  		Detail:   "warning 2, I should not have been consolidated",
    77  		Subject: &hcl.Range{
    78  			Filename: "bar.tf",
    79  			Start:    hcl.Pos{Line: 1, Column: 1, Byte: 0},
    80  			End:      hcl.Pos{Line: 1, Column: 1, Byte: 0},
    81  		},
    82  		Extra: doNotConsolidate(true),
    83  	})
    84  
    85  	diags = diags.Append(&hcl.Diagnostic{
    86  		Severity: hcl.DiagWarning,
    87  		Summary:  "do not consolidate",
    88  		Detail:   "warning 3, I should not have been consolidated",
    89  		Subject: &hcl.Range{
    90  			Filename: "bar.tf",
    91  			Start:    hcl.Pos{Line: 1, Column: 1, Byte: 0},
    92  			End:      hcl.Pos{Line: 1, Column: 1, Byte: 0},
    93  		},
    94  		Extra: doNotConsolidate(true),
    95  	})
    96  
    97  	// We're using ForRPC here to force the diagnostics to be of a consistent
    98  	// type that we can easily assert against below.
    99  	got := diags.ConsolidateWarnings(2).ForRPC()
   100  	want := Diagnostics{
   101  		// First set
   102  		&rpcFriendlyDiag{
   103  			Severity_: Warning,
   104  			Summary_:  "Warning 1",
   105  			Detail_:   "This one has a subject 0",
   106  			Subject_: &SourceRange{
   107  				Filename: "foo.tf",
   108  				Start:    SourcePos{Line: 1, Column: 1, Byte: 0},
   109  				End:      SourcePos{Line: 1, Column: 1, Byte: 0},
   110  			},
   111  		},
   112  		&rpcFriendlyDiag{
   113  			Severity_: Error,
   114  			Summary_:  "Error 1",
   115  			Detail_:   "This one has a subject 0",
   116  			Subject_: &SourceRange{
   117  				Filename: "foo.tf",
   118  				Start:    SourcePos{Line: 1, Column: 1, Byte: 0},
   119  				End:      SourcePos{Line: 1, Column: 1, Byte: 0},
   120  			},
   121  		},
   122  		&rpcFriendlyDiag{
   123  			Severity_: Warning,
   124  			Summary_:  "Warning 2",
   125  			Detail_:   "This one is sourceless 0",
   126  		},
   127  		&rpcFriendlyDiag{
   128  			Severity_: Warning,
   129  			Summary_:  "Warning 3",
   130  		},
   131  
   132  		// Second set (consolidation begins; note additional paragraph in Warning 1 detail)
   133  		&rpcFriendlyDiag{
   134  			Severity_: Warning,
   135  			Summary_:  "Warning 1",
   136  			Detail_:   "This one has a subject 1\n\n(and 2 more similar warnings elsewhere)",
   137  			Subject_: &SourceRange{
   138  				Filename: "foo.tf",
   139  				Start:    SourcePos{Line: 1, Column: 1, Byte: 0},
   140  				End:      SourcePos{Line: 1, Column: 1, Byte: 0},
   141  			},
   142  		},
   143  		&rpcFriendlyDiag{
   144  			Severity_: Error,
   145  			Summary_:  "Error 1",
   146  			Detail_:   "This one has a subject 1",
   147  			Subject_: &SourceRange{
   148  				Filename: "foo.tf",
   149  				Start:    SourcePos{Line: 1, Column: 1, Byte: 0},
   150  				End:      SourcePos{Line: 1, Column: 1, Byte: 0},
   151  			},
   152  		},
   153  		&rpcFriendlyDiag{
   154  			Severity_: Warning,
   155  			Summary_:  "Warning 2",
   156  			Detail_:   "This one is sourceless 1",
   157  		},
   158  		&rpcFriendlyDiag{
   159  			Severity_: Warning,
   160  			Summary_:  "Warning 3",
   161  		},
   162  
   163  		// Third set (no more Warning 1, because it's consolidated)
   164  		&rpcFriendlyDiag{
   165  			Severity_: Error,
   166  			Summary_:  "Error 1",
   167  			Detail_:   "This one has a subject 2",
   168  			Subject_: &SourceRange{
   169  				Filename: "foo.tf",
   170  				Start:    SourcePos{Line: 1, Column: 1, Byte: 0},
   171  				End:      SourcePos{Line: 1, Column: 1, Byte: 0},
   172  			},
   173  		},
   174  		&rpcFriendlyDiag{
   175  			Severity_: Warning,
   176  			Summary_:  "Warning 2",
   177  			Detail_:   "This one is sourceless 2",
   178  		},
   179  		&rpcFriendlyDiag{
   180  			Severity_: Warning,
   181  			Summary_:  "Warning 3",
   182  		},
   183  
   184  		// Fourth set (still no warning 1)
   185  		&rpcFriendlyDiag{
   186  			Severity_: Error,
   187  			Summary_:  "Error 1",
   188  			Detail_:   "This one has a subject 3",
   189  			Subject_: &SourceRange{
   190  				Filename: "foo.tf",
   191  				Start:    SourcePos{Line: 1, Column: 1, Byte: 0},
   192  				End:      SourcePos{Line: 1, Column: 1, Byte: 0},
   193  			},
   194  		},
   195  		&rpcFriendlyDiag{
   196  			Severity_: Warning,
   197  			Summary_:  "Warning 2",
   198  			Detail_:   "This one is sourceless 3",
   199  		},
   200  		&rpcFriendlyDiag{
   201  			Severity_: Warning,
   202  			Summary_:  "Warning 3",
   203  		},
   204  
   205  		// Special straggler warning gets to show up unconsolidated, because
   206  		// there is only one of it.
   207  		&rpcFriendlyDiag{
   208  			Severity_: Warning,
   209  			Summary_:  "Warning 4",
   210  			Detail_:   "Only one of this one",
   211  			Subject_: &SourceRange{
   212  				Filename: "foo.tf",
   213  				Start:    SourcePos{Line: 1, Column: 1, Byte: 0},
   214  				End:      SourcePos{Line: 1, Column: 1, Byte: 0},
   215  			},
   216  		},
   217  
   218  		// The final set of warnings should not have been consolidated because
   219  		// of our filter function.
   220  		&rpcFriendlyDiag{
   221  			Severity_: Warning,
   222  			Summary_:  "do not consolidate",
   223  			Detail_:   "warning 1, I should not have been consolidated",
   224  			Subject_: &SourceRange{
   225  				Filename: "bar.tf",
   226  				Start:    SourcePos{Line: 1, Column: 1, Byte: 0},
   227  				End:      SourcePos{Line: 1, Column: 1, Byte: 0},
   228  			},
   229  		},
   230  		&rpcFriendlyDiag{
   231  			Severity_: Warning,
   232  			Summary_:  "do not consolidate",
   233  			Detail_:   "warning 2, I should not have been consolidated",
   234  			Subject_: &SourceRange{
   235  				Filename: "bar.tf",
   236  				Start:    SourcePos{Line: 1, Column: 1, Byte: 0},
   237  				End:      SourcePos{Line: 1, Column: 1, Byte: 0},
   238  			},
   239  		},
   240  		&rpcFriendlyDiag{
   241  			Severity_: Warning,
   242  			Summary_:  "do not consolidate",
   243  			Detail_:   "warning 3, I should not have been consolidated",
   244  			Subject_: &SourceRange{
   245  				Filename: "bar.tf",
   246  				Start:    SourcePos{Line: 1, Column: 1, Byte: 0},
   247  				End:      SourcePos{Line: 1, Column: 1, Byte: 0},
   248  			},
   249  		},
   250  	}
   251  
   252  	if diff := cmp.Diff(want, got); diff != "" {
   253  		t.Errorf("wrong result\n%s", diff)
   254  	}
   255  }
   256  
   257  type doNotConsolidate bool
   258  
   259  var _ DiagnosticExtraDoNotConsolidate = doNotConsolidate(true)
   260  
   261  func (d doNotConsolidate) DoNotConsolidateDiagnostic() bool {
   262  	return bool(d)
   263  }