diff options
| author | Michael Stapelberg <stapelberg@debian.org> | 2014-06-19 09:22:53 +0200 | 
|---|---|---|
| committer | Michael Stapelberg <stapelberg@debian.org> | 2014-06-19 09:22:53 +0200 | 
| commit | 8a39ee361feb9bf46d728ff1ba4f07ca1d9610b1 (patch) | |
| tree | 4449f2036cccf162e8417cc5841a35815b3e7ac5 /src/pkg/bytes | |
| parent | c8bf49ef8a92e2337b69c14b9b88396efe498600 (diff) | |
| download | golang-upstream/1.3.tar.gz | |
Imported Upstream version 1.3upstream/1.3
Diffstat (limited to 'src/pkg/bytes')
| -rw-r--r-- | src/pkg/bytes/bytes.go | 10 | ||||
| -rw-r--r-- | src/pkg/bytes/bytes_test.go | 36 | ||||
| -rw-r--r-- | src/pkg/bytes/compare_test.go | 4 | ||||
| -rw-r--r-- | src/pkg/bytes/reader.go | 52 | ||||
| -rw-r--r-- | src/pkg/bytes/reader_test.go | 82 | 
5 files changed, 148 insertions, 36 deletions
| diff --git a/src/pkg/bytes/bytes.go b/src/pkg/bytes/bytes.go index 01a5d9ae4..0c53e4c0b 100644 --- a/src/pkg/bytes/bytes.go +++ b/src/pkg/bytes/bytes.go @@ -265,8 +265,8 @@ func Fields(s []byte) [][]byte {  // FieldsFunc interprets s as a sequence of UTF-8-encoded Unicode code points.  // It splits the slice s at each run of code points c satisfying f(c) and -// returns a slice of subslices of s.  If no code points in s satisfy f(c), an -// empty slice is returned. +// returns a slice of subslices of s.  If all code points in s satisfy f(c), or +// len(s) == 0, an empty slice is returned.  func FieldsFunc(s []byte, f func(rune) bool) [][]byte {  	n := 0  	inField := false @@ -356,7 +356,11 @@ func Map(mapping func(r rune) rune, s []byte) []byte {  		}  		r = mapping(r)  		if r >= 0 { -			if nbytes+utf8.RuneLen(r) > maxbytes { +			rl := utf8.RuneLen(r) +			if rl < 0 { +				rl = len(string(utf8.RuneError)) +			} +			if nbytes+rl > maxbytes {  				// Grow the buffer.  				maxbytes = maxbytes*2 + utf8.UTFMax  				nb := make([]byte, maxbytes) diff --git a/src/pkg/bytes/bytes_test.go b/src/pkg/bytes/bytes_test.go index ab5da4fbf..394dd7a44 100644 --- a/src/pkg/bytes/bytes_test.go +++ b/src/pkg/bytes/bytes_test.go @@ -785,6 +785,16 @@ func TestMap(t *testing.T) {  	if string(m) != expect {  		t.Errorf("drop: expected %q got %q", expect, m)  	} + +	// 6. Invalid rune +	invalidRune := func(r rune) rune { +		return utf8.MaxRune + 1 +	} +	m = Map(invalidRune, []byte("x")) +	expect = "\uFFFD" +	if string(m) != expect { +		t.Errorf("invalidRune: expected %q got %q", expect, m) +	}  }  func TestToUpper(t *testing.T) { runStringTests(t, ToUpper, "ToUpper", upperTests) } @@ -1073,6 +1083,8 @@ var TitleTests = []TitleTest{  	{"123a456", "123a456"},  	{"double-blind", "Double-Blind"},  	{"ÿøû", "Ÿøû"}, +	{"with_underscore", "With_underscore"}, +	{"unicode \xe2\x80\xa8 line separator", "Unicode \xe2\x80\xa8 Line Separator"},  }  func TestTitle(t *testing.T) { @@ -1132,7 +1144,7 @@ func TestEqualFold(t *testing.T) {  func TestBufferGrowNegative(t *testing.T) {  	defer func() {  		if err := recover(); err == nil { -			t.Fatal("Grow(-1) should have paniced") +			t.Fatal("Grow(-1) should have panicked")  		}  	}()  	var b Buffer @@ -1142,7 +1154,7 @@ func TestBufferGrowNegative(t *testing.T) {  func TestBufferTruncateNegative(t *testing.T) {  	defer func() {  		if err := recover(); err == nil { -			t.Fatal("Truncate(-1) should have paniced") +			t.Fatal("Truncate(-1) should have panicked")  		}  	}()  	var b Buffer @@ -1152,7 +1164,7 @@ func TestBufferTruncateNegative(t *testing.T) {  func TestBufferTruncateOutOfRange(t *testing.T) {  	defer func() {  		if err := recover(); err == nil { -			t.Fatal("Truncate(20) should have paniced") +			t.Fatal("Truncate(20) should have panicked")  		}  	}()  	var b Buffer @@ -1160,6 +1172,24 @@ func TestBufferTruncateOutOfRange(t *testing.T) {  	b.Truncate(20)  } +var containsTests = []struct { +	b, subslice []byte +	want        bool +}{ +	{[]byte("hello"), []byte("hel"), true}, +	{[]byte("日本語"), []byte("日本"), true}, +	{[]byte("hello"), []byte("Hello, world"), false}, +	{[]byte("東京"), []byte("京東"), false}, +} + +func TestContains(t *testing.T) { +	for _, tt := range containsTests { +		if got := Contains(tt.b, tt.subslice); got != tt.want { +			t.Errorf("Contains(%q, %q) = %v, want %v", tt.b, tt.subslice, got, tt.want) +		} +	} +} +  var makeFieldsInput = func() []byte {  	x := make([]byte, 1<<20)  	// Input is ~10% space, ~10% 2-byte UTF-8, rest ASCII non-space. diff --git a/src/pkg/bytes/compare_test.go b/src/pkg/bytes/compare_test.go index 0a36f5ad3..63522374e 100644 --- a/src/pkg/bytes/compare_test.go +++ b/src/pkg/bytes/compare_test.go @@ -1,3 +1,7 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +  package bytes_test  import ( diff --git a/src/pkg/bytes/reader.go b/src/pkg/bytes/reader.go index 77511b945..d2d40fa7c 100644 --- a/src/pkg/bytes/reader.go +++ b/src/pkg/bytes/reader.go @@ -16,40 +16,41 @@ import (  // Unlike a Buffer, a Reader is read-only and supports seeking.  type Reader struct {  	s        []byte -	i        int // current reading index -	prevRune int // index of previous rune; or < 0 +	i        int64 // current reading index +	prevRune int   // index of previous rune; or < 0  }  // Len returns the number of bytes of the unread portion of the  // slice.  func (r *Reader) Len() int { -	if r.i >= len(r.s) { +	if r.i >= int64(len(r.s)) {  		return 0  	} -	return len(r.s) - r.i +	return int(int64(len(r.s)) - r.i)  }  func (r *Reader) Read(b []byte) (n int, err error) {  	if len(b) == 0 {  		return 0, nil  	} -	if r.i >= len(r.s) { +	if r.i >= int64(len(r.s)) {  		return 0, io.EOF  	} -	n = copy(b, r.s[r.i:]) -	r.i += n  	r.prevRune = -1 +	n = copy(b, r.s[r.i:]) +	r.i += int64(n)  	return  }  func (r *Reader) ReadAt(b []byte, off int64) (n int, err error) { +	// cannot modify state - see io.ReaderAt  	if off < 0 { -		return 0, errors.New("bytes: invalid offset") +		return 0, errors.New("bytes.Reader.ReadAt: negative offset")  	}  	if off >= int64(len(r.s)) {  		return 0, io.EOF  	} -	n = copy(b, r.s[int(off):]) +	n = copy(b, r.s[off:])  	if n < len(b) {  		err = io.EOF  	} @@ -57,49 +58,51 @@ func (r *Reader) ReadAt(b []byte, off int64) (n int, err error) {  }  func (r *Reader) ReadByte() (b byte, err error) { -	if r.i >= len(r.s) { +	r.prevRune = -1 +	if r.i >= int64(len(r.s)) {  		return 0, io.EOF  	}  	b = r.s[r.i]  	r.i++ -	r.prevRune = -1  	return  }  func (r *Reader) UnreadByte() error { +	r.prevRune = -1  	if r.i <= 0 { -		return errors.New("bytes.Reader: at beginning of slice") +		return errors.New("bytes.Reader.UnreadByte: at beginning of slice")  	}  	r.i-- -	r.prevRune = -1  	return nil  }  func (r *Reader) ReadRune() (ch rune, size int, err error) { -	if r.i >= len(r.s) { +	if r.i >= int64(len(r.s)) { +		r.prevRune = -1  		return 0, 0, io.EOF  	} -	r.prevRune = r.i +	r.prevRune = int(r.i)  	if c := r.s[r.i]; c < utf8.RuneSelf {  		r.i++  		return rune(c), 1, nil  	}  	ch, size = utf8.DecodeRune(r.s[r.i:]) -	r.i += size +	r.i += int64(size)  	return  }  func (r *Reader) UnreadRune() error {  	if r.prevRune < 0 { -		return errors.New("bytes.Reader: previous operation was not ReadRune") +		return errors.New("bytes.Reader.UnreadRune: previous operation was not ReadRune")  	} -	r.i = r.prevRune +	r.i = int64(r.prevRune)  	r.prevRune = -1  	return nil  }  // Seek implements the io.Seeker interface.  func (r *Reader) Seek(offset int64, whence int) (int64, error) { +	r.prevRune = -1  	var abs int64  	switch whence {  	case 0: @@ -109,22 +112,19 @@ func (r *Reader) Seek(offset int64, whence int) (int64, error) {  	case 2:  		abs = int64(len(r.s)) + offset  	default: -		return 0, errors.New("bytes: invalid whence") +		return 0, errors.New("bytes.Reader.Seek: invalid whence")  	}  	if abs < 0 { -		return 0, errors.New("bytes: negative position") -	} -	if abs >= 1<<31 { -		return 0, errors.New("bytes: position out of range") +		return 0, errors.New("bytes.Reader.Seek: negative position")  	} -	r.i = int(abs) +	r.i = abs  	return abs, nil  }  // WriteTo implements the io.WriterTo interface.  func (r *Reader) WriteTo(w io.Writer) (n int64, err error) {  	r.prevRune = -1 -	if r.i >= len(r.s) { +	if r.i >= int64(len(r.s)) {  		return 0, nil  	}  	b := r.s[r.i:] @@ -132,7 +132,7 @@ func (r *Reader) WriteTo(w io.Writer) (n int64, err error) {  	if m > len(b) {  		panic("bytes.Reader.WriteTo: invalid Write count")  	} -	r.i += m +	r.i += int64(m)  	n = int64(m)  	if m != len(b) && err == nil {  		err = io.ErrShortWrite diff --git a/src/pkg/bytes/reader_test.go b/src/pkg/bytes/reader_test.go index 19f014da0..d3dce5349 100644 --- a/src/pkg/bytes/reader_test.go +++ b/src/pkg/bytes/reader_test.go @@ -10,6 +10,7 @@ import (  	"io"  	"io/ioutil"  	"os" +	"sync"  	"testing"  ) @@ -26,9 +27,9 @@ func TestReader(t *testing.T) {  		{seek: os.SEEK_SET, off: 0, n: 20, want: "0123456789"},  		{seek: os.SEEK_SET, off: 1, n: 1, want: "1"},  		{seek: os.SEEK_CUR, off: 1, wantpos: 3, n: 2, want: "34"}, -		{seek: os.SEEK_SET, off: -1, seekerr: "bytes: negative position"}, -		{seek: os.SEEK_SET, off: 1<<31 - 1}, -		{seek: os.SEEK_CUR, off: 1, seekerr: "bytes: position out of range"}, +		{seek: os.SEEK_SET, off: -1, seekerr: "bytes.Reader.Seek: negative position"}, +		{seek: os.SEEK_SET, off: 1 << 33, wantpos: 1 << 33}, +		{seek: os.SEEK_CUR, off: 1, wantpos: 1<<33 + 1},  		{seek: os.SEEK_SET, n: 5, want: "01234"},  		{seek: os.SEEK_CUR, n: 5, want: "56789"},  		{seek: os.SEEK_END, off: -1, n: 1, wantpos: 9, want: "9"}, @@ -60,6 +61,16 @@ func TestReader(t *testing.T) {  	}  } +func TestReadAfterBigSeek(t *testing.T) { +	r := NewReader([]byte("0123456789")) +	if _, err := r.Seek(1<<31+5, os.SEEK_SET); err != nil { +		t.Fatal(err) +	} +	if n, err := r.Read(make([]byte, 10)); n != 0 || err != io.EOF { +		t.Errorf("Read = %d, %v; want 0, EOF", n, err) +	} +} +  func TestReaderAt(t *testing.T) {  	r := NewReader([]byte("0123456789"))  	tests := []struct { @@ -73,7 +84,7 @@ func TestReaderAt(t *testing.T) {  		{1, 9, "123456789", nil},  		{11, 10, "", io.EOF},  		{0, 0, "", nil}, -		{-1, 0, "", "bytes: invalid offset"}, +		{-1, 0, "", "bytes.Reader.ReadAt: negative offset"},  	}  	for i, tt := range tests {  		b := make([]byte, tt.n) @@ -88,6 +99,43 @@ func TestReaderAt(t *testing.T) {  	}  } +func TestReaderAtConcurrent(t *testing.T) { +	// Test for the race detector, to verify ReadAt doesn't mutate +	// any state. +	r := NewReader([]byte("0123456789")) +	var wg sync.WaitGroup +	for i := 0; i < 5; i++ { +		wg.Add(1) +		go func(i int) { +			defer wg.Done() +			var buf [1]byte +			r.ReadAt(buf[:], int64(i)) +		}(i) +	} +	wg.Wait() +} + +func TestEmptyReaderConcurrent(t *testing.T) { +	// Test for the race detector, to verify a Read that doesn't yield any bytes +	// is okay to use from multiple goroutines. This was our historic behavior. +	// See golang.org/issue/7856 +	r := NewReader([]byte{}) +	var wg sync.WaitGroup +	for i := 0; i < 5; i++ { +		wg.Add(2) +		go func() { +			defer wg.Done() +			var buf [1]byte +			r.Read(buf[:]) +		}() +		go func() { +			defer wg.Done() +			r.Read(nil) +		}() +	} +	wg.Wait() +} +  func TestReaderWriteTo(t *testing.T) {  	for i := 0; i < 30; i += 3 {  		var l int @@ -133,6 +181,32 @@ func TestReaderLen(t *testing.T) {  	}  } +var UnreadRuneErrorTests = []struct { +	name string +	f    func(*Reader) +}{ +	{"Read", func(r *Reader) { r.Read([]byte{0}) }}, +	{"ReadByte", func(r *Reader) { r.ReadByte() }}, +	{"UnreadRune", func(r *Reader) { r.UnreadRune() }}, +	{"Seek", func(r *Reader) { r.Seek(0, 1) }}, +	{"WriteTo", func(r *Reader) { r.WriteTo(&Buffer{}) }}, +} + +func TestUnreadRuneError(t *testing.T) { +	for _, tt := range UnreadRuneErrorTests { +		reader := NewReader([]byte("0123456789")) +		if _, _, err := reader.ReadRune(); err != nil { +			// should not happen +			t.Fatal(err) +		} +		tt.f(reader) +		err := reader.UnreadRune() +		if err == nil { +			t.Errorf("Unreading after %s: expected error", tt.name) +		} +	} +} +  func TestReaderDoubleUnreadRune(t *testing.T) {  	buf := NewBuffer([]byte("groucho"))  	if _, _, err := buf.ReadRune(); err != nil { | 
