| // Copyright (c) HashiCorp, Inc. |
| // SPDX-License-Identifier: MPL-2.0 |
| |
| package tfjson |
| |
| import ( |
| "encoding/json" |
| "testing" |
| |
| "github.com/google/go-cmp/cmp" |
| ) |
| |
| func TestValidateOutput_error(t *testing.T) { |
| errOutput := `{ |
| "valid": false, |
| "error_count": 1, |
| "warning_count": 0, |
| "diagnostics": [ |
| { |
| "severity": "error", |
| "summary": "Could not load plugin", |
| "detail": "\nPlugin reinitialization required..." |
| } |
| ] |
| }` |
| var parsed ValidateOutput |
| if err := json.Unmarshal([]byte(errOutput), &parsed); err != nil { |
| t.Fatal(err) |
| } |
| |
| expected := &ValidateOutput{ |
| ErrorCount: 1, |
| Diagnostics: []Diagnostic{ |
| { |
| Severity: "error", |
| Summary: "Could not load plugin", |
| Detail: "\nPlugin reinitialization required...", |
| }, |
| }, |
| } |
| if diff := cmp.Diff(expected, &parsed); diff != "" { |
| t.Fatalf("output mismatch: %s", diff) |
| } |
| } |
| |
| func TestValidateOutput_basic(t *testing.T) { |
| errOutput := `{ |
| "valid": false, |
| "error_count": 1, |
| "warning_count": 1, |
| "diagnostics": [ |
| { |
| "severity": "warning", |
| "summary": "\"anonymous\": [DEPRECATED] For versions later than 3.0.0, absence of a token enables this mode" |
| }, |
| { |
| "severity": "error", |
| "summary": "Missing required argument", |
| "detail": "The argument \"name\" is required, but no definition was found.", |
| "range": { |
| "filename": "main.tf", |
| "start": { |
| "line": 14, |
| "column": 37, |
| "byte": 200 |
| }, |
| "end": { |
| "line": 14, |
| "column": 37, |
| "byte": 200 |
| } |
| } |
| } |
| ] |
| }` |
| var parsed ValidateOutput |
| if err := json.Unmarshal([]byte(errOutput), &parsed); err != nil { |
| t.Fatal(err) |
| } |
| |
| expected := &ValidateOutput{ |
| ErrorCount: 1, |
| WarningCount: 1, |
| Diagnostics: []Diagnostic{ |
| { |
| Severity: "warning", |
| Summary: "\"anonymous\": [DEPRECATED] For versions later than 3.0.0, absence of a token enables this mode", |
| }, |
| { |
| Severity: "error", |
| Summary: "Missing required argument", |
| Detail: "The argument \"name\" is required, but no definition was found.", |
| Range: &Range{ |
| Filename: "main.tf", |
| Start: Pos{ |
| Line: 14, |
| Column: 37, |
| Byte: 200, |
| }, |
| End: Pos{ |
| Line: 14, |
| Column: 37, |
| Byte: 200, |
| }, |
| }, |
| }, |
| }, |
| } |
| if diff := cmp.Diff(expected, &parsed); diff != "" { |
| t.Fatalf("output mismatch: %s", diff) |
| } |
| } |
| |
| func TestValidateOutput_versioned(t *testing.T) { |
| errOutput := `{ |
| "format_version": "0.1", |
| "valid": false, |
| "error_count": 1, |
| "warning_count": 1, |
| "diagnostics": [ |
| { |
| "severity": "warning", |
| "summary": "Deprecated Attribute", |
| "detail": "Deprecated in favor of project_id", |
| "range": { |
| "filename": "main.tf", |
| "start": { |
| "line": 21, |
| "column": 25, |
| "byte": 408 |
| }, |
| "end": { |
| "line": 21, |
| "column": 42, |
| "byte": 425 |
| } |
| }, |
| "snippet": { |
| "context": "resource \"google_project_access_approval_settings\" \"project_access_approval\"", |
| "code": " project = \"my-project-name\"", |
| "start_line": 21, |
| "highlight_start_offset": 24, |
| "highlight_end_offset": 41, |
| "values": [] |
| } |
| }, |
| { |
| "severity": "error", |
| "summary": "Missing required argument", |
| "detail": "The argument \"enrolled_services\" is required, but no definition was found.", |
| "range": { |
| "filename": "main.tf", |
| "start": { |
| "line": 19, |
| "column": 78, |
| "byte": 340 |
| }, |
| "end": { |
| "line": 19, |
| "column": 79, |
| "byte": 341 |
| } |
| }, |
| "snippet": { |
| "context": "resource \"google_project_access_approval_settings\" \"project_access_approval\"", |
| "code": "resource \"google_project_access_approval_settings\" \"project_access_approval\" {", |
| "start_line": 19, |
| "highlight_start_offset": 77, |
| "highlight_end_offset": 78, |
| "values": [] |
| } |
| } |
| ] |
| }` |
| var parsed ValidateOutput |
| if err := json.Unmarshal([]byte(errOutput), &parsed); err != nil { |
| t.Fatal(err) |
| } |
| |
| expected := &ValidateOutput{ |
| FormatVersion: "0.1", |
| ErrorCount: 1, |
| WarningCount: 1, |
| Diagnostics: []Diagnostic{ |
| { |
| Severity: "warning", |
| Summary: "Deprecated Attribute", |
| Detail: "Deprecated in favor of project_id", |
| Range: &Range{ |
| Filename: "main.tf", |
| Start: Pos{Line: 21, Column: 25, Byte: 408}, |
| End: Pos{Line: 21, Column: 42, Byte: 425}, |
| }, |
| Snippet: &DiagnosticSnippet{ |
| Context: ptrToString(`resource "google_project_access_approval_settings" "project_access_approval"`), |
| Code: ` project = "my-project-name"`, |
| StartLine: 21, |
| HighlightStartOffset: 24, |
| HighlightEndOffset: 41, |
| Values: []DiagnosticExpressionValue{}, |
| }, |
| }, |
| { |
| Severity: "error", |
| Summary: "Missing required argument", |
| Detail: `The argument "enrolled_services" is required, but no definition was found.`, |
| Range: &Range{ |
| Filename: "main.tf", |
| Start: Pos{Line: 19, Column: 78, Byte: 340}, |
| End: Pos{Line: 19, Column: 79, Byte: 341}, |
| }, |
| Snippet: &DiagnosticSnippet{ |
| Context: ptrToString(`resource "google_project_access_approval_settings" "project_access_approval"`), |
| Code: `resource "google_project_access_approval_settings" "project_access_approval" {`, |
| StartLine: 19, |
| HighlightStartOffset: 77, |
| HighlightEndOffset: 78, |
| Values: []DiagnosticExpressionValue{}, |
| }, |
| }, |
| }, |
| } |
| if diff := cmp.Diff(expected, &parsed); diff != "" { |
| t.Fatalf("output mismatch: %s", diff) |
| } |
| } |
| |
| func TestValidateOutput_versioned10(t *testing.T) { |
| errOutput := `{ |
| "format_version": "1.0", |
| "valid": false, |
| "error_count": 1, |
| "warning_count": 1, |
| "diagnostics": [ |
| { |
| "severity": "warning", |
| "summary": "Deprecated Attribute", |
| "detail": "Deprecated in favor of project_id", |
| "range": { |
| "filename": "main.tf", |
| "start": { |
| "line": 21, |
| "column": 25, |
| "byte": 408 |
| }, |
| "end": { |
| "line": 21, |
| "column": 42, |
| "byte": 425 |
| } |
| }, |
| "snippet": { |
| "context": "resource \"google_project_access_approval_settings\" \"project_access_approval\"", |
| "code": " project = \"my-project-name\"", |
| "start_line": 21, |
| "highlight_start_offset": 24, |
| "highlight_end_offset": 41, |
| "values": [] |
| } |
| }, |
| { |
| "severity": "error", |
| "summary": "Missing required argument", |
| "detail": "The argument \"enrolled_services\" is required, but no definition was found.", |
| "range": { |
| "filename": "main.tf", |
| "start": { |
| "line": 19, |
| "column": 78, |
| "byte": 340 |
| }, |
| "end": { |
| "line": 19, |
| "column": 79, |
| "byte": 341 |
| } |
| }, |
| "snippet": { |
| "context": "resource \"google_project_access_approval_settings\" \"project_access_approval\"", |
| "code": "resource \"google_project_access_approval_settings\" \"project_access_approval\" {", |
| "start_line": 19, |
| "highlight_start_offset": 77, |
| "highlight_end_offset": 78, |
| "values": [] |
| } |
| } |
| ] |
| }` |
| var parsed ValidateOutput |
| if err := json.Unmarshal([]byte(errOutput), &parsed); err != nil { |
| t.Fatal(err) |
| } |
| |
| expected := &ValidateOutput{ |
| FormatVersion: "1.0", |
| ErrorCount: 1, |
| WarningCount: 1, |
| Diagnostics: []Diagnostic{ |
| { |
| Severity: "warning", |
| Summary: "Deprecated Attribute", |
| Detail: "Deprecated in favor of project_id", |
| Range: &Range{ |
| Filename: "main.tf", |
| Start: Pos{Line: 21, Column: 25, Byte: 408}, |
| End: Pos{Line: 21, Column: 42, Byte: 425}, |
| }, |
| Snippet: &DiagnosticSnippet{ |
| Context: ptrToString(`resource "google_project_access_approval_settings" "project_access_approval"`), |
| Code: ` project = "my-project-name"`, |
| StartLine: 21, |
| HighlightStartOffset: 24, |
| HighlightEndOffset: 41, |
| Values: []DiagnosticExpressionValue{}, |
| }, |
| }, |
| { |
| Severity: "error", |
| Summary: "Missing required argument", |
| Detail: `The argument "enrolled_services" is required, but no definition was found.`, |
| Range: &Range{ |
| Filename: "main.tf", |
| Start: Pos{Line: 19, Column: 78, Byte: 340}, |
| End: Pos{Line: 19, Column: 79, Byte: 341}, |
| }, |
| Snippet: &DiagnosticSnippet{ |
| Context: ptrToString(`resource "google_project_access_approval_settings" "project_access_approval"`), |
| Code: `resource "google_project_access_approval_settings" "project_access_approval" {`, |
| StartLine: 19, |
| HighlightStartOffset: 77, |
| HighlightEndOffset: 78, |
| Values: []DiagnosticExpressionValue{}, |
| }, |
| }, |
| }, |
| } |
| if diff := cmp.Diff(expected, &parsed); diff != "" { |
| t.Fatalf("output mismatch: %s", diff) |
| } |
| } |
| |
| func ptrToString(val string) *string { |
| return &val |
| } |