decred.org/dcrdex@v1.0.5/server/market/epump_test.go (about) 1 package market 2 3 import ( 4 "context" 5 "math/rand" 6 "runtime" 7 "sync" 8 "testing" 9 "time" 10 ) 11 12 func TestMarket_epochPumpHalt(t *testing.T) { 13 // This tests stopping the epochPump. 14 15 ctx, cancel := context.WithCancel(context.Background()) 16 defer cancel() 17 18 ePump := newEpochPump() 19 var wg sync.WaitGroup 20 wg.Add(1) 21 go func() { 22 defer wg.Done() 23 ePump.Run(ctx) 24 }() 25 26 eq0 := NewEpoch(123413513, 1000) 27 rq0 := ePump.Insert(eq0) 28 29 eq1 := NewEpoch(123413514, 1000) 30 rq1 := ePump.Insert(eq1) // testing ep.q append 31 32 close(rq1.ready) 33 34 var rq0Out *readyEpoch 35 select { 36 case rq0Out = <-ePump.ready: 37 t.Fatalf("readyQueue provided out of order, got epoch %d", rq0Out.Epoch) 38 default: 39 // good, nothing was supposed to come out yet 40 } 41 42 close(rq0.ready) 43 44 rq0Out = <-ePump.ready 45 if rq0Out.EpochQueue.Epoch != eq0.Epoch { 46 t.Errorf("expected epoch %d, got %d", eq0.Epoch, rq0Out.EpochQueue.Epoch) 47 } 48 49 cancel() // testing len(ep.q) == 0 (Ready to shutdown), with rq1 in head 50 wg.Wait() 51 52 // pump should be done, but the final readyEpoch should have been sent on 53 // the buffered ready chan. 54 rq1Out := <-ePump.ready 55 if rq1Out.EpochQueue.Epoch != eq1.Epoch { 56 t.Errorf("expected epoch %d, got %d", eq1.Epoch, rq1Out.EpochQueue.Epoch) 57 } 58 59 // Test shutdown with multiple queued epochs. 60 ctx, cancel = context.WithCancel(context.Background()) 61 defer cancel() 62 63 ePump = newEpochPump() 64 wg.Add(1) 65 go func() { 66 defer wg.Done() 67 ePump.Run(ctx) 68 }() 69 70 eq0 = NewEpoch(123413513, 1000) 71 rq0 = ePump.Insert(eq0) 72 eq1 = NewEpoch(123413514, 1000) 73 rq1 = ePump.Insert(eq1) 74 eq2 := NewEpoch(123413515, 1000) 75 rq2 := ePump.Insert(eq2) 76 77 cancel() // testing len(ep.q) != 0 (stop after it drains the queue). 78 runtime.Gosched() // let Run start shutting things down 79 time.Sleep(50 * time.Millisecond) 80 81 // Make sure epochs come out in order. 82 close(rq0.ready) 83 rq0Out = <-ePump.ready 84 if rq0Out.EpochQueue.Epoch != eq0.Epoch { 85 t.Errorf("expected epoch %d, got %d", eq0.Epoch, rq0Out.EpochQueue.Epoch) 86 } 87 88 close(rq1.ready) 89 rq1Out = <-ePump.ready 90 if rq1Out.EpochQueue.Epoch != eq1.Epoch { 91 t.Errorf("expected epoch %d, got %d", eq1.Epoch, rq1Out.EpochQueue.Epoch) 92 } 93 94 close(rq2.ready) 95 rq2Out := <-ePump.ready 96 if rq2Out.EpochQueue.Epoch != eq2.Epoch { 97 t.Errorf("expected epoch %d, got %d", eq2.Epoch, rq2Out.EpochQueue.Epoch) 98 } 99 100 select { 101 case _, ok := <-ePump.ready: 102 if ok { 103 t.Errorf("ready channel should be closed now (Run returned), but something came through") 104 } 105 case <-time.After(time.Second): 106 t.Errorf("ready channel should be closed by now (Run returned)") 107 } 108 109 rqX := ePump.Insert(eq2) 110 if rqX != nil { 111 t.Errorf("halted epoch pump allowed insertion of new epoch queue") 112 } 113 114 wg.Wait() 115 } 116 117 func Test_epochPump_next(t *testing.T) { 118 ctx, cancel := context.WithCancel(context.Background()) 119 defer cancel() 120 121 ep := newEpochPump() 122 var wg sync.WaitGroup 123 wg.Add(1) 124 go func() { 125 ep.Run(ctx) 126 wg.Done() 127 }() 128 129 waitTime := int64(5 * time.Second) 130 if testing.Short() { 131 waitTime = int64(1 * time.Second) 132 } 133 134 var epochStart, epochDur, numEpochs int64 = 123413513, 1_000, 100 135 epochs := make([]*readyEpoch, numEpochs) 136 for i := int64(0); i < numEpochs; i++ { 137 rq := ep.Insert(NewEpoch(i+epochStart, epochDur)) 138 epochs[i] = rq 139 140 // Simulate preimage collection, randomly making the queues ready. 141 go func() { 142 wait := time.Duration(rand.Int63n(waitTime)) 143 time.Sleep(wait) 144 close(rq.ready) 145 }() 146 } 147 148 // Receive all the ready epochs, verifying they come in order. 149 for i := epochStart; i < numEpochs+epochStart; i++ { 150 rq := <-ep.ready 151 if rq.Epoch != i { 152 t.Errorf("Received epoch %d, expected %d", rq.Epoch, i) 153 } 154 } 155 // All fake preimage collection goroutines are done now. 156 157 cancel() 158 wg.Wait() 159 }