You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

120 lines
2.8 KiB

  1. package common
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "fmt"
  6. "io"
  7. mrand "math/rand"
  8. "sync"
  9. "testing"
  10. "time"
  11. "github.com/stretchr/testify/assert"
  12. )
  13. func TestRandStr(t *testing.T) {
  14. l := 243
  15. s := RandStr(l)
  16. assert.Equal(t, l, len(s))
  17. }
  18. func TestRandBytes(t *testing.T) {
  19. l := 243
  20. b := RandBytes(l)
  21. assert.Equal(t, l, len(b))
  22. }
  23. func TestRandIntn(t *testing.T) {
  24. n := 243
  25. for i := 0; i < 100; i++ {
  26. x := RandIntn(n)
  27. assert.True(t, x < n)
  28. }
  29. }
  30. // It is essential that these tests run and never repeat their outputs
  31. // lest we've been pwned and the behavior of our randomness is controlled.
  32. // See Issues:
  33. // * https://github.com/tendermint/tmlibs/issues/99
  34. // * https://github.com/tendermint/tendermint/issues/973
  35. func TestUniqueRng(t *testing.T) {
  36. buf := new(bytes.Buffer)
  37. outputs := make(map[string][]int)
  38. for i := 0; i < 100; i++ {
  39. testThemAll(buf)
  40. output := buf.String()
  41. buf.Reset()
  42. runs, seen := outputs[output]
  43. if seen {
  44. t.Errorf("Run #%d's output was already seen in previous runs: %v", i, runs)
  45. }
  46. outputs[output] = append(outputs[output], i)
  47. }
  48. }
  49. func testThemAll(out io.Writer) {
  50. // Reset the internal PRNG
  51. reset()
  52. // Set math/rand's Seed so that any direct invocations
  53. // of math/rand will reveal themselves.
  54. mrand.Seed(1)
  55. perm := RandPerm(10)
  56. blob, _ := json.Marshal(perm)
  57. fmt.Fprintf(out, "perm: %s\n", blob)
  58. fmt.Fprintf(out, "randInt: %d\n", RandInt())
  59. fmt.Fprintf(out, "randUint: %d\n", RandUint())
  60. fmt.Fprintf(out, "randIntn: %d\n", RandIntn(97))
  61. fmt.Fprintf(out, "randInt31: %d\n", RandInt31())
  62. fmt.Fprintf(out, "randInt32: %d\n", RandInt32())
  63. fmt.Fprintf(out, "randInt63: %d\n", RandInt63())
  64. fmt.Fprintf(out, "randInt64: %d\n", RandInt64())
  65. fmt.Fprintf(out, "randUint32: %d\n", RandUint32())
  66. fmt.Fprintf(out, "randUint64: %d\n", RandUint64())
  67. fmt.Fprintf(out, "randUint16Exp: %d\n", RandUint16Exp())
  68. fmt.Fprintf(out, "randUint32Exp: %d\n", RandUint32Exp())
  69. fmt.Fprintf(out, "randUint64Exp: %d\n", RandUint64Exp())
  70. }
  71. func TestRngConcurrencySafety(t *testing.T) {
  72. var wg sync.WaitGroup
  73. for i := 0; i < 100; i++ {
  74. wg.Add(1)
  75. go func() {
  76. defer wg.Done()
  77. _ = RandUint64()
  78. <-time.After(time.Millisecond * time.Duration(RandIntn(100)))
  79. _ = RandPerm(3)
  80. }()
  81. }
  82. wg.Wait()
  83. }
  84. func BenchmarkRandBytes10B(b *testing.B) {
  85. benchmarkRandBytes(b, 10)
  86. }
  87. func BenchmarkRandBytes100B(b *testing.B) {
  88. benchmarkRandBytes(b, 100)
  89. }
  90. func BenchmarkRandBytes1KiB(b *testing.B) {
  91. benchmarkRandBytes(b, 1024)
  92. }
  93. func BenchmarkRandBytes10KiB(b *testing.B) {
  94. benchmarkRandBytes(b, 10*1024)
  95. }
  96. func BenchmarkRandBytes100KiB(b *testing.B) {
  97. benchmarkRandBytes(b, 100*1024)
  98. }
  99. func BenchmarkRandBytes1MiB(b *testing.B) {
  100. benchmarkRandBytes(b, 1024*1024)
  101. }
  102. func benchmarkRandBytes(b *testing.B, n int) {
  103. for i := 0; i < b.N; i++ {
  104. _ = RandBytes(n)
  105. }
  106. b.ReportAllocs()
  107. }