github.com/terraform-linters/tflint@v0.51.2-0.20240520175844-3750771571b6/integrationtest/langserver/langserver_test.go (about)

     1  package main
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"io"
     7  	"log"
     8  	"os"
     9  	"path/filepath"
    10  	"strings"
    11  	"testing"
    12  
    13  	"github.com/hashicorp/logutils"
    14  	lsp "github.com/sourcegraph/go-lsp"
    15  	"github.com/sourcegraph/jsonrpc2"
    16  	"github.com/terraform-linters/tflint/langserver"
    17  	"github.com/terraform-linters/tflint/plugin"
    18  	"github.com/terraform-linters/tflint/tflint"
    19  )
    20  
    21  type jsonrpcMessage struct {
    22  	JSONRPC string      `json:"jsonrpc"`
    23  	ID      int         `json:"id,omitempty"`
    24  	Method  string      `json:"method"`
    25  	Params  interface{} `json:"params"`
    26  }
    27  
    28  func TestMain(m *testing.M) {
    29  	// Disable the bundled plugin because the `os.Executable()` is go(1) in the tests
    30  	tflint.DisableBundledPlugin = true
    31  	defer func() {
    32  		tflint.DisableBundledPlugin = false
    33  	}()
    34  
    35  	filter := &logutils.LevelFilter{
    36  		Levels:   []logutils.LogLevel{"TRACE", "DEBUG", "INFO", "WARN", "ERROR"},
    37  		MinLevel: logutils.LogLevel(""),
    38  		Writer:   os.Stderr,
    39  	}
    40  	log.SetOutput(filter)
    41  	os.Exit(m.Run())
    42  }
    43  
    44  func startServer(t *testing.T, configPath string) (io.Writer, io.Reader, *plugin.Plugin) {
    45  	handler, plugin, err := langserver.NewHandler(configPath, tflint.EmptyConfig())
    46  	if err != nil {
    47  		t.Fatal(err)
    48  	}
    49  
    50  	stdin, stdinWriter := io.Pipe()
    51  	stdoutReader, stdout := io.Pipe()
    52  
    53  	var connOpt []jsonrpc2.ConnOpt
    54  	jsonrpc2.NewConn(
    55  		context.Background(),
    56  		jsonrpc2.NewBufferedStream(langserver.NewConn(stdin, stdout), jsonrpc2.VSCodeObjectCodec{}),
    57  		handler,
    58  		connOpt...,
    59  	)
    60  
    61  	return stdinWriter, stdoutReader, plugin
    62  }
    63  
    64  func pathToURI(path string) lsp.DocumentURI {
    65  	path = filepath.ToSlash(path)
    66  	parts := strings.SplitN(path, "/", 2)
    67  
    68  	head := parts[0]
    69  	if head != "" {
    70  		head = "/" + head
    71  	}
    72  
    73  	rest := ""
    74  	if len(parts) > 1 {
    75  		rest = "/" + parts[1]
    76  	}
    77  
    78  	return lsp.DocumentURI("file://" + head + rest)
    79  }
    80  
    81  func shutdownRequest() string {
    82  	return toJSONRPC2(`{"id":0,"method":"shutdown","params":{},"jsonrpc":"2.0"}`)
    83  }
    84  
    85  func exitRequest() string {
    86  	return toJSONRPC2(`{"id":0,"method":"exit","params":{},"jsonrpc":"2.0"}`)
    87  }
    88  
    89  func emptyResponse() string {
    90  	return toJSONRPC2(`{"id":0,"result":null,"jsonrpc":"2.0"}`)
    91  }
    92  
    93  func toJSONRPC2(json string) string {
    94  	return fmt.Sprintf("Content-Length: %d\r\n\r\n%s", len(json), json)
    95  }
    96  
    97  func withinFixtureDir(t *testing.T, dir string, test func(dir string)) {
    98  	current, err := os.Getwd()
    99  	if err != nil {
   100  		t.Fatal(err)
   101  	}
   102  	defer func() {
   103  		if err = os.Chdir(current); err != nil {
   104  			t.Fatal(err)
   105  		}
   106  	}()
   107  
   108  	dir, err = filepath.Abs("test-fixtures/" + dir)
   109  	if err != nil {
   110  		t.Fatal(err)
   111  	}
   112  	test(dir)
   113  }
   114  
   115  func withinTempDir(t *testing.T, test func(dir string)) {
   116  	current, err := os.Getwd()
   117  	if err != nil {
   118  		t.Fatal(err)
   119  	}
   120  	defer func() {
   121  		if err = os.Chdir(current); err != nil {
   122  			t.Fatal(err)
   123  		}
   124  	}()
   125  
   126  	dir, err := os.MkdirTemp("", "withinTempDir")
   127  	if err != nil {
   128  		t.Fatal(err)
   129  	}
   130  	defer os.RemoveAll(dir)
   131  
   132  	// on macOS MkdirTemp returns a /var/folders/... path
   133  	// In other contexts these paths are returned with their full /private/var/folders/... path
   134  	// EvalSymlinks will resolve the /var/folders/... path to the full path
   135  	dir, err = filepath.EvalSymlinks(dir)
   136  	if err != nil {
   137  		t.Fatal(err)
   138  	}
   139  
   140  	test(dir)
   141  }