// Copyright 2009 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 gob

import (
	"bytes"
	"reflect"
	"sync"
	"testing"
)

type typeT struct {
	id  typeId
	str string
}

var basicTypes = []typeT{
	{tBool, "bool"},
	{tInt, "int"},
	{tUint, "uint"},
	{tFloat, "float"},
	{tBytes, "bytes"},
	{tString, "string"},
}

func getTypeUnlocked(name string, rt reflect.Type) gobType {
	typeLock.Lock()
	defer typeLock.Unlock()
	t, err := getBaseType(name, rt)
	if err != nil {
		panic("getTypeUnlocked: " + err.Error())
	}
	return t
}

// Sanity checks
func TestBasic(t *testing.T) {
	for _, tt := range basicTypes {
		if tt.id.string() != tt.str {
			t.Errorf("checkType: expected %q got %s", tt.str, tt.id.string())
		}
		if tt.id == 0 {
			t.Errorf("id for %q is zero", tt.str)
		}
	}
}

// Reregister some basic types to check registration is idempotent.
func TestReregistration(t *testing.T) {
	newtyp := getTypeUnlocked("int", reflect.TypeFor[int]())
	if newtyp != tInt.gobType() {
		t.Errorf("reregistration of %s got new type", newtyp.string())
	}
	newtyp = getTypeUnlocked("uint", reflect.TypeFor[uint]())
	if newtyp != tUint.gobType() {
		t.Errorf("reregistration of %s got new type", newtyp.string())
	}
	newtyp = getTypeUnlocked("string", reflect.TypeFor[string]())
	if newtyp != tString.gobType() {
		t.Errorf("reregistration of %s got new type", newtyp.string())
	}
}

func TestArrayType(t *testing.T) {
	var a3 [3]int
	a3int := getTypeUnlocked("foo", reflect.TypeOf(a3))
	newa3int := getTypeUnlocked("bar", reflect.TypeOf(a3))
	if a3int != newa3int {
		t.Errorf("second registration of [3]int creates new type")
	}
	var a4 [4]int
	a4int := getTypeUnlocked("goo", reflect.TypeOf(a4))
	if a3int == a4int {
		t.Errorf("registration of [3]int creates same type as [4]int")
	}
	var b3 [3]bool
	a3bool := getTypeUnlocked("", reflect.TypeOf(b3))
	if a3int == a3bool {
		t.Errorf("registration of [3]bool creates same type as [3]int")
	}
	str := a3bool.string()
	expected := "[3]bool"
	if str != expected {
		t.Errorf("array printed as %q; expected %q", str, expected)
	}
}

func TestSliceType(t *testing.T) {
	var s []int
	sint := getTypeUnlocked("slice", reflect.TypeOf(s))
	var news []int
	newsint := getTypeUnlocked("slice1", reflect.TypeOf(news))
	if sint != newsint {
		t.Errorf("second registration of []int creates new type")
	}
	var b []bool
	sbool := getTypeUnlocked("", reflect.TypeOf(b))
	if sbool == sint {
		t.Errorf("registration of []bool creates same type as []int")
	}
	str := sbool.string()
	expected := "[]bool"
	if str != expected {
		t.Errorf("slice printed as %q; expected %q", str, expected)
	}
}

func TestMapType(t *testing.T) {
	var m map[string]int
	mapStringInt := getTypeUnlocked("map", reflect.TypeOf(m))
	var newm map[string]int
	newMapStringInt := getTypeUnlocked("map1", reflect.TypeOf(newm))
	if mapStringInt != newMapStringInt {
		t.Errorf("second registration of map[string]int creates new type")
	}
	var b map[string]bool
	mapStringBool := getTypeUnlocked("", reflect.TypeOf(b))
	if mapStringBool == mapStringInt {
		t.Errorf("registration of map[string]bool creates same type as map[string]int")
	}
	str := mapStringBool.string()
	expected := "map[string]bool"
	if str != expected {
		t.Errorf("map printed as %q; expected %q", str, expected)
	}
}

type Bar struct {
	X string
}

// This structure has pointers and refers to itself, making it a good test case.
type Foo struct {
	A int
	B int32 // will become int
	C string
	D []byte
	E *float64    // will become float64
	F ****float64 // will become float64
	G *Bar
	H *Bar // should not interpolate the definition of Bar again
	I *Foo // will not explode
}

func TestStructType(t *testing.T) {
	sstruct := getTypeUnlocked("Foo", reflect.TypeFor[Foo]())
	str := sstruct.string()
	// If we can print it correctly, we built it correctly.
	expected := "Foo = struct { A int; B int; C string; D bytes; E float; F float; G Bar = struct { X string; }; H Bar; I Foo; }"
	if str != expected {
		t.Errorf("struct printed as %q; expected %q", str, expected)
	}
}

// Should be OK to register the same type multiple times, as long as they're
// at the same level of indirection.
func TestRegistration(t *testing.T) {
	type T struct{ a int }
	Register(new(T))
	Register(new(T))
}

type N1 struct{}
type N2 struct{}

// See comment in type.go/Register.
func TestRegistrationNaming(t *testing.T) {
	testCases := []struct {
		t    any
		name string
	}{
		{&N1{}, "*gob.N1"},
		{N2{}, "encoding/gob.N2"},
	}

	for _, tc := range testCases {
		Register(tc.t)

		tct := reflect.TypeOf(tc.t)
		ct, _ := nameToConcreteType.Load(tc.name)
		if ct != tct {
			t.Errorf("nameToConcreteType[%q] = %v, want %v", tc.name, ct, tct)
		}
		// concreteTypeToName is keyed off the base type.
		if tct.Kind() == reflect.Pointer {
			tct = tct.Elem()
		}
		if n, _ := concreteTypeToName.Load(tct); n != tc.name {
			t.Errorf("concreteTypeToName[%v] got %v, want %v", tct, n, tc.name)
		}
	}
}

func TestStressParallel(t *testing.T) {
	type T2 struct{ A int }
	c := make(chan bool)
	const N = 10
	for i := 0; i < N; i++ {
		go func() {
			p := new(T2)
			Register(p)
			b := new(bytes.Buffer)
			enc := NewEncoder(b)
			err := enc.Encode(p)
			if err != nil {
				t.Error("encoder fail:", err)
			}
			dec := NewDecoder(b)
			err = dec.Decode(p)
			if err != nil {
				t.Error("decoder fail:", err)
			}
			c <- true
		}()
	}
	for i := 0; i < N; i++ {
		<-c
	}
}

// Issue 23328. Note that this test name is known to cmd/dist/test.go.
func TestTypeRace(t *testing.T) {
	c := make(chan bool)
	var wg sync.WaitGroup
	for i := 0; i < 2; i++ {
		wg.Add(1)
		go func(i int) {
			defer wg.Done()
			var buf bytes.Buffer
			enc := NewEncoder(&buf)
			dec := NewDecoder(&buf)
			var x any
			switch i {
			case 0:
				x = &N1{}
			case 1:
				x = &N2{}
			default:
				t.Errorf("bad i %d", i)
				return
			}
			m := make(map[string]string)
			<-c
			if err := enc.Encode(x); err != nil {
				t.Error(err)
				return
			}
			if err := enc.Encode(x); err != nil {
				t.Error(err)
				return
			}
			if err := dec.Decode(&m); err == nil {
				t.Error("decode unexpectedly succeeded")
				return
			}
		}(i)
	}
	close(c)
	wg.Wait()
}
