@@ -2,13 +2,16 @@ package cliui_test
2
2
3
3
import (
4
4
"context"
5
+ "fmt"
5
6
"io"
6
7
"os"
8
+ "regexp"
7
9
"runtime"
8
10
"sync"
9
11
"testing"
10
12
"time"
11
13
14
+ "github.com/coder/coder/v2/testutil"
12
15
"github.com/stretchr/testify/assert"
13
16
14
17
"github.com/coder/coder/v2/cli/cliui"
@@ -25,7 +28,11 @@ func TestProvisionerJob(t *testing.T) {
25
28
t .Parallel ()
26
29
27
30
test := newProvisionerJob (t )
28
- go func () {
31
+
32
+ ctx , cancel := context .WithTimeout (context .Background (), testutil .WaitShort )
33
+ defer cancel ()
34
+
35
+ testutil .Go (t , func () {
29
36
<- test .Next
30
37
test .JobMutex .Lock ()
31
38
test .Job .Status = codersdk .ProvisionerJobRunning
@@ -39,20 +46,26 @@ func TestProvisionerJob(t *testing.T) {
39
46
test .Job .CompletedAt = & now
40
47
close (test .Logs )
41
48
test .JobMutex .Unlock ()
42
- }()
43
- test .PTY .ExpectMatch ("Queued" )
44
- test .Next <- struct {}{}
45
- test .PTY .ExpectMatch ("Queued" )
46
- test .PTY .ExpectMatch ("Running" )
47
- test .Next <- struct {}{}
48
- test .PTY .ExpectMatch ("Running" )
49
+ })
50
+ testutil .Eventually (ctx , t , func (ctx context.Context ) (done bool ) {
51
+ test .PTY .ExpectMatch (cliui .ProvisioningStateQueued )
52
+ test .Next <- struct {}{}
53
+ test .PTY .ExpectMatch (cliui .ProvisioningStateQueued )
54
+ test .PTY .ExpectMatch (cliui .ProvisioningStateRunning )
55
+ test .Next <- struct {}{}
56
+ test .PTY .ExpectMatch (cliui .ProvisioningStateRunning )
57
+ return true
58
+ }, testutil .IntervalFast )
49
59
})
50
60
51
61
t .Run ("Stages" , func (t * testing.T ) {
52
62
t .Parallel ()
53
63
54
64
test := newProvisionerJob (t )
55
- go func () {
65
+ ctx , cancel := context .WithTimeout (context .Background (), testutil .WaitShort )
66
+ defer cancel ()
67
+
68
+ testutil .Go (t , func () {
56
69
<- test .Next
57
70
test .JobMutex .Lock ()
58
71
test .Job .Status = codersdk .ProvisionerJobRunning
@@ -70,13 +83,86 @@ func TestProvisionerJob(t *testing.T) {
70
83
test .Job .CompletedAt = & now
71
84
close (test .Logs )
72
85
test .JobMutex .Unlock ()
73
- }()
74
- test .PTY .ExpectMatch ("Queued" )
75
- test .Next <- struct {}{}
76
- test .PTY .ExpectMatch ("Queued" )
77
- test .PTY .ExpectMatch ("Something" )
78
- test .Next <- struct {}{}
79
- test .PTY .ExpectMatch ("Something" )
86
+ })
87
+ testutil .Eventually (ctx , t , func (ctx context.Context ) (done bool ) {
88
+ test .PTY .ExpectMatch (cliui .ProvisioningStateQueued )
89
+ test .Next <- struct {}{}
90
+ test .PTY .ExpectMatch (cliui .ProvisioningStateQueued )
91
+ test .PTY .ExpectMatch ("Something" )
92
+ test .Next <- struct {}{}
93
+ test .PTY .ExpectMatch ("Something" )
94
+ return true
95
+ }, testutil .IntervalFast )
96
+ })
97
+
98
+ t .Run ("Queue Position" , func (t * testing.T ) {
99
+ t .Parallel ()
100
+
101
+ stage := cliui .ProvisioningStateQueued
102
+
103
+ tests := []struct {
104
+ name string
105
+ queuePos int
106
+ expected string
107
+ }{
108
+ {
109
+ name : "first" ,
110
+ queuePos : 0 ,
111
+ expected : fmt .Sprintf ("%s$" , stage ),
112
+ },
113
+ {
114
+ name : "next" ,
115
+ queuePos : 1 ,
116
+ expected : fmt .Sprintf (`%s %s$` , stage , regexp .QuoteMeta ("(next)" )),
117
+ },
118
+ {
119
+ name : "other" ,
120
+ queuePos : 4 ,
121
+ expected : fmt .Sprintf (`%s %s$` , stage , regexp .QuoteMeta ("(position: 4)" )),
122
+ },
123
+ }
124
+
125
+ for _ , tc := range tests {
126
+ tc := tc
127
+
128
+ t .Run (tc .name , func (t * testing.T ) {
129
+ t .Parallel ()
130
+
131
+ test := newProvisionerJob (t )
132
+ test .JobMutex .Lock ()
133
+ test .Job .QueuePosition = tc .queuePos
134
+ test .Job .QueueSize = tc .queuePos
135
+ test .JobMutex .Unlock ()
136
+
137
+ ctx , cancel := context .WithTimeout (context .Background (), testutil .WaitShort )
138
+ defer cancel ()
139
+
140
+ testutil .Go (t , func () {
141
+ <- test .Next
142
+ test .JobMutex .Lock ()
143
+ test .Job .Status = codersdk .ProvisionerJobRunning
144
+ now := dbtime .Now ()
145
+ test .Job .StartedAt = & now
146
+ test .JobMutex .Unlock ()
147
+ <- test .Next
148
+ test .JobMutex .Lock ()
149
+ test .Job .Status = codersdk .ProvisionerJobSucceeded
150
+ now = dbtime .Now ()
151
+ test .Job .CompletedAt = & now
152
+ close (test .Logs )
153
+ test .JobMutex .Unlock ()
154
+ })
155
+ testutil .Eventually (ctx , t , func (ctx context.Context ) (done bool ) {
156
+ test .PTY .ExpectRegexMatch (tc .expected )
157
+ test .Next <- struct {}{}
158
+ test .PTY .ExpectMatch (cliui .ProvisioningStateQueued ) // step completed
159
+ test .PTY .ExpectMatch (cliui .ProvisioningStateRunning )
160
+ test .Next <- struct {}{}
161
+ test .PTY .ExpectMatch (cliui .ProvisioningStateRunning )
162
+ return true
163
+ }, testutil .IntervalFast )
164
+ })
165
+ }
80
166
})
81
167
82
168
// This cannot be ran in parallel because it uses a signal.
@@ -90,7 +176,11 @@ func TestProvisionerJob(t *testing.T) {
90
176
}
91
177
92
178
test := newProvisionerJob (t )
93
- go func () {
179
+
180
+ ctx , cancel := context .WithTimeout (context .Background (), testutil .WaitShort )
181
+ defer cancel ()
182
+
183
+ testutil .Go (t , func () {
94
184
<- test .Next
95
185
currentProcess , err := os .FindProcess (os .Getpid ())
96
186
assert .NoError (t , err )
@@ -103,12 +193,15 @@ func TestProvisionerJob(t *testing.T) {
103
193
test .Job .CompletedAt = & now
104
194
close (test .Logs )
105
195
test .JobMutex .Unlock ()
106
- }()
107
- test .PTY .ExpectMatch ("Queued" )
108
- test .Next <- struct {}{}
109
- test .PTY .ExpectMatch ("Gracefully canceling" )
110
- test .Next <- struct {}{}
111
- test .PTY .ExpectMatch ("Queued" )
196
+ })
197
+ testutil .Eventually (ctx , t , func (ctx context.Context ) (done bool ) {
198
+ test .PTY .ExpectMatch (cliui .ProvisioningStateQueued )
199
+ test .Next <- struct {}{}
200
+ test .PTY .ExpectMatch ("Gracefully canceling" )
201
+ test .Next <- struct {}{}
202
+ test .PTY .ExpectMatch (cliui .ProvisioningStateQueued )
203
+ return true
204
+ }, testutil .IntervalFast )
112
205
})
113
206
}
114
207
0 commit comments