From 2d6804c7467f3c78214cb7133e730e7b8112461a Mon Sep 17 00:00:00 2001 From: Jonathan Yu Date: Mon, 28 Feb 2022 09:50:55 -0800 Subject: [PATCH] chore: improve coverage of cryptorand package (#377) Check error cases in cryptorand functions, such as failures to read random data and input parameter validation. --- cryptorand/errors_test.go | 86 ++++++++++++++++++++++++++++++++++++++ cryptorand/numbers_test.go | 14 +++++++ 2 files changed, 100 insertions(+) create mode 100644 cryptorand/errors_test.go diff --git a/cryptorand/errors_test.go b/cryptorand/errors_test.go new file mode 100644 index 0000000000..f228ebd289 --- /dev/null +++ b/cryptorand/errors_test.go @@ -0,0 +1,86 @@ +package cryptorand_test + +import ( + "crypto/rand" + "io" + "testing" + "testing/iotest" + + "github.com/stretchr/testify/require" + + "github.com/coder/coder/cryptorand" +) + +// TestRandError checks that the code handles errors when reading from +// the rand.Reader. +// +// This test replaces the global rand.Reader, so cannot be parallelized +//nolint:paralleltest +func TestRandError(t *testing.T) { + var origReader = rand.Reader + t.Cleanup(func() { + rand.Reader = origReader + }) + + rand.Reader = iotest.ErrReader(io.ErrShortBuffer) + + t.Run("Int63", func(t *testing.T) { + _, err := cryptorand.Int63() + require.ErrorIs(t, err, io.ErrShortBuffer, "expected Int63 error") + }) + + t.Run("Uint64", func(t *testing.T) { + _, err := cryptorand.Uint64() + require.ErrorIs(t, err, io.ErrShortBuffer, "expected Uint64 error") + }) + + t.Run("Int31", func(t *testing.T) { + _, err := cryptorand.Int31() + require.ErrorIs(t, err, io.ErrShortBuffer, "expected Int31 error") + }) + + t.Run("Int31n", func(t *testing.T) { + _, err := cryptorand.Int31n(100) + require.ErrorIs(t, err, io.ErrShortBuffer, "expected Int31n error") + }) + + t.Run("Uint32", func(t *testing.T) { + _, err := cryptorand.Uint32() + require.ErrorIs(t, err, io.ErrShortBuffer, "expected Uint32 error") + }) + + t.Run("Int", func(t *testing.T) { + _, err := cryptorand.Int() + require.ErrorIs(t, err, io.ErrShortBuffer, "expected Int error") + }) + + t.Run("Intn_32bit", func(t *testing.T) { + _, err := cryptorand.Intn(100) + require.ErrorIs(t, err, io.ErrShortBuffer, "expected Intn error") + }) + + t.Run("Intn_64bit", func(t *testing.T) { + _, err := cryptorand.Intn(int(1 << 35)) + require.ErrorIs(t, err, io.ErrShortBuffer, "expected Intn error") + }) + + t.Run("Float64", func(t *testing.T) { + _, err := cryptorand.Float64() + require.ErrorIs(t, err, io.ErrShortBuffer, "expected Float64 error") + }) + + t.Run("Float32", func(t *testing.T) { + _, err := cryptorand.Float32() + require.ErrorIs(t, err, io.ErrShortBuffer, "expected Float32 error") + }) + + t.Run("Bool", func(t *testing.T) { + _, err := cryptorand.Bool() + require.ErrorIs(t, err, io.ErrShortBuffer, "expected Bool error") + }) + + t.Run("StringCharset", func(t *testing.T) { + _, err := cryptorand.HexString(10) + require.ErrorIs(t, err, io.ErrShortBuffer, "expected HexString error") + }) +} diff --git a/cryptorand/numbers_test.go b/cryptorand/numbers_test.go index 105ce080b0..88ccee118f 100644 --- a/cryptorand/numbers_test.go +++ b/cryptorand/numbers_test.go @@ -92,6 +92,11 @@ func TestInt63n(t *testing.T) { require.True(t, v >= 0, "values must be positive") require.True(t, v < 1<<35, "values must be less than 1<<35") } + + // Expect a panic if max is negative + require.PanicsWithValue(t, "invalid argument to Int63n", func() { + cryptorand.Int63n(0) + }) } func TestInt31n(t *testing.T) { @@ -116,6 +121,15 @@ func TestIntn(t *testing.T) { require.True(t, v >= 0, "values must be positive") require.True(t, v < 100, "values must be less than 100") } + + // Ensure Intn works for int larger than 32 bits + _, err := cryptorand.Intn(1 << 35) + require.NoError(t, err, "expected Intn to work for 64-bit int") + + // Expect a panic if max is negative + require.PanicsWithValue(t, "n must be a positive nonzero number", func() { + cryptorand.Intn(0) + }) } func TestFloat64(t *testing.T) {