// Copyright 2019 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 json_test

import (
	"math"
	"strings"
	"testing"

	"github.com/google/go-cmp/cmp"
	"github.com/google/go-cmp/cmp/cmpopts"
	"google.golang.org/protobuf/internal/encoding/json"
)

// splitLines is a cmpopts.Option for comparing strings with line breaks.
var splitLines = cmpopts.AcyclicTransformer("SplitLines", func(s string) []string {
	return strings.Split(s, "\n")
})

func TestEncoder(t *testing.T) {
	tests := []struct {
		desc          string
		write         func(*json.Encoder)
		wantOut       string
		wantOutIndent string
	}{
		{
			desc: "null",
			write: func(e *json.Encoder) {
				e.WriteNull()
			},
			wantOut:       `null`,
			wantOutIndent: `null`,
		},
		{
			desc: "true",
			write: func(e *json.Encoder) {
				e.WriteBool(true)
			},
			wantOut:       `true`,
			wantOutIndent: `true`,
		},
		{
			desc: "false",
			write: func(e *json.Encoder) {
				e.WriteBool(false)
			},
			wantOut:       `false`,
			wantOutIndent: `false`,
		},
		{
			desc: "string",
			write: func(e *json.Encoder) {
				e.WriteString("hello world")
			},
			wantOut:       `"hello world"`,
			wantOutIndent: `"hello world"`,
		},
		{
			desc: "string contains escaped characters",
			write: func(e *json.Encoder) {
				e.WriteString("\u0000\"\\/\b\f\n\r\t")
			},
			wantOut: `"\u0000\"\\/\b\f\n\r\t"`,
		},
		{
			desc: "float64",
			write: func(e *json.Encoder) {
				e.WriteFloat(1.0199999809265137, 64)
			},
			wantOut:       `1.0199999809265137`,
			wantOutIndent: `1.0199999809265137`,
		},
		{
			desc: "float64 max value",
			write: func(e *json.Encoder) {
				e.WriteFloat(math.MaxFloat64, 64)
			},
			wantOut:       `1.7976931348623157e+308`,
			wantOutIndent: `1.7976931348623157e+308`,
		},
		{
			desc: "float64 min value",
			write: func(e *json.Encoder) {
				e.WriteFloat(-math.MaxFloat64, 64)
			},
			wantOut:       `-1.7976931348623157e+308`,
			wantOutIndent: `-1.7976931348623157e+308`,
		},
		{
			desc: "float64 NaN",
			write: func(e *json.Encoder) {
				e.WriteFloat(math.NaN(), 64)
			},
			wantOut:       `"NaN"`,
			wantOutIndent: `"NaN"`,
		},
		{
			desc: "float64 Infinity",
			write: func(e *json.Encoder) {
				e.WriteFloat(math.Inf(+1), 64)
			},
			wantOut:       `"Infinity"`,
			wantOutIndent: `"Infinity"`,
		},
		{
			desc: "float64 -Infinity",
			write: func(e *json.Encoder) {
				e.WriteFloat(math.Inf(-1), 64)
			},
			wantOut:       `"-Infinity"`,
			wantOutIndent: `"-Infinity"`,
		},
		{
			desc: "float32",
			write: func(e *json.Encoder) {
				e.WriteFloat(1.02, 32)
			},
			wantOut:       `1.02`,
			wantOutIndent: `1.02`,
		},
		{
			desc: "float32 max value",
			write: func(e *json.Encoder) {
				e.WriteFloat(math.MaxFloat32, 32)
			},
			wantOut:       `3.4028235e+38`,
			wantOutIndent: `3.4028235e+38`,
		},
		{
			desc: "float32 min value",
			write: func(e *json.Encoder) {
				e.WriteFloat(-math.MaxFloat32, 32)
			},
			wantOut:       `-3.4028235e+38`,
			wantOutIndent: `-3.4028235e+38`,
		},
		{
			desc: "int",
			write: func(e *json.Encoder) {
				e.WriteInt(-math.MaxInt64)
			},
			wantOut:       `-9223372036854775807`,
			wantOutIndent: `-9223372036854775807`,
		},
		{
			desc: "uint",
			write: func(e *json.Encoder) {
				e.WriteUint(math.MaxUint64)
			},
			wantOut:       `18446744073709551615`,
			wantOutIndent: `18446744073709551615`,
		},
		{
			desc: "empty object",
			write: func(e *json.Encoder) {
				e.StartObject()
				e.EndObject()
			},
			wantOut:       `{}`,
			wantOutIndent: `{}`,
		},
		{
			desc: "empty array",
			write: func(e *json.Encoder) {
				e.StartArray()
				e.EndArray()
			},
			wantOut:       `[]`,
			wantOutIndent: `[]`,
		},
		{
			desc: "object with one member",
			write: func(e *json.Encoder) {
				e.StartObject()
				e.WriteName("hello")
				e.WriteString("world")
				e.EndObject()
			},
			wantOut: `{"hello":"world"}`,
			wantOutIndent: `{
	"hello": "world"
}`,
		},
		{
			desc: "array with one member",
			write: func(e *json.Encoder) {
				e.StartArray()
				e.WriteNull()
				e.EndArray()
			},
			wantOut: `[null]`,
			wantOutIndent: `[
	null
]`,
		},
		{
			desc: "simple object",
			write: func(e *json.Encoder) {
				e.StartObject()
				{
					e.WriteName("null")
					e.WriteNull()
				}
				{
					e.WriteName("bool")
					e.WriteBool(true)
				}
				{
					e.WriteName("string")
					e.WriteString("hello")
				}
				{
					e.WriteName("float")
					e.WriteFloat(6.28318, 64)
				}
				{
					e.WriteName("int")
					e.WriteInt(42)
				}
				{
					e.WriteName("uint")
					e.WriteUint(47)
				}
				e.EndObject()
			},
			wantOut: `{"null":null,"bool":true,"string":"hello","float":6.28318,"int":42,"uint":47}`,
			wantOutIndent: `{
	"null": null,
	"bool": true,
	"string": "hello",
	"float": 6.28318,
	"int": 42,
	"uint": 47
}`,
		},
		{
			desc: "simple array",
			write: func(e *json.Encoder) {
				e.StartArray()
				{
					e.WriteString("hello")
					e.WriteFloat(6.28318, 32)
					e.WriteInt(42)
					e.WriteUint(47)
					e.WriteBool(true)
					e.WriteNull()
				}
				e.EndArray()
			},
			wantOut: `["hello",6.28318,42,47,true,null]`,
			wantOutIndent: `[
	"hello",
	6.28318,
	42,
	47,
	true,
	null
]`,
		},
		{
			desc: "fancy object",
			write: func(e *json.Encoder) {
				e.StartObject()
				{
					e.WriteName("object0")
					e.StartObject()
					e.EndObject()
				}
				{
					e.WriteName("array0")
					e.StartArray()
					e.EndArray()
				}
				{
					e.WriteName("object1")
					e.StartObject()
					{
						e.WriteName("null")
						e.WriteNull()
					}
					{
						e.WriteName("object1-1")
						e.StartObject()
						{
							e.WriteName("bool")
							e.WriteBool(false)
						}
						{
							e.WriteName("float")
							e.WriteFloat(3.14159, 32)
						}
						e.EndObject()
					}
					e.EndObject()
				}
				{
					e.WriteName("array1")
					e.StartArray()
					{
						e.WriteNull()
						e.StartObject()
						e.EndObject()
						e.StartObject()
						{
							e.WriteName("hello")
							e.WriteString("world")
						}
						{
							e.WriteName("hola")
							e.WriteString("mundo")
						}
						e.EndObject()
						e.StartArray()
						{
							e.WriteUint(1)
							e.WriteUint(0)
							e.WriteUint(1)
						}
						e.EndArray()
					}
					e.EndArray()
				}
				e.EndObject()
			},
			wantOutIndent: `{
	"object0": {},
	"array0": [],
	"object1": {
		"null": null,
		"object1-1": {
			"bool": false,
			"float": 3.14159
		}
	},
	"array1": [
		null,
		{},
		{
			"hello": "world",
			"hola": "mundo"
		},
		[
			1,
			0,
			1
		]
	]
}`,
		}}

	for _, tc := range tests {
		t.Run(tc.desc, func(t *testing.T) {
			if tc.wantOut != "" {
				enc, err := json.NewEncoder("")
				if err != nil {
					t.Fatalf("NewEncoder() returned error: %v", err)
				}
				tc.write(enc)
				got := string(enc.Bytes())
				if got != tc.wantOut {
					t.Errorf("%s:\n<got>:\n%v\n<want>\n%v\n", tc.desc, got, tc.wantOut)
				}
			}
			if tc.wantOutIndent != "" {
				enc, err := json.NewEncoder("\t")
				if err != nil {
					t.Fatalf("NewEncoder() returned error: %v", err)
				}
				tc.write(enc)
				got, want := string(enc.Bytes()), tc.wantOutIndent
				if got != want {
					t.Errorf("%s(indent):\n<got>:\n%v\n<want>\n%v\n<diff -want +got>\n%v\n",
						tc.desc, got, want, cmp.Diff(want, got, splitLines))
				}
			}
		})
	}
}

func TestWriteStringError(t *testing.T) {
	tests := []string{"abc\xff"}

	for _, in := range tests {
		t.Run(in, func(t *testing.T) {
			enc, err := json.NewEncoder("")
			if err != nil {
				t.Fatalf("NewEncoder() returned error: %v", err)
			}
			if err := enc.WriteString(in); err == nil {
				t.Errorf("WriteString(%v): got nil error, want error", in)
			}
		})
	}
}
