// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package profiler

import (
	"bytes"
	"testing"

	"cloud.google.com/go/internal/testutil"
	"github.com/google/go-cmp/cmp/cmpopts"
	"github.com/google/pprof/profile"
)

type fakeFunc struct {
	name   string
	file   string
	lineno int
}

func (f *fakeFunc) Name() string {
	return f.name
}
func (f *fakeFunc) FileLine(_ uintptr) (string, int) {
	return f.file, f.lineno
}

var cmpOpt = cmpopts.IgnoreUnexported(profile.Profile{}, profile.Function{},
	profile.Line{}, profile.Location{}, profile.Sample{}, profile.ValueType{})

// TestRuntimeFunctionTrimming tests if symbolize trims runtime functions as intended.
func TestRuntimeFunctionTrimming(t *testing.T) {
	fakeFuncMap := map[uintptr]*fakeFunc{
		0x10: &fakeFunc{"runtime.goexit", "runtime.go", 10},
		0x20: &fakeFunc{"runtime.other", "runtime.go", 20},
		0x30: &fakeFunc{"foo", "foo.go", 30},
		0x40: &fakeFunc{"bar", "bar.go", 40},
	}
	backupFuncForPC := funcForPC
	funcForPC = func(pc uintptr) function {
		return fakeFuncMap[pc]
	}
	defer func() {
		funcForPC = backupFuncForPC
	}()
	testLoc := []*profile.Location{
		{ID: 1, Address: 0x10},
		{ID: 2, Address: 0x20},
		{ID: 3, Address: 0x30},
		{ID: 4, Address: 0x40},
	}
	testProfile := &profile.Profile{
		Sample: []*profile.Sample{
			{Location: []*profile.Location{testLoc[0], testLoc[1], testLoc[3], testLoc[2]}},
			{Location: []*profile.Location{testLoc[1], testLoc[3], testLoc[2]}},
			{Location: []*profile.Location{testLoc[3], testLoc[2], testLoc[1]}},
			{Location: []*profile.Location{testLoc[3], testLoc[2], testLoc[0]}},
			{Location: []*profile.Location{testLoc[0], testLoc[1], testLoc[3], testLoc[0]}},
			{Location: []*profile.Location{testLoc[1], testLoc[0]}},
		},
		Location: testLoc,
	}
	testProfiles := make([]*profile.Profile, 2)
	testProfiles[0] = testProfile.Copy()
	testProfiles[1] = testProfile.Copy()
	// Test case for CPU profile.
	testProfiles[0].PeriodType = &profile.ValueType{Type: "cpu", Unit: "nanoseconds"}
	// Test case for heap profile.
	testProfiles[1].PeriodType = &profile.ValueType{Type: "space", Unit: "bytes"}
	wantFunc := []*profile.Function{
		{ID: 1, Name: "runtime.goexit", SystemName: "runtime.goexit", Filename: "runtime.go"},
		{ID: 2, Name: "runtime.other", SystemName: "runtime.other", Filename: "runtime.go"},
		{ID: 3, Name: "foo", SystemName: "foo", Filename: "foo.go"},
		{ID: 4, Name: "bar", SystemName: "bar", Filename: "bar.go"},
	}
	wantLoc := []*profile.Location{
		{ID: 1, Address: 0x10, Line: []profile.Line{{Function: wantFunc[0], Line: 10}}},
		{ID: 2, Address: 0x20, Line: []profile.Line{{Function: wantFunc[1], Line: 20}}},
		{ID: 3, Address: 0x30, Line: []profile.Line{{Function: wantFunc[2], Line: 30}}},
		{ID: 4, Address: 0x40, Line: []profile.Line{{Function: wantFunc[3], Line: 40}}},
	}
	wantProfiles := []*profile.Profile{
		{
			PeriodType: &profile.ValueType{Type: "cpu", Unit: "nanoseconds"},
			Sample: []*profile.Sample{
				{Location: []*profile.Location{wantLoc[1], wantLoc[3], wantLoc[2]}},
				{Location: []*profile.Location{wantLoc[1], wantLoc[3], wantLoc[2]}},
				{Location: []*profile.Location{wantLoc[3], wantLoc[2], wantLoc[1]}},
				{Location: []*profile.Location{wantLoc[3], wantLoc[2]}},
				{Location: []*profile.Location{wantLoc[1], wantLoc[3]}},
				{Location: []*profile.Location{wantLoc[1]}},
			},
			Location: wantLoc,
			Function: wantFunc,
		},
		{
			PeriodType: &profile.ValueType{Type: "space", Unit: "bytes"},
			Sample: []*profile.Sample{
				{Location: []*profile.Location{wantLoc[3], wantLoc[2]}},
				{Location: []*profile.Location{wantLoc[3], wantLoc[2]}},
				{Location: []*profile.Location{wantLoc[3], wantLoc[2], wantLoc[1]}},
				{Location: []*profile.Location{wantLoc[3], wantLoc[2]}},
				{Location: []*profile.Location{wantLoc[3]}},
				{Location: []*profile.Location{wantLoc[0]}},
			},
			Location: wantLoc,
			Function: wantFunc,
		},
	}
	for i := 0; i < 2; i++ {
		symbolize(testProfiles[i])
		if !testutil.Equal(testProfiles[i], wantProfiles[i], cmpOpt) {
			t.Errorf("incorrect trimming (testcase = %d): got {%v}, want {%v}", i, testProfiles[i], wantProfiles[i])
		}
	}
}

// TestParseAndSymbolize tests if parseAndSymbolize parses and symbolizes
// profiles as intended.
func TestParseAndSymbolize(t *testing.T) {
	fakeFuncMap := map[uintptr]*fakeFunc{
		0x10: &fakeFunc{"foo", "foo.go", 10},
		0x20: &fakeFunc{"bar", "bar.go", 20},
	}
	backupFuncForPC := funcForPC
	funcForPC = func(pc uintptr) function {
		return fakeFuncMap[pc]
	}
	defer func() {
		funcForPC = backupFuncForPC
	}()

	testLoc := []*profile.Location{
		{ID: 1, Address: 0x10},
		{ID: 2, Address: 0x20},
	}
	testProfile := &profile.Profile{
		SampleType: []*profile.ValueType{
			&profile.ValueType{Type: "cpu", Unit: "nanoseconds"},
		},
		PeriodType: &profile.ValueType{Type: "cpu", Unit: "nanoseconds"},
		Sample: []*profile.Sample{
			{Location: []*profile.Location{testLoc[0], testLoc[1]}, Value: []int64{1}},
			{Location: []*profile.Location{testLoc[1]}, Value: []int64{1}},
		},
		Location: testLoc,
	}
	testProfiles := make([]*profile.Profile, 2)
	testProfiles[0] = testProfile.Copy()
	testProfiles[1] = testProfile.Copy()

	wantFunc := []*profile.Function{
		{ID: 1, Name: "foo", SystemName: "foo", Filename: "foo.go"},
		{ID: 2, Name: "bar", SystemName: "bar", Filename: "bar.go"},
	}
	wantLoc := []*profile.Location{
		{ID: 1, Address: 0x10, Line: []profile.Line{{Function: wantFunc[0], Line: 10}}},
		{ID: 2, Address: 0x20, Line: []profile.Line{{Function: wantFunc[1], Line: 20}}},
	}
	wantProfile := &profile.Profile{
		SampleType: []*profile.ValueType{
			&profile.ValueType{Type: "cpu", Unit: "nanoseconds"},
		},
		PeriodType: &profile.ValueType{Type: "cpu", Unit: "nanoseconds"},
		Sample: []*profile.Sample{
			{Location: []*profile.Location{wantLoc[0], wantLoc[1]}, Value: []int64{1}},
			{Location: []*profile.Location{wantLoc[1]}, Value: []int64{1}},
		},
		Location: wantLoc,
		Function: wantFunc,
	}

	// Profile already symbolized.
	testProfiles[1].Location = []*profile.Location{
		{ID: 1, Address: 0x10, Line: []profile.Line{{Function: wantFunc[0], Line: 10}}},
		{ID: 2, Address: 0x20, Line: []profile.Line{{Function: wantFunc[1], Line: 20}}},
	}
	testProfiles[1].Function = []*profile.Function{
		{ID: 1, Name: "foo", SystemName: "foo", Filename: "foo.go"},
		{ID: 2, Name: "bar", SystemName: "bar", Filename: "bar.go"},
	}
	for i := 0; i < 2; i++ {
		var prof bytes.Buffer
		testProfiles[i].Write(&prof)

		parseAndSymbolize(&prof)
		gotProfile, err := profile.ParseData(prof.Bytes())
		if err != nil {
			t.Errorf("parsing symbolized profile (testcase = %d) got err: %v, want no error", i, err)
		}
		if !testutil.Equal(gotProfile, wantProfile, cmpOpt) {
			t.Errorf("incorrect symbolization (testcase = %d): got {%v}, want {%v}", i, gotProfile, wantProfile)
		}
	}
}

func TestIsSymbolizedGoVersion(t *testing.T) {
	for _, tc := range []struct {
		input string
		want  bool
	}{
		{"go1.9beta2", true},
		{"go1.9", true},
		{"go1.9.1", true},
		{"go1.10", true},
		{"go1.10.1", true},
		{"go2.0", true},
		{"go3.1", true},
		{"go1.8", false},
		{"go1.8.1", false},
		{"go1.7", false},
		{"devel ", false},
	} {
		if got := isSymbolizedGoVersion(tc.input); got != tc.want {
			t.Errorf("isSymbolizedGoVersion(%v) got %v, want %v", tc.input, got, tc.want)
		}
	}
}
