diff options
Diffstat (limited to 'src/bytes/bytes_test.go')
| -rw-r--r-- | src/bytes/bytes_test.go | 81 |
1 files changed, 78 insertions, 3 deletions
diff --git a/src/bytes/bytes_test.go b/src/bytes/bytes_test.go index ead581718a..14b52a8035 100644 --- a/src/bytes/bytes_test.go +++ b/src/bytes/bytes_test.go @@ -7,6 +7,7 @@ package bytes_test import ( . "bytes" "fmt" + "internal/asan" "internal/testenv" "iter" "math" @@ -1786,9 +1787,20 @@ var ReplaceTests = []ReplaceTest{ func TestReplace(t *testing.T) { for _, tt := range ReplaceTests { - in := append([]byte(tt.in), "<spare>"...) + var ( + in = []byte(tt.in) + old = []byte(tt.old) + new = []byte(tt.new) + ) + if !asan.Enabled { + allocs := testing.AllocsPerRun(10, func() { Replace(in, old, new, tt.n) }) + if allocs > 1 { + t.Errorf("Replace(%q, %q, %q, %d) allocates %.2f objects", tt.in, tt.old, tt.new, tt.n, allocs) + } + } + in = append(in, "<spare>"...) in = in[:len(tt.in)] - out := Replace(in, []byte(tt.old), []byte(tt.new), tt.n) + out := Replace(in, old, new, tt.n) if s := string(out); s != tt.out { t.Errorf("Replace(%q, %q, %q, %d) = %q, want %q", tt.in, tt.old, tt.new, tt.n, s, tt.out) } @@ -1796,7 +1808,7 @@ func TestReplace(t *testing.T) { t.Errorf("Replace(%q, %q, %q, %d) didn't copy", tt.in, tt.old, tt.new, tt.n) } if tt.n == -1 { - out := ReplaceAll(in, []byte(tt.old), []byte(tt.new)) + out := ReplaceAll(in, old, new) if s := string(out); s != tt.out { t.Errorf("ReplaceAll(%q, %q, %q) = %q, want %q", tt.in, tt.old, tt.new, s, tt.out) } @@ -1804,6 +1816,69 @@ func TestReplace(t *testing.T) { } } +func FuzzReplace(f *testing.F) { + for _, tt := range ReplaceTests { + f.Add([]byte(tt.in), []byte(tt.old), []byte(tt.new), tt.n) + } + f.Fuzz(func(t *testing.T, in, old, new []byte, n int) { + differentImpl := func(in, old, new []byte, n int) []byte { + var out Buffer + if n < 0 { + n = math.MaxInt + } + for i := 0; i < len(in); { + if n == 0 { + out.Write(in[i:]) + break + } + if HasPrefix(in[i:], old) { + out.Write(new) + i += len(old) + n-- + if len(old) != 0 { + continue + } + if i == len(in) { + break + } + } + if len(old) == 0 { + _, length := utf8.DecodeRune(in[i:]) + out.Write(in[i : i+length]) + i += length + } else { + out.WriteByte(in[i]) + i++ + } + } + if len(old) == 0 && n != 0 { + out.Write(new) + } + return out.Bytes() + } + if simple, replace := differentImpl(in, old, new, n), Replace(in, old, new, n); !slices.Equal(simple, replace) { + t.Errorf("The two implementations do not match %q != %q for Replace(%q, %q, %q, %d)", simple, replace, in, old, new, n) + } + }) +} + +func BenchmarkReplace(b *testing.B) { + for _, tt := range ReplaceTests { + desc := fmt.Sprintf("%q %q %q %d", tt.in, tt.old, tt.new, tt.n) + var ( + in = []byte(tt.in) + old = []byte(tt.old) + new = []byte(tt.new) + ) + b.Run(desc, func(b *testing.B) { + b.ReportAllocs() + for b.Loop() { + Replace(in, old, new, tt.n) + } + }) + } +} + type TitleTest struct { in, out string } |
