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

// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT.

//go:build go1.21

package trace_test

import (
	"bytes"
	"flag"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strings"
	"testing"

	"golang.org/x/exp/trace"
	"golang.org/x/exp/trace/internal/raw"
	"golang.org/x/exp/trace/internal/testtrace"
	"golang.org/x/exp/trace/internal/version"
)

var (
	logEvents  = flag.Bool("log-events", false, "whether to log high-level events; significantly slows down tests")
	dumpTraces = flag.Bool("dump-traces", false, "dump traces even on success")
)

func TestReaderGolden(t *testing.T) {
	matches, err := filepath.Glob("./testdata/tests/*.test")
	if err != nil {
		t.Fatalf("failed to glob for tests: %v", err)
	}
	for _, testPath := range matches {
		testPath := testPath
		testName, err := filepath.Rel("./testdata", testPath)
		if err != nil {
			t.Fatalf("failed to relativize testdata path: %v", err)
		}
		t.Run(testName, func(t *testing.T) {
			tr, exp, err := testtrace.ParseFile(testPath)
			if err != nil {
				t.Fatalf("failed to parse test file at %s: %v", testPath, err)
			}
			testReader(t, tr, exp)
		})
	}
}

func FuzzReader(f *testing.F) {
	// Currently disabled because the parser doesn't do much validation and most
	// getters can be made to panic. Turn this on once the parser is meant to
	// reject invalid traces.
	const testGetters = false

	f.Fuzz(func(t *testing.T, b []byte) {
		r, err := trace.NewReader(bytes.NewReader(b))
		if err != nil {
			return
		}
		for {
			ev, err := r.ReadEvent()
			if err != nil {
				break
			}

			if !testGetters {
				continue
			}
			// Make sure getters don't do anything that panics
			switch ev.Kind() {
			case trace.EventLabel:
				ev.Label()
			case trace.EventLog:
				ev.Log()
			case trace.EventMetric:
				ev.Metric()
			case trace.EventRangeActive, trace.EventRangeBegin:
				ev.Range()
			case trace.EventRangeEnd:
				ev.Range()
				ev.RangeAttributes()
			case trace.EventStateTransition:
				ev.StateTransition()
			case trace.EventRegionBegin, trace.EventRegionEnd:
				ev.Region()
			case trace.EventTaskBegin, trace.EventTaskEnd:
				ev.Task()
			case trace.EventSync:
			case trace.EventStackSample:
			case trace.EventBad:
			}
		}
	})
}

func testReader(t *testing.T, tr io.Reader, exp *testtrace.Expectation) {
	r, err := trace.NewReader(tr)
	if err != nil {
		if err := exp.Check(err); err != nil {
			t.Error(err)
		}
		return
	}
	v := testtrace.NewValidator()
	for {
		ev, err := r.ReadEvent()
		if err == io.EOF {
			break
		}
		if err != nil {
			if err := exp.Check(err); err != nil {
				t.Error(err)
			}
			return
		}
		if *logEvents {
			t.Log(ev.String())
		}
		if err := v.Event(ev); err != nil {
			t.Error(err)
		}
	}
	if err := exp.Check(nil); err != nil {
		t.Error(err)
	}
}

func dumpTraceToText(t *testing.T, b []byte) string {
	t.Helper()

	br, err := raw.NewReader(bytes.NewReader(b))
	if err != nil {
		t.Fatalf("dumping trace: %v", err)
	}
	var sb strings.Builder
	tw, err := raw.NewTextWriter(&sb, version.Go122)
	if err != nil {
		t.Fatalf("dumping trace: %v", err)
	}
	for {
		ev, err := br.ReadEvent()
		if err == io.EOF {
			break
		}
		if err != nil {
			t.Fatalf("dumping trace: %v", err)
		}
		if err := tw.WriteEvent(ev); err != nil {
			t.Fatalf("dumping trace: %v", err)
		}
	}
	return sb.String()
}

func dumpTraceToFile(t *testing.T, testName string, stress bool, b []byte) string {
	t.Helper()

	desc := "default"
	if stress {
		desc = "stress"
	}
	name := fmt.Sprintf("%s.%s.trace.", testName, desc)
	f, err := os.CreateTemp("", name)
	if err != nil {
		t.Fatalf("creating temp file: %v", err)
	}
	defer f.Close()
	if _, err := io.Copy(f, bytes.NewReader(b)); err != nil {
		t.Fatalf("writing trace dump to %q: %v", f.Name(), err)
	}
	return f.Name()
}
