Skip to content

Commit

Permalink
Fix byteReader issue (#7)
Browse files Browse the repository at this point in the history
* add failing test case with flate.Reader

* fix local byteReader implementation -- fixes #6

* ReadByte() : if a byte is read, store the error, and returned the byte
  with no error
* if an error is stored, return it (from ReadByte() or Read())

* ignore error in ReadByte if reader returns 1 byte

following discussion on PR #7

* fix typo

Co-authored-by: Agniva De Sarker <agnivade@yahoo.co.in>
  • Loading branch information
LeGEC and agnivade authored Dec 19, 2020
1 parent bcd7e1b commit 8fd2afa
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 3 deletions.
43 changes: 43 additions & 0 deletions reader_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package validator

import (
"bytes"
"compress/flate"
"io"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

// flateIt takes and input string, compresses it using flate, and returns a flate.Reader() of the compressed content
func flateIt(t *testing.T, input string) io.Reader {
t.Helper()

var zipped bytes.Buffer
w, err := flate.NewWriter(&zipped, flate.DefaultCompression)
require.NoError(t, err)

_, err = w.Write([]byte(input))
require.NoError(t, err)

err = w.Close()
require.NoError(t, err)

return flate.NewReader(&zipped)
}

func TestValidateZippedReader(t *testing.T) {
// wrap an innocuous "<foo></foo>" XML payload in a flate.Reader :
zipped := flateIt(t, `<foo></foo>`)

// Validate should not trigger an error on that Reader :
err := Validate(zipped)
assert.NoError(t, err, "Should not error on a valid XML document")

// an invalid document should still error :
zipped = flateIt(t, `<x::Root/>`)

err = Validate(zipped)
assert.Error(t, err, "Should error on an invalid XML document")
}
17 changes: 14 additions & 3 deletions validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,20 @@ type byteReader struct {
}

func (r *byteReader) ReadByte() (byte, error) {
p := make([]byte, 1)
_, err := r.r.Read(p)
return p[0], err
var p [1]byte
n, err := r.r.Read(p[:])

// The doc for the io.ByteReader interface states:
// If ReadByte returns an error, no input byte was consumed, and the returned byte value is undefined.
// So if a byte is actually extracted from the reader, and we want to return it, we mustn't return the error.
if n > 0 {
// this byteReader is only used in the context of the Validate() function,
// we deliberately choose to completely ignore the error in this case.
// return the byte extracted from the reader
return p[0], nil
}

return 0, err
}

func (r *byteReader) Read(p []byte) (int, error) {
Expand Down

0 comments on commit 8fd2afa

Please # to comment.