// Copyright 2017 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 strings_test

import (
	"bytes"
	"errors"
	"io"
	"runtime"
	. "strings"
	"testing"
	"testing/iotest"
)

func check(t *testing.T, b *Builder, want string) {
	t.Helper()
	got := b.String()
	if got != want {
		t.Errorf("String: got %#q; want %#q", got, want)
		return
	}
	if n := b.Len(); n != len(got) {
		t.Errorf("Len: got %d; but len(String()) is %d", n, len(got))
	}
}

func TestBuilder(t *testing.T) {
	var b Builder
	check(t, &b, "")
	n, err := b.WriteString("hello")
	if err != nil || n != 5 {
		t.Errorf("WriteString: got %d,%s; want 5,nil", n, err)
	}
	check(t, &b, "hello")
	if err = b.WriteByte(' '); err != nil {
		t.Errorf("WriteByte: %s", err)
	}
	check(t, &b, "hello ")
	n, err = b.WriteString("world")
	if err != nil || n != 5 {
		t.Errorf("WriteString: got %d,%s; want 5,nil", n, err)
	}
	check(t, &b, "hello world")
}

func TestBuilderString(t *testing.T) {
	var b Builder
	b.WriteString("alpha")
	check(t, &b, "alpha")
	s1 := b.String()
	b.WriteString("beta")
	check(t, &b, "alphabeta")
	s2 := b.String()
	b.WriteString("gamma")
	check(t, &b, "alphabetagamma")
	s3 := b.String()

	// Check that subsequent operations didn't change the returned strings.
	if want := "alpha"; s1 != want {
		t.Errorf("first String result is now %q; want %q", s1, want)
	}
	if want := "alphabeta"; s2 != want {
		t.Errorf("second String result is now %q; want %q", s2, want)
	}
	if want := "alphabetagamma"; s3 != want {
		t.Errorf("third String result is now %q; want %q", s3, want)
	}
}

func TestBuilderReset(t *testing.T) {
	var b Builder
	check(t, &b, "")
	b.WriteString("aaa")
	s := b.String()
	check(t, &b, "aaa")
	b.Reset()
	check(t, &b, "")

	// Ensure that writing after Reset doesn't alter
	// previously returned strings.
	b.WriteString("bbb")
	check(t, &b, "bbb")
	if want := "aaa"; s != want {
		t.Errorf("previous String result changed after Reset: got %q; want %q", s, want)
	}
}

func TestBuilderGrow(t *testing.T) {
	for _, growLen := range []int{0, 100, 1000, 10000, 100000} {
		var b Builder
		b.Grow(growLen)
		p := bytes.Repeat([]byte{'a'}, growLen)
		allocs := numAllocs(func() { b.Write(p) })
		if allocs > 0 {
			t.Errorf("growLen=%d: allocation occurred during write", growLen)
		}
		if b.String() != string(p) {
			t.Errorf("growLen=%d: bad data written after Grow", growLen)
		}
	}
}

func TestBuilderWrite2(t *testing.T) {
	const s0 = "hello 世界"
	for _, tt := range []struct {
		name string
		fn   func(b *Builder) (int, error)
		n    int
		want string
	}{
		{
			"Write",
			func(b *Builder) (int, error) { return b.Write([]byte(s0)) },
			len(s0),
			s0,
		},
		{
			"WriteRune",
			func(b *Builder) (int, error) { return b.WriteRune('a') },
			1,
			"a",
		},
		{
			"WriteRuneWide",
			func(b *Builder) (int, error) { return b.WriteRune('世') },
			3,
			"世",
		},
		{
			"WriteString",
			func(b *Builder) (int, error) { return b.WriteString(s0) },
			len(s0),
			s0,
		},
	} {
		t.Run(tt.name, func(t *testing.T) {
			var b Builder
			n, err := tt.fn(&b)
			if err != nil {
				t.Fatalf("first call: got %s", err)
			}
			if n != tt.n {
				t.Errorf("first call: got n=%d; want %d", n, tt.n)
			}
			check(t, &b, tt.want)

			n, err = tt.fn(&b)
			if err != nil {
				t.Fatalf("second call: got %s", err)
			}
			if n != tt.n {
				t.Errorf("second call: got n=%d; want %d", n, tt.n)
			}
			check(t, &b, tt.want+tt.want)
		})
	}
}

func TestBuilderWriteByte(t *testing.T) {
	var b Builder
	if err := b.WriteByte('a'); err != nil {
		t.Error(err)
	}
	if err := b.WriteByte(0); err != nil {
		t.Error(err)
	}
	check(t, &b, "a\x00")
}

func TestBuilderReadFrom(t *testing.T) {
	for _, tt := range []struct {
		name string
		fn   func(io.Reader) io.Reader
	}{
		{"Reader", func(r io.Reader) io.Reader { return r }},
		{"DataErrReader", iotest.DataErrReader},
		{"OneByteReader", iotest.OneByteReader},
	} {
		t.Run(tt.name, func(t *testing.T) {
			var b Builder

			r := tt.fn(NewReader("hello"))
			n, err := b.ReadFrom(r)
			if err != nil {
				t.Fatalf("first call: got %s", err)
			}
			if n != 5 {
				t.Errorf("first call: got n=%d; want 5", n)
			}
			check(t, &b, "hello")

			r = tt.fn(NewReader(" world"))
			n, err = b.ReadFrom(r)
			if err != nil {
				t.Fatalf("first call: got %s", err)
			}
			if n != 6 {
				t.Errorf("first call: got n=%d; want 6", n)
			}
			check(t, &b, "hello world")
		})
	}
}

var errRead = errors.New("boom")

// errorReader sends reads to the underlying reader
// but returns errRead instead of io.EOF.
type errorReader struct {
	r io.Reader
}

func (r errorReader) Read(b []byte) (int, error) {
	n, err := r.r.Read(b)
	if err == io.EOF {
		err = errRead
	}
	return n, err
}

func TestBuilderReadFromError(t *testing.T) {
	var b Builder
	r := errorReader{NewReader("hello")}
	n, err := b.ReadFrom(r)
	if n != 5 {
		t.Errorf("got n=%d; want 5", n)
	}
	if err != errRead {
		t.Errorf("got err=%q; want %q", err, errRead)
	}
	check(t, &b, "hello")
}

type negativeReader struct{}

func (r negativeReader) Read([]byte) (int, error) { return -1, nil }

func TestBuilderReadFromNegativeReader(t *testing.T) {
	var b Builder
	defer func() {
		switch err := recover().(type) {
		case nil:
			t.Fatal("ReadFrom didn't panic")
		case error:
			wantErr := "strings.Builder: reader returned negative count from Read"
			if err.Error() != wantErr {
				t.Fatalf("recovered panic: got %v; want %v", err.Error(), wantErr)
			}
		default:
			t.Fatalf("unexpected panic value: %#v", err)
		}
	}()

	b.ReadFrom(negativeReader{})
}

func TestBuilderAllocs(t *testing.T) {
	var b Builder
	b.Grow(5)
	var s string
	allocs := numAllocs(func() {
		b.WriteString("hello")
		s = b.String()
	})
	if want := "hello"; s != want {
		t.Errorf("String: got %#q; want %#q", s, want)
	}
	if allocs > 0 {
		t.Fatalf("got %d alloc(s); want 0", allocs)
	}
}

func numAllocs(fn func()) uint64 {
	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(1))
	var m1, m2 runtime.MemStats
	runtime.ReadMemStats(&m1)
	fn()
	runtime.ReadMemStats(&m2)
	return m2.Mallocs - m1.Mallocs
}
