aboutsummaryrefslogtreecommitdiff
path: root/go
diff options
context:
space:
mode:
authorEugene Kliuchnikov <eustas@google.com>2017-05-29 17:55:14 +0200
committerGitHub <noreply@github.com>2017-05-29 17:55:14 +0200
commit03739d2b113afe60638069c4e1604dc2ac27380d (patch)
tree4ce3aa5ed7679b4a6f999dbad9483eb2f6cab7cb /go
parent2c001010aa49b06de83bf28ec43be4fed8be3fbd (diff)
downloadbrotli-03739d2b113afe60638069c4e1604dc2ac27380d.zip
brotli-03739d2b113afe60638069c4e1604dc2ac27380d.tar.gz
brotli-03739d2b113afe60638069c4e1604dc2ac27380d.tar.bz2
Update (#555)
Update: * new CLI; bro -> brotli; + man page * JNI wrappers preparation (for bazel build) * add raw binary dictionary representation `dictionary.bin` * add ability to side-load brotli RFC dictionary * decoder persists last error now * fix `BrotliDecoderDecompress` documentation * go reader don't block until necessary * more consistent bazel target names * Java dictionary data compiled footprint reduced * Java tests refactoring
Diffstat (limited to 'go')
-rwxr-xr-xgo/cbrotli/cbrotli_test.go81
-rwxr-xr-xgo/cbrotli/reader.go9
2 files changed, 88 insertions, 2 deletions
diff --git a/go/cbrotli/cbrotli_test.go b/go/cbrotli/cbrotli_test.go
index 0a9368b..f59ec58 100755
--- a/go/cbrotli/cbrotli_test.go
+++ b/go/cbrotli/cbrotli_test.go
@@ -9,9 +9,11 @@ import (
"bytes"
"fmt"
"io"
+ "io/ioutil"
"math"
"math/rand"
"testing"
+ "time"
)
func checkCompressedData(compressedData, wantOriginalData []byte) error {
@@ -173,6 +175,85 @@ func TestEncoderFlush(t *testing.T) {
}
}
+type readerWithTimeout struct {
+ io.ReadCloser
+}
+
+func (r readerWithTimeout) Read(p []byte) (int, error) {
+ type result struct {
+ n int
+ err error
+ }
+ ch := make(chan result)
+ go func() {
+ n, err := r.ReadCloser.Read(p)
+ ch <- result{n, err}
+ }()
+ select {
+ case result := <-ch:
+ return result.n, result.err
+ case <-time.After(5 * time.Second):
+ return 0, fmt.Errorf("read timed out")
+ }
+}
+
+func TestDecoderStreaming(t *testing.T) {
+ pr, pw := io.Pipe()
+ writer := NewWriter(pw, WriterOptions{Quality: 5, LGWin: 20})
+ reader := readerWithTimeout{NewReader(pr)}
+ defer func() {
+ if err := reader.Close(); err != nil {
+ t.Errorf("reader.Close: %v", err)
+ }
+ go ioutil.ReadAll(pr) // swallow the "EOF" token from writer.Close
+ if err := writer.Close(); err != nil {
+ t.Errorf("writer.Close: %v", err)
+ }
+ }()
+
+ ch := make(chan []byte)
+ errch := make(chan error)
+ go func() {
+ for {
+ segment, ok := <-ch
+ if !ok {
+ return
+ }
+ if n, err := writer.Write(segment); err != nil || n != len(segment) {
+ errch <- fmt.Errorf("write=%v,%v, want %v,%v", n, err, len(segment), nil)
+ return
+ }
+ if err := writer.Flush(); err != nil {
+ errch <- fmt.Errorf("flush: %v", err)
+ return
+ }
+ }
+ }()
+ defer close(ch)
+
+ segments := [...][]byte{
+ []byte("first"),
+ []byte("second"),
+ []byte("third"),
+ }
+ for k, segment := range segments {
+ t.Run(fmt.Sprintf("Segment%d", k), func(t *testing.T) {
+ select {
+ case ch <- segment:
+ case err := <-errch:
+ t.Fatalf("write: %v", err)
+ case <-time.After(5 * time.Second):
+ t.Fatalf("timed out")
+ }
+ wantLen := len(segment)
+ got := make([]byte, wantLen)
+ if n, err := reader.Read(got); err != nil || n != wantLen || !bytes.Equal(got, segment) {
+ t.Fatalf("read[%d]=%q,%v,%v, want %q,%v,%v", k, got, n, err, segment, wantLen, nil)
+ }
+ })
+ }
+}
+
func TestReader(t *testing.T) {
content := bytes.Repeat([]byte("hello world!"), 10000)
encoded, _ := Encode(content, WriterOptions{Quality: 5})
diff --git a/go/cbrotli/reader.go b/go/cbrotli/reader.go
index a05809b..3d8d424 100755
--- a/go/cbrotli/reader.go
+++ b/go/cbrotli/reader.go
@@ -95,7 +95,7 @@ func (r *Reader) Read(p []byte) (n int, err error) {
return 0, nil
}
- for n == 0 {
+ for {
var written, consumed C.size_t
var data *C.uint8_t
if len(r.in) != 0 {
@@ -128,9 +128,14 @@ func (r *Reader) Read(p []byte) (n int, err error) {
return 0, errInvalidState
}
+ // Calling r.src.Read may block. Don't block if we have data to return.
+ if n > 0 {
+ return n, nil
+ }
+
// Top off the buffer.
encN, err := r.src.Read(r.buf)
- if encN == 0 && n == 0 {
+ if encN == 0 {
// Not enough data to complete decoding.
if err == io.EOF {
return 0, io.ErrUnexpectedEOF