1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
|
package correlation
import (
"bytes"
"crypto/rand"
"strings"
"testing"
"time"
"github.com/oklog/ulid/v2"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func emptyRandomSource() func() {
oldEntropySource := ulidEntropySource
// Use an empty random source, which will lead to ULID generation failure
ulidEntropySource = &bytes.Buffer{}
return func() {
ulidEntropySource = oldEntropySource
}
}
func requireValidRecentULID(require *require.Assertions, got string) {
uid, err := ulid.Parse(got)
require.NoError(err, "Expected correlationID to be a valid ULID, got %s", got)
utime := ulid.Time(uid.Time())
diff := time.Since(utime)
require.True(diff > 0, "Expected ULID to be generated in the past")
require.True(diff < 1*time.Second, "Expected ULID to be generated with recent timestamp. Timestamp is %v", utime)
}
func TestRandom(t *testing.T) {
require := require.New(t)
got, err := RandomID()
require.NoError(err, "Expected no error from RandomID")
requireValidRecentULID(require, got)
}
func TestSafeRandom(t *testing.T) {
t.Run("is valid", func(t *testing.T) {
require := require.New(t)
got := SafeRandomID()
requireValidRecentULID(require, got)
})
t.Run("is random", func(t *testing.T) {
got1 := SafeRandomID()
got2 := SafeRandomID()
require.NotEqual(t, got1, got2)
})
}
func TestRandomEntropyFailure(t *testing.T) {
restore := emptyRandomSource()
defer restore()
require := require.New(t)
got, err := RandomID()
require.NoError(err, "Expected no error from RandomID")
require.NotEqual(got, "", "Expected a non-empty string response")
require.True(strings.HasPrefix(got, "E:"), "Expecting fallback to pseudorandom correlationID")
}
func TestSafeRandomEntropyFailure(t *testing.T) {
restore := emptyRandomSource()
defer restore()
require := require.New(t)
got := SafeRandomID()
require.NotEqual(got, "", "Expected a non-empty string response")
require.True(strings.HasPrefix(got, "E:"), "Expecting fallback to pseudorandom correlationID")
}
// TestSafeMonotonicReader tests safeMonotonicReader for data races. It should be ran with -race.
func TestSafeMonotonicReader(t *testing.T) {
t.Run("MonotonicRead", func(t *testing.T) {
r := safeMonotonicReader{
delegate: ulid.Monotonic(rand.Reader, 0),
}
go func() {
d := make([]byte, 100)
assert.NoError(t, r.MonotonicRead(100, d))
}()
go func() {
d := make([]byte, 100)
assert.NoError(t, r.MonotonicRead(100, d))
}()
})
t.Run("Read", func(t *testing.T) {
r := safeMonotonicReader{
delegate: ulid.Monotonic(rand.Reader, 0),
}
go func() {
d := make([]byte, 100)
_, err := r.Read(d)
assert.NoError(t, err)
}()
go func() {
d := make([]byte, 100)
_, err := r.Read(d)
assert.NoError(t, err)
}()
})
}
func BenchmarkSafeRandomID(b *testing.B) {
// run the Fib function b.N times
for n := 0; n < b.N; n++ {
SafeRandomID()
}
}
|