gopkg.in/goose.v2@v2.0.1/testservices/identityservice/util_test.go (about) 1 package identityservice 2 3 import ( 4 "bytes" 5 "crypto/rand" 6 "fmt" 7 "io" 8 "testing/iotest" 9 10 gc "gopkg.in/check.v1" 11 ) 12 13 type UtilSuite struct{} 14 15 var _ = gc.Suite(&UtilSuite{}) 16 17 func (s *UtilSuite) TestRandomHexTokenHasLength(c *gc.C) { 18 val := randomHexToken() 19 c.Assert(val, gc.HasLen, 32) 20 } 21 22 func (s *UtilSuite) TestRandomHexTokenIsHex(c *gc.C) { 23 val := randomHexToken() 24 for i, b := range val { 25 switch { 26 case (b >= 'a' && b <= 'f') || (b >= '0' && b <= '9'): 27 continue 28 default: 29 c.Logf("char %d of %s was not in the right range", 30 i, val) 31 c.Fail() 32 } 33 } 34 } 35 36 func (s *UtilSuite) TestDefaultReader(c *gc.C) { 37 raw := make([]byte, 6) 38 c.Assert(string(raw), gc.Equals, "\x00\x00\x00\x00\x00\x00") 39 n, err := io.ReadFull(randReader, raw) 40 c.Assert(err, gc.IsNil) 41 c.Assert(n, gc.Equals, 6) 42 c.Assert(string(raw), gc.Not(gc.Equals), "\x00\x00\x00\x00\x00\x00") 43 } 44 45 func (s *UtilSuite) TestSetReader(c *gc.C) { 46 orig := randReader 47 // This test will be mutating global state (randReader), ensure that we 48 // restore it sanely even if tests fail 49 defer func() { randReader = orig }() 50 // "randomize" everything to the letter 'n' 51 nRandom := bytes.NewBufferString("nnnnnnnnnnnnnnnnnnnnnnn") 52 c.Assert(randReader, gc.Equals, rand.Reader) 53 cleanup := setReader(nRandom) 54 c.Assert(randReader, gc.Equals, nRandom) 55 raw := make([]byte, 6) 56 n, err := io.ReadFull(randReader, raw) 57 c.Assert(err, gc.IsNil) 58 c.Assert(n, gc.Equals, 6) 59 c.Assert(string(raw), gc.Equals, "nnnnnn") 60 cleanup() 61 c.Assert(randReader, gc.Equals, rand.Reader) 62 } 63 64 // Change how we get random data, the default is to use crypto/rand 65 // This mostly exists to be able to test error side effects 66 // The return value is a function you can call to restore the previous 67 // randomizer 68 func setReader(r io.Reader) (restore func()) { 69 old := randReader 70 randReader = r 71 return func() { 72 randReader = old 73 } 74 } 75 76 func (s *UtilSuite) TestNotEnoughRandomBytes(c *gc.C) { 77 // No error, just not enough bytes 78 shortRand := bytes.NewBufferString("xx") 79 cleanup := setReader(shortRand) 80 defer cleanup() 81 c.Assert(randomHexToken, gc.PanicMatches, "failed to read 16 random bytes \\(read 2 bytes\\): unexpected EOF") 82 } 83 84 type ErrReader struct{} 85 86 func (e ErrReader) Read(b []byte) (n int, err error) { 87 b[0] = 'x' 88 b[1] = 'x' 89 b[2] = 'x' 90 return 3, fmt.Errorf("Not enough bytes") 91 } 92 93 func (s *UtilSuite) TestRandomBytesError(c *gc.C) { 94 // No error, just not enough bytes 95 cleanup := setReader(ErrReader{}) 96 defer cleanup() 97 c.Assert(randomHexToken, gc.PanicMatches, "failed to read 16 random bytes \\(read 3 bytes\\): Not enough bytes") 98 } 99 100 func (s *UtilSuite) TestSlowBytes(c *gc.C) { 101 // Even when we have to read one byte at a time, we can still get our 102 // hex token 103 defer setReader(iotest.OneByteReader(rand.Reader))() 104 val := randomHexToken() 105 c.Assert(val, gc.HasLen, 32) 106 }