package api import ( "bytes" "crypto/sha256" "crypto/sha512" "encoding/base64" "errors" "hash" "io" "io/ioutil" "math/rand" "testing" "testing/iotest" "github.com/hashicorp/nomad/api/internal/testutil" "github.com/stretchr/testify/require" ) func TestChecksumValidatingReader(t *testing.T) { testutil.Parallel(t) data := make([]byte, 4096) _, err := rand.Read(data) require.NoError(t, err) cases := []struct { algo string hash hash.Hash }{ {"sha-256", sha256.New()}, {"sha-512", sha512.New()}, } for _, c := range cases { t.Run("valid: "+c.algo, func(t *testing.T) { _, err := c.hash.Write(data) require.NoError(t, err) checksum := c.hash.Sum(nil) digest := c.algo + "=" + base64.StdEncoding.EncodeToString(checksum) r := iotest.HalfReader(bytes.NewReader(data)) cr, err := newChecksumValidatingReader(ioutil.NopCloser(r), digest) require.NoError(t, err) _, err = io.Copy(ioutil.Discard, cr) require.NoError(t, err) }) t.Run("invalid: "+c.algo, func(t *testing.T) { _, err := c.hash.Write(data) require.NoError(t, err) checksum := c.hash.Sum(nil) // mess up checksum checksum[0]++ digest := c.algo + "=" + base64.StdEncoding.EncodeToString(checksum) r := iotest.HalfReader(bytes.NewReader(data)) cr, err := newChecksumValidatingReader(ioutil.NopCloser(r), digest) require.NoError(t, err) _, err = io.Copy(ioutil.Discard, cr) require.Error(t, err) require.Equal(t, errMismatchChecksum, err) }) } } func TestChecksumValidatingReader_PropagatesError(t *testing.T) { testutil.Parallel(t) pr, pw := io.Pipe() defer pr.Close() defer pw.Close() expectedErr := errors.New("some error") go func() { pw.Write([]byte("some input")) pw.CloseWithError(expectedErr) }() cr, err := newChecksumValidatingReader(pr, "sha-256=aaaa") require.NoError(t, err) _, err = io.Copy(ioutil.Discard, cr) require.Error(t, err) require.Equal(t, expectedErr, err) }