@@ -15,7 +15,9 @@ import (
1515 "fmt"
1616 "io"
1717 "io/fs"
18+ "math/rand"
1819 "os"
20+ "strconv"
1921 "strings"
2022 "time"
2123 "unicode"
2830 flagShort bool
2931 flagRunRegexp string
3032 flagSkipRegexp string
33+ flagShuffle string
3134 flagCount int
3235)
3336
@@ -44,6 +47,7 @@ func Init() {
4447 flag .BoolVar (& flagShort , "test.short" , false , "short: run smaller test suite to save time" )
4548 flag .StringVar (& flagRunRegexp , "test.run" , "" , "run: regexp of tests to run" )
4649 flag .StringVar (& flagSkipRegexp , "test.skip" , "" , "skip: regexp of tests to run" )
50+ flag .StringVar (& flagShuffle , "test.shuffle" , "off" , "shuffle: off, on, <numeric-seed>" )
4751
4852 flag .IntVar (& flagCount , "test.count" , 1 , "run each test or benchmark `count` times" )
4953
@@ -479,6 +483,27 @@ type testDeps interface {
479483 MatchString (pat , str string ) (bool , error )
480484}
481485
486+ func (m * M ) shuffle () error {
487+ var n int64
488+
489+ if flagShuffle == "on" {
490+ n = time .Now ().UnixNano ()
491+ } else {
492+ var err error
493+ n , err = strconv .ParseInt (flagShuffle , 10 , 64 )
494+ if err != nil {
495+ m .exitCode = 2
496+ return fmt .Errorf (`testing: -shuffle should be "off", "on", or a valid integer: %v` , err )
497+ }
498+ }
499+
500+ fmt .Println ("-test.shuffle" , n )
501+ rng := rand .New (rand .NewSource (n ))
502+ rng .Shuffle (len (m .Tests ), func (i , j int ) { m .Tests [i ], m .Tests [j ] = m .Tests [j ], m .Tests [i ] })
503+ rng .Shuffle (len (m .Benchmarks ), func (i , j int ) { m .Benchmarks [i ], m .Benchmarks [j ] = m .Benchmarks [j ], m .Benchmarks [i ] })
504+ return nil
505+ }
506+
482507// Run runs the tests. It returns an exit code to pass to os.Exit.
483508func (m * M ) Run () (code int ) {
484509 defer func () {
@@ -489,6 +514,13 @@ func (m *M) Run() (code int) {
489514 flag .Parse ()
490515 }
491516
517+ if flagShuffle != "off" {
518+ if err := m .shuffle (); err != nil {
519+ fmt .Fprintln (os .Stderr , err )
520+ return
521+ }
522+ }
523+
492524 testRan , testOk := runTests (m .deps .MatchString , m .Tests )
493525 if ! testRan && * matchBenchmarks == "" {
494526 fmt .Fprintln (os .Stderr , "testing: warning: no tests to run" )
0 commit comments