learnlytics-go/templ/lsp/protocol/diagnostics_test.go
2025-03-20 12:35:13 +01:00

641 lines
16 KiB
Go

// SPDX-FileCopyrightText: 2019 The Go Language Server Authors
// SPDX-License-Identifier: BSD-3-Clause
package protocol
import (
"testing"
"encoding/json"
"github.com/google/go-cmp/cmp"
"github.com/a-h/templ/lsp/uri"
)
func TestDiagnostic(t *testing.T) {
t.Parallel()
const (
want = `{"range":{"start":{"line":25,"character":1},"end":{"line":27,"character":3}},"severity":1,"code":"foo/bar","codeDescription":{"href":"file:///path/to/test.go"},"source":"test foo bar","message":"foo bar","tags":[1,2],"relatedInformation":[{"location":{"uri":"file:///path/to/basic.go","range":{"start":{"line":25,"character":1},"end":{"line":27,"character":3}}},"message":"basic_gen.go"}],"data":"testData"}`
wantNilSeverity = `{"range":{"start":{"line":25,"character":1},"end":{"line":27,"character":3}},"code":"foo/bar","codeDescription":{"href":"file:///path/to/test.go"},"source":"test foo bar","message":"foo bar","relatedInformation":[{"location":{"uri":"file:///path/to/basic.go","range":{"start":{"line":25,"character":1},"end":{"line":27,"character":3}}},"message":"basic_gen.go"}],"data":"testData"}`
wantNilCode = `{"range":{"start":{"line":25,"character":1},"end":{"line":27,"character":3}},"severity":1,"codeDescription":{"href":"file:///path/to/test.go"},"source":"test foo bar","message":"foo bar","relatedInformation":[{"location":{"uri":"file:///path/to/basic.go","range":{"start":{"line":25,"character":1},"end":{"line":27,"character":3}}},"message":"basic_gen.go"}],"data":"testData"}`
wantNilRelatedInformation = `{"range":{"start":{"line":25,"character":1},"end":{"line":27,"character":3}},"severity":1,"code":"foo/bar","codeDescription":{"href":"file:///path/to/test.go"},"source":"test foo bar","message":"foo bar","data":"testData"}`
wantNilAll = `{"range":{"start":{"line":25,"character":1},"end":{"line":27,"character":3}},"message":"foo bar"}`
wantInvalid = `{"range":{"start":{"line":2,"character":1},"end":{"line":3,"character":2}},"severity":1,"code":"foo/bar","codeDescription":{"href":"file:///path/to/test.go"},"source":"test foo bar","message":"foo bar","relatedInformation":[{"location":{"uri":"file:///path/to/basic.go","range":{"start":{"line":2,"character":1},"end":{"line":3,"character":2}}},"message":"basic_gen.go"}],"data":"invalidData"}`
)
wantType := Diagnostic{
Range: Range{
Start: Position{
Line: 25,
Character: 1,
},
End: Position{
Line: 27,
Character: 3,
},
},
Severity: DiagnosticSeverityError,
Code: "foo/bar",
CodeDescription: &CodeDescription{
Href: uri.File("/path/to/test.go"),
},
Source: "test foo bar",
Message: "foo bar",
Tags: []DiagnosticTag{
DiagnosticTagUnnecessary,
DiagnosticTagDeprecated,
},
RelatedInformation: []DiagnosticRelatedInformation{
{
Location: Location{
URI: uri.File("/path/to/basic.go"),
Range: Range{
Start: Position{
Line: 25,
Character: 1,
},
End: Position{
Line: 27,
Character: 3,
},
},
},
Message: "basic_gen.go",
},
},
Data: "testData",
}
wantTypeNilSeverity := Diagnostic{
Range: Range{
Start: Position{
Line: 25,
Character: 1,
},
End: Position{
Line: 27,
Character: 3,
},
},
Code: "foo/bar",
CodeDescription: &CodeDescription{
Href: uri.File("/path/to/test.go"),
},
Source: "test foo bar",
Message: "foo bar",
RelatedInformation: []DiagnosticRelatedInformation{
{
Location: Location{
URI: uri.File("/path/to/basic.go"),
Range: Range{
Start: Position{
Line: 25,
Character: 1,
},
End: Position{
Line: 27,
Character: 3,
},
},
},
Message: "basic_gen.go",
},
},
Data: "testData",
}
wantTypeNilCode := Diagnostic{
Range: Range{
Start: Position{
Line: 25,
Character: 1,
},
End: Position{
Line: 27,
Character: 3,
},
},
Severity: DiagnosticSeverityError,
CodeDescription: &CodeDescription{
Href: uri.File("/path/to/test.go"),
},
Source: "test foo bar",
Message: "foo bar",
RelatedInformation: []DiagnosticRelatedInformation{
{
Location: Location{
URI: uri.File("/path/to/basic.go"),
Range: Range{
Start: Position{
Line: 25,
Character: 1,
},
End: Position{
Line: 27,
Character: 3,
},
},
},
Message: "basic_gen.go",
},
},
Data: "testData",
}
wantTypeNilRelatedInformation := Diagnostic{
Range: Range{
Start: Position{
Line: 25,
Character: 1,
},
End: Position{
Line: 27,
Character: 3,
},
},
Severity: DiagnosticSeverityError,
Code: "foo/bar",
CodeDescription: &CodeDescription{
Href: uri.File("/path/to/test.go"),
},
Source: "test foo bar",
Message: "foo bar",
Data: "testData",
}
wantTypeNilAll := Diagnostic{
Range: Range{
Start: Position{
Line: 25,
Character: 1,
},
End: Position{
Line: 27,
Character: 3,
},
},
Message: "foo bar",
}
t.Run("Marshal", func(t *testing.T) {
t.Parallel()
tests := []struct {
name string
field Diagnostic
want string
wantMarshalErr bool
wantErr bool
}{
{
name: "Valid",
field: wantType,
want: want,
wantMarshalErr: false,
wantErr: false,
},
{
name: "ValidNilSeverity",
field: wantTypeNilSeverity,
want: wantNilSeverity,
wantMarshalErr: false,
wantErr: false,
},
{
name: "ValidNilCode",
field: wantTypeNilCode,
want: wantNilCode,
wantMarshalErr: false,
wantErr: false,
},
{
name: "ValidNilRelatedInformation",
field: wantTypeNilRelatedInformation,
want: wantNilRelatedInformation,
wantMarshalErr: false,
wantErr: false,
},
{
name: "ValidNilAll",
field: wantTypeNilAll,
want: wantNilAll,
wantMarshalErr: false,
wantErr: false,
},
{
name: "Invalid",
field: wantType,
want: wantInvalid,
wantMarshalErr: false,
wantErr: true,
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
got, err := json.Marshal(&tt.field)
if (err != nil) != tt.wantMarshalErr {
t.Fatal(err)
}
if diff := cmp.Diff(tt.want, string(got)); (diff != "") != tt.wantErr {
t.Errorf("%s: wantErr: %t\n(-want +got)\n%s", tt.name, tt.wantErr, diff)
}
})
}
})
t.Run("Unmarshal", func(t *testing.T) {
t.Parallel()
tests := []struct {
name string
field string
want Diagnostic
wantUnmarshalErr bool
wantErr bool
}{
{
name: "Valid",
field: want,
want: wantType,
wantUnmarshalErr: false,
wantErr: false,
},
{
name: "ValidNilSeverity",
field: wantNilSeverity,
want: wantTypeNilSeverity,
wantUnmarshalErr: false,
wantErr: false,
},
{
name: "ValidNilCode",
field: wantNilCode,
want: wantTypeNilCode,
wantUnmarshalErr: false,
wantErr: false,
},
{
name: "ValidNilRelatedInformation",
field: wantNilRelatedInformation,
want: wantTypeNilRelatedInformation,
wantUnmarshalErr: false,
wantErr: false,
},
{
name: "ValidNilAll",
field: wantNilAll,
want: wantTypeNilAll,
wantUnmarshalErr: false,
wantErr: false,
},
{
name: "Invalid",
field: wantInvalid,
want: wantType,
wantUnmarshalErr: false,
wantErr: true,
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
var got Diagnostic
if err := json.Unmarshal([]byte(tt.field), &got); (err != nil) != tt.wantUnmarshalErr {
t.Fatal(err)
}
if diff := cmp.Diff(tt.want, got); (diff != "") != tt.wantErr {
t.Errorf("%s: wantErr: %t\n(-want +got)\n%s", tt.name, tt.wantErr, diff)
}
})
}
})
}
func TestDiagnosticSeverity_String(t *testing.T) {
t.Parallel()
tests := []struct {
name string
d DiagnosticSeverity
want string
}{
{
name: "Error",
d: DiagnosticSeverityError,
want: "Error",
},
{
name: "Warning",
d: DiagnosticSeverityWarning,
want: "Warning",
},
{
name: "Information",
d: DiagnosticSeverityInformation,
want: "Information",
},
{
name: "Hint",
d: DiagnosticSeverityHint,
want: "Hint",
},
{
name: "Unknown",
d: DiagnosticSeverity(0),
want: "0",
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
if got := tt.d.String(); got != tt.want {
t.Errorf("DiagnosticSeverity.String() = %v, want %v", tt.want, got)
}
})
}
}
func TestDiagnosticTag_String(t *testing.T) {
t.Parallel()
tests := []struct {
name string
d DiagnosticTag
want string
}{
{
name: "Unnecessary",
d: DiagnosticTagUnnecessary,
want: "Unnecessary",
},
{
name: "Deprecated",
d: DiagnosticTagDeprecated,
want: "Deprecated",
},
{
name: "Unknown",
d: DiagnosticTag(0),
want: "0",
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
if got := tt.d.String(); got != tt.want {
t.Errorf("DiagnosticSeverity.String() = %v, want %v", tt.want, got)
}
})
}
}
func TestDiagnosticRelatedInformation(t *testing.T) {
t.Parallel()
const (
want = `{"location":{"uri":"file:///path/to/basic.go","range":{"start":{"line":25,"character":1},"end":{"line":27,"character":3}}},"message":"basic_gen.go"}`
wantInvalid = `{"location":{"uri":"file:///path/to/basic.go","range":{"start":{"line":2,"character":1},"end":{"line":3,"character":2}}},"message":"basic_gen.go"}`
)
wantType := DiagnosticRelatedInformation{
Location: Location{
URI: uri.File("/path/to/basic.go"),
Range: Range{
Start: Position{
Line: 25,
Character: 1,
},
End: Position{
Line: 27,
Character: 3,
},
},
},
Message: "basic_gen.go",
}
t.Run("Marshal", func(t *testing.T) {
t.Parallel()
tests := []struct {
name string
field DiagnosticRelatedInformation
want string
wantMarshalErr bool
wantErr bool
}{
{
name: "Valid",
field: wantType,
want: want,
wantMarshalErr: false,
wantErr: false,
},
{
name: "Invalid",
field: wantType,
want: wantInvalid,
wantMarshalErr: false,
wantErr: true,
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
got, err := json.Marshal(&tt.field)
if (err != nil) != tt.wantMarshalErr {
t.Fatal(err)
}
if diff := cmp.Diff(tt.want, string(got)); (diff != "") != tt.wantErr {
t.Errorf("%s: wantErr: %t\n(-want +got)\n%s", tt.name, tt.wantErr, diff)
}
})
}
})
t.Run("Unmarshal", func(t *testing.T) {
t.Parallel()
tests := []struct {
name string
field string
want DiagnosticRelatedInformation
wantUnmarshalErr bool
wantErr bool
}{
{
name: "Valid",
field: want,
want: wantType,
wantUnmarshalErr: false,
wantErr: false,
},
{
name: "Invalid",
field: wantInvalid,
want: wantType,
wantUnmarshalErr: false,
wantErr: true,
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
var got DiagnosticRelatedInformation
if err := json.Unmarshal([]byte(tt.field), &got); (err != nil) != tt.wantUnmarshalErr {
t.Fatal(err)
}
if diff := cmp.Diff(tt.want, got); (diff != "") != tt.wantErr {
t.Errorf("%s: wantErr: %t\n(-want +got)\n%s", tt.name, tt.wantErr, diff)
}
})
}
})
}
func TestPublishDiagnosticsParams(t *testing.T) {
t.Parallel()
const (
want = `{"uri":"file:///path/to/diagnostics.go","version":1,"diagnostics":[{"range":{"start":{"line":25,"character":1},"end":{"line":27,"character":3}},"severity":1,"code":"foo/bar","source":"test foo bar","message":"foo bar","relatedInformation":[{"location":{"uri":"file:///path/to/diagnostics.go","range":{"start":{"line":25,"character":1},"end":{"line":27,"character":3}}},"message":"diagnostics.go"}]}]}`
wantInvalid = `{"uri":"file:///path/to/diagnostics_gen.go","version":2,"diagnostics":[{"range":{"start":{"line":2,"character":1},"end":{"line":3,"character":2}},"severity":1,"code":"foo/bar","source":"test foo bar","message":"foo bar","relatedInformation":[{"location":{"uri":"file:///path/to/diagnostics_gen.go","range":{"start":{"line":2,"character":1},"end":{"line":3,"character":2}}},"message":"diagnostics_gen.go"}]}]}`
)
wantType := PublishDiagnosticsParams{
URI: DocumentURI("file:///path/to/diagnostics.go"),
Version: 1,
Diagnostics: []Diagnostic{
{
Range: Range{
Start: Position{
Line: 25,
Character: 1,
},
End: Position{
Line: 27,
Character: 3,
},
},
Severity: DiagnosticSeverityError,
Code: "foo/bar",
Source: "test foo bar",
Message: "foo bar",
RelatedInformation: []DiagnosticRelatedInformation{
{
Location: Location{
URI: uri.File("/path/to/diagnostics.go"),
Range: Range{
Start: Position{
Line: 25,
Character: 1,
},
End: Position{
Line: 27,
Character: 3,
},
},
},
Message: "diagnostics.go",
},
},
},
},
}
t.Run("Marshal", func(t *testing.T) {
t.Parallel()
tests := []struct {
name string
field PublishDiagnosticsParams
want string
wantMarshalErr bool
wantErr bool
}{
{
name: "Valid",
field: wantType,
want: want,
wantMarshalErr: false,
wantErr: false,
},
{
name: "Invalid",
field: wantType,
want: wantInvalid,
wantMarshalErr: false,
wantErr: true,
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
got, err := json.Marshal(&tt.field)
if (err != nil) != tt.wantMarshalErr {
t.Fatal(err)
}
if diff := cmp.Diff(tt.want, string(got)); (diff != "") != tt.wantErr {
t.Errorf("%s: wantErr: %t\n(-want +got)\n%s", tt.name, tt.wantErr, diff)
}
})
}
})
t.Run("Unmarshal", func(t *testing.T) {
t.Parallel()
tests := []struct {
name string
field string
want PublishDiagnosticsParams
wantUnmarshalErr bool
wantErr bool
}{
{
name: "Valid",
field: want,
want: wantType,
wantUnmarshalErr: false,
wantErr: false,
},
{
name: "Invalid",
field: wantInvalid,
want: wantType,
wantUnmarshalErr: false,
wantErr: true,
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
var got PublishDiagnosticsParams
if err := json.Unmarshal([]byte(tt.field), &got); (err != nil) != tt.wantUnmarshalErr {
t.Fatal(err)
}
if diff := cmp.Diff(tt.want, got); (diff != "") != tt.wantErr {
t.Errorf("%s: wantErr: %t\n(-want +got)\n%s", tt.name, tt.wantErr, diff)
}
})
}
})
}