gitlab.com/ignitionrobotics/web/ign-go@v1.0.0-rc4/queue_test.go (about)

     1  package ign
     2  
     3  import (
     4  	"fmt"
     5  	"sync"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/stretchr/testify/suite"
    10  )
    11  
    12  type QueueTestSuite struct {
    13  	suite.Suite
    14  	queue *Queue
    15  }
    16  
    17  const (
    18  	testValue = "test value"
    19  )
    20  
    21  func (suite *QueueTestSuite) SetupTest() {
    22  	suite.queue = NewQueue()
    23  }
    24  
    25  // ***************************************************************************************
    26  // ** Queue initialization
    27  // ***************************************************************************************
    28  
    29  // no elements at initialization
    30  func (suite *QueueTestSuite) TestNoElementsAtInitialization() {
    31  	length := suite.queue.GetLen()
    32  	suite.Equalf(0, length, "No elements expected at initialization, currently: %v", length)
    33  }
    34  
    35  // ***************************************************************************************
    36  // ** Enqueue && GetLen
    37  // ***************************************************************************************
    38  
    39  // single enqueue (1 element, 1 goroutine)
    40  func (suite *QueueTestSuite) TestEnqueueLenSingleGR() {
    41  	suite.queue.Enqueue(testValue)
    42  	length := suite.queue.GetLen()
    43  	suite.Equalf(1, length, "Expected number of elements in queue: 1, currently: %v", length)
    44  
    45  	suite.queue.Enqueue(5)
    46  	length = suite.queue.GetLen()
    47  	suite.Equalf(2, length, "Expected number of elements in queue: 2, currently: %v", length)
    48  }
    49  
    50  // single enqueue and wait for next element
    51  func (suite *QueueTestSuite) TestEnqueueWaitForNextElementSingleGR() {
    52  	waitForNextElement := make(chan interface{})
    53  	// add the listener manually (ONLY for testings purposes)
    54  	suite.queue.waitForNextElementChan <- waitForNextElement
    55  
    56  	value := 100
    57  	// enqueue from a different GR to avoid blocking the listener channel
    58  	go suite.queue.Enqueue(value)
    59  	// wait for the enqueued element
    60  	result := <-waitForNextElement
    61  
    62  	suite.Equal(value, result)
    63  }
    64  
    65  // TestEnqueueLenMultipleGR enqueues elements concurrently
    66  //
    67  // Detailed steps:
    68  //	1 - Enqueue totalGRs concurrently (from totalGRs different GRs)
    69  //	2 - Verifies the len, it should be equal to totalGRs
    70  //	3 - Verifies that all elements from 0 to totalGRs were enqueued
    71  func (suite *QueueTestSuite) TestEnqueueLenMultipleGR() {
    72  	var (
    73  		totalGRs = 500
    74  		wg       sync.WaitGroup
    75  	)
    76  
    77  	// concurrent enqueueing
    78  	// multiple GRs concurrently enqueueing consecutive integers from 0 to (totalGRs - 1)
    79  	for i := 0; i < totalGRs; i++ {
    80  		wg.Add(1)
    81  		go func(value int) {
    82  			defer wg.Done()
    83  			suite.queue.Enqueue(value)
    84  		}(i)
    85  	}
    86  	wg.Wait()
    87  
    88  	// check that there are totalGRs elements enqueued
    89  	totalElements := suite.queue.GetLen()
    90  	suite.Equalf(totalGRs, totalElements, "Total enqueued elements should be %v, currently: %v", totalGRs, totalElements)
    91  
    92  	// checking that the expected elements (1, 2, 3, ... totalGRs-1 ) were enqueued
    93  	var (
    94  		tmpVal                interface{}
    95  		val                   int
    96  		err                   *ErrMsg
    97  		totalElementsVerified int
    98  	)
    99  	// slice to check every element
   100  	sl2check := make([]bool, totalGRs)
   101  
   102  	for i := 0; i < totalElements; i++ {
   103  		tmpVal, err = suite.queue.GetElement(i)
   104  		suite.Nil(err, "No error should be returned trying to get an existent element")
   105  
   106  		val = tmpVal.(int)
   107  		if !sl2check[val] {
   108  			totalElementsVerified++
   109  			sl2check[val] = true
   110  		} else {
   111  			suite.Failf("Duplicated element", "Unexpected duplicated value: %v", val)
   112  		}
   113  	}
   114  	suite.True(totalElementsVerified == totalGRs, "Enqueued elements are missing")
   115  }
   116  
   117  // call GetLen concurrently
   118  func (suite *QueueTestSuite) TestGetLenMultipleGRs() {
   119  	var (
   120  		totalGRs               = 100
   121  		totalElementsToEnqueue = 10
   122  		wg                     sync.WaitGroup
   123  	)
   124  
   125  	for i := 0; i < totalElementsToEnqueue; i++ {
   126  		suite.queue.Enqueue(i)
   127  	}
   128  
   129  	for i := 0; i < totalGRs; i++ {
   130  		wg.Add(1)
   131  		go func() {
   132  			defer wg.Done()
   133  
   134  			total := suite.queue.GetLen()
   135  			suite.Equalf(totalElementsToEnqueue, total, "Expected len: %v", totalElementsToEnqueue)
   136  		}()
   137  	}
   138  	wg.Wait()
   139  }
   140  
   141  // ***************************************************************************************
   142  // ** GetCap
   143  // ***************************************************************************************
   144  
   145  // single GR getCapacity
   146  func (suite *QueueTestSuite) TestGetCapSingleGR() {
   147  	// initial capacity
   148  	suite.Equal(cap(suite.queue.slice), suite.queue.GetCap(), "unexpected capacity")
   149  
   150  	// checking after adding 2 items
   151  	suite.queue.Enqueue(1)
   152  	suite.queue.Enqueue(2)
   153  	suite.Equal(cap(suite.queue.slice), suite.queue.GetCap(), "unexpected capacity")
   154  }
   155  
   156  // ***************************************************************************************
   157  // ** Get
   158  // ***************************************************************************************
   159  
   160  // get a valid element
   161  func (suite *QueueTestSuite) TestGetSingleGR() {
   162  	suite.queue.Enqueue(testValue)
   163  	val, err := suite.queue.GetElement(0)
   164  
   165  	// verify error (should be nil)
   166  	suite.Nil(err, "No error should be enqueueing an element")
   167  
   168  	// verify element's value
   169  	suite.Equalf(testValue, val, "Different element returned: %v", val)
   170  }
   171  
   172  // get a invalid element
   173  func (suite *QueueTestSuite) TestGetInvalidElementSingleGR() {
   174  	suite.queue.Enqueue(testValue)
   175  	val, err := suite.queue.GetElement(1)
   176  
   177  	// verify error
   178  	suite.Equal(ErrorQueueIndexOutOfBounds, err.ErrCode, "An error should be returned after ask for a no existent element")
   179  
   180  	// verify element's value
   181  	suite.Equalf(val, nil, "Nil should be returned, currently returned: %v", val)
   182  }
   183  
   184  // call Get concurrently
   185  func (suite *QueueTestSuite) TestGetMultipleGRs() {
   186  	var (
   187  		totalGRs               = 100
   188  		totalElementsToEnqueue = 10
   189  		wg                     sync.WaitGroup
   190  	)
   191  
   192  	for i := 0; i < totalElementsToEnqueue; i++ {
   193  		suite.queue.Enqueue(i)
   194  	}
   195  
   196  	for i := 0; i < totalGRs; i++ {
   197  		wg.Add(1)
   198  		go func() {
   199  			defer wg.Done()
   200  			val, err := suite.queue.GetElement(5)
   201  
   202  			suite.Nil(err, "No error should be returned trying to get an existent element")
   203  			suite.Equal(5, val.(int), "Expected element's value: 5")
   204  		}()
   205  	}
   206  	wg.Wait()
   207  
   208  	total := suite.queue.GetLen()
   209  	suite.Equalf(totalElementsToEnqueue, total, "Expected len: %v", totalElementsToEnqueue)
   210  }
   211  
   212  // ***************************************************************************************
   213  // ** Remove
   214  // ***************************************************************************************
   215  
   216  // remove elements
   217  func (suite *QueueTestSuite) TestRemoveSingleGR() {
   218  	suite.queue.Enqueue(testValue)
   219  	suite.queue.Enqueue(5)
   220  
   221  	// removing first element
   222  	err := suite.queue.Remove(testValue)
   223  	suite.Nil(err, "Unexpected error")
   224  
   225  	// get element at index 0
   226  	val, err2 := suite.queue.GetElement(0)
   227  	suite.Nil(err2, "Unexpected error")
   228  	suite.Equal(5, val, "Queue returned the wrong element")
   229  }
   230  
   231  func (suite *QueueTestSuite) TestRemoveNotFound() {
   232  	suite.queue.Enqueue(testValue)
   233  
   234  	err := suite.queue.Remove("anotherValue")
   235  
   236  	suite.Equal(ErrorIDNotFound, err.ErrCode)
   237  }
   238  
   239  // TestRemoveMultipleGRs removes elements concurrently.
   240  //
   241  // Detailed steps:
   242  //	1 - Enqueues totalElementsToEnqueue consecutive elements (0, 1, 2, 3, ... totalElementsToEnqueue - 1)
   243  //	2 - Hits queue.Remove(1) concurrently from totalElementsToRemove different GRs
   244  //	3 - Verifies the final len == totalElementsToEnqueue - totalElementsToRemove
   245  //	4 - Verifies that final 2nd element == (1 + totalElementsToRemove)
   246  func (suite *QueueTestSuite) TestRemoveMultipleGRs() {
   247  	var (
   248  		wg                     sync.WaitGroup
   249  		totalElementsToEnqueue = 100
   250  		totalElementsToRemove  = 90
   251  	)
   252  
   253  	for i := 0; i < totalElementsToEnqueue; i++ {
   254  		suite.queue.Enqueue(testValue)
   255  	}
   256  
   257  	for i := 0; i < totalElementsToRemove; i++ {
   258  		wg.Add(1)
   259  		go func() {
   260  			defer wg.Done()
   261  			err := suite.queue.Remove(testValue)
   262  			suite.Nil(err, "Unexpected error during concurrent Remove(n)")
   263  		}()
   264  	}
   265  	wg.Wait()
   266  
   267  	// check len, should be == totalElementsToEnqueue - totalElementsToRemove
   268  	totalElementsAfterRemove := suite.queue.GetLen()
   269  	suite.Equal(totalElementsToEnqueue-totalElementsToRemove, totalElementsAfterRemove, "Total elements on list does not match with expected number")
   270  
   271  	// check current 2nd element (index 1) on the queue
   272  	_, err := suite.queue.GetElement(1)
   273  	suite.Nil(err, "No error should be returned when getting an existent element")
   274  }
   275  
   276  // ***************************************************************************************
   277  // ** Dequeue
   278  // ***************************************************************************************
   279  
   280  // dequeue an empty queue
   281  func (suite *QueueTestSuite) TestDequeueEmptyQueueSingleGR() {
   282  	val, err := suite.queue.Dequeue()
   283  
   284  	// error expected
   285  	suite.Equal(ErrorQueueEmpty, err.ErrCode, "Can't dequeue an empty queue")
   286  
   287  	// no value expected
   288  	suite.Equal(nil, val, "Can't get a value different than nil from an empty queue")
   289  }
   290  
   291  // dequeue all elements
   292  func (suite *QueueTestSuite) TestDequeueSingleGR() {
   293  	suite.queue.Enqueue(testValue)
   294  	suite.queue.Enqueue(5)
   295  
   296  	// get the first element
   297  	val, err := suite.queue.Dequeue()
   298  	suite.Nil(err, "Unexpected error")
   299  	suite.Equal(testValue, val, "Wrong element's value")
   300  	length := suite.queue.GetLen()
   301  	suite.Equal(1, length, "Incorrect number of queue elements")
   302  
   303  	// get the second element
   304  	val, err = suite.queue.Dequeue()
   305  	suite.Nil(err, "Unexpected error")
   306  	suite.Equal(5, val, "Wrong element's value")
   307  	length = suite.queue.GetLen()
   308  	suite.Equal(0, length, "Incorrect number of queue elements")
   309  
   310  }
   311  
   312  // TestDequeueMultipleGRs dequeues elements concurrently
   313  //
   314  // Detailed steps:
   315  //	1 - Enqueues totalElementsToEnqueue consecutive integers
   316  //	2 - Dequeues totalElementsToDequeue concurrently from totalElementsToDequeue GRs
   317  //	3 - Verifies the final len, should be equal to totalElementsToEnqueue - totalElementsToDequeue
   318  //	4 - Verifies that the next dequeued element's value is equal to totalElementsToDequeue
   319  func (suite *QueueTestSuite) TestDequeueMultipleGRs() {
   320  	var (
   321  		wg                     sync.WaitGroup
   322  		totalElementsToEnqueue = 100
   323  		totalElementsToDequeue = 90
   324  	)
   325  
   326  	for i := 0; i < totalElementsToEnqueue; i++ {
   327  		suite.queue.Enqueue(i)
   328  	}
   329  
   330  	for i := 0; i < totalElementsToDequeue; i++ {
   331  		wg.Add(1)
   332  		go func() {
   333  			defer wg.Done()
   334  			_, err := suite.queue.Dequeue()
   335  			suite.Nil(err, "Unexpected error during concurrent Dequeue()")
   336  		}()
   337  	}
   338  	wg.Wait()
   339  
   340  	// check len, should be == totalElementsToEnqueue - totalElementsToDequeue
   341  	totalElementsAfterDequeue := suite.queue.GetLen()
   342  	suite.Equal(totalElementsToEnqueue-totalElementsToDequeue, totalElementsAfterDequeue, "Total elements on queue (after Dequeue) does not match with expected number")
   343  
   344  	// check current first element
   345  	val, err := suite.queue.Dequeue()
   346  	suite.Nil(err, "No error should be returned when dequeuing an existent element")
   347  	suite.Equalf(totalElementsToDequeue, val, "The expected last element's value should be: %v", totalElementsToEnqueue-totalElementsToDequeue)
   348  }
   349  
   350  // ***************************************************************************************
   351  // ** DequeueOrWaitForNextElement
   352  // ***************************************************************************************
   353  
   354  // single GR DequeueOrWaitForNextElement with a previous enqueued element
   355  func (suite *QueueTestSuite) TestDequeueOrWaitForNextElementWithEnqueuedElementSingleGR() {
   356  	value := 100
   357  	length := suite.queue.GetLen()
   358  	suite.queue.Enqueue(value)
   359  
   360  	result, err := suite.queue.DequeueOrWaitForNextElement()
   361  
   362  	suite.Nil(err)
   363  	suite.Equal(value, result)
   364  	// length must be exactly the same as it was before
   365  	suite.Equal(length, suite.queue.GetLen())
   366  }
   367  
   368  // single GR DequeueOrWaitForNextElement 1 element
   369  func (suite *QueueTestSuite) TestDequeueOrWaitForNextElementWithEmptyQueue() {
   370  	var (
   371  		value  = 100
   372  		result interface{}
   373  		err    *ErrMsg
   374  		done   = make(chan struct{})
   375  	)
   376  
   377  	// waiting for next enqueued element
   378  	go func() {
   379  		result, err = suite.queue.DequeueOrWaitForNextElement()
   380  		done <- struct{}{}
   381  	}()
   382  
   383  	// enqueue an element
   384  	go func() {
   385  		suite.queue.Enqueue(value)
   386  	}()
   387  
   388  	select {
   389  	// wait for the dequeued element
   390  	case <-done:
   391  		suite.Nil(err)
   392  		suite.Equal(value, result)
   393  
   394  	// the following comes first if more time than expected happened while waiting for the dequeued element
   395  	case <-time.After(2 * time.Second):
   396  		suite.Fail("too much time waiting for the enqueued element")
   397  
   398  	}
   399  }
   400  
   401  // single GR calling DequeueOrWaitForNextElement (WaitForNextElementChanCapacity + 1) times, last one should return error
   402  func (suite *QueueTestSuite) TestDequeueOrWaitForNextElementWithFullWaitingChannel() {
   403  	// enqueue WaitForNextElementChanCapacity listeners to future enqueued elements
   404  	for i := 0; i < WaitForNextElementChanCapacity; i++ {
   405  		suite.queue.waitForNextElementChan <- make(chan interface{})
   406  	}
   407  
   408  	result, err := suite.queue.DequeueOrWaitForNextElement()
   409  	suite.Nil(result)
   410  	suite.Equal(ErrorQueueTooManyListeners, err.ErrCode)
   411  }
   412  
   413  // multiple GRs, calling DequeueOrWaitForNextElement from different GRs and enqueuing the expected values later
   414  func (suite *QueueTestSuite) TestDequeueOrWaitForNextElementMultiGR() {
   415  	var (
   416  		wg sync.WaitGroup
   417  		// channel to enqueue dequeued values
   418  		dequeuedValues = make(chan int, WaitForNextElementChanCapacity)
   419  		// map[dequeued_value] = times dequeued
   420  		mp = make(map[int]int)
   421  	)
   422  
   423  	for i := 0; i < WaitForNextElementChanCapacity; i++ {
   424  		go func() {
   425  			// wait for the next enqueued element
   426  			result, err := suite.queue.DequeueOrWaitForNextElement()
   427  			// no error && no nil result
   428  			suite.Nil(err)
   429  			suite.NotNil(result)
   430  
   431  			// send each dequeued element into the dequeuedValues channel
   432  			resultInt, _ := result.(int)
   433  			dequeuedValues <- resultInt
   434  
   435  			// let the wg.Wait() know that this GR is done
   436  			wg.Done()
   437  		}()
   438  	}
   439  
   440  	// enqueue all needed elements
   441  	for i := 0; i < WaitForNextElementChanCapacity; i++ {
   442  		wg.Add(1)
   443  		suite.queue.Enqueue(i)
   444  		// save the enqueued value as index
   445  		mp[i] = 0
   446  	}
   447  
   448  	// wait until all GRs dequeue the elements
   449  	wg.Wait()
   450  	// close dequeuedValues channel in order to only read the previous enqueued values (from the channel)
   451  	close(dequeuedValues)
   452  
   453  	// verify that all enqueued values were dequeued
   454  	for v := range dequeuedValues {
   455  		val, ok := mp[v]
   456  		suite.Truef(ok, "element dequeued but never enqueued: %v", val)
   457  		// increment the m[p] value meaning the value p was dequeued
   458  		mp[v] = val + 1
   459  	}
   460  	// verify that there are no duplicates
   461  	for k, v := range mp {
   462  		suite.Equalf(1, v, "%v was dequeued %v times", k, v)
   463  	}
   464  }
   465  
   466  // multiple GRs, calling DequeueOrWaitForNextElement from different GRs and enqueuing the expected values later
   467  func (suite *QueueTestSuite) TestDequeueOrWaitForNextElementMultiGR2() {
   468  	var (
   469  		done       = make(chan int, 10)
   470  		total      = 2000
   471  		results    = make(map[int]struct{})
   472  		totalOk    = 0
   473  		totalError = 0
   474  	)
   475  
   476  	go func(queue *Queue, done chan int, total int) {
   477  		for i := 0; i < total; i++ {
   478  			go func(queue *Queue, done chan int) {
   479  				rawValue, err := queue.DequeueOrWaitForNextElement()
   480  				if err != nil {
   481  					fmt.Println(err)
   482  					// error
   483  					done <- -1
   484  				} else {
   485  					val, _ := rawValue.(int)
   486  					done <- val
   487  				}
   488  			}(queue, done)
   489  
   490  			go func(queue *Queue, value int) {
   491  				queue.Enqueue(value)
   492  			}(queue, i)
   493  		}
   494  	}(suite.queue, done, total)
   495  
   496  	i := 0
   497  	for {
   498  		v := <-done
   499  		if v != -1 {
   500  			totalOk++
   501  			_, ok := results[v]
   502  			suite.Falsef(ok, "duplicated value %v", v)
   503  
   504  			results[v] = struct{}{}
   505  		} else {
   506  			totalError++
   507  		}
   508  
   509  		i++
   510  		if i == total {
   511  			break
   512  		}
   513  	}
   514  
   515  	suite.Equal(total, totalError+totalOk)
   516  }
   517  
   518  // call DequeueOrWaitForNextElement(), wait some time and enqueue an item
   519  func (suite *QueueTestSuite) TestDequeueOrWaitForNextElementGapSingleGR() {
   520  	var (
   521  		expectedValue = 50
   522  		done          = make(chan struct{}, 3)
   523  	)
   524  
   525  	// DequeueOrWaitForNextElement()
   526  	go func(queue *Queue, done chan struct{}) {
   527  		val, err := queue.DequeueOrWaitForNextElement()
   528  		suite.Nil(err)
   529  		suite.Equal(expectedValue, val)
   530  		done <- struct{}{}
   531  	}(suite.queue, done)
   532  
   533  	// wait and Enqueue function
   534  	go func(queue *Queue, done chan struct{}) {
   535  		time.Sleep(time.Millisecond * dequeueOrWaitForNextElementInvokeGapTime * dequeueOrWaitForNextElementInvokeGapTime)
   536  		queue.Enqueue(expectedValue)
   537  		done <- struct{}{}
   538  	}(suite.queue, done)
   539  
   540  	for i := 0; i < 2; i++ {
   541  		select {
   542  		case <-done:
   543  		case <-time.After(2 * time.Millisecond * dequeueOrWaitForNextElementInvokeGapTime * dequeueOrWaitForNextElementInvokeGapTime):
   544  			suite.FailNow("Too much time waiting for the value")
   545  		}
   546  	}
   547  }
   548  
   549  // ***************************************************************************************
   550  // ** Swap
   551  // ***************************************************************************************
   552  func (suite *QueueTestSuite) TestSwapEmptyQueue() {
   553  	const (
   554  		a = 4
   555  		b = 4
   556  	)
   557  
   558  	err := suite.queue.Swap(a, b)
   559  	suite.Equal(ErrorQueueEmpty, err.ErrCode)
   560  }
   561  
   562  func (suite *QueueTestSuite) TestSwapIndexesNotFound() {
   563  	const (
   564  		size = 2
   565  		a    = 4
   566  		b    = 3
   567  	)
   568  
   569  	for i := 0; i < size; i++ {
   570  		suite.queue.Enqueue(i)
   571  	}
   572  
   573  	err := suite.queue.Swap(a, b)
   574  
   575  	suite.Equal(ErrorIDNotFound, err.ErrCode)
   576  }
   577  
   578  func (suite *QueueTestSuite) TestSwapSameIndex() {
   579  	const (
   580  		size = 10
   581  		a    = 4
   582  		b    = 4
   583  	)
   584  
   585  	for i := 0; i < size; i++ {
   586  		suite.queue.Enqueue(i)
   587  	}
   588  
   589  	err := suite.queue.Swap(a, b)
   590  
   591  	suite.Equal(ErrorQueueSwapIndexesMatch, err.ErrCode)
   592  }
   593  
   594  func (suite *QueueTestSuite) TestSwapElements() {
   595  
   596  	const (
   597  		size = 10
   598  		a    = 3
   599  		b    = 4
   600  	)
   601  
   602  	for i := 0; i < size; i++ {
   603  		suite.queue.Enqueue(i)
   604  	}
   605  
   606  	oldValueFromA, _ := suite.queue.GetElement(a)
   607  	oldValueFromB, _ := suite.queue.GetElement(b)
   608  
   609  	suite.queue.Swap(a, b)
   610  
   611  	newValueFromA, _ := suite.queue.GetElement(a)
   612  	newValueFromB, _ := suite.queue.GetElement(b)
   613  
   614  	suite.Equal(oldValueFromA, newValueFromB)
   615  	suite.Equal(oldValueFromB, newValueFromA)
   616  }
   617  
   618  // ***************************************************************************************
   619  // ** Move elements inside an empty queue
   620  // ***************************************************************************************
   621  func (suite *QueueTestSuite) TestMoveToFrontEmptyQueue() {
   622  	const (
   623  		front = 10
   624  	)
   625  
   626  	suite.Equal(ErrorQueueEmpty, suite.queue.MoveToFront(front).ErrCode)
   627  }
   628  
   629  func (suite *QueueTestSuite) TestMoveToBackEmptyQueue() {
   630  	const (
   631  		back = 1
   632  	)
   633  
   634  	suite.Equal(ErrorQueueEmpty, suite.queue.MoveToBack(back).ErrCode)
   635  }
   636  
   637  // ***************************************************************************************
   638  // ** Move elements to the front
   639  // ***************************************************************************************
   640  func (suite *QueueTestSuite) TestMoveToFront() {
   641  	const (
   642  		size  = 10
   643  		front = 5
   644  	)
   645  
   646  	for i := 0; i < size; i++ {
   647  		suite.queue.Enqueue(i + 1)
   648  	}
   649  
   650  	result := []interface{}{5, 1, 2, 3, 4, 6, 7, 8, 9, 10}
   651  
   652  	suite.Nil(suite.queue.MoveToFront(front))
   653  	suite.Equal(result, suite.queue.slice)
   654  }
   655  
   656  func (suite *QueueTestSuite) TestMoveToFrontAlreadyInFront() {
   657  	const (
   658  		size  = 10
   659  		front = "sim-1"
   660  	)
   661  
   662  	for i := 1; i < size; i++ {
   663  		item := fmt.Sprintf("sim-%d", i)
   664  		suite.queue.Enqueue(item)
   665  	}
   666  
   667  	suite.Equal(ErrorQueueMoveIndexFrontPosition, suite.queue.MoveToFront(front).ErrCode)
   668  }
   669  
   670  func (suite *QueueTestSuite) TestMoveToFrontNotFound() {
   671  	suite.queue.Enqueue(testValue)
   672  
   673  	err := suite.queue.MoveToFront("anotherValue")
   674  
   675  	suite.Equal(ErrorIDNotFound, err.ErrCode)
   676  }
   677  
   678  // ***************************************************************************************
   679  // ** Move elements to the back
   680  // ***************************************************************************************
   681  func (suite *QueueTestSuite) TestMoveToBack() {
   682  	const (
   683  		size = 10
   684  		back = 5
   685  	)
   686  
   687  	for i := 0; i < size; i++ {
   688  		suite.queue.Enqueue(i + 1)
   689  	}
   690  
   691  	result := []interface{}{1, 2, 3, 4, 6, 7, 8, 9, 10, 5}
   692  
   693  	suite.Nil(suite.queue.MoveToBack(back))
   694  	suite.Equal(result, suite.queue.slice)
   695  }
   696  
   697  func (suite *QueueTestSuite) TestMoveToBackAlreadyInBack() {
   698  	const (
   699  		size = 10
   700  		back = "sim-9"
   701  	)
   702  
   703  	for i := 1; i < size; i++ {
   704  		item := fmt.Sprintf("sim-%d", i)
   705  		suite.queue.Enqueue(item)
   706  	}
   707  
   708  	suite.Equal(ErrorQueueMoveIndexBackPosition, suite.queue.MoveToBack(back).ErrCode)
   709  }
   710  
   711  func (suite *QueueTestSuite) TestMoveToBackNotFound() {
   712  	suite.queue.Enqueue(testValue)
   713  
   714  	err := suite.queue.MoveToBack("anotherValue")
   715  
   716  	suite.Equal(ErrorIDNotFound, err.ErrCode)
   717  }
   718  
   719  // ***************************************************************************************
   720  // ** Get all elements
   721  // ***************************************************************************************
   722  func (suite *QueueTestSuite) TestGetAll() {
   723  	const (
   724  		size = 10
   725  	)
   726  	var slice []interface{}
   727  
   728  	for i := 0; i < size; i++ {
   729  		suite.queue.Enqueue(i)
   730  		slice = append(slice, i)
   731  	}
   732  
   733  	result, err := suite.queue.GetElements()
   734  	suite.Nil(err)
   735  	suite.Equal(slice, result)
   736  }
   737  
   738  func (suite *QueueTestSuite) TestGetAllFiltered() {
   739  	const (
   740  		size = 10
   741  	)
   742  	var (
   743  		offset = 4
   744  		limit  = 2
   745  	)
   746  	var slice []interface{}
   747  	for i := 1; i < size; i++ {
   748  		suite.queue.Enqueue(i)
   749  		slice = append(slice, i)
   750  	}
   751  
   752  	expected := []interface{}{5, 6}
   753  
   754  	result, err := suite.queue.GetFilteredElements(offset, limit)
   755  	suite.Nil(err)
   756  	suite.Equal(slice, suite.queue.slice)
   757  	suite.Equal(expected, result)
   758  }
   759  
   760  func (suite *QueueTestSuite) TestGetAllFilteredOutOfBounds() {
   761  	const (
   762  		size = 10
   763  	)
   764  	var (
   765  		limit  = 2
   766  		offset = 10
   767  	)
   768  	var slice []interface{}
   769  	for i := 0; i < size; i++ {
   770  		suite.queue.Enqueue(i)
   771  		slice = append(slice, i)
   772  	}
   773  
   774  	_, err := suite.queue.GetFilteredElements(offset, limit)
   775  	suite.Equal(ErrorQueueIndexOutOfBounds, err.ErrCode)
   776  	suite.Equal(slice, suite.queue.slice)
   777  }
   778  
   779  func (suite *QueueTestSuite) TestGetAllFilteredWrongRange() {
   780  	const (
   781  		size = 10
   782  	)
   783  	var (
   784  		limit  = -5
   785  		offset = -3
   786  	)
   787  	var slice []interface{}
   788  	for i := 0; i < size; i++ {
   789  		suite.queue.Enqueue(i)
   790  		slice = append(slice, i)
   791  	}
   792  
   793  	_, err := suite.queue.GetFilteredElements(offset, limit)
   794  	suite.Equal(err.ErrCode, ErrorQueueIndexOutOfBounds)
   795  	suite.Equal(slice, suite.queue.slice)
   796  }
   797  
   798  func (suite *QueueTestSuite) TestGetAllFilteredLimitOutOfBounds() {
   799  	const (
   800  		size = 10
   801  	)
   802  	var (
   803  		limit  = 50
   804  		offset = 5
   805  	)
   806  
   807  	for i := 1; i < size; i++ {
   808  		suite.queue.Enqueue(i)
   809  	}
   810  
   811  	expected := []interface{}{6, 7, 8, 9}
   812  
   813  	result, err := suite.queue.GetFilteredElements(offset, limit)
   814  	suite.Nil(err)
   815  	suite.Equal(expected, result)
   816  }
   817  
   818  // ***************************************************************************************
   819  // ** Find by criteria
   820  // ***************************************************************************************
   821  func (suite *QueueTestSuite) TestQueueFindNotFound() {
   822  	const (
   823  		size = 10
   824  	)
   825  
   826  	for i := 1; i < size; i++ {
   827  		item := fmt.Sprintf("sim-%d", i)
   828  		suite.queue.Enqueue(item)
   829  	}
   830  
   831  	results := suite.queue.Find(func(element interface{}) bool {
   832  		return element == "sim-11"
   833  	})
   834  
   835  	suite.Empty(results)
   836  }
   837  
   838  func (suite *QueueTestSuite) TestQueueFind() {
   839  	const (
   840  		size = 10
   841  	)
   842  
   843  	for i := 1; i < size; i++ {
   844  		item := fmt.Sprintf("sim-%d", i)
   845  		suite.queue.Enqueue(item)
   846  	}
   847  
   848  	expected := []int{7, 8}
   849  	results := suite.queue.Find(func(element interface{}) bool {
   850  		return element == "sim-8" || element == "sim-9"
   851  	})
   852  
   853  	suite.NotEmpty(results)
   854  	suite.Equal(expected, results)
   855  }
   856  
   857  // ***************************************************************************************
   858  // ** Find one by target
   859  // ***************************************************************************************
   860  func (suite *QueueTestSuite) TestQueueFindOneNotFound() {
   861  	const (
   862  		size = 10
   863  	)
   864  
   865  	for i := 1; i < size; i++ {
   866  		item := fmt.Sprintf("sim-%d", i)
   867  		suite.queue.Enqueue(item)
   868  	}
   869  
   870  	result := suite.queue.FindOne("sim-11")
   871  	suite.Equal(-1, result)
   872  }
   873  
   874  func (suite *QueueTestSuite) TestQueueFindOne() {
   875  	const (
   876  		size = 10
   877  	)
   878  
   879  	for i := 1; i < size; i++ {
   880  		item := fmt.Sprintf("sim-%d", i)
   881  		suite.queue.Enqueue(item)
   882  	}
   883  
   884  	result := suite.queue.FindOne("sim-9")
   885  	suite.Equal(8, result)
   886  }
   887  
   888  // ***************************************************************************************
   889  // ** Find by IDS
   890  // ***************************************************************************************
   891  func (suite *QueueTestSuite) TestQueueFindByIDsNotFound() {
   892  	const (
   893  		size = 10
   894  	)
   895  
   896  	for i := 1; i < size; i++ {
   897  		item := fmt.Sprintf("sim-%d", i)
   898  		suite.queue.Enqueue(item)
   899  	}
   900  
   901  	ids := []int{10, 11}
   902  	results := suite.queue.FindByIDs(ids)
   903  
   904  	suite.Empty(results)
   905  }
   906  
   907  func (suite *QueueTestSuite) TestQueueFindByIDs() {
   908  	const (
   909  		size = 10
   910  	)
   911  
   912  	for i := 1; i < size; i++ {
   913  		item := fmt.Sprintf("sim-%d", i)
   914  		suite.queue.Enqueue(item)
   915  	}
   916  
   917  	ids := []int{7, 8}
   918  	expected := []interface{}{"sim-8", "sim-9"}
   919  
   920  	results := suite.queue.FindByIDs(ids)
   921  
   922  	suite.NotEmpty(results)
   923  	suite.Equal(expected, results)
   924  }
   925  
   926  func TestQueueTestSuite(t *testing.T) {
   927  	suite.Run(t, new(QueueTestSuite))
   928  }