| // Copyright 2020 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| package par | |
| import ( | |
| "sync" | |
| "testing" | |
| ) | |
| func TestQueueIdle(t *testing.T) { | |
| q := NewQueue(1) | |
| select { | |
| case <-q.Idle(): | |
| default: | |
| t.Errorf("NewQueue(1) is not initially idle.") | |
| } | |
| started := make(chan struct{}) | |
| unblock := make(chan struct{}) | |
| q.Add(func() { | |
| close(started) | |
| <-unblock | |
| }) | |
| <-started | |
| idle := q.Idle() | |
| select { | |
| case <-idle: | |
| t.Errorf("NewQueue(1) is marked idle while processing work.") | |
| default: | |
| } | |
| close(unblock) | |
| <-idle // Should be closed as soon as the Add callback returns. | |
| } | |
| func TestQueueBacklog(t *testing.T) { | |
| const ( | |
| maxActive = 2 | |
| totalWork = 3 * maxActive | |
| ) | |
| q := NewQueue(maxActive) | |
| t.Logf("q = NewQueue(%d)", maxActive) | |
| var wg sync.WaitGroup | |
| wg.Add(totalWork) | |
| started := make([]chan struct{}, totalWork) | |
| unblock := make(chan struct{}) | |
| for i := range started { | |
| started[i] = make(chan struct{}) | |
| i := i | |
| q.Add(func() { | |
| close(started[i]) | |
| <-unblock | |
| wg.Done() | |
| }) | |
| } | |
| for i, c := range started { | |
| if i < maxActive { | |
| <-c // Work item i should be started immediately. | |
| } else { | |
| select { | |
| case <-c: | |
| t.Errorf("Work item %d started before previous items finished.", i) | |
| default: | |
| } | |
| } | |
| } | |
| close(unblock) | |
| for _, c := range started[maxActive:] { | |
| <-c | |
| } | |
| wg.Wait() | |
| } | |