github.com/grailbio/base@v0.0.11/syncqueue/ordered_queue_test.go (about)

     1  package syncqueue_test
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	"github.com/grailbio/base/syncqueue"
     8  	"github.com/stretchr/testify/assert"
     9  )
    10  
    11  func checkNext(t *testing.T, q *syncqueue.OrderedQueue, value interface{}, ok bool) {
    12  	actualValue, actualOk, actualErr := q.Next()
    13  	assert.Equal(t, nil, actualErr)
    14  	assert.Equal(t, ok, actualOk)
    15  	assert.Equal(t, value, actualValue)
    16  }
    17  
    18  func TestBasic(t *testing.T) {
    19  	testCases := []struct {
    20  		indices []int
    21  		entries []string
    22  	}{
    23  		{
    24  			[]int{0, 1, 2},
    25  			[]string{"zero", "one", "two"},
    26  		},
    27  		{
    28  			[]int{2, 1, 0},
    29  			[]string{"two", "one", "zero"},
    30  		},
    31  		{
    32  			[]int{0, 2, 1},
    33  			[]string{"zero", "two", "one"},
    34  		},
    35  	}
    36  
    37  	for _, testCase := range testCases {
    38  		q := syncqueue.NewOrderedQueue(10)
    39  		for i, entry := range testCase.entries {
    40  			q.Insert(testCase.indices[i], entry)
    41  		}
    42  		q.Close(nil)
    43  
    44  		t.Logf("testCase: %v", testCase.entries)
    45  		checkNext(t, q, "zero", true)
    46  		checkNext(t, q, "one", true)
    47  		checkNext(t, q, "two", true)
    48  		checkNext(t, q, nil, false)
    49  	}
    50  }
    51  
    52  func TestNoBlockWhenNextPresent(t *testing.T) {
    53  	q := syncqueue.NewOrderedQueue(2)
    54  	q.Insert(0, "zero")
    55  	q.Insert(1, "one")
    56  	q.Close(nil)
    57  
    58  	checkNext(t, q, "zero", true)
    59  	checkNext(t, q, "one", true)
    60  	checkNext(t, q, nil, false)
    61  }
    62  
    63  func TestNoBlockWhenInsertNext(t *testing.T) {
    64  	q := syncqueue.NewOrderedQueue(2)
    65  	q.Insert(1, "one")
    66  	q.Insert(0, "zero")
    67  	q.Close(nil)
    68  
    69  	checkNext(t, q, "zero", true)
    70  	checkNext(t, q, "one", true)
    71  	checkNext(t, q, nil, false)
    72  }
    73  
    74  func TestInsertBlockWithNextAvailable(t *testing.T) {
    75  	resultChan := make(chan bool, 1)
    76  
    77  	q := syncqueue.NewOrderedQueue(2)
    78  	q.Insert(1, "one")
    79  	q.Insert(0, "zero")
    80  
    81  	go func() {
    82  		q.Insert(2, "two")
    83  		resultChan <- true
    84  		close(resultChan)
    85  	}()
    86  
    87  	checkNext(t, q, "zero", true)
    88  	result := <-resultChan
    89  	assert.True(t, result, "Expected insert(2, two) to complete after removing an item from the queue")
    90  	q.Close(nil)
    91  
    92  	checkNext(t, q, "one", true)
    93  	checkNext(t, q, "two", true)
    94  	checkNext(t, q, nil, false)
    95  }
    96  
    97  func TestInsertBlockWithoutNextAvailable(t *testing.T) {
    98  	resultChan := make(chan bool, 1)
    99  
   100  	q := syncqueue.NewOrderedQueue(2)
   101  	q.Insert(1, "one")
   102  
   103  	go func() {
   104  		q.Insert(2, "two")
   105  		resultChan <- true
   106  		close(resultChan)
   107  	}()
   108  
   109  	q.Insert(0, "zero")
   110  	checkNext(t, q, "zero", true)
   111  
   112  	// Wait until insert two finishes
   113  	result := <-resultChan
   114  	assert.True(t, result, "Expected insert(2, two) to complete after removing an item from the queue")
   115  	q.Close(nil)
   116  
   117  	checkNext(t, q, "one", true)
   118  	checkNext(t, q, "two", true)
   119  	checkNext(t, q, nil, false)
   120  }
   121  
   122  func TestNextBlockWhenEmpty(t *testing.T) {
   123  	resultChan := make(chan bool, 1)
   124  
   125  	q := syncqueue.NewOrderedQueue(2)
   126  	go func() {
   127  		checkNext(t, q, "zero", true)
   128  		resultChan <- true
   129  		close(resultChan)
   130  	}()
   131  
   132  	// Insert zero and then wait until Next returns
   133  	q.Insert(0, "zero")
   134  	result := <-resultChan
   135  	assert.True(t, result, "Expected Next() to complete after inserting zero")
   136  
   137  	q.Close(nil)
   138  	checkNext(t, q, nil, false)
   139  }
   140  
   141  func TestInsertGetsError(t *testing.T) {
   142  	errors := make(chan error, 1)
   143  
   144  	q := syncqueue.NewOrderedQueue(1)
   145  	q.Insert(0, "zero")
   146  
   147  	go func() {
   148  		errors <- q.Insert(1, "one")
   149  		close(errors)
   150  	}()
   151  
   152  	// Close q with an error.
   153  	q.Close(fmt.Errorf("Foo error"))
   154  
   155  	// Wait for Insert to return with an error, and verify the value of the error.
   156  	e := <-errors
   157  	assert.Equal(t, "Foo error", e.Error())
   158  }
   159  
   160  func TestNextGetsError(t *testing.T) {
   161  	errorChan := make(chan error, 1)
   162  
   163  	q := syncqueue.NewOrderedQueue(1)
   164  	go func() {
   165  		_, _, err := q.Next()
   166  		errorChan <- err
   167  		close(errorChan)
   168  	}()
   169  
   170  	q.Close(fmt.Errorf("Foo error"))
   171  	err := <-errorChan
   172  	assert.Equal(t, "Foo error", err.Error())
   173  }