diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a860320..90fbe22 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -3,7 +3,7 @@ name: Test jobs: test: - timeout-minutes: 5 + timeout-minutes: 30 strategy: matrix: go-version: [1.19.x, 1.20.x] @@ -41,10 +41,6 @@ jobs: run: go install golang.org/x/tools/gopls@latest working-directory: / - - name: Install Edwood - run: go install -tags 'duitdraw mux9p' github.com/rjkroege/edwood@v0.2.1-0.20191103164119-87ca479e7ef7 - working-directory: / - - name: Install pyls on unix if: matrix.platform != 'windows-latest' run: sudo python3 -m pip install 'python-language-server[yapf]' diff --git a/cmd/acme-lsp/main_test.go b/cmd/acme-lsp/main_test.go deleted file mode 100644 index aa6fd3a..0000000 --- a/cmd/acme-lsp/main_test.go +++ /dev/null @@ -1,194 +0,0 @@ -package main - -import ( - "context" - "fmt" - "io/ioutil" - "log" - "net" - "os" - "os/exec" - "runtime" - "sync" - "testing" - "time" - - "github.com/fhs/acme-lsp/internal/acme" - "github.com/fhs/acme-lsp/internal/lsp/acmelsp/config" -) - -func TestMain(m *testing.M) { - // TODO: Replace Xvfb with a fake devdraw. - var x *exec.Cmd - var authfile string - - switch runtime.GOOS { - case "linux", "freebsd", "openbsd", "netbsd", "dragonfly": - if os.Getenv("DISPLAY") == "" { - dp := fmt.Sprintf(":%d", xvfbServerNumber()) - - var err error - authfile, err = createAuthFile(dp) - if err != nil { - log.Printf("failed to create auth file: %v", err) - } else { - os.Setenv("XAUTHORITY", authfile) - } - - x = exec.Command("Xvfb", dp, "-screen", "0", "1024x768x24") - x.Stdout = os.Stdout - x.Stderr = os.Stderr - if err := x.Start(); err != nil { - log.Fatalf("failed to execute Xvfb: %v", err) - } - // Wait for Xvfb to start up. - for i := 0; i < 60; i++ { - err := exec.Command("xdpyinfo", "-display", dp).Run() - if err == nil { - break - } - if _, ok := err.(*exec.ExitError); !ok { - log.Fatalf("failed to execute xdpyinfo: %v", err) - } - log.Printf("waiting for Xvfb (try %v) ...\n", i) - time.Sleep(time.Second) - } - os.Setenv("DISPLAY", dp) - } - } - e := m.Run() - - if x != nil { - // Kill Xvfb gracefully, so that it cleans up the /tmp/.X*-lock file. - x.Process.Signal(os.Interrupt) - x.Wait() - - } - if authfile != "" { - os.Unsetenv("XAUTHORITY") - os.Remove(authfile) - } - os.Exit(e) -} - -func createAuthFile(display string) (authfile string, err error) { - // Generated by mcookie(1). See also xvfb-run(1). - const cookie = "8e983fb3d46f59eed620181dfaab5a7a" - - f, err := ioutil.TempFile("", "xvfb-xauth-") - if err != nil { - return "", err - } - name := f.Name() - - cmd := exec.Command("xauth", "add", display, ".", cookie) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - cmd.Env = append(os.Environ(), fmt.Sprintf("XAUTHORITY=%v", name)) - err = cmd.Run() - if err != nil { - os.Remove(name) - return "", err - } - return name, nil -} - -// XvfbServerNumber finds a free server number for Xfvb. -// Similar logic is used by /usr/bin/xvfb-run:/^find_free_servernum/ -func xvfbServerNumber() int { - for n := 99; n < 1000; n++ { - if _, err := os.Stat(fmt.Sprintf("/tmp/.X%d-lock", n)); os.IsNotExist(err) { - return n - } - } - panic("no free X server number") -} - -func TestAcmeLSP(t *testing.T) { - t.Skip("hangs") - switch runtime.GOOS { - case "darwin": - t.Skip("skipping on darwin because Edwood is crashing") - case "windows": - t.Skip("skipping on windows because unix domain sockets are not supported") - } - dir, err := ioutil.TempDir("", "acme-lsp-test") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(dir) - - os.Setenv("NAMESPACE", dir) - - cfg := config.Default() - cfg.Servers = map[string]*config.Server{ - "gopls": { - Command: []string{"gopls", "serve"}, - }, - } - cfg.FilenameHandlers = []config.FilenameHandler{ - { - Pattern: `\.go`, - ServerKey: "gopls", - }, - } - // Setup custom acme package - acme.Network = cfg.AcmeNetwork - acme.Address = cfg.AcmeAddress - - ctx, cancel := context.WithCancel(context.Background()) - var wg sync.WaitGroup - - defer func() { - cancel() - wg.Wait() - }() - - // Use Edwood instead of plan9port acme because it's - // easier to install on CI systems and it seems to be - // easier to kill than acme. Sending a KILL signal to - // acme doesn't really kill it. - cmd := exec.CommandContext(ctx, "edwood", "-c", "1") - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - cmd.Env = append(os.Environ(), fmt.Sprintf("NAMESPACE=%v", dir)) - if err := cmd.Start(); err != nil { - t.Fatalf("failed to start edwood: %v", err) - } - wg.Add(1) - go func() { - defer wg.Done() - if err := cmd.Wait(); err != nil { - t.Logf("edwood died: %v", err) - } - }() - - // Wait for acme to start up. - acmeReady := false - for i := 0; i < 60; i++ { - conn, err := net.Dial(cfg.AcmeNetwork, cfg.AcmeAddress) - if err == nil { - conn.Close() - acmeReady = true - break - } - t.Logf("waiting for acme (try %d) ...", i) - time.Sleep(time.Second) - } - if !acmeReady { - t.Fatalf("acme did not become ready") - } - - app, err := NewApplication(ctx, cfg, nil) - if err != nil { - t.Fatalf("failed to create application: %v", err) - } - - wg.Add(1) - go func() { - defer wg.Done() - if err := app.Run(ctx); err != nil { - t.Logf("acme-lsp: %v", err) - } - }() -}