blob: dbc7a18f1df204a9f5c790d5434550af41538efa [file] [log] [blame]
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001// Package testutil provides initalization and utility routines for unit tests.
2//
Asim Shankarc920db32014-10-16 19:18:21 -07003// Configures logging, random number generators and other global state.
4// Typical usage in _test.go files:
Jiri Simsa764efb72014-12-25 20:57:03 -08005// import "v.io/core/veyron/lib/testutil"
Asim Shankarc920db32014-10-16 19:18:21 -07006// func init() { testutil.Init() }
Jiri Simsa5293dcb2014-05-10 09:56:38 -07007package testutil
8
9import (
10 "flag"
Jiri Simsa870ddd62014-06-27 14:56:58 -070011 "math/rand"
Jiri Simsa5293dcb2014-05-10 09:56:38 -070012 "os"
13 "runtime"
Jiri Simsa870ddd62014-06-27 14:56:58 -070014 "strconv"
Asim Shankar20282032014-07-07 22:48:00 -070015 "sync"
Jiri Simsa870ddd62014-06-27 14:56:58 -070016 "time"
Cosmos Nicolaoue3391532014-11-25 19:08:32 -080017
Jiri Simsa764efb72014-12-25 20:57:03 -080018 "v.io/core/veyron2/vlog"
Jiri Simsa5293dcb2014-05-10 09:56:38 -070019)
20
Asim Shankarc920db32014-10-16 19:18:21 -070021const SeedEnv = "VEYRON_RNG_SEED"
Jiri Simsa870ddd62014-06-27 14:56:58 -070022
Asim Shankar20282032014-07-07 22:48:00 -070023// Random is a concurrent-access friendly source of randomness.
24type Random struct {
25 mu sync.Mutex
26 rand *rand.Rand
27}
28
29// Int returns a non-negative pseudo-random int.
30func (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).
37func (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.
44func (r *Random) Int63() int64 {
45 r.mu.Lock()
46 defer r.mu.Unlock()
47 return r.rand.Int63()
48}
49
Asim Shankarc920db32014-10-16 19:18:21 -070050var Rand *Random
Cosmos Nicolaoue3391532014-11-25 19:08:32 -080051var once sync.Once
Jiri Simsa870ddd62014-06-27 14:56:58 -070052
Asim Shankarc920db32014-10-16 19:18:21 -070053// 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.
60func Init() {
Cosmos Nicolaoue3391532014-11-25 19:08:32 -080061 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 Simsa870ddd62014-06-27 14:56:58 -070066 }
Cosmos Nicolaoue3391532014-11-25 19:08:32 -080067 // 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 Simsa870ddd62014-06-27 14:56:58 -070087 }
Cosmos Nicolaoue3391532014-11-25 19:08:32 -080088 once.Do(init)
Jiri Simsa5293dcb2014-05-10 09:56:38 -070089}
Ankurfb9255a2015-01-21 15:29:38 -080090
91// UnsetPrincipalEnvVars unsets all environment variables pertaining to principal
92// initialization.
93func UnsetPrincipalEnvVars() {
94 os.Setenv("VEYRON_CREDENTIALS", "")
95 os.Setenv("VEYRON_AGENT_FD", "")
96}