package concurrency

import (
	"math/rand"
	"testing"
	"time"

	"github.com/stretchr/testify/suite"
)

type PoolTestSuite struct {
	suite.Suite
}

func TestPoolTestSuite(t *testing.T) {
	suite.Run(t, new(PoolTestSuite))
}

func (suite *PoolTestSuite) TestPool() {
	assert := suite.Assert()
	pool, err := NewPool(25) // 3 worker goroutines in the pool
	assert.NoError(err)
	pool.Start()

	concurrency := 100
	channels := make([]chan struct{}, concurrency)
	for i := 0; i < concurrency; i++ {
		ch := make(chan struct{})
		channels[i] = ch
		pool.Submit(func() {
			duration := time.Duration(int64(rand.Float64() * float64(time.Millisecond) * 50))
			time.Sleep(duration)
			close(ch)
		})
	}
	pool.Wait()
	for _, ch := range channels {
		select {
		case <-ch:
		case <-time.After(time.Second):
			panic("timeout")
		}
	}
}

func (suite *PoolTestSuite) TestPoolExecutePanicFunction() {
	assert := suite.Assert()
	pool, err := NewPool(2) // 3 worker goroutines in the pool
	assert.NoError(err)
	pool.Start()
	concurrency := 10
	channels := make([]chan struct{}, concurrency)
	for i := 0; i < concurrency; i++ {
		ch := make(chan struct{})
		channels[i] = ch
		pool.Submit(func() {
			close(ch)
			panic("test")
		})
	}
	pool.Submit(func() {
		panic("test")
	})
	pool.Wait()
}
