// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build go.1.16
// +build go.1.16

// Running this program in the tools directory will produce a coverage file /tmp/cover.out
// and a coverage report for all the packages under internal/lsp, accumulated by all the tests
// under gopls.
//
// -o controls where the coverage file is written, defaulting to /tmp/cover.out
// -i coverage-file will generate the report from an existing coverage file
// -v controls verbosity (0: only report coverage, 1: report as each directory is finished,
//      2: report on each test, 3: more details, 4: too much)
// -t tests only tests packages in the given comma-separated list of directories in gopls.
//      The names should start with ., as in ./internal/regtest/bench
// -run tests. If set, -run tests is passed on to the go test command.
//
// Despite gopls' use of goroutines, the counts are almost deterministic.
package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"sort"
	"strings"
	"time"

	"golang.org/x/tools/cover"
)

var (
	proFile = flag.String("i", "", "existing profile file")
	outFile = flag.String("o", "/tmp/cover.out", "where to write the coverage file")
	verbose = flag.Int("v", 0, "how much detail to print as tests are running")
	tests   = flag.String("t", "", "list of tests to run")
	run     = flag.String("run", "", "value of -run to pass to go test")
)

func main() {
	log.SetFlags(log.Lshortfile)
	flag.Parse()

	if *proFile != "" {
		report(*proFile)
		return
	}

	checkCwd()
	// find the packages under gopls containing tests
	tests := listDirs("gopls")
	tests = onlyTests(tests)
	tests = realTestName(tests)

	// report coverage for packages under internal/lsp
	parg := "golang.org/x/tools/internal/lsp/..."

	accum := []string{}
	seen := make(map[string]bool)
	now := time.Now()
	for _, toRun := range tests {
		if excluded(toRun) {
			continue
		}
		x := runTest(toRun, parg)
		if *verbose > 0 {
			fmt.Printf("finished %s %.1fs\n", toRun, time.Since(now).Seconds())
		}
		lines := bytes.Split(x, []byte{'\n'})
		for _, l := range lines {
			if len(l) == 0 {
				continue
			}
			if !seen[string(l)] {
				// not accumulating counts, so only works for mode:set
				seen[string(l)] = true
				accum = append(accum, string(l))
			}
		}
	}
	sort.Strings(accum[1:])
	if err := os.WriteFile(*outFile, []byte(strings.Join(accum, "\n")), 0644); err != nil {
		log.Print(err)
	}
	report(*outFile)
}

type result struct {
	Time    time.Time
	Test    string
	Action  string
	Package string
	Output  string
	Elapsed float64
}

func runTest(tName, parg string) []byte {
	args := []string{"test", "-short", "-coverpkg", parg, "-coverprofile", *outFile,
		"-json"}
	if *run != "" {
		args = append(args, fmt.Sprintf("-run=%s", *run))
	}
	args = append(args, tName)
	cmd := exec.Command("go", args...)
	cmd.Dir = "./gopls"
	ans, err := cmd.Output()
	if *verbose > 1 {
		got := strings.Split(string(ans), "\n")
		for _, g := range got {
			if g == "" {
				continue
			}
			var m result
			if err := json.Unmarshal([]byte(g), &m); err != nil {
				log.Printf("%T/%v", err, err) // shouldn't happen
				continue
			}
			maybePrint(m)
		}
	}
	if err != nil {
		log.Printf("%s: %q, cmd=%s", tName, ans, cmd.String())
	}
	buf, err := os.ReadFile(*outFile)
	if err != nil {
		log.Fatal(err)
	}
	return buf
}

func report(fn string) {
	profs, err := cover.ParseProfiles(fn)
	if err != nil {
		log.Fatal(err)
	}
	for _, p := range profs {
		statements, counts := 0, 0
		for _, x := range p.Blocks {
			statements += x.NumStmt
			if x.Count != 0 {
				counts += x.NumStmt // sic: if any were executed, all were
			}
		}
		pc := 100 * float64(counts) / float64(statements)
		fmt.Printf("%3.0f%% %3d/%3d %s\n", pc, counts, statements, p.FileName)
	}
}

var todo []string // tests to run

func excluded(tname string) bool {
	if *tests == "" { // run all tests
		return false
	}
	if todo == nil {
		todo = strings.Split(*tests, ",")
	}
	for _, nm := range todo {
		if tname == nm { // run this test
			return false
		}
	}
	// not in list, skip it
	return true
}

// should m.Package be printed sometime?
func maybePrint(m result) {
	switch m.Action {
	case "pass", "fail", "skip":
		fmt.Printf("%s %s %.3f\n", m.Action, m.Test, m.Elapsed)
	case "run":
		if *verbose > 2 {
			fmt.Printf("%s %s %.3f\n", m.Action, m.Test, m.Elapsed)
		}
	case "output":
		if *verbose > 3 {
			fmt.Printf("%s %s %q %.3f\n", m.Action, m.Test, m.Output, m.Elapsed)
		}
	default:
		log.Fatalf("unknown action %s\n", m.Action)
	}
}

// return only the directories that contain tests
func onlyTests(s []string) []string {
	ans := []string{}
outer:
	for _, d := range s {
		files, err := os.ReadDir(d)
		if err != nil {
			log.Fatalf("%s: %v", d, err)
		}
		for _, de := range files {
			if strings.Contains(de.Name(), "_test.go") {
				ans = append(ans, d)
				continue outer
			}
		}
	}
	return ans
}

// replace the prefix gopls/ with ./ as the tests are run in the gopls directory
func realTestName(p []string) []string {
	ans := []string{}
	for _, x := range p {
		x = x[len("gopls/"):]
		ans = append(ans, "./"+x)
	}
	return ans
}

// make sure we start in a tools directory
func checkCwd() {
	dir, err := os.Getwd()
	if err != nil {
		log.Fatal(err)
	}
	// we expect to be a the root of golang.org/x/tools
	cmd := exec.Command("go", "list", "-m", "-f", "{{.Dir}}", "golang.org/x/tools")
	buf, err := cmd.Output()
	buf = bytes.Trim(buf, "\n \t") // remove \n at end
	if err != nil {
		log.Fatal(err)
	}
	if string(buf) != dir {
		log.Fatalf("wrong directory: in %q, should be in %q", dir, string(buf))
	}
	// and we expect gopls and internal/lsp as subdirectories
	_, err = os.Stat("gopls")
	if err != nil {
		log.Fatalf("expected a gopls directory, %v", err)
	}
	_, err = os.Stat("internal/lsp")
	if err != nil {
		log.Fatalf("expected to see internal/lsp, %v", err)
	}
}

func listDirs(dir string) []string {
	ans := []string{}
	f := func(path string, dirEntry os.DirEntry, err error) error {
		if strings.HasSuffix(path, "/testdata") || strings.HasSuffix(path, "/typescript") {
			return filepath.SkipDir
		}
		if dirEntry.IsDir() {
			ans = append(ans, path)
		}
		return nil
	}
	filepath.WalkDir(dir, f)
	return ans
}
