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 }