Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 1 | // Package testutil provides initalization and utility routines for unit tests. |
| 2 | // |
Asim Shankar | c920db3 | 2014-10-16 19:18:21 -0700 | [diff] [blame] | 3 | // Configures logging, random number generators and other global state. |
| 4 | // Typical usage in _test.go files: |
Jiri Simsa | 764efb7 | 2014-12-25 20:57:03 -0800 | [diff] [blame] | 5 | // import "v.io/core/veyron/lib/testutil" |
Asim Shankar | c920db3 | 2014-10-16 19:18:21 -0700 | [diff] [blame] | 6 | // func init() { testutil.Init() } |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 7 | package testutil |
| 8 | |
| 9 | import ( |
| 10 | "flag" |
Jiri Simsa | 870ddd6 | 2014-06-27 14:56:58 -0700 | [diff] [blame] | 11 | "math/rand" |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 12 | "os" |
| 13 | "runtime" |
Jiri Simsa | 870ddd6 | 2014-06-27 14:56:58 -0700 | [diff] [blame] | 14 | "strconv" |
Asim Shankar | 2028203 | 2014-07-07 22:48:00 -0700 | [diff] [blame] | 15 | "sync" |
Jiri Simsa | 870ddd6 | 2014-06-27 14:56:58 -0700 | [diff] [blame] | 16 | "time" |
Cosmos Nicolaou | e339153 | 2014-11-25 19:08:32 -0800 | [diff] [blame] | 17 | |
Jiri Simsa | 764efb7 | 2014-12-25 20:57:03 -0800 | [diff] [blame] | 18 | "v.io/core/veyron2/vlog" |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 19 | ) |
| 20 | |
Asim Shankar | c920db3 | 2014-10-16 19:18:21 -0700 | [diff] [blame] | 21 | const SeedEnv = "VEYRON_RNG_SEED" |
Jiri Simsa | 870ddd6 | 2014-06-27 14:56:58 -0700 | [diff] [blame] | 22 | |
Asim Shankar | 2028203 | 2014-07-07 22:48:00 -0700 | [diff] [blame] | 23 | // Random is a concurrent-access friendly source of randomness. |
| 24 | type Random struct { |
| 25 | mu sync.Mutex |
| 26 | rand *rand.Rand |
| 27 | } |
| 28 | |
| 29 | // Int returns a non-negative pseudo-random int. |
| 30 | func (r *Random) Int() int { |
| 31 | r.mu.Lock() |
| 32 | defer r.mu.Unlock() |
| 33 | return r.rand.Int() |
| 34 | } |
| 35 | |
| 36 | // Intn returns a non-negative pseudo-random int in the range [0, n). |
| 37 | func (r *Random) Intn(n int) int { |
| 38 | r.mu.Lock() |
| 39 | defer r.mu.Unlock() |
| 40 | return r.rand.Intn(n) |
| 41 | } |
| 42 | |
| 43 | // Int63 returns a non-negative 63-bit pseudo-random integer as an int64. |
| 44 | func (r *Random) Int63() int64 { |
| 45 | r.mu.Lock() |
| 46 | defer r.mu.Unlock() |
| 47 | return r.rand.Int63() |
| 48 | } |
| 49 | |
Asim Shankar | c920db3 | 2014-10-16 19:18:21 -0700 | [diff] [blame] | 50 | var Rand *Random |
Cosmos Nicolaou | e339153 | 2014-11-25 19:08:32 -0800 | [diff] [blame] | 51 | var once sync.Once |
Jiri Simsa | 870ddd6 | 2014-06-27 14:56:58 -0700 | [diff] [blame] | 52 | |
Asim Shankar | c920db3 | 2014-10-16 19:18:21 -0700 | [diff] [blame] | 53 | // Init sets up state for running tests: Adjusting GOMAXPROCS, |
| 54 | // configuring the vlog logging library, setting up the random number generator |
| 55 | // etc. |
| 56 | // |
| 57 | // Doing so requires flags to be parse, so this function explicitly parses |
| 58 | // flags. Thus, it is NOT a good idea to call this from the init() function |
| 59 | // of any module except "main" or _test.go files. |
| 60 | func Init() { |
Cosmos Nicolaou | e339153 | 2014-11-25 19:08:32 -0800 | [diff] [blame] | 61 | init := func() { |
| 62 | if os.Getenv("GOMAXPROCS") == "" { |
| 63 | // Set the number of logical processors to the number of CPUs, |
| 64 | // if GOMAXPROCS is not set in the environment. |
| 65 | runtime.GOMAXPROCS(runtime.NumCPU()) |
Jiri Simsa | 870ddd6 | 2014-06-27 14:56:58 -0700 | [diff] [blame] | 66 | } |
Cosmos Nicolaou | e339153 | 2014-11-25 19:08:32 -0800 | [diff] [blame] | 67 | // At this point all of the flags that we're going to use for |
| 68 | // tests must be defined. |
| 69 | // This will be the case if this is called from the init() |
| 70 | // function of a _test.go file. |
| 71 | flag.Parse() |
| 72 | vlog.ConfigureLibraryLoggerFromFlags() |
| 73 | |
| 74 | // Initialize pseudo-random number generator. |
| 75 | seed := time.Now().UnixNano() |
| 76 | seedString := os.Getenv(SeedEnv) |
| 77 | if seedString != "" { |
| 78 | var err error |
| 79 | base, bitSize := 0, 64 |
| 80 | seed, err = strconv.ParseInt(seedString, base, bitSize) |
| 81 | if err != nil { |
| 82 | vlog.Fatalf("ParseInt(%v, %v, %v) failed: %v", seedString, base, bitSize, err) |
| 83 | } |
| 84 | } |
| 85 | vlog.Infof("Seeding pseudo-random number generator with %v", seed) |
| 86 | Rand = &Random{rand: rand.New(rand.NewSource(seed))} |
Jiri Simsa | 870ddd6 | 2014-06-27 14:56:58 -0700 | [diff] [blame] | 87 | } |
Cosmos Nicolaou | e339153 | 2014-11-25 19:08:32 -0800 | [diff] [blame] | 88 | once.Do(init) |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 89 | } |
Ankur | fb9255a | 2015-01-21 15:29:38 -0800 | [diff] [blame] | 90 | |
| 91 | // UnsetPrincipalEnvVars unsets all environment variables pertaining to principal |
| 92 | // initialization. |
| 93 | func UnsetPrincipalEnvVars() { |
| 94 | os.Setenv("VEYRON_CREDENTIALS", "") |
| 95 | os.Setenv("VEYRON_AGENT_FD", "") |
| 96 | } |