@@ -114,53 +114,16 @@ type workProgress struct {
114114 complete bool // seen 'end'
115115}
116116
117- // This method, provided for debugging, accesses mutable fields without a lock,
118- // so it must not be called concurrent with any State mutation.
119- func (s State ) String () string {
120- var b strings.Builder
121- b .WriteString ("#### log messages (see RPC logs for full text):\n " )
122- for _ , msg := range s .logs {
123- summary := fmt .Sprintf ("%v: %q" , msg .Type , msg .Message )
124- if len (summary ) > 60 {
125- summary = summary [:57 ] + "..."
126- }
127- // Some logs are quite long, and since they should be reproduced in the RPC
128- // logs on any failure we include here just a short summary.
129- fmt .Fprint (& b , "\t " + summary + "\n " )
130- }
131- b .WriteString ("\n " )
132- b .WriteString ("#### diagnostics:\n " )
133- for name , params := range s .diagnostics {
134- fmt .Fprintf (& b , "\t %s (version %d):\n " , name , params .Version )
135- for _ , d := range params .Diagnostics {
136- fmt .Fprintf (& b , "\t \t %d:%d [%s]: %s\n " , d .Range .Start .Line , d .Range .Start .Character , d .Source , d .Message )
137- }
138- }
139- b .WriteString ("\n " )
140- b .WriteString ("#### outstanding work:\n " )
141- for token , state := range s .work {
142- if state .complete {
143- continue
144- }
145- name := state .title
146- if name == "" {
147- name = fmt .Sprintf ("!NO NAME(token: %s)" , token )
148- }
149- fmt .Fprintf (& b , "\t %s: %.2f\n " , name , state .percent )
150- }
151- b .WriteString ("#### completed work:\n " )
152- for name , count := range s .completedWork {
153- fmt .Fprintf (& b , "\t %s: %d\n " , name , count )
154- }
155- return b .String ()
117+ type awaitResult struct {
118+ verdict Verdict
119+ reason string
156120}
157121
158- // A condition is satisfied when all expectations are simultaneously
159- // met. At that point, the 'met' channel is closed. On any failure, err is set
160- // and the failed channel is closed.
122+ // A condition is satisfied when its expectation is [Met] or [Unmeetable]. The
123+ // result is sent on the verdict channel.
161124type condition struct {
162- expectations [] Expectation
163- verdict chan Verdict
125+ expectation Expectation
126+ verdict chan awaitResult
164127}
165128
166129func (a * Awaiter ) onDiagnostics (_ context.Context , d * protocol.PublishDiagnosticsParams ) error {
@@ -334,27 +297,13 @@ func (a *Awaiter) onUnregisterCapability(_ context.Context, m *protocol.Unregist
334297
335298func (a * Awaiter ) checkConditionsLocked () {
336299 for id , condition := range a .waiters {
337- if v , _ := checkExpectations (a .state , condition . expectations ); v != Unmet {
300+ if v , why := condition . expectation . Check (a .state ); v != Unmet {
338301 delete (a .waiters , id )
339- condition .verdict <- v
302+ condition .verdict <- awaitResult { v , why }
340303 }
341304 }
342305}
343306
344- // checkExpectations reports whether s meets all expectations.
345- func checkExpectations (s State , expectations []Expectation ) (Verdict , string ) {
346- finalVerdict := Met
347- var summary strings.Builder
348- for _ , e := range expectations {
349- v := e .Check (s )
350- if v > finalVerdict {
351- finalVerdict = v
352- }
353- fmt .Fprintf (& summary , "%v: %s\n " , v , e .Description )
354- }
355- return finalVerdict , summary .String ()
356- }
357-
358307// Await blocks until the given expectations are all simultaneously met.
359308//
360309// Generally speaking Await should be avoided because it blocks indefinitely if
@@ -363,38 +312,38 @@ func checkExpectations(s State, expectations []Expectation) (Verdict, string) {
363312// waiting.
364313func (e * Env ) Await (expectations ... Expectation ) {
365314 e .T .Helper ()
366- if err := e .Awaiter .Await (e .Ctx , expectations ... ); err != nil {
315+ if err := e .Awaiter .Await (e .Ctx , AllOf ( expectations ... ) ); err != nil {
367316 e .T .Fatal (err )
368317 }
369318}
370319
371320// OnceMet blocks until the precondition is met by the state or becomes
372321// unmeetable. If it was met, OnceMet checks that the state meets all
373322// expectations in mustMeets.
374- func (e * Env ) OnceMet (precondition Expectation , mustMeets ... Expectation ) {
323+ func (e * Env ) OnceMet (pre Expectation , mustMeets ... Expectation ) {
375324 e .T .Helper ()
376- e .Await (OnceMet (precondition , mustMeets ... ))
325+ e .Await (OnceMet (pre , AllOf ( mustMeets ... ) ))
377326}
378327
379328// Await waits for all expectations to simultaneously be met. It should only be
380329// called from the main test goroutine.
381- func (a * Awaiter ) Await (ctx context.Context , expectations ... Expectation ) error {
330+ func (a * Awaiter ) Await (ctx context.Context , expectation Expectation ) error {
382331 a .mu .Lock ()
383332 // Before adding the waiter, we check if the condition is currently met or
384333 // failed to avoid a race where the condition was realized before Await was
385334 // called.
386- switch verdict , summary := checkExpectations (a .state , expectations ); verdict {
335+ switch verdict , why := expectation . Check (a .state ); verdict {
387336 case Met :
388337 a .mu .Unlock ()
389338 return nil
390339 case Unmeetable :
391- err := fmt .Errorf ("unmeetable expectations :\n %s\n state :\n %v " , summary , a . state )
340+ err := fmt .Errorf ("unmeetable expectation :\n %s\n reason :\n %s " , indent ( expectation . Description ), indent ( why ) )
392341 a .mu .Unlock ()
393342 return err
394343 }
395344 cond := & condition {
396- expectations : expectations ,
397- verdict : make (chan Verdict ),
345+ expectation : expectation ,
346+ verdict : make (chan awaitResult ),
398347 }
399348 a .waiters [nextAwaiterRegistration .Add (1 )] = cond
400349 a .mu .Unlock ()
@@ -403,19 +352,17 @@ func (a *Awaiter) Await(ctx context.Context, expectations ...Expectation) error
403352 select {
404353 case <- ctx .Done ():
405354 err = ctx .Err ()
406- case v := <- cond .verdict :
407- if v != Met {
408- err = fmt .Errorf ("condition has final verdict %v" , v )
355+ case res := <- cond .verdict :
356+ if res .verdict != Met {
357+ err = fmt .Errorf ("the following condition is %s:\n %s\n reason:\n %s" ,
358+ res .verdict , indent (expectation .Description ), indent (res .reason ))
409359 }
410360 }
411- a .mu .Lock ()
412- defer a .mu .Unlock ()
413- _ , summary := checkExpectations (a .state , expectations )
361+ return err
362+ }
414363
415- // Debugging an unmet expectation can be tricky, so we put some effort into
416- // nicely formatting the failure.
417- if err != nil {
418- return fmt .Errorf ("waiting on:\n %s\n err:%v\n \n state:\n %v" , summary , err , a .state )
419- }
420- return nil
364+ // indent indents all lines of msg, including the first.
365+ func indent (msg string ) string {
366+ const prefix = " "
367+ return prefix + strings .ReplaceAll (msg , "\n " , "\n " + prefix )
421368}
0 commit comments