blob: e6a111992bb824b1e612cc07a3c7755b139e3e79 [file] [log] [blame]
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package tfjson
import (
"encoding/json"
"testing"
"time"
"github.com/google/go-cmp/cmp"
"github.com/hashicorp/go-version"
)
var cmpOpts = cmp.AllowUnexported(allLogMessageTypes...)
func TestLogging_generic(t *testing.T) {
testCases := []struct {
rawMessage string
expectedMessage LogMsg
}{
{
`{"@level":"info","@message":"Installing provider version: hashicorp/aws v6.8.0...","@module":"terraform.ui","@timestamp":"2025-08-11T15:09:18.827459+00:00","type":"log"}`,
LogMessage{
baseLogMessage: baseLogMessage{
Lvl: Info,
Msg: "Installing provider version: hashicorp/aws v6.8.0...",
Time: time.Date(2025, 8, 11, 15, 9, 18, 827459000, time.UTC),
},
},
},
{
`{"@level":"info","@message":"Terraform 1.9.0","@module":"terraform.ui","@timestamp":"2025-08-11T15:09:15.919212+00:00","terraform":"1.9.0","type":"version","ui":"1.2"}`,
VersionLogMessage{
baseLogMessage: baseLogMessage{
Lvl: Info,
Msg: "Terraform 1.9.0",
Time: time.Date(2025, 8, 11, 15, 9, 15, 919212000, time.UTC),
},
Terraform: version.Must(version.NewVersion("1.9.0")),
UI: version.Must(version.NewVersion("1.2")),
},
},
{
`{"@level":"error","@message":"Error: Unclosed configuration block","@module":"terraform.ui","@timestamp":"2025-08-13T10:40:46.749685+00:00","diagnostic":{"severity":"error","summary":"Unclosed configuration block","detail":"There is no closing brace for this block before the end of the file. This may be caused by incorrect brace nesting elsewhere in this file.","range":{"filename":"main.tf","start":{"line":11,"column":30,"byte":153},"end":{"line":11,"column":31,"byte":154}},"snippet":{"context":"resource \"random_pet\" \"name\"","code":"resource \"random_pet\" \"name\" {","start_line":11,"highlight_start_offset":29,"highlight_end_offset":30,"values":[]}},"type":"diagnostic"}`,
DiagnosticLogMessage{
baseLogMessage: baseLogMessage{
Lvl: Error,
Msg: "Error: Unclosed configuration block",
Time: time.Date(2025, 8, 13, 10, 40, 46, 749685000, time.UTC),
},
Diagnostic: Diagnostic{
Severity: DiagnosticSeverityError,
Summary: "Unclosed configuration block",
Detail: "There is no closing brace for this block before the end of the file. This may be caused by incorrect brace nesting elsewhere in this file.",
Range: &Range{
Filename: "main.tf",
Start: Pos{
Line: 11,
Column: 30,
Byte: 153,
},
End: Pos{
Line: 11,
Column: 31,
Byte: 154,
},
},
Snippet: &DiagnosticSnippet{
Context: ptrToString(`resource "random_pet" "name"`),
Code: `resource "random_pet" "name" {`,
StartLine: 11,
HighlightStartOffset: 29,
HighlightEndOffset: 30,
Values: []DiagnosticExpressionValue{},
},
},
},
},
{
`{"@level":"debug","@message":"Foobar","@module":"terraform.ui","@timestamp":"2025-08-11T15:09:18.827459+00:00","type":"FOO"}`,
UnknownLogMessage{
baseLogMessage: baseLogMessage{
Lvl: Debug,
Msg: "Foobar",
Time: time.Date(2025, 8, 11, 15, 9, 18, 827459000, time.UTC),
},
},
},
}
for _, tc := range testCases {
msg, err := UnmarshalLogMessage([]byte(tc.rawMessage))
if err != nil {
t.Fatal(err)
}
if diff := cmp.Diff(tc.expectedMessage, msg, cmpOpts); diff != "" {
t.Fatalf("unexpected message: %s", diff)
}
}
}
func TestLogging_query(t *testing.T) {
testCases := []struct {
rawMessage string
expectedMessage LogMsg
}{
{
`{"@level":"info","@message":"list.concept_pet.pets: Starting query...","@module":"terraform.ui","@timestamp":"2025-08-28T18:07:11.534006+00:00","list_start":{"address":"list.concept_pet.pets","resource_type":"concept_pet"},"type":"list_start"}`,
ListStartMessage{
baseLogMessage: baseLogMessage{
Lvl: Info,
Msg: "list.concept_pet.pets: Starting query...",
Time: time.Date(2025, 8, 28, 18, 7, 11, 534006000, time.UTC),
},
ListStart: ListStartData{
Address: "list.concept_pet.pets",
ResourceType: "concept_pet",
InputConfig: nil,
},
},
},
{
`{"@level":"info","@message":"list.concept_pet.pets: Result found","@module":"terraform.ui","@timestamp":"2025-08-28T18:07:11.534589+00:00","list_resource_found":{"address":"list.concept_pet.pets","display_name":"This is a easy-antelope","identity":{"id":"easy-antelope","legs":6},"resource_type":"concept_pet"},"type":"list_resource_found"}`,
ListResourceFoundMessage{
baseLogMessage: baseLogMessage{
Lvl: Info,
Msg: "list.concept_pet.pets: Result found",
Time: time.Date(2025, 8, 28, 18, 7, 11, 534589000, time.UTC),
},
ListResourceFound: ListResourceFoundData{
Address: "list.concept_pet.pets",
ResourceType: "concept_pet",
DisplayName: "This is a easy-antelope",
Identity: map[string]json.RawMessage{
"id": json.RawMessage(`"easy-antelope"`),
"legs": json.RawMessage("6"),
},
},
},
},
{
`{"@level":"info","@message":"list.concept_pet.pets: List complete","@module":"terraform.ui","@timestamp":"2025-08-28T18:07:11.534661+00:00","list_complete":{"address":"list.concept_pet.pets","resource_type":"concept_pet","total":5},"type":"list_complete"}`,
ListCompleteMessage{
baseLogMessage: baseLogMessage{
Lvl: Info,
Msg: "list.concept_pet.pets: List complete",
Time: time.Date(2025, 8, 28, 18, 7, 11, 534661000, time.UTC),
},
ListComplete: ListCompleteData{
Address: "list.concept_pet.pets",
ResourceType: "concept_pet",
Total: 5,
},
},
},
}
for _, tc := range testCases {
msg, err := UnmarshalLogMessage([]byte(tc.rawMessage))
if err != nil {
t.Fatal(err)
}
if diff := cmp.Diff(tc.expectedMessage, msg, cmpOpts); diff != "" {
t.Fatalf("unexpected message: %s", diff)
}
}
}