Skip to content

Commit edbdf27

Browse files
committed
fix goroutine leaks and close channels in window tests
1 parent a54c66a commit edbdf27

File tree

2 files changed

+135
-105
lines changed

2 files changed

+135
-105
lines changed

window/manager_test.go

Lines changed: 102 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,21 @@ func createTemp(dir, contents string) (*os.File, error) {
3030

3131
func TestManagerOpenEmpty(t *testing.T) {
3232
wm := NewManager()
33-
eventCh, redrawCh := make(chan event.Event), make(chan struct{})
33+
eventCh, redrawCh, waitCh := make(chan event.Event), make(chan struct{}), make(chan struct{})
3434
wm.Init(eventCh, redrawCh)
3535
go func() {
36-
<-redrawCh
36+
defer func() {
37+
close(eventCh)
38+
close(redrawCh)
39+
close(waitCh)
40+
}()
41+
ev := <-eventCh
42+
if ev.Type != event.Error {
43+
t.Errorf("event type should be %d but got: %d", event.Error, ev.Type)
44+
}
45+
if expected := "no file name"; ev.Error.Error() != expected {
46+
t.Errorf("err should be %q but got: %v", expected, ev.Error)
47+
}
3748
}()
3849
wm.SetSize(110, 20)
3950
if err := wm.Open(""); err != nil {
@@ -62,21 +73,14 @@ func TestManagerOpenEmpty(t *testing.T) {
6273
if err != nil {
6374
t.Errorf("err should be nil but got: %v", err)
6475
}
65-
go wm.Emit(event.Event{Type: event.Write})
66-
ev := <-eventCh
67-
if ev.Type != event.Error {
68-
t.Errorf("event type should be %d but got: %d", event.Error, ev.Type)
69-
}
70-
if expected := "no file name"; ev.Error.Error() != expected {
71-
t.Errorf("err should be %q but got: %v", expected, ev.Error)
72-
}
76+
wm.Emit(event.Event{Type: event.Write})
77+
<-waitCh
7378
wm.Close()
7479
}
7580

7681
func TestManagerOpenStates(t *testing.T) {
7782
wm := NewManager()
78-
eventCh, redrawCh := make(chan event.Event), make(chan struct{})
79-
wm.Init(eventCh, redrawCh)
83+
wm.Init(nil, nil)
8084
wm.SetSize(110, 20)
8185
str := "Hello, world! こんにちは、世界!"
8286
f, err := createTemp(t.TempDir(), str)
@@ -114,14 +118,19 @@ func TestManagerOpenStates(t *testing.T) {
114118

115119
func TestManagerOpenNonExistsWrite(t *testing.T) {
116120
wm := NewManager()
117-
eventCh, redrawCh := make(chan event.Event), make(chan struct{})
121+
eventCh, redrawCh, waitCh := make(chan event.Event), make(chan struct{}), make(chan struct{})
118122
wm.Init(eventCh, redrawCh)
119123
go func() {
120-
for {
121-
select {
122-
case <-eventCh:
123-
case <-redrawCh:
124-
}
124+
defer func() {
125+
close(eventCh)
126+
close(redrawCh)
127+
close(waitCh)
128+
}()
129+
for range 16 {
130+
<-redrawCh
131+
}
132+
if ev := <-eventCh; ev.Type != event.QuitAll {
133+
t.Errorf("event type should be %d but got: %d", event.QuitAll, ev.Type)
125134
}
126135
}()
127136
wm.SetSize(110, 20)
@@ -168,13 +177,13 @@ func TestManagerOpenNonExistsWrite(t *testing.T) {
168177
if string(bs) != str {
169178
t.Errorf("file contents should be %q but got %q", str, string(bs))
170179
}
180+
<-waitCh
171181
wm.Close()
172182
}
173183

174184
func TestManagerOpenExpandBacktick(t *testing.T) {
175185
wm := NewManager()
176-
eventCh, redrawCh := make(chan event.Event), make(chan struct{})
177-
wm.Init(eventCh, redrawCh)
186+
wm.Init(nil, nil)
178187
wm.SetSize(110, 20)
179188
cmd, name := "`which ls`", "ls"
180189
if runtime.GOOS == "windows" {
@@ -208,8 +217,7 @@ func TestEditorOpenExpandHomedir(t *testing.T) {
208217
t.Skip("skip on Windows")
209218
}
210219
wm := NewManager()
211-
eventCh, redrawCh := make(chan event.Event), make(chan struct{})
212-
wm.Init(eventCh, redrawCh)
220+
wm.Init(nil, nil)
213221
wm.SetSize(110, 20)
214222
str := "Hello, world!"
215223
f, err := createTemp(t.TempDir(), str)
@@ -246,21 +254,48 @@ func TestManagerOpenChdirWrite(t *testing.T) {
246254
t.Skip("skip on Windows")
247255
}
248256
wm := NewManager()
249-
eventCh, redrawCh := make(chan event.Event), make(chan struct{})
257+
eventCh, redrawCh, waitCh := make(chan event.Event), make(chan struct{}), make(chan struct{})
250258
wm.Init(eventCh, redrawCh)
251-
go func() {
252-
for {
253-
select {
254-
case <-eventCh:
255-
case <-redrawCh:
256-
}
257-
}
258-
}()
259-
wm.SetSize(110, 20)
260259
f, err := createTemp(t.TempDir(), "Hello")
261260
if err != nil {
262261
t.Fatalf("err should be nil but got: %v", err)
263262
}
263+
go func() {
264+
defer func() {
265+
close(eventCh)
266+
close(redrawCh)
267+
close(waitCh)
268+
}()
269+
ev := <-eventCh
270+
if ev.Type != event.Info {
271+
t.Errorf("event type should be %d but got: %d", event.Info, ev.Type)
272+
}
273+
dir, err := filepath.EvalSymlinks(filepath.Dir(f.Name()))
274+
if err != nil {
275+
t.Errorf("err should be nil but got: %v", err)
276+
}
277+
if expected := dir; ev.Error.Error() != expected {
278+
t.Errorf("err should be %q but got: %v", expected, ev.Error)
279+
}
280+
ev = <-eventCh
281+
if ev.Type != event.Info {
282+
t.Errorf("event type should be %d but got: %d", event.Info, ev.Type)
283+
}
284+
if expected := filepath.Dir(dir); ev.Error.Error() != expected {
285+
t.Errorf("err should be %q but got: %v", expected, ev.Error)
286+
}
287+
for range 11 {
288+
<-redrawCh
289+
}
290+
ev = <-eventCh
291+
if ev.Type != event.Info {
292+
t.Errorf("event type should be %d but got: %d", event.Info, ev.Type)
293+
}
294+
if expected := "13 (0xd) bytes written"; !strings.HasSuffix(ev.Error.Error(), expected) {
295+
t.Errorf("err should be %q but got: %v", expected, ev.Error)
296+
}
297+
}()
298+
wm.SetSize(110, 20)
264299
wm.Emit(event.Event{Type: event.Chdir, Arg: filepath.Dir(f.Name())})
265300
if err := wm.Open(filepath.Base(f.Name())); err != nil {
266301
t.Fatalf("err should be nil but got: %v", err)
@@ -284,21 +319,13 @@ func TestManagerOpenChdirWrite(t *testing.T) {
284319
if expected := "Hello, world!"; string(bs) != expected {
285320
t.Errorf("file contents should be %q but got %q", expected, string(bs))
286321
}
322+
<-waitCh
287323
wm.Close()
288324
}
289325

290326
func TestManagerOpenDirectory(t *testing.T) {
291327
wm := NewManager()
292-
eventCh, redrawCh := make(chan event.Event), make(chan struct{})
293-
wm.Init(eventCh, redrawCh)
294-
go func() {
295-
for {
296-
select {
297-
case <-eventCh:
298-
case <-redrawCh:
299-
}
300-
}
301-
}()
328+
wm.Init(nil, nil)
302329
wm.SetSize(110, 20)
303330
dir := t.TempDir()
304331
if err := wm.Open(dir); err != nil {
@@ -313,8 +340,7 @@ func TestManagerOpenDirectory(t *testing.T) {
313340

314341
func TestManagerRead(t *testing.T) {
315342
wm := NewManager()
316-
eventCh, redrawCh := make(chan event.Event), make(chan struct{})
317-
wm.Init(eventCh, redrawCh)
343+
wm.Init(nil, nil)
318344
wm.SetSize(110, 20)
319345
r := strings.NewReader("Hello, world!")
320346
if err := wm.Read(r); err != nil {
@@ -345,14 +371,16 @@ func TestManagerRead(t *testing.T) {
345371

346372
func TestManagerOnly(t *testing.T) {
347373
wm := NewManager()
348-
eventCh, redrawCh := make(chan event.Event), make(chan struct{})
374+
eventCh, redrawCh, waitCh := make(chan event.Event), make(chan struct{}), make(chan struct{})
349375
wm.Init(eventCh, redrawCh)
350376
go func() {
351-
for {
352-
select {
353-
case <-eventCh:
354-
case <-redrawCh:
355-
}
377+
defer func() {
378+
close(eventCh)
379+
close(redrawCh)
380+
close(waitCh)
381+
}()
382+
for range 4 {
383+
<-eventCh
356384
}
357385
}()
358386
wm.SetSize(110, 20)
@@ -379,19 +407,22 @@ func TestManagerOnly(t *testing.T) {
379407
t.Errorf("layout should be %#v but got %#v", expected, got)
380408
}
381409

410+
<-waitCh
382411
wm.Close()
383412
}
384413

385414
func TestManagerAlternative(t *testing.T) {
386415
wm := NewManager()
387-
eventCh, redrawCh := make(chan event.Event), make(chan struct{})
416+
eventCh, redrawCh, waitCh := make(chan event.Event), make(chan struct{}), make(chan struct{})
388417
wm.Init(eventCh, redrawCh)
389418
go func() {
390-
for {
391-
select {
392-
case <-eventCh:
393-
case <-redrawCh:
394-
}
419+
defer func() {
420+
close(eventCh)
421+
close(redrawCh)
422+
close(waitCh)
423+
}()
424+
for range 9 {
425+
<-eventCh
395426
}
396427
}()
397428
wm.SetSize(110, 20)
@@ -475,19 +506,22 @@ func TestManagerAlternative(t *testing.T) {
475506
t.Errorf("windowIndex should be %d but got %d", expected, windowIndex)
476507
}
477508

509+
<-waitCh
478510
wm.Close()
479511
}
480512

481513
func TestManagerWincmd(t *testing.T) {
482514
wm := NewManager()
483-
eventCh, redrawCh := make(chan event.Event), make(chan struct{})
515+
eventCh, redrawCh, waitCh := make(chan event.Event), make(chan struct{}), make(chan struct{})
484516
wm.Init(eventCh, redrawCh)
485517
go func() {
486-
for {
487-
select {
488-
case <-eventCh:
489-
case <-redrawCh:
490-
}
518+
defer func() {
519+
close(eventCh)
520+
close(redrawCh)
521+
close(waitCh)
522+
}()
523+
for range 17 {
524+
<-eventCh
491525
}
492526
}()
493527
wm.SetSize(110, 20)
@@ -538,6 +572,7 @@ func TestManagerWincmd(t *testing.T) {
538572
t.Errorf("layout should be %#v but got %#v", expected, got)
539573
}
540574

575+
<-waitCh
541576
wm.Close()
542577
}
543578

@@ -556,6 +591,11 @@ func TestManagerCopyCutPaste(t *testing.T) {
556591
}
557592
_, _, _, _ = wm.State()
558593
go func() {
594+
defer func() {
595+
close(eventCh)
596+
close(redrawCh)
597+
close(waitCh)
598+
}()
559599
<-redrawCh
560600
<-redrawCh
561601
<-redrawCh
@@ -620,7 +660,6 @@ func TestManagerCopyCutPaste(t *testing.T) {
620660
if expected := "Hefoobarfoobarfoobarlrld!"; !strings.HasPrefix(string(ws.Bytes), expected) {
621661
t.Errorf("Bytes should start with %q but got %q", expected, string(ws.Bytes))
622662
}
623-
close(waitCh)
624663
}()
625664
wm.Emit(event.Event{Type: event.CursorNext, Mode: mode.Normal, Count: 3})
626665
wm.Emit(event.Event{Type: event.StartVisual})

0 commit comments

Comments
 (0)