package main

import (
	"context"
	"testing"
	"time"
)

func TestCancelAndJoin(t *testing.T) {
	ctx, cancel := context.WithCancel(context.Background())
	done := Start(ctx, make(chan int), func(int) { t.Error("unexpected work") })
	cancel()
	select {
	case <-done:
	case <-time.After(time.Second):
		t.Fatal("worker did not exit")
	}
}
func TestDrainAndJoin(t *testing.T) {
	jobs := make(chan int, 3)
	for _, n := range []int{1, 2, 3} {
		jobs <- n
	}
	close(jobs)
	sum := 0
	<-Start(context.Background(), jobs, func(n int) { sum += n })
	if sum != 6 {
		t.Fatalf("sum = %d", sum)
	}
}

func TestCancelDoesNotInterruptCallback(t *testing.T) {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	jobs := make(chan int, 1)
	jobs <- 1
	entered, release := make(chan struct{}), make(chan struct{})
	done := Start(ctx, jobs, func(int) { close(entered); <-release })
	<-entered
	cancel()
	select {
	case <-done:
		t.Fatal("callback was interrupted")
	default:
	}
	close(release)
	select {
	case <-done:
	case <-time.After(time.Second):
		t.Fatal("worker did not exit")
	}
}

func TestBlockedSendCanCancel(t *testing.T) {
	ctx, cancel := context.WithCancel(context.Background())
	done := make(chan struct{})
	go func() { defer close(done); SendResult(ctx, make(chan int), 7) }()
	cancel()
	select {
	case <-done:
	case <-time.After(time.Second):
		t.Fatal("send did not stop")
	}
}
