golang.org/x/tools/gopls@v0.15.3/internal/progress/progress_test.go (about) 1 // Copyright 2020 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package progress 6 7 import ( 8 "context" 9 "fmt" 10 "sync" 11 "testing" 12 13 "golang.org/x/tools/gopls/internal/protocol" 14 ) 15 16 type fakeClient struct { 17 protocol.Client 18 19 token protocol.ProgressToken 20 21 mu sync.Mutex 22 created, begun, reported, messages, ended int 23 } 24 25 func (c *fakeClient) checkToken(token protocol.ProgressToken) { 26 if token == nil { 27 panic("nil token in progress message") 28 } 29 if c.token != nil && c.token != token { 30 panic(fmt.Errorf("invalid token in progress message: got %v, want %v", token, c.token)) 31 } 32 } 33 34 func (c *fakeClient) WorkDoneProgressCreate(ctx context.Context, params *protocol.WorkDoneProgressCreateParams) error { 35 c.mu.Lock() 36 defer c.mu.Unlock() 37 c.checkToken(params.Token) 38 c.created++ 39 return nil 40 } 41 42 func (c *fakeClient) Progress(ctx context.Context, params *protocol.ProgressParams) error { 43 c.mu.Lock() 44 defer c.mu.Unlock() 45 c.checkToken(params.Token) 46 switch params.Value.(type) { 47 case *protocol.WorkDoneProgressBegin: 48 c.begun++ 49 case *protocol.WorkDoneProgressReport: 50 c.reported++ 51 case *protocol.WorkDoneProgressEnd: 52 c.ended++ 53 default: 54 panic(fmt.Errorf("unknown progress value %T", params.Value)) 55 } 56 return nil 57 } 58 59 func (c *fakeClient) ShowMessage(context.Context, *protocol.ShowMessageParams) error { 60 c.mu.Lock() 61 defer c.mu.Unlock() 62 c.messages++ 63 return nil 64 } 65 66 func setup() (context.Context, *Tracker, *fakeClient) { 67 c := &fakeClient{} 68 tracker := NewTracker(c) 69 tracker.SetSupportsWorkDoneProgress(true) 70 return context.Background(), tracker, c 71 } 72 73 func TestProgressTracker_Reporting(t *testing.T) { 74 for _, test := range []struct { 75 name string 76 supported bool 77 token protocol.ProgressToken 78 wantReported, wantCreated, wantBegun, wantEnded int 79 wantMessages int 80 }{ 81 { 82 name: "unsupported", 83 wantMessages: 2, 84 }, 85 { 86 name: "random token", 87 supported: true, 88 wantCreated: 1, 89 wantBegun: 1, 90 wantReported: 1, 91 wantEnded: 1, 92 }, 93 { 94 name: "string token", 95 supported: true, 96 token: "token", 97 wantBegun: 1, 98 wantReported: 1, 99 wantEnded: 1, 100 }, 101 { 102 name: "numeric token", 103 supported: true, 104 token: 1, 105 wantReported: 1, 106 wantBegun: 1, 107 wantEnded: 1, 108 }, 109 } { 110 test := test 111 t.Run(test.name, func(t *testing.T) { 112 ctx, tracker, client := setup() 113 ctx, cancel := context.WithCancel(ctx) 114 defer cancel() 115 tracker.supportsWorkDoneProgress = test.supported 116 work := tracker.Start(ctx, "work", "message", test.token, nil) 117 client.mu.Lock() 118 gotCreated, gotBegun := client.created, client.begun 119 client.mu.Unlock() 120 if gotCreated != test.wantCreated { 121 t.Errorf("got %d created tokens, want %d", gotCreated, test.wantCreated) 122 } 123 if gotBegun != test.wantBegun { 124 t.Errorf("got %d work begun, want %d", gotBegun, test.wantBegun) 125 } 126 // Ignore errors: this is just testing the reporting behavior. 127 work.Report(ctx, "report", 50) 128 client.mu.Lock() 129 gotReported := client.reported 130 client.mu.Unlock() 131 if gotReported != test.wantReported { 132 t.Errorf("got %d progress reports, want %d", gotReported, test.wantCreated) 133 } 134 work.End(ctx, "done") 135 client.mu.Lock() 136 gotEnded, gotMessages := client.ended, client.messages 137 client.mu.Unlock() 138 if gotEnded != test.wantEnded { 139 t.Errorf("got %d ended reports, want %d", gotEnded, test.wantEnded) 140 } 141 if gotMessages != test.wantMessages { 142 t.Errorf("got %d messages, want %d", gotMessages, test.wantMessages) 143 } 144 }) 145 } 146 } 147 148 func TestProgressTracker_Cancellation(t *testing.T) { 149 for _, token := range []protocol.ProgressToken{nil, 1, "a"} { 150 ctx, tracker, _ := setup() 151 var canceled bool 152 cancel := func() { canceled = true } 153 work := tracker.Start(ctx, "work", "message", token, cancel) 154 if err := tracker.Cancel(work.Token()); err != nil { 155 t.Fatal(err) 156 } 157 if !canceled { 158 t.Errorf("tracker.cancel(...): cancel not called") 159 } 160 } 161 }