func (suite *FixedFIFOTestSuite) TestDequeueOrWaitForNextElementWithFullWaitingChannel() {
	for i := 0; i < WaitForNextElementChanCapacity; i++ {
		suite.fifo.waitForNextElementChan <- make(chan interface{})
	}
	result, err := suite.fifo.DequeueOrWaitForNextElement()
	suite.Nil(result)
	suite.Error(err)
	customError, ok := err.(*QueueError)
	suite.True(ok, "Expected error type: QueueError")
	suite.Equalf(QueueErrorCodeEmptyQueue, customError.Code(), "Expected code: '%v'", QueueErrorCodeEmptyQueue)
}
single GR calling DequeueOrWaitForNextElement (WaitForNextElementChanCapacity + 1) times, last one should return error
package goconcurrentqueue
import (
	"context"
	"sync"
	"testing"
	"time"
	"github.com/stretchr/testify/suite"
)
const (
	fixedFIFOQueueCapacity = 500
)
type FixedFIFOTestSuite struct {
	suite.Suite
	fifo *FixedFIFO
}
func (suite *FixedFIFOTestSuite) SetupTest() {
	suite.fifo = NewFixedFIFO(fixedFIFOQueueCapacity)
}
func TestFixedFIFOTestSuite(t *testing.T) {
	suite.Run(t, new(FixedFIFOTestSuite))
}
func (suite *FixedFIFOTestSuite) TestEnqueueLockSingleGR() {
	suite.NoError(suite.fifo.Enqueue(1), "Unlocked queue allows to enqueue elements")
	suite.fifo.Lock()
	err := suite.fifo.Enqueue(1)
	suite.Error(err, "Locked queue does not allow to enqueue elements")
	customError, ok := err.(*QueueError)
	suite.True(ok, "Expected error type: QueueError")
	suite.Equalf(QueueErrorCodeLockedQueue, customError.Code(), "Expected code: '%v'", QueueErrorCodeLockedQueue)
}
func (suite *FixedFIFOTestSuite) TestEnqueueLenSingleGR() {
	suite.fifo.Enqueue(testValue)
	len := suite.fifo.GetLen()
	suite.Equalf(1, len, "Expected number of elements in queue: 1, currently: %v", len)
	suite.fifo.Enqueue(5)
	len = suite.fifo.GetLen()
	suite.Equalf(2, len, "Expected number of elements in queue: 2, currently: %v", len)
}
func (suite *FixedFIFOTestSuite) TestEnqueueFullCapacitySingleGR() {
	total := 5
	suite.fifo = NewFixedFIFO(total)
	for i := 0; i < total; i++ {
		suite.NoError(suite.fifo.Enqueue(i), "no error expected when queue is not full")
	}
	err := suite.fifo.Enqueue(0)
	suite.Error(err, "error expected when queue is full")
	customError, ok := err.(*QueueError)
	suite.True(ok, "Expected error type: QueueError")
	suite.Equalf(QueueErrorCodeFullCapacity, customError.Code(), "Expected code: '%v'", QueueErrorCodeFullCapacity)
}
func (suite *FixedFIFOTestSuite) TestEnqueueListenerToExpireSingleGR() {
	var (
		uselessChan = make(chan interface{})
		value = "my-test-value"
	)
	suite.fifo.waitForNextElementChan <- uselessChan
	suite.fifo.Enqueue(value)
	dequeuedValue, _ := suite.fifo.Dequeue()
	suite.Equal(value, dequeuedValue)
}
func (suite *FixedFIFOTestSuite) TestEnqueueLenMultipleGR() {
	var (
		totalGRs = 500
		wg       sync.WaitGroup
	)
	for i := 0; i < totalGRs; i++ {
		wg.Add(1)
		go func(value int) {
			defer wg.Done()
			suite.fifo.Enqueue(value)
		}(i)
	}
	wg.Wait()
	totalElements := suite.fifo.GetLen()
	suite.Equalf(totalGRs, totalElements, "Total enqueued elements should be %v, currently: %v", totalGRs, totalElements)
	var (
		tmpVal                interface{}
		val                   int
		err                   error
		totalElementsVerified int
	)
	allElements := make([]bool, totalGRs)
	for i := 0; i < totalElements; i++ {
		tmpVal, err = suite.fifo.Dequeue()
		suite.NoError(err, "No error should be returned trying to get an existent element")
		val = tmpVal.(int)
		if allElements[val] {
			suite.Failf("Duplicated element", "Unexpected duplicated value: %v", val)
		} else {
			allElements[val] = true
			totalElementsVerified++
		}
	}
	suite.True(totalElementsVerified == totalGRs, "Enqueued elements are missing")
}
func (suite *FixedFIFOTestSuite) TestGetLenMultipleGRs() {
	var (
		totalGRs               = 100
		totalElementsToEnqueue = 10
		wg                     sync.WaitGroup
	)
	for i := 0; i < totalElementsToEnqueue; i++ {
		suite.fifo.Enqueue(i)
	}
	for i := 0; i < totalGRs; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			total := suite.fifo.GetLen()
			suite.Equalf(totalElementsToEnqueue, total, "Expected len: %v", totalElementsToEnqueue)
		}()
	}
	wg.Wait()
}
func (suite *FixedFIFOTestSuite) TestGetCapSingleGR() {
	suite.Equal(fixedFIFOQueueCapacity, suite.fifo.GetCap(), "unexpected capacity")
	suite.fifo = NewFixedFIFO(10)
	suite.Equal(10, suite.fifo.GetCap(), "unexpected capacity")
}
func (suite *FixedFIFOTestSuite) TestDequeueLockSingleGR() {
	suite.fifo.Enqueue(1)
	_, err := suite.fifo.Dequeue()
	suite.NoError(err, "Unlocked queue allows to dequeue elements")
	suite.fifo.Enqueue(1)
	suite.fifo.Lock()
	_, err = suite.fifo.Dequeue()
	suite.Error(err, "Locked queue does not allow to dequeue elements")
	customError, ok := err.(*QueueError)
	suite.True(ok, "Expected error type: QueueError")
	suite.Equalf(QueueErrorCodeLockedQueue, customError.Code(), "Expected code: '%v'", QueueErrorCodeLockedQueue)
}
func (suite *FixedFIFOTestSuite) TestDequeueEmptyQueueSingleGR() {
	val, err := suite.fifo.Dequeue()
	suite.Errorf(err, "Can't dequeue an empty queue")
	customError, ok := err.(*QueueError)
	suite.True(ok, "Expected error type: QueueError")
	suite.Equalf(QueueErrorCodeEmptyQueue, customError.Code(), "Expected code: '%v'", QueueErrorCodeEmptyQueue)
	suite.Equal(nil, val, "Can't get a value different than nil from an empty queue")
}
func (suite *FixedFIFOTestSuite) TestDequeueSingleGR() {
	suite.fifo.Enqueue(testValue)
	suite.fifo.Enqueue(5)
	val, err := suite.fifo.Dequeue()
	suite.NoError(err, "Unexpected error")
	suite.Equal(testValue, val, "Wrong element's value")
	len := suite.fifo.GetLen()
	suite.Equal(1, len, "Incorrect number of queue elements")
	val, err = suite.fifo.Dequeue()
	suite.NoError(err, "Unexpected error")
	suite.Equal(5, val, "Wrong element's value")
	len = suite.fifo.GetLen()
	suite.Equal(0, len, "Incorrect number of queue elements")
}
func (suite *FixedFIFOTestSuite) TestDequeueClosedChannelSingleGR() {
	suite.fifo.Enqueue(1)
	close(suite.fifo.queue)
	suite.fifo.Dequeue()
	val, err := suite.fifo.Dequeue()
	suite.Nil(val, "nil value expected after internal channel was closed")
	suite.Error(err, "error expected after internal queue channel was closed")
	customError, ok := err.(*QueueError)
	suite.True(ok, "Expected error type: QueueError")
	suite.Equalf(QueueErrorCodeInternalChannelClosed, customError.Code(), "Expected code: '%v'", QueueErrorCodeInternalChannelClosed)
}
func (suite *FixedFIFOTestSuite) TestDequeueMultipleGRs() {
	var (
		wg                     sync.WaitGroup
		totalElementsToEnqueue = 100
		totalElementsToDequeue = 90
	)
	for i := 0; i < totalElementsToEnqueue; i++ {
		suite.fifo.Enqueue(i)
	}
	for i := 0; i < totalElementsToDequeue; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			_, err := suite.fifo.Dequeue()
			suite.NoError(err, "Unexpected error during concurrent Dequeue()")
		}()
	}
	wg.Wait()
	totalElementsAfterDequeue := suite.fifo.GetLen()
	suite.Equal(totalElementsToEnqueue-totalElementsToDequeue, totalElementsAfterDequeue, "Total elements on queue (after Dequeue) does not match with expected number")
	val, err := suite.fifo.Dequeue()
	suite.NoError(err, "No error should be returned when dequeuing an existent element")
	suite.Equalf(totalElementsToDequeue, val, "The expected last element's value should be: %v", totalElementsToEnqueue-totalElementsToDequeue)
}
func (suite *FixedFIFOTestSuite) TestDequeueOrWaitForNextElementLockSingleGR() {
	suite.fifo.Lock()
	result, err := suite.fifo.DequeueOrWaitForNextElement()
	suite.Nil(result, "No value expected if queue is locked")
	suite.Error(err, "Locked queue does not allow to enqueue elements")
	customError, ok := err.(*QueueError)
	suite.True(ok, "Expected error type: QueueError")
	suite.Equalf(QueueErrorCodeLockedQueue, customError.Code(), "Expected code: '%v'", QueueErrorCodeLockedQueue)
}
func (suite *FixedFIFOTestSuite) TestDequeueOrWaitForNextElementWithEnqueuedElementSingleGR() {
	value := 100
	len := suite.fifo.GetLen()
	suite.fifo.Enqueue(value)
	result, err := suite.fifo.DequeueOrWaitForNextElement()
	suite.NoError(err)
	suite.Equal(value, result)
	suite.Equal(len, suite.fifo.GetLen())
}
func (suite *FixedFIFOTestSuite) TestDequeueOrWaitForNextElementWithEmptyQueue() {
	var (
		value  = 100
		result interface{}
		err    error
		done   = make(chan struct{})
	)
	wait4gr := make(chan struct{})
	go func(ready chan struct{}) {
		wait4gr <- struct{}{}
		result, err = suite.fifo.DequeueOrWaitForNextElement()
		done <- struct{}{}
	}(wait4gr)
	<-wait4gr
	go func() {
		suite.fifo.Enqueue(value)
	}()
	select {
	case <-done:
		suite.NoError(err)
		suite.Equal(value, result)
	case <-time.After(2 * time.Second):
		suite.Fail("too much time waiting for the enqueued element")
	}
}