github.com/gruntwork-io/terraform@v0.11.12-beta1/tfdiags/diagnostics_test.go (about)

     1  package tfdiags
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"reflect"
     7  	"strings"
     8  	"testing"
     9  
    10  	"github.com/hashicorp/go-multierror"
    11  
    12  	"github.com/davecgh/go-spew/spew"
    13  	"github.com/hashicorp/hcl2/hcl"
    14  )
    15  
    16  func TestBuild(t *testing.T) {
    17  	type diagFlat struct {
    18  		Severity Severity
    19  		Summary  string
    20  		Detail   string
    21  		Subject  *SourceRange
    22  		Context  *SourceRange
    23  	}
    24  
    25  	tests := map[string]struct {
    26  		Cons func(Diagnostics) Diagnostics
    27  		Want []diagFlat
    28  	}{
    29  		"nil": {
    30  			func(diags Diagnostics) Diagnostics {
    31  				return diags
    32  			},
    33  			nil,
    34  		},
    35  		"fmt.Errorf": {
    36  			func(diags Diagnostics) Diagnostics {
    37  				diags = diags.Append(fmt.Errorf("oh no bad"))
    38  				return diags
    39  			},
    40  			[]diagFlat{
    41  				{
    42  					Severity: Error,
    43  					Summary:  "oh no bad",
    44  				},
    45  			},
    46  		},
    47  		"errors.New": {
    48  			func(diags Diagnostics) Diagnostics {
    49  				diags = diags.Append(errors.New("oh no bad"))
    50  				return diags
    51  			},
    52  			[]diagFlat{
    53  				{
    54  					Severity: Error,
    55  					Summary:  "oh no bad",
    56  				},
    57  			},
    58  		},
    59  		"hcl.Diagnostic": {
    60  			func(diags Diagnostics) Diagnostics {
    61  				diags = diags.Append(&hcl.Diagnostic{
    62  					Severity: hcl.DiagError,
    63  					Summary:  "Something bad happened",
    64  					Detail:   "It was really, really bad.",
    65  					Subject: &hcl.Range{
    66  						Filename: "foo.tf",
    67  						Start:    hcl.Pos{Line: 1, Column: 10, Byte: 9},
    68  						End:      hcl.Pos{Line: 2, Column: 3, Byte: 25},
    69  					},
    70  					Context: &hcl.Range{
    71  						Filename: "foo.tf",
    72  						Start:    hcl.Pos{Line: 1, Column: 1, Byte: 0},
    73  						End:      hcl.Pos{Line: 3, Column: 1, Byte: 30},
    74  					},
    75  				})
    76  				return diags
    77  			},
    78  			[]diagFlat{
    79  				{
    80  					Severity: Error,
    81  					Summary:  "Something bad happened",
    82  					Detail:   "It was really, really bad.",
    83  					Subject: &SourceRange{
    84  						Filename: "foo.tf",
    85  						Start:    SourcePos{Line: 1, Column: 10, Byte: 9},
    86  						End:      SourcePos{Line: 2, Column: 3, Byte: 25},
    87  					},
    88  					Context: &SourceRange{
    89  						Filename: "foo.tf",
    90  						Start:    SourcePos{Line: 1, Column: 1, Byte: 0},
    91  						End:      SourcePos{Line: 3, Column: 1, Byte: 30},
    92  					},
    93  				},
    94  			},
    95  		},
    96  		"hcl.Diagnostics": {
    97  			func(diags Diagnostics) Diagnostics {
    98  				diags = diags.Append(hcl.Diagnostics{
    99  					{
   100  						Severity: hcl.DiagError,
   101  						Summary:  "Something bad happened",
   102  						Detail:   "It was really, really bad.",
   103  					},
   104  					{
   105  						Severity: hcl.DiagWarning,
   106  						Summary:  "Also, somebody sneezed",
   107  						Detail:   "How rude!",
   108  					},
   109  				})
   110  				return diags
   111  			},
   112  			[]diagFlat{
   113  				{
   114  					Severity: Error,
   115  					Summary:  "Something bad happened",
   116  					Detail:   "It was really, really bad.",
   117  				},
   118  				{
   119  					Severity: Warning,
   120  					Summary:  "Also, somebody sneezed",
   121  					Detail:   "How rude!",
   122  				},
   123  			},
   124  		},
   125  		"multierror.Error": {
   126  			func(diags Diagnostics) Diagnostics {
   127  				err := multierror.Append(nil, errors.New("bad thing A"))
   128  				err = multierror.Append(err, errors.New("bad thing B"))
   129  				diags = diags.Append(err)
   130  				return diags
   131  			},
   132  			[]diagFlat{
   133  				{
   134  					Severity: Error,
   135  					Summary:  "bad thing A",
   136  				},
   137  				{
   138  					Severity: Error,
   139  					Summary:  "bad thing B",
   140  				},
   141  			},
   142  		},
   143  		"concat Diagnostics": {
   144  			func(diags Diagnostics) Diagnostics {
   145  				var moreDiags Diagnostics
   146  				moreDiags = moreDiags.Append(errors.New("bad thing A"))
   147  				moreDiags = moreDiags.Append(errors.New("bad thing B"))
   148  				return diags.Append(moreDiags)
   149  			},
   150  			[]diagFlat{
   151  				{
   152  					Severity: Error,
   153  					Summary:  "bad thing A",
   154  				},
   155  				{
   156  					Severity: Error,
   157  					Summary:  "bad thing B",
   158  				},
   159  			},
   160  		},
   161  		"single Diagnostic": {
   162  			func(diags Diagnostics) Diagnostics {
   163  				return diags.Append(SimpleWarning("Don't forget your toothbrush!"))
   164  			},
   165  			[]diagFlat{
   166  				{
   167  					Severity: Warning,
   168  					Summary:  "Don't forget your toothbrush!",
   169  				},
   170  			},
   171  		},
   172  		"multiple appends": {
   173  			func(diags Diagnostics) Diagnostics {
   174  				diags = diags.Append(SimpleWarning("Don't forget your toothbrush!"))
   175  				diags = diags.Append(fmt.Errorf("exploded"))
   176  				return diags
   177  			},
   178  			[]diagFlat{
   179  				{
   180  					Severity: Warning,
   181  					Summary:  "Don't forget your toothbrush!",
   182  				},
   183  				{
   184  					Severity: Error,
   185  					Summary:  "exploded",
   186  				},
   187  			},
   188  		},
   189  	}
   190  
   191  	for name, test := range tests {
   192  		t.Run(name, func(t *testing.T) {
   193  			gotDiags := test.Cons(nil)
   194  			var got []diagFlat
   195  			for _, item := range gotDiags {
   196  				desc := item.Description()
   197  				source := item.Source()
   198  				got = append(got, diagFlat{
   199  					Severity: item.Severity(),
   200  					Summary:  desc.Summary,
   201  					Detail:   desc.Detail,
   202  					Subject:  source.Subject,
   203  					Context:  source.Context,
   204  				})
   205  			}
   206  
   207  			if !reflect.DeepEqual(got, test.Want) {
   208  				t.Errorf("wrong result\ngot: %swant: %s", spew.Sdump(got), spew.Sdump(test.Want))
   209  			}
   210  		})
   211  	}
   212  }
   213  
   214  func TestDiagnosticsErr(t *testing.T) {
   215  	t.Run("empty", func(t *testing.T) {
   216  		var diags Diagnostics
   217  		err := diags.Err()
   218  		if err != nil {
   219  			t.Errorf("got non-nil error %#v; want nil", err)
   220  		}
   221  	})
   222  	t.Run("warning only", func(t *testing.T) {
   223  		var diags Diagnostics
   224  		diags = diags.Append(SimpleWarning("bad"))
   225  		err := diags.Err()
   226  		if err != nil {
   227  			t.Errorf("got non-nil error %#v; want nil", err)
   228  		}
   229  	})
   230  	t.Run("one error", func(t *testing.T) {
   231  		var diags Diagnostics
   232  		diags = diags.Append(errors.New("didn't work"))
   233  		err := diags.Err()
   234  		if err == nil {
   235  			t.Fatalf("got nil error %#v; want non-nil", err)
   236  		}
   237  		if got, want := err.Error(), "didn't work"; got != want {
   238  			t.Errorf("wrong error message\ngot:  %s\nwant: %s", got, want)
   239  		}
   240  	})
   241  	t.Run("two errors", func(t *testing.T) {
   242  		var diags Diagnostics
   243  		diags = diags.Append(errors.New("didn't work"))
   244  		diags = diags.Append(errors.New("didn't work either"))
   245  		err := diags.Err()
   246  		if err == nil {
   247  			t.Fatalf("got nil error %#v; want non-nil", err)
   248  		}
   249  		want := strings.TrimSpace(`
   250  2 problems:
   251  
   252  - didn't work
   253  - didn't work either
   254  `)
   255  		if got := err.Error(); got != want {
   256  			t.Errorf("wrong error message\ngot:  %s\nwant: %s", got, want)
   257  		}
   258  	})
   259  	t.Run("error and warning", func(t *testing.T) {
   260  		var diags Diagnostics
   261  		diags = diags.Append(errors.New("didn't work"))
   262  		diags = diags.Append(SimpleWarning("didn't work either"))
   263  		err := diags.Err()
   264  		if err == nil {
   265  			t.Fatalf("got nil error %#v; want non-nil", err)
   266  		}
   267  		// Since this "as error" mode is just a fallback for
   268  		// non-diagnostics-aware situations like tests, we don't actually
   269  		// distinguish warnings and errors here since the point is to just
   270  		// get the messages rendered. User-facing code should be printing
   271  		// each diagnostic separately, so won't enter this codepath,
   272  		want := strings.TrimSpace(`
   273  2 problems:
   274  
   275  - didn't work
   276  - didn't work either
   277  `)
   278  		if got := err.Error(); got != want {
   279  			t.Errorf("wrong error message\ngot:  %s\nwant: %s", got, want)
   280  		}
   281  	})
   282  }