// Copyright 2016 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 pprof

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"reflect"
	"runtime"
	"runtime/pprof/internal/profile"
	"strings"
	"testing"
)

// translateCPUProfile parses binary CPU profiling stack trace data
// generated by runtime.CPUProfile() into a profile struct.
// This is only used for testing. Real conversions stream the
// data into the profileBuilder as it becomes available.
func translateCPUProfile(data []uint64) (*profile.Profile, error) {
	var buf bytes.Buffer
	b := newProfileBuilder(&buf)
	if err := b.addCPUData(data, nil); err != nil {
		return nil, err
	}
	b.build()
	return profile.Parse(&buf)
}

// fmtJSON returns a pretty-printed JSON form for x.
// It works reasonbly well for printing protocol-buffer
// data structures like profile.Profile.
func fmtJSON(x interface{}) string {
	js, _ := json.MarshalIndent(x, "", "\t")
	return string(js)
}

func TestConvertCPUProfileEmpty(t *testing.T) {
	// A test server with mock cpu profile data.
	var buf bytes.Buffer

	b := []uint64{3, 0, 500} // empty profile at 500 Hz (2ms sample period)
	p, err := translateCPUProfile(b)
	if err != nil {
		t.Fatalf("translateCPUProfile: %v", err)
	}
	if err := p.Write(&buf); err != nil {
		t.Fatalf("writing profile: %v", err)
	}

	p, err = profile.Parse(&buf)
	if err != nil {
		t.Fatalf("profile.Parse: %v", err)
	}

	// Expected PeriodType and SampleType.
	periodType := &profile.ValueType{Type: "cpu", Unit: "nanoseconds"}
	sampleType := []*profile.ValueType{
		{Type: "samples", Unit: "count"},
		{Type: "cpu", Unit: "nanoseconds"},
	}

	checkProfile(t, p, 2000*1000, periodType, sampleType, nil)
}

func f1() { f1() }
func f2() { f2() }

// testPCs returns two PCs and two corresponding memory mappings
// to use in test profiles.
func testPCs(t *testing.T) (addr1, addr2 uint64, map1, map2 *profile.Mapping) {
	switch runtime.GOOS {
	case "linux", "android", "netbsd":
		// Figure out two addresses from /proc/self/maps.
		mmap, err := ioutil.ReadFile("/proc/self/maps")
		if err != nil {
			t.Fatal(err)
		}
		mprof := &profile.Profile{}
		if err = mprof.ParseMemoryMap(bytes.NewReader(mmap)); err != nil {
			t.Fatalf("parsing /proc/self/maps: %v", err)
		}
		if len(mprof.Mapping) < 2 {
			// It is possible for a binary to only have 1 executable
			// region of memory.
			t.Skipf("need 2 or more mappings, got %v", len(mprof.Mapping))
		}
		addr1 = mprof.Mapping[0].Start
		map1 = mprof.Mapping[0]
		map1.BuildID, _ = elfBuildID(map1.File)
		addr2 = mprof.Mapping[1].Start
		map2 = mprof.Mapping[1]
		map2.BuildID, _ = elfBuildID(map2.File)
	default:
		addr1 = uint64(funcPC(f1))
		addr2 = uint64(funcPC(f2))
	}
	return
}

func TestConvertCPUProfile(t *testing.T) {
	addr1, addr2, map1, map2 := testPCs(t)

	b := []uint64{
		3, 0, 500, // hz = 500
		5, 0, 10, uint64(addr1), uint64(addr1 + 2), // 10 samples in addr1
		5, 0, 40, uint64(addr2), uint64(addr2 + 2), // 40 samples in addr2
		5, 0, 10, uint64(addr1), uint64(addr1 + 2), // 10 samples in addr1
	}
	p, err := translateCPUProfile(b)
	if err != nil {
		t.Fatalf("translating profile: %v", err)
	}
	period := int64(2000 * 1000)
	periodType := &profile.ValueType{Type: "cpu", Unit: "nanoseconds"}
	sampleType := []*profile.ValueType{
		{Type: "samples", Unit: "count"},
		{Type: "cpu", Unit: "nanoseconds"},
	}
	samples := []*profile.Sample{
		{Value: []int64{20, 20 * 2000 * 1000}, Location: []*profile.Location{
			{ID: 1, Mapping: map1, Address: addr1},
			{ID: 2, Mapping: map1, Address: addr1 + 1},
		}},
		{Value: []int64{40, 40 * 2000 * 1000}, Location: []*profile.Location{
			{ID: 3, Mapping: map2, Address: addr2},
			{ID: 4, Mapping: map2, Address: addr2 + 1},
		}},
	}
	checkProfile(t, p, period, periodType, sampleType, samples)
}

func checkProfile(t *testing.T, p *profile.Profile, period int64, periodType *profile.ValueType, sampleType []*profile.ValueType, samples []*profile.Sample) {
	if p.Period != period {
		t.Fatalf("p.Period = %d, want %d", p.Period, period)
	}
	if !reflect.DeepEqual(p.PeriodType, periodType) {
		t.Fatalf("p.PeriodType = %v\nwant = %v", fmtJSON(p.PeriodType), fmtJSON(periodType))
	}
	if !reflect.DeepEqual(p.SampleType, sampleType) {
		t.Fatalf("p.SampleType = %v\nwant = %v", fmtJSON(p.SampleType), fmtJSON(sampleType))
	}
	// Clear line info since it is not in the expected samples.
	// If we used f1 and f2 above, then the samples will have line info.
	for _, s := range p.Sample {
		for _, l := range s.Location {
			l.Line = nil
		}
	}
	if fmtJSON(p.Sample) != fmtJSON(samples) { // ignore unexported fields
		if len(p.Sample) == len(samples) {
			for i := range p.Sample {
				if !reflect.DeepEqual(p.Sample[i], samples[i]) {
					t.Errorf("sample %d = %v\nwant = %v\n", i, fmtJSON(p.Sample[i]), fmtJSON(samples[i]))
				}
			}
			if t.Failed() {
				t.FailNow()
			}
		}
		t.Fatalf("p.Sample = %v\nwant = %v", fmtJSON(p.Sample), fmtJSON(samples))
	}
}

var profSelfMapsTests = `
00400000-0040b000 r-xp 00000000 fc:01 787766                             /bin/cat
0060a000-0060b000 r--p 0000a000 fc:01 787766                             /bin/cat
0060b000-0060c000 rw-p 0000b000 fc:01 787766                             /bin/cat
014ab000-014cc000 rw-p 00000000 00:00 0                                  [heap]
7f7d76af8000-7f7d7797c000 r--p 00000000 fc:01 1318064                    /usr/lib/locale/locale-archive
7f7d7797c000-7f7d77b36000 r-xp 00000000 fc:01 1180226                    /lib/x86_64-linux-gnu/libc-2.19.so
7f7d77b36000-7f7d77d36000 ---p 001ba000 fc:01 1180226                    /lib/x86_64-linux-gnu/libc-2.19.so
7f7d77d36000-7f7d77d3a000 r--p 001ba000 fc:01 1180226                    /lib/x86_64-linux-gnu/libc-2.19.so
7f7d77d3a000-7f7d77d3c000 rw-p 001be000 fc:01 1180226                    /lib/x86_64-linux-gnu/libc-2.19.so
7f7d77d3c000-7f7d77d41000 rw-p 00000000 00:00 0
7f7d77d41000-7f7d77d64000 r-xp 00000000 fc:01 1180217                    /lib/x86_64-linux-gnu/ld-2.19.so
7f7d77f3f000-7f7d77f42000 rw-p 00000000 00:00 0
7f7d77f61000-7f7d77f63000 rw-p 00000000 00:00 0
7f7d77f63000-7f7d77f64000 r--p 00022000 fc:01 1180217                    /lib/x86_64-linux-gnu/ld-2.19.so
7f7d77f64000-7f7d77f65000 rw-p 00023000 fc:01 1180217                    /lib/x86_64-linux-gnu/ld-2.19.so
7f7d77f65000-7f7d77f66000 rw-p 00000000 00:00 0
7ffc342a2000-7ffc342c3000 rw-p 00000000 00:00 0                          [stack]
7ffc34343000-7ffc34345000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000090 00:00 0                  [vsyscall]
->
00400000 0040b000 00000000 /bin/cat
7f7d7797c000 7f7d77b36000 00000000 /lib/x86_64-linux-gnu/libc-2.19.so
7f7d77d41000 7f7d77d64000 00000000 /lib/x86_64-linux-gnu/ld-2.19.so
7ffc34343000 7ffc34345000 00000000 [vdso]
ffffffffff600000 ffffffffff601000 00000090 [vsyscall]

00400000-07000000 r-xp 00000000 00:00 0 
07000000-07093000 r-xp 06c00000 00:2e 536754                             /path/to/gobench_server_main
07093000-0722d000 rw-p 06c92000 00:2e 536754                             /path/to/gobench_server_main
0722d000-07b21000 rw-p 00000000 00:00 0 
c000000000-c000036000 rw-p 00000000 00:00 0 
->
07000000 07093000 06c00000 /path/to/gobench_server_main
`

func TestProcSelfMaps(t *testing.T) {
	for tx, tt := range strings.Split(profSelfMapsTests, "\n\n") {
		i := strings.Index(tt, "->\n")
		if i < 0 {
			t.Fatal("malformed test case")
		}
		in, out := tt[:i], tt[i+len("->\n"):]
		if len(out) > 0 && out[len(out)-1] != '\n' {
			out += "\n"
		}
		var buf bytes.Buffer
		parseProcSelfMaps([]byte(in), func(lo, hi, offset uint64, file, buildID string) {
			fmt.Fprintf(&buf, "%08x %08x %08x %s\n", lo, hi, offset, file)
		})
		if buf.String() != out {
			t.Errorf("#%d: have:\n%s\nwant:\n%s\n%q\n%q", tx, buf.String(), out, buf.String(), out)
		}
	}
}
