Skip to content

Commit

Permalink
test(yamlls): more integration tests
Browse files Browse the repository at this point in the history
  • Loading branch information
qvalentin committed Mar 12, 2024
1 parent 25b3336 commit d73e845
Show file tree
Hide file tree
Showing 4 changed files with 281 additions and 59 deletions.
155 changes: 96 additions & 59 deletions internal/adapter/yamlls/diagnostics_integration_test.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
package yamlls

import (
"encoding/json"
"fmt"
"log"
"os"
"path/filepath"
"regexp"
"strings"
"testing"
"time"

Expand All @@ -24,36 +22,7 @@ import (
// must be relative to this file
var TEST_DATA_DIR = "../../../testdata/charts/bitnami/"

type jsonRpcDiagnostics struct {
Params lsp.PublishDiagnosticsParams `json:"params"`
Jsonrpc string `json:"jsonrpc"`
Method string `json:"method"`
}

type readWriteCloseMock struct {
diagnosticsChan chan lsp.PublishDiagnosticsParams
}

func (proc readWriteCloseMock) Read(p []byte) (int, error) {
return 1, nil
}

func (proc readWriteCloseMock) Write(p []byte) (int, error) {
if strings.HasPrefix(string(p), "Content-Length: ") {
return 1, nil
}
var diagnostics jsonRpcDiagnostics
json.NewDecoder(strings.NewReader(string(p))).Decode(&diagnostics)

proc.diagnosticsChan <- diagnostics.Params
return 1, nil
}

func (proc readWriteCloseMock) Close() error {
return nil
}

func readTestFiles(dir string, channel chan<- lsp.DidOpenTextDocumentParams, doneChan chan<- int) {
func readTestFiles(dir string, channel chan<- string, doneChan chan<- int) {
libRegEx, e := regexp.Compile(".*(/|\\\\)templates(/|\\\\).*\\.ya?ml")
if e != nil {
log.Fatal(e)
Expand All @@ -67,16 +36,8 @@ func readTestFiles(dir string, channel chan<- lsp.DidOpenTextDocumentParams, don
count := 0
filepath.WalkDir(dir, func(path string, d os.DirEntry, err error) error {
if d.Type().IsRegular() && libRegEx.MatchString(path) {
contentBytes, _ := os.ReadFile(path)
count++
channel <- lsp.DidOpenTextDocumentParams{
TextDocument: lsp.TextDocumentItem{
URI: uri.File(path),
LanguageID: "",
Version: 0,
Text: string(contentBytes),
},
}
channel <- path
}
return nil
})
Expand All @@ -86,15 +47,13 @@ func readTestFiles(dir string, channel chan<- lsp.DidOpenTextDocumentParams, don
func sendTestFilesToYamlls(documents *lsplocal.DocumentStore, yamllsConnector *Connector,
doneReadingFilesChan <-chan int,
doneSendingFilesChan chan<- int,
filesChan <-chan lsp.DidOpenTextDocumentParams,
filesChan <-chan string,
) {
ownCount := 0
for {
select {
case d := <-filesChan:
documents.DidOpen(&d, util.DefaultConfig)
tree := lsplocal.ParseAst(nil, d.TextDocument.Text)
yamllsConnector.DocumentDidOpen(tree, d)
openFile(&testing.T{}, documents, d, yamllsConnector)
ownCount++
case count := <-doneReadingFilesChan:
if count != ownCount {
Expand All @@ -107,15 +66,9 @@ func sendTestFilesToYamlls(documents *lsplocal.DocumentStore, yamllsConnector *C
}

func TestYamllsDiagnosticsIntegration(t *testing.T) {
diagnosticsChan := make(chan lsp.PublishDiagnosticsParams)
doneReadingFilesChan := make(chan int)
doneSendingFilesChan := make(chan int)

dir := t.TempDir()
documents := lsplocal.NewDocumentStore()
con := jsonrpc2.NewConn(jsonrpc2.NewStream(readWriteCloseMock{diagnosticsChan}))
zapLogger, _ := zap.NewProduction()
client := protocol.ClientDispatcher(con, zapLogger)
config := util.DefaultConfig.YamllsConfiguration

yamllsSettings := util.DefaultYamllsSettings
Expand All @@ -126,15 +79,9 @@ func TestYamllsDiagnosticsIntegration(t *testing.T) {
Enable: false,
}
config.YamllsSettings = yamllsSettings
yamllsConnector := NewConnector(config, client, documents)
yamllsConnector, documents, diagnosticsChan := getYamlLsConnector(t, config)

if yamllsConnector.server == nil {
t.Fatal("Could not connect to yaml-language-server")
}

yamllsConnector.CallInitialize(uri.File(dir))

didOpenChan := make(chan lsp.DidOpenTextDocumentParams)
didOpenChan := make(chan string)
go readTestFiles(TEST_DATA_DIR, didOpenChan, doneReadingFilesChan)
go sendTestFilesToYamlls(documents,
yamllsConnector, doneReadingFilesChan, doneSendingFilesChan, didOpenChan)
Expand Down Expand Up @@ -166,3 +113,93 @@ func TestYamllsDiagnosticsIntegration(t *testing.T) {
assert.LessOrEqual(t, diagnosticsCount, 23)
assert.Equal(t, 2368, sentCount, "Count of files in test data not equal to actual count")
}

func TestYamllsDiagnosticsIntegrationWithSchema(t *testing.T) {
diagnosticsChan := make(chan lsp.PublishDiagnosticsParams)
dir := t.TempDir()
documents := lsplocal.NewDocumentStore()
con := jsonrpc2.NewConn(jsonrpc2.NewStream(readWriteCloseMock{diagnosticsChan}))
zapLogger, _ := zap.NewProduction()
client := protocol.ClientDispatcher(con, zapLogger)

config := util.DefaultConfig.YamllsConfiguration

content, err := os.ReadFile("../../../testdata/example/templates/service.yaml")
if err != nil {
t.Fatal("Could not read test file", err)
}

yamllsConnector := NewConnector(config, client, documents)

if yamllsConnector.server == nil {
t.Fatal("Could not connect to yaml-language-server")
}

yamllsConnector.CallInitialize(uri.File(dir))
d := lsp.DidOpenTextDocumentParams{
TextDocument: lsp.TextDocumentItem{
URI: uri.File("tmp/templates/test.yaml"),
LanguageID: "",
Version: 0,
Text: string(content),
},
}
documents.DidOpen(&d, util.DefaultConfig)
tree := lsplocal.ParseAst(nil, d.TextDocument.Text)
yamllsConnector.DocumentDidOpen(tree, d)

expected := lsp.PublishDiagnosticsParams{
URI: uri.File("tmp/templates/test.yaml"),
Diagnostics: []lsp.Diagnostic{
{
Range: protocol.Range{
Start: protocol.Position{
Line: 1.0,
Character: 0,
},
End: protocol.Position{
Line: 1,
Character: 5,
},
},
Severity: 1,
Code: 0.0,
CodeDescription: nil,
Source: "yaml-schema: https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/v1.22.4-standalone-strict/_definitions.json",
Message: "Yamlls: Property wrong is not allowed.",
Tags: nil,
RelatedInformation: nil,
Data: map[string]interface{}{
"properties": []interface{}{
"status",
},
"schemaUri": []interface{}{
"https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/v1.22.4-standalone-strict/_definitions.json",
},
},
},
},
}

diagnostic := []lsp.PublishDiagnosticsParams{}
afterCh := time.After(10 * time.Second)
for {
if len(diagnostic) == 2 {
break
}
select {
case d := <-diagnosticsChan:
diagnostic = append(diagnostic, d)
case <-afterCh:
t.Fatal("Timed out waiting for diagnostics")
}
}

assert.Contains(t, diagnostic, expected)
assert.Contains(t, diagnostic, lsp.PublishDiagnosticsParams{
URI: uri.File("tmp/templates/test.yaml"),
Version: 0,
Diagnostics: []lsp.Diagnostic{},
},
)
}
87 changes: 87 additions & 0 deletions internal/adapter/yamlls/hover_integration_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package yamlls

import (
"context"
"strings"
"testing"
"time"

"github.com/mrjosh/helm-ls/internal/util"
"github.com/stretchr/testify/assert"
lsp "go.lsp.dev/protocol"
"go.lsp.dev/uri"
)

func TestYamllsHoverIntegration(t *testing.T) {
config := util.DefaultConfig.YamllsConfiguration

testCases := []struct {
desc string
file string
position lsp.Position

word string
expected string
}{
{
desc: "test hover on deployment.yaml",
file: "../../../testdata/example/templates/deployment.yaml",
position: lsp.Position{
Line: 0,
Character: 0,
},
word: "apiVersion",
expected: "APIVersion defines the versioned schema of this representation of an object",
},
{
desc: "test hover on deployment.yaml, template",
file: "../../../testdata/example/templates/deployment.yaml",
position: lsp.Position{
Line: 13,
Character: 3,
},
word: "template",
expected: "Template describes the pods that will be created",
},
{
desc: "test hover on deployment.yaml with value",
file: "../../../testdata/example/templates/deployment.yaml",
position: lsp.Position{
Line: 1,
Character: 13,
},
word: "kind",
expected: "Kind is a string value representing the REST resource this object represents",
},
{
desc: "test hover on file without templates",
file: "../../../testdata/example/templates/deployment-no-templates.yaml",
position: lsp.Position{
Line: 0,
Character: 1,
},
word: "",
expected: "APIVersion defines the versioned schema of this representation of an object",
},
}
for _, tt1 := range testCases {
tt := tt1
t.Run(tt.desc, func(t *testing.T) {
t.Parallel()
yamllsConnector, documents, _ := getYamlLsConnector(t, config)
openFile(t, documents, tt.file, yamllsConnector)

assert.Eventually(t, func() bool {
result, err := yamllsConnector.CallHover(context.Background(), lsp.HoverParams{
TextDocumentPositionParams: lsp.TextDocumentPositionParams{
TextDocument: lsp.TextDocumentIdentifier{
URI: uri.File(tt.file),
},
Position: tt.position,
},
}, tt.word)
return err == nil && strings.Contains(result.Contents.Value, tt.expected)
}, time.Second*10, time.Second/2)
})
}
}
84 changes: 84 additions & 0 deletions internal/adapter/yamlls/integration_test_utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package yamlls

import (
"encoding/json"
"os"
"strings"
"testing"

lsplocal "github.com/mrjosh/helm-ls/internal/lsp"
"github.com/mrjosh/helm-ls/internal/util"
"go.lsp.dev/jsonrpc2"
"go.lsp.dev/protocol"
lsp "go.lsp.dev/protocol"
"go.lsp.dev/uri"
"go.uber.org/zap"
)

type jsonRpcDiagnostics struct {

Check failure on line 18 in internal/adapter/yamlls/integration_test_utils.go

View workflow job for this annotation

GitHub Actions / lint (1.21.5, ubuntu-latest)

var-naming: type jsonRpcDiagnostics should be jsonRPCDiagnostics (revive)
Params lsp.PublishDiagnosticsParams `json:"params"`
Jsonrpc string `json:"jsonrpc"`
Method string `json:"method"`
}

type readWriteCloseMock struct {
diagnosticsChan chan lsp.PublishDiagnosticsParams
}

func (proc readWriteCloseMock) Read(p []byte) (int, error) {

Check failure on line 28 in internal/adapter/yamlls/integration_test_utils.go

View workflow job for this annotation

GitHub Actions / lint (1.21.5, ubuntu-latest)

unused-parameter: parameter 'p' seems to be unused, consider removing or renaming it as _ (revive)
return 1, nil
}

func (proc readWriteCloseMock) Write(p []byte) (int, error) {
if strings.HasPrefix(string(p), "Content-Length: ") {
return 1, nil
}
var diagnostics jsonRpcDiagnostics
json.NewDecoder(strings.NewReader(string(p))).Decode(&diagnostics)

Check failure on line 37 in internal/adapter/yamlls/integration_test_utils.go

View workflow job for this annotation

GitHub Actions / lint (1.21.5, ubuntu-latest)

Error return value of `(*encoding/json.Decoder).Decode` is not checked (errcheck)

proc.diagnosticsChan <- diagnostics.Params
return 1, nil
}

func (proc readWriteCloseMock) Close() error {
return nil
}

func getYamlLsConnector(t *testing.T, config util.YamllsConfiguration) (*Connector, *lsplocal.DocumentStore, chan lsp.PublishDiagnosticsParams) {
dir := t.TempDir()
documents := lsplocal.NewDocumentStore()
diagnosticsChan := make(chan lsp.PublishDiagnosticsParams)
con := jsonrpc2.NewConn(jsonrpc2.NewStream(readWriteCloseMock{diagnosticsChan}))
zapLogger, _ := zap.NewProduction()
client := protocol.ClientDispatcher(con, zapLogger)

yamllsConnector := NewConnector(config, client, documents)

if yamllsConnector.server == nil {
t.Fatal("Could not connect to yaml-language-server")
}

yamllsConnector.CallInitialize(uri.File(dir))

Check failure on line 61 in internal/adapter/yamlls/integration_test_utils.go

View workflow job for this annotation

GitHub Actions / lint (1.21.5, ubuntu-latest)

Error return value of `yamllsConnector.CallInitialize` is not checked (errcheck)

return yamllsConnector, documents, diagnosticsChan
}

func openFile(t *testing.T, documents *lsplocal.DocumentStore, path string, yamllsConnector *Connector) {
fileURI := uri.File(path)

content, err := os.ReadFile(path)
if err != nil {
t.Fatal("Could not read test file", err)
}
d := lsp.DidOpenTextDocumentParams{
TextDocument: lsp.TextDocumentItem{
URI: fileURI,
LanguageID: "",
Version: 0,
Text: string(content),
},
}
documents.DidOpen(&d, util.DefaultConfig)

Check failure on line 81 in internal/adapter/yamlls/integration_test_utils.go

View workflow job for this annotation

GitHub Actions / lint (1.21.5, ubuntu-latest)

Error return value of `documents.DidOpen` is not checked (errcheck)
tree := lsplocal.ParseAst(nil, d.TextDocument.Text)
yamllsConnector.DocumentDidOpen(tree, d)
}
Loading

0 comments on commit d73e845

Please sign in to comment.