scrape: fix two loop variable scoping bugs in test - #12296
Merged
Conversation
Consider code like:
for i := 0; i < numTargets; i++ {
stopFuncs = append(stopFuncs, func() {
time.Sleep(i*20*time.Millisecond)
})
}
Because the loop variable i is shared by all closures,
all the stopFuncs sleep for numTargets*20 ms.
If the i were made per-iteration, as we are considering
for a future Go release, the stopFuncs would have sleep
durations ranging from 0 to (numTargets-1)*20 ms.
Two tests had code like this and were checking that the
aggregate sleep was at least numTargets*20 ms
("at least as long as the last target slept"). This is only true
today because i == numTarget during all the sleeps.
To keep the code working even if the semantics of this loop
change, this PR computes
d := time.Duration((i+1)*20) * time.Millisecond
outside the closure (but inside the loop body), and then each
closure has its own d. Now the sleeps range from 20 ms
to numTargets*20 ms, keeping the test passing
(and probably behaving closer to the intent of the test author).
The failure being fixed can be reproduced by using the current
Go development branch with
GOEXPERIMENT=loopvar go test
Signed-off-by: Russ Cox <rsc@golang.org>
Member
|
Thank you for providing such a comprehensive explanation and the solution! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Consider code like:
Because the loop variable i is shared by all closures, all the stopFuncs sleep for numTargets*20 ms.
If the i were made per-iteration, as we are considering for a future Go release, the stopFuncs would have sleep durations ranging from 0 to (numTargets-1)*20 ms.
Two tests had code like this and were checking that the aggregate sleep was at least numTargets*20 ms
("at least as long as the last target slept"). This is only true today because i == numTarget during all the sleeps.
To keep the code working even if the semantics of this loop change, this PR computes
outside the closure (but inside the loop body), and then each closure has its own d. Now the sleeps range from 20 ms to numTargets*20 ms, keeping the test passing
(and probably behaving closer to the intent of the test author).
The failure being fixed can be reproduced by using the current Go development branch with