package main

import (
	"sync"
	"sync/atomic"
	"testing"
)

func TestCount(t *testing.T) {
	if got := Count(1000); got != 1000 {
		t.Fatal(got)
	}
}
func TestOnceValue(t *testing.T) {
	var calls atomic.Int64
	f := sync.OnceValue(func() int { calls.Add(1); return 7 })
	var wg sync.WaitGroup
	for range 20 {
		wg.Go(func() {
			if f() != 7 {
				t.Error("bad value")
			}
		})
	}
	wg.Wait()
	if calls.Load() != 1 {
		t.Fatal(calls.Load())
	}
}
func TestMailboxDrain(t *testing.T) {
	m := NewMailbox()
	var wg sync.WaitGroup
	wg.Go(func() {
		for i := 1; i <= 10; i++ {
			m.Send(i)
		}
		m.Close()
	})
	sum := 0
	for {
		n, ok := m.Receive()
		if !ok {
			break
		}
		sum += n
	}
	wg.Wait()
	if sum != 55 {
		t.Fatal(sum)
	}
}

func TestOncePanicCountsAsDone(t *testing.T) {
	var once sync.Once
	calls := 0
	func() { defer func() { _ = recover() }(); once.Do(func() { calls++; panic("failed") }) }()
	once.Do(func() { calls++ })
	if calls != 1 {
		t.Fatal(calls)
	}
}
func TestOnceValueRepeatsPanic(t *testing.T) {
	calls := 0
	f := sync.OnceValue(func() int { calls++; panic("failed") })
	for range 2 {
		func() {
			defer func() {
				if r := recover(); r != "failed" {
					t.Errorf("panic=%v", r)
				}
			}()
			f()
		}()
	}
	if calls != 1 {
		t.Fatal(calls)
	}
}
