package main

import (
	"context"
	"go.uber.org/goleak"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"
	"time"
)

//go:noinline
func leakedWorker(stop <-chan struct{}, done chan<- struct{}) { <-stop; close(done) }
func TestLeakDetectedAndCleaned(t *testing.T) {
	stop := make(chan struct{})
	done := make(chan struct{})
	go leakedWorker(stop, done)
	err := goleak.Find()
	if err == nil {
		close(stop)
		<-done
		t.Fatal("expected diagnostic")
	}
	if !strings.Contains(err.Error(), "leakedWorker") {
		close(stop)
		<-done
		t.Fatal(err)
	}
	t.Log("leakedWorker detected=true")
	close(stop)
	<-done
	goleak.VerifyNone(t)
}
func TestWorkerStops(t *testing.T) {
	defer goleak.VerifyNone(t)
	ctx, cancel := context.WithCancel(context.Background())
	done := make(chan struct{})
	go func() { defer close(done); <-ctx.Done() }()
	cancel()
	select {
	case <-done:
	case <-time.After(time.Second):
		t.Fatal("worker did not stop")
	}
}

func add(values []int) int {
	total := 0
	for _, v := range values {
		total += v
	}
	return total
}
func TestAdd(t *testing.T) {
	if add([]int{1, 2, 3}) != 6 {
		t.Fatal("add")
	}
}
func BenchmarkAdd(b *testing.B) {
	xs := make([]int, 1024)
	for i := range xs {
		xs[i] = i
	}
	b.ReportAllocs()
	for b.Loop() {
		_ = add(xs)
	}
}

func TestRouting(t *testing.T) {
	w := httptest.NewRecorder()
	diagnosticsMux().ServeHTTP(w, httptest.NewRequest("POST", "/debug/fgprof", nil))
	if w.Code != 405 {
		t.Fatal(w.Code)
	}
	w = httptest.NewRecorder()
	http.NewServeMux().ServeHTTP(w, httptest.NewRequest("GET", "/debug/fgprof", nil))
	if w.Code != 404 {
		t.Fatal(w.Code)
	}
}
