Comment 4 for bug 1780766

Revision history for this message
John A Meinel (jameinel) wrote :

The problem seems to lie in here:
func (c *fakeAPIClient) Actions(args params.Entities) (params.ActionResults, error) {
 // If the test supplies a delay time too long, we'll return an error
 // to prevent the test hanging. If the given wait is up, then return
 // the results; otherwise, return a pending status.

 // First, sync.
 _ = <-time.NewTimer(0 * time.Second).C

 select {
 case _ = <-c.delay.C:
  // The API delay timer is up. Pass pre-canned results back.
  return params.ActionResults{Results: c.actionResults}, c.apiErr
 case _ = <-c.timeout.C:
  // Timeout to prevent tests from hanging.
  return params.ActionResults{}, errors.New("test timed out before wait time")
 default:
  // Timeout should only be nonzero in case we want to test
  // pending behavior with a --wait flag on FetchCommand.
  return params.ActionResults{Results: []params.ActionResult{{
   Status: params.ActionPending,
   Output: map[string]interface{}{},
   Started: time.Date(2015, time.February, 14, 8, 15, 0, 0, time.UTC),
   Enqueued: time.Date(2015, time.February, 14, 8, 13, 0, 0, time.UTC),
  }}}, nil
 }

The issue is that while it is true that the setup does:
  fakeClient := makeFakeClient(
   0*time.Second, // No API delay
   5*time.Second, // 5 second test timeout
   tc.tags,
   tc.results,
   tc.actionsByNames,
   "", // No API error
  )

which creates:
  delay: time.NewTimer(delay),
  timeout: time.NewTimer(timeout),

Apparently there is no guarantee that time.NewTimer(0) will actually be ready before the 'default:' branch is evaluated.

the _ = <time.NewTimer(0 *time.Second).C seems very strange.
Presumably it is meant to handle the case where c.delay.C isn't actually ready, but I don't think it actually gives us that.

Note also that all of these are *real* time.NewTimer calls, not *clock* calls. Which also adds real-clock-skew issues.

I'd like to fix those things, but the easier thing to do is just add '--wait 1s' to all the calls, in which case the code will see the Pending result, and keep trying until it sees something else.