// Copyright 2022 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 go1.18
// +build go1.18

package vulncheck

import (
	"bytes"
	"context"
	"fmt"
	"os"
	"path/filepath"
	"sort"
	"testing"

	"github.com/google/go-cmp/cmp"
	"github.com/google/go-cmp/cmp/cmpopts"
	"golang.org/x/tools/go/packages"
	"golang.org/x/tools/internal/lsp/cache"
	"golang.org/x/tools/internal/lsp/fake"
	"golang.org/x/tools/internal/lsp/source"
	"golang.org/x/tools/internal/lsp/tests"
	"golang.org/x/vuln/client"
	"golang.org/x/vuln/osv"
)

func TestCmd_Run(t *testing.T) {
	runTest(t, workspace1, proxy1, func(ctx context.Context, snapshot source.Snapshot) {
		cmd := &cmd{Client: testClient1}
		cfg := packagesCfg(ctx, snapshot)
		result, err := cmd.Run(ctx, cfg, "./...")
		if err != nil {
			t.Fatal(err)
		}
		// Check that we find the right number of vulnerabilities.
		// There should be three entries as there are three vulnerable
		// symbols in the two import-reachable OSVs.
		var got []report
		for _, v := range result {
			got = append(got, toReport(v))
		}

		var want = []report{
			{
				Vuln: Vuln{
					ID:             "GO-2022-01",
					Symbol:         "VulnData.Vuln1",
					PkgPath:        "golang.org/amod/avuln",
					ModPath:        "golang.org/amod",
					URL:            "https://pkg.go.dev/vuln/GO-2022-01",
					CurrentVersion: "v1.1.3",
					FixedVersion:   "v1.0.4",
					CallStackSummaries: []string{
						"golang.org/entry/x.X calls golang.org/amod/avuln.VulnData.Vuln1",
						"golang.org/entry/x.X calls golang.org/cmod/c.C1, which eventually calls golang.org/amod/avuln.VulnData.Vuln2",
					},
				},
				CallStacksStr: []string{
					"golang.org/entry/x.X [approx.] (x.go:8)\n" +
						"golang.org/amod/avuln.VulnData.Vuln1 (avuln.go:3)\n",
					"golang.org/entry/x.X (x.go:8)\n" +
						"golang.org/cmod/c.C1 (c.go:13)\n" +
						"golang.org/amod/avuln.VulnData.Vuln2 (avuln.go:4)\n",
				},
			},
			{
				Vuln: Vuln{
					ID:                 "GO-2022-02",
					Symbol:             "Vuln",
					PkgPath:            "golang.org/bmod/bvuln",
					ModPath:            "golang.org/bmod",
					URL:                "https://pkg.go.dev/vuln/GO-2022-02",
					CurrentVersion:     "v0.5.0",
					CallStackSummaries: []string{"golang.org/entry/y.Y calls golang.org/bmod/bvuln.Vuln"},
				},
				CallStacksStr: []string{
					"golang.org/entry/y.Y [approx.] (y.go:5)\n" +
						"golang.org/bmod/bvuln.Vuln (bvuln.go:2)\n",
				},
			},
		}
		// sort reports for stability before comparison.
		for _, rpts := range [][]report{got, want} {
			sort.Slice(rpts, func(i, j int) bool {
				a, b := rpts[i], rpts[j]
				if a.ID != b.ID {
					return a.ID < b.ID
				}
				if a.PkgPath != b.PkgPath {
					return a.PkgPath < b.PkgPath
				}
				return a.Symbol < b.Symbol
			})
		}
		if diff := cmp.Diff(want, got, cmpopts.IgnoreFields(report{}, "Vuln.CallStacks")); diff != "" {
			t.Error(diff)
		}

	})
}

type report struct {
	Vuln
	// Trace is stringified Vuln.CallStacks
	CallStacksStr []string
}

func toReport(v Vuln) report {
	var r = report{Vuln: v}
	for _, s := range v.CallStacks {
		r.CallStacksStr = append(r.CallStacksStr, CallStackString(s))
	}
	return r
}

func CallStackString(callstack CallStack) string {
	var b bytes.Buffer
	for _, entry := range callstack {
		fname := filepath.Base(entry.URI.SpanURI().Filename())
		fmt.Fprintf(&b, "%v (%v:%d)\n", entry.Name, fname, entry.Pos.Line)
	}
	return b.String()
}

const workspace1 = `
-- go.mod --
module golang.org/entry

require (
	golang.org/cmod v1.1.3
)
go 1.18
-- x/x.go --
package x

import 	(
   "golang.org/cmod/c"
   "golang.org/entry/y"
)

func X() {
	c.C1().Vuln1() // vuln use: X -> Vuln1
}

func CallY() {
	y.Y()  // vuln use: CallY -> y.Y -> bvuln.Vuln 
}

-- y/y.go --
package y

import "golang.org/cmod/c"

func Y() {
	c.C2()() // vuln use: Y -> bvuln.Vuln
}
`

const proxy1 = `
-- golang.org/cmod@v1.1.3/go.mod --
module golang.org/cmod

go 1.12
-- golang.org/cmod@v1.1.3/c/c.go --
package c

import (
	"golang.org/amod/avuln"
	"golang.org/bmod/bvuln"
)

type I interface {
	Vuln1()
}

func C1() I {
	v := avuln.VulnData{}
	v.Vuln2() // vuln use
	return v
}

func C2() func() {
	return bvuln.Vuln
}
-- golang.org/amod@v1.1.3/go.mod --
module golang.org/amod

go 1.14
-- golang.org/amod@v1.1.3/avuln/avuln.go --
package avuln

type VulnData struct {}
func (v VulnData) Vuln1() {}
func (v VulnData) Vuln2() {}
-- golang.org/bmod@v0.5.0/go.mod --
module golang.org/bmod

go 1.14
-- golang.org/bmod@v0.5.0/bvuln/bvuln.go --
package bvuln

func Vuln() {
	// something evil
}
`

// testClient contains the following test vulnerabilities
//
//	golang.org/amod/avuln.{VulnData.Vuln1, vulnData.Vuln2}
//	golang.org/bmod/bvuln.{Vuln}
var testClient1 = &mockClient{
	ret: map[string][]*osv.Entry{
		"golang.org/amod": {
			{
				ID: "GO-2022-01",
				References: []osv.Reference{
					{
						Type: "href",
						URL:  "pkg.go.dev/vuln/GO-2022-01",
					},
				},
				Affected: []osv.Affected{{
					Package:           osv.Package{Name: "golang.org/amod/avuln"},
					Ranges:            osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Introduced: "1.0.0"}, {Fixed: "1.0.4"}, {Introduced: "1.1.2"}}}},
					EcosystemSpecific: osv.EcosystemSpecific{Symbols: []string{"VulnData.Vuln1", "VulnData.Vuln2"}},
				}},
			},
		},
		"golang.org/bmod": {
			{
				ID: "GO-2022-02",
				Affected: []osv.Affected{{
					Package:           osv.Package{Name: "golang.org/bmod/bvuln"},
					Ranges:            osv.Affects{{Type: osv.TypeSemver}},
					EcosystemSpecific: osv.EcosystemSpecific{Symbols: []string{"Vuln"}},
				}},
			},
		},
	},
}

type mockClient struct {
	client.Client
	ret map[string][]*osv.Entry
}

func (mc *mockClient) GetByModule(ctx context.Context, a string) ([]*osv.Entry, error) {
	return mc.ret[a], nil
}

func runTest(t *testing.T, workspaceData, proxyData string, test func(context.Context, source.Snapshot)) {
	ws, err := fake.NewSandbox(&fake.SandboxConfig{
		Files:      fake.UnpackTxt(workspaceData),
		ProxyFiles: fake.UnpackTxt(proxyData),
	})
	if err != nil {
		t.Fatal(err)
	}
	defer ws.Close()

	ctx := tests.Context(t)

	// get the module cache populated and the go.sum file at the root auto-generated.
	dir := ws.Workdir.RootURI().SpanURI().Filename()
	if err := ws.RunGoCommand(ctx, dir, "list", []string{"-mod=mod", "..."}, true); err != nil {
		t.Fatal(err)
	}

	cache := cache.New(nil)
	session := cache.NewSession(ctx)
	options := source.DefaultOptions().Clone()
	tests.DefaultOptions(options)
	session.SetOptions(options)
	envs := []string{}
	for k, v := range ws.GoEnv() {
		envs = append(envs, k+"="+v)
	}
	options.SetEnvSlice(envs)
	name := ws.RootDir()
	folder := ws.Workdir.RootURI().SpanURI()
	view, snapshot, release, err := session.NewView(ctx, name, folder, options)
	if err != nil {
		t.Fatal(err)
	}
	defer release()
	defer view.Shutdown(ctx)

	test(ctx, snapshot)
}

// TODO: expose this as a method of Snapshot.
func packagesCfg(ctx context.Context, snapshot source.Snapshot) *packages.Config {
	view := snapshot.View()
	viewBuildFlags := view.Options().BuildFlags
	var viewEnv []string
	if e := view.Options().EnvSlice(); e != nil {
		viewEnv = append(os.Environ(), e...)
	}
	return &packages.Config{
		// Mode will be set by cmd.Run.
		Context:    ctx,
		Tests:      true,
		BuildFlags: viewBuildFlags,
		Env:        viewEnv,
		Dir:        view.Folder().Filename(),
	}
}
