// 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.

package scan

import (
	"strings"
	"testing"

	"golang.org/x/vuln/internal/govulncheck"
)

func TestFrame(t *testing.T) {
	for _, test := range []struct {
		name     string
		frame    *govulncheck.Frame
		wantFunc string
		wantPos  string
	}{
		{
			name: "position and function",
			frame: &govulncheck.Frame{
				Package:  "golang.org/x/vuln/internal/vulncheck",
				Function: "Foo",
				Position: &govulncheck.Position{Filename: "some/path/file.go", Line: 12},
			},
			wantFunc: "golang.org/x/vuln/internal/vulncheck.Foo",
			wantPos:  "some/path/file.go:12",
		},
		{
			name: "receiver",
			frame: &govulncheck.Frame{
				Package:  "golang.org/x/vuln/internal/vulncheck",
				Receiver: "Bar",
				Function: "Foo",
			},
			wantFunc: "golang.org/x/vuln/internal/vulncheck.Bar.Foo",
		},
		{
			name:     "function and receiver",
			frame:    &govulncheck.Frame{Receiver: "*ServeMux", Function: "Handle"},
			wantFunc: "ServeMux.Handle",
		},
		{
			name:     "package and function",
			frame:    &govulncheck.Frame{Package: "net/http", Function: "Get"},
			wantFunc: "net/http.Get",
		},
		{
			name:     "package, function and receiver",
			frame:    &govulncheck.Frame{Package: "net/http", Receiver: "*ServeMux", Function: "Handle"},
			wantFunc: "net/http.ServeMux.Handle",
		},
	} {
		t.Run(test.name, func(t *testing.T) {
			buf := &strings.Builder{}
			addSymbolName(buf, test.frame)
			got := buf.String()
			if got != test.wantFunc {
				t.Errorf("want %v func name; got %v", test.wantFunc, got)
			}
			if got := posToString(test.frame.Position); got != test.wantPos {
				t.Errorf("want %v call position; got %v", test.wantPos, got)
			}
		})
	}
}

func TestVuln(t *testing.T) {
	// vuln creates a Vuln with symbol info syms.
	// Each element of syms is a pair <p, s> where
	// p is both the module and package path, and
	// s is the called symbol. If s is "", then
	// there is no called symbol.
	vuln := func(syms ...[2]string) []*govulncheck.Finding {
		result := []*govulncheck.Finding{}
		for _, sym := range syms {
			result = append(result, &govulncheck.Finding{
				OSV:          "",
				FixedVersion: "",
				Trace: []*govulncheck.Frame{{
					Module:   sym[0],
					Package:  sym[0],
					Function: sym[1],
					Position: &govulncheck.Position{},
				}},
			})
		}
		return result
	}

	for _, test := range []struct {
		desc string
		v    []*govulncheck.Finding
		want bool
	}{
		{"called - single module", vuln([2]string{"golang.org/p1", "Foo"}), true},
		{"called - multi modules", vuln([2]string{"golang.org/p1", "Foo"}, [2]string{"golang.org/p2", "Bar"}), true},
		// The following case is not expected to happen in practice, but we check it for sanity.
		{"called - mixed multi modules", vuln([2]string{"golang.org/p1", ""}, [2]string{"golang.org/p2", "Bar"}), true},
		{"not called - single module", vuln([2]string{"golang.org/p1", ""}), false},
		{"not called - multi modules", vuln([2]string{"golang.org/p1", ""}, [2]string{"golang.org/p2", ""}), false},
	} {
		if IsCalled(test.v) != test.want {
			t.Errorf("want called=%t for %v; got the opposite", test.want, test.desc)
		}
	}
}
