readylist_test.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. package h2mux
  2. import (
  3. "testing"
  4. "time"
  5. "github.com/stretchr/testify/assert"
  6. )
  7. func assertEmpty(t *testing.T, rl *ReadyList) {
  8. select {
  9. case <-rl.ReadyChannel():
  10. t.Fatal("Spurious wakeup")
  11. default:
  12. }
  13. }
  14. func assertClosed(t *testing.T, rl *ReadyList) {
  15. select {
  16. case _, ok := <-rl.ReadyChannel():
  17. assert.False(t, ok, "ReadyChannel was not closed")
  18. case <-time.After(100 * time.Millisecond):
  19. t.Fatalf("Timeout")
  20. }
  21. }
  22. func receiveWithTimeout(t *testing.T, rl *ReadyList) uint32 {
  23. select {
  24. case i := <-rl.ReadyChannel():
  25. return i
  26. case <-time.After(100 * time.Millisecond):
  27. t.Fatalf("Timeout")
  28. return 0
  29. }
  30. }
  31. func TestReadyListEmpty(t *testing.T) {
  32. rl := NewReadyList()
  33. // no signals, receive should fail
  34. assertEmpty(t, rl)
  35. }
  36. func TestReadyListSignal(t *testing.T) {
  37. rl := NewReadyList()
  38. assertEmpty(t, rl)
  39. rl.Signal(0)
  40. if receiveWithTimeout(t, rl) != 0 {
  41. t.Fatalf("Received wrong ID of signalled event")
  42. }
  43. assertEmpty(t, rl)
  44. }
  45. func TestReadyListMultipleSignals(t *testing.T) {
  46. rl := NewReadyList()
  47. assertEmpty(t, rl)
  48. // Signals should not block;
  49. // Duplicate unhandled signals should not cause multiple wakeups
  50. signalled := [5]bool{}
  51. for i := range signalled {
  52. rl.Signal(uint32(i))
  53. rl.Signal(uint32(i))
  54. }
  55. // All signals should be received once (in any order)
  56. for range signalled {
  57. i := receiveWithTimeout(t, rl)
  58. if signalled[i] {
  59. t.Fatalf("Received signal %d more than once", i)
  60. }
  61. signalled[i] = true
  62. }
  63. for i := range signalled {
  64. if !signalled[i] {
  65. t.Fatalf("Never received signal %d", i)
  66. }
  67. }
  68. assertEmpty(t, rl)
  69. }
  70. func TestReadyListClose(t *testing.T) {
  71. rl := NewReadyList()
  72. rl.Close()
  73. // readyList.run() occurs in a separate goroutine,
  74. // so there's no way to directly check that run() has terminated.
  75. // Perform an indirect check: is the ready channel closed?
  76. assertClosed(t, rl)
  77. // a second rl.Close() shouldn't cause a panic
  78. rl.Close()
  79. // Signal shouldn't block after Close()
  80. done := make(chan struct{})
  81. go func() {
  82. for i := 0; i < 5; i++ {
  83. rl.Signal(uint32(i))
  84. }
  85. close(done)
  86. }()
  87. select {
  88. case <-done:
  89. case <-time.After(100 * time.Millisecond):
  90. t.Fatal("Test timed out")
  91. }
  92. }
  93. func TestReadyDescriptorQueue(t *testing.T) {
  94. var queue readyDescriptorQueue
  95. items := [4]readyDescriptor{}
  96. for i := range items {
  97. items[i].ID = uint32(i)
  98. }
  99. if !queue.Empty() {
  100. t.Fatalf("nil queue should be empty")
  101. }
  102. queue.Enqueue(&items[3])
  103. queue.Enqueue(&items[1])
  104. queue.Enqueue(&items[0])
  105. queue.Enqueue(&items[2])
  106. if queue.Empty() {
  107. t.Fatalf("Empty should be false after enqueue")
  108. }
  109. i := queue.Dequeue().ID
  110. if i != 3 {
  111. t.Fatalf("item 3 should have been dequeued, got %d instead", i)
  112. }
  113. i = queue.Dequeue().ID
  114. if i != 1 {
  115. t.Fatalf("item 1 should have been dequeued, got %d instead", i)
  116. }
  117. i = queue.Dequeue().ID
  118. if i != 0 {
  119. t.Fatalf("item 0 should have been dequeued, got %d instead", i)
  120. }
  121. i = queue.Dequeue().ID
  122. if i != 2 {
  123. t.Fatalf("item 2 should have been dequeued, got %d instead", i)
  124. }
  125. if !queue.Empty() {
  126. t.Fatal("queue should be empty after dequeuing all items")
  127. }
  128. if queue.Dequeue() != nil {
  129. t.Fatal("dequeue on empty queue should return nil")
  130. }
  131. }
  132. func TestReadyDescriptorMap(t *testing.T) {
  133. m := newReadyDescriptorMap()
  134. m.Delete(42)
  135. // (delete of missing key should be a noop)
  136. x := m.SetIfMissing(42)
  137. if x == nil {
  138. t.Fatal("SetIfMissing for new key returned nil")
  139. }
  140. if m.SetIfMissing(42) != nil {
  141. t.Fatal("SetIfMissing for existing key returned non-nil")
  142. }
  143. // this delete has effect
  144. m.Delete(42)
  145. // the next set should reuse the old object
  146. y := m.SetIfMissing(666)
  147. if y == nil {
  148. t.Fatal("SetIfMissing for new key returned nil")
  149. }
  150. if x != y {
  151. t.Fatal("SetIfMissing didn't reuse freed object")
  152. }
  153. }