Skip to content

Commit bf4b91c

Browse files
committed
harden tests.
1 parent f2df3ec commit bf4b91c

File tree

1 file changed

+40
-32
lines changed

1 file changed

+40
-32
lines changed

dial_queue_test.go

+40-32
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ package dht
22

33
import (
44
"context"
5+
"fmt"
56
"sync"
7+
"sync/atomic"
68
"testing"
79
"time"
810

@@ -12,7 +14,6 @@ import (
1214

1315
func init() {
1416
DialQueueScalingMutePeriod = 0
15-
DialQueueMaxIdle = 1 * time.Second
1617
}
1718

1819
func TestDialQueueErrorsWithTooManyConsumers(t *testing.T) {
@@ -41,13 +42,14 @@ func TestDialQueueErrorsWithTooManyConsumers(t *testing.T) {
4142
}
4243

4344
func TestDialQueueGrowsOnSlowDials(t *testing.T) {
45+
DialQueueMaxIdle = 10 * time.Minute
46+
4447
in := queue.NewChanQueue(context.Background(), queue.NewXORDistancePQ("test"))
4548
hang := make(chan struct{})
4649

47-
var wg sync.WaitGroup
48-
wg.Add(19) // we expect 19 workers
50+
var cnt int32
4951
dialFn := func(ctx context.Context, p peer.ID) error {
50-
wg.Done()
52+
atomic.AddInt32(&cnt, 1)
5153
<-hang
5254
return nil
5355
}
@@ -65,26 +67,25 @@ func TestDialQueueGrowsOnSlowDials(t *testing.T) {
6567
time.Sleep(100 * time.Millisecond)
6668
}
6769

68-
doneCh := make(chan struct{})
70+
for i := 0; i < 20; i++ {
71+
if atomic.LoadInt32(&cnt) > int32(DialQueueMinParallelism) {
72+
return
73+
}
74+
time.Sleep(100 * time.Millisecond)
75+
}
6976

70-
// wait in a goroutine in case the test fails and we block.
71-
go func() {
72-
defer close(doneCh)
73-
wg.Wait()
74-
}()
77+
t.Errorf("expected 19 concurrent dials, got %d", atomic.LoadInt32(&cnt))
7578

76-
select {
77-
case <-doneCh:
78-
case <-time.After(2 * time.Second):
79-
t.Error("expected 19 concurrent dials, got less")
80-
}
8179
}
8280

8381
func TestDialQueueShrinksWithNoConsumers(t *testing.T) {
82+
// reduce interference from the other shrink path.
83+
DialQueueMaxIdle = 10 * time.Minute
84+
8485
in := queue.NewChanQueue(context.Background(), queue.NewXORDistancePQ("test"))
8586
hang := make(chan struct{})
8687

87-
var wg sync.WaitGroup
88+
wg := new(sync.WaitGroup)
8889
wg.Add(13)
8990
dialFn := func(ctx context.Context, p peer.ID) error {
9091
wg.Done()
@@ -94,48 +95,55 @@ func TestDialQueueShrinksWithNoConsumers(t *testing.T) {
9495

9596
dq := newDialQueue(context.Background(), "test", in, dialFn, 3)
9697

97-
// Enqueue 13 jobs, one per worker we'll grow to.
98-
for i := 0; i < 13; i++ {
99-
in.EnqChan <- peer.ID(i)
100-
}
98+
defer func() {
99+
recover()
100+
fmt.Println(dq.nWorkers)
101+
}()
101102

102103
// acquire 3 consumers, everytime we acquire a consumer, we will grow the pool because no dial job is completed
103104
// and immediately returnable.
104105
for i := 0; i < 3; i++ {
105106
_ = dq.Consume()
106-
time.Sleep(100 * time.Millisecond)
107107
}
108108

109-
waitForWg(t, &wg, 2*time.Second)
109+
// Enqueue 13 jobs, one per worker we'll grow to.
110+
for i := 0; i < 13; i++ {
111+
in.EnqChan <- peer.ID(i)
112+
}
113+
114+
waitForWg(t, wg, 2*time.Second)
110115

111116
// Release a few dialFn, but not all of them because downscaling happens when workers detect there are no
112117
// consumers to consume their values. So the other three will be these witnesses.
113-
for i := 0; i < 10; i++ {
118+
for i := 0; i < 3; i++ {
114119
hang <- struct{}{}
115120
}
116121

117122
// allow enough time for signalling and dispatching values to outstanding consumers.
118-
time.Sleep(500 * time.Millisecond)
123+
time.Sleep(1 * time.Second)
119124

120-
// unblock the other three.
121-
hang <- struct{}{}
122-
hang <- struct{}{}
123-
hang <- struct{}{}
125+
// unblock the rest.
126+
for i := 0; i < 10; i++ {
127+
hang <- struct{}{}
128+
}
124129

130+
wg = new(sync.WaitGroup)
125131
// we should now only have 6 workers, because all the shrink events will have been honoured.
126132
wg.Add(6)
127133

128-
// enqueue more jobs
129-
for i := 0; i < 20; i++ {
134+
// enqueue more jobs.
135+
for i := 0; i < 6; i++ {
130136
in.EnqChan <- peer.ID(i)
131137
}
132138

133139
// let's check we have 6 workers hanging.
134-
waitForWg(t, &wg, 2*time.Second)
140+
waitForWg(t, wg, 2*time.Second)
135141
}
136142

137143
// Inactivity = workers are idle because the DHT query is progressing slow and is producing too few peers to dial.
138-
func TestDialQueueShrinksWithInactivity(t *testing.T) {
144+
func TestDialQueueShrinksWithWhenIdle(t *testing.T) {
145+
DialQueueMaxIdle = 1 * time.Second
146+
139147
in := queue.NewChanQueue(context.Background(), queue.NewXORDistancePQ("test"))
140148
hang := make(chan struct{})
141149

0 commit comments

Comments
 (0)