THRIFT-5855: go fuzzers

Add fuzzers for go support, to improve the reliability/robustness of the implementation
diff --git a/lib/go/test/fuzz/fuzz.go b/lib/go/test/fuzz/fuzz.go
index 0698379..bad6b41 100644
--- a/lib/go/test/fuzz/fuzz.go
+++ b/lib/go/test/fuzz/fuzz.go
@@ -29,11 +29,15 @@
 
 	"github.com/apache/thrift/lib/go/test/fuzz/gen-go/shared"
 	"github.com/apache/thrift/lib/go/test/fuzz/gen-go/tutorial"
+	"github.com/apache/thrift/lib/go/test/fuzz/gen-go/fuzztest"
 	"github.com/apache/thrift/lib/go/thrift"
 )
 
 const nbFuzzedProtocols = 2
 
+// 10MB message size limit to prevent over-allocation during fuzzing
+const FUZZ_MAX_MESSAGE_SIZE = 10 * 1024 * 1024
+
 func fuzzChooseProtocol(d byte, t thrift.TTransport) thrift.TProtocol {
 	switch d % nbFuzzedProtocols {
 	default:
@@ -42,10 +46,12 @@
 		return thrift.NewTBinaryProtocolFactoryConf(nil).GetProtocol(t)
 	case 1:
 		return thrift.NewTCompactProtocolFactoryConf(nil).GetProtocol(t)
+	case 2:
+		return thrift.NewTJSONProtocolFactory().GetProtocol(t)
 	}
 }
 
-func Fuzz(data []byte) int {
+func FuzzTutorial(data []byte) int {
 	if len(data) < 2 {
 		return 0
 	}
@@ -142,3 +148,242 @@
 	fmt.Print("zip()\n")
 	return nil
 }
+
+func FuzzParseBinary(data []byte) int {
+	// Skip if input is too small
+	if len(data) < 1 {
+		return 0
+	}
+
+	// Create transport and protocol
+	transport := thrift.NewTMemoryBufferLen(len(data))
+	defer func() {
+		transport.Close()
+		// Reset the buffer to release memory
+		transport.Buffer.Reset()
+	}()
+	transport.Write(data)
+	config := &thrift.TConfiguration{
+		MaxMessageSize: FUZZ_MAX_MESSAGE_SIZE,
+	}
+	protocol := thrift.NewTBinaryProtocolFactoryConf(config).GetProtocol(transport)
+
+	// Try to read the FuzzTest structure
+	fuzzTest := fuzztest.NewFuzzTest()
+	err := fuzzTest.Read(context.Background(), protocol)
+	if err != nil {
+		// Invalid input, but not a crash
+		return 0
+	}
+
+	// Successfully parsed
+	return 1
+}
+
+func FuzzParseCompact(data []byte) int {
+	// Skip if input is too small
+	if len(data) < 1 {
+		return 0
+	}
+
+	// Create transport and protocol
+	transport := thrift.NewTMemoryBufferLen(len(data))
+	defer func() {
+		transport.Close()
+		// Reset the buffer to release memory
+		transport.Buffer.Reset()
+	}()
+	transport.Write(data)
+	config := &thrift.TConfiguration{
+		MaxMessageSize: FUZZ_MAX_MESSAGE_SIZE,
+	}
+	protocol := thrift.NewTCompactProtocolFactoryConf(config).GetProtocol(transport)
+
+	// Try to read the FuzzTest structure
+	fuzzTest := fuzztest.NewFuzzTest()
+	err := fuzzTest.Read(context.Background(), protocol)
+	if err != nil {
+		// Invalid input, but not a crash
+		return 0
+	}
+
+	// Successfully parsed
+	return 1
+}
+
+func FuzzParseJson(data []byte) int {
+	// Skip if input is too small
+	if len(data) < 1 {
+		return 0
+	}
+
+	// Create transport and protocol
+	transport := thrift.NewTMemoryBufferLen(len(data))
+	defer func() {
+		transport.Close()
+		// Reset the buffer to release memory
+		transport.Buffer.Reset()
+	}()
+	transport.Write(data)
+	protocol := thrift.NewTJSONProtocolFactory().GetProtocol(transport)
+
+	// Try to read the FuzzTest structure
+	fuzzTest := fuzztest.NewFuzzTest()
+	err := fuzzTest.Read(context.Background(), protocol)
+	if err != nil {
+		// Invalid input, but not a crash
+		return 0
+	}
+
+	// Successfully parsed
+	return 1
+}
+
+func FuzzRoundtripBinary(data []byte) int {
+	// Skip if input is too small
+	if len(data) < 1 {
+		return 0
+	}
+
+	config := &thrift.TConfiguration{
+		MaxMessageSize: FUZZ_MAX_MESSAGE_SIZE,
+	}
+
+	// First parse
+	transport := thrift.NewTMemoryBufferLen(len(data))
+	transport.Write(data)
+	protocol := thrift.NewTBinaryProtocolFactoryConf(config).GetProtocol(transport)
+
+	// Try to read the FuzzTest structure
+	test1 := fuzztest.NewFuzzTest()
+	err := test1.Read(context.Background(), protocol)
+	if err != nil {
+		// Invalid input, but not a crash
+		return 0
+	}
+
+	// Serialize back
+	outTransport := thrift.NewTMemoryBuffer()
+	outProtocol := thrift.NewTBinaryProtocolFactoryConf(config).GetProtocol(outTransport)
+	err = test1.Write(context.Background(), outProtocol)
+	if err != nil {
+		return 0
+	}
+
+	// Get serialized data and deserialize again
+	serialized := outTransport.Bytes()
+	reTransport := thrift.NewTMemoryBufferLen(len(serialized))
+	reTransport.Write(serialized)
+	reProtocol := thrift.NewTBinaryProtocolFactoryConf(config).GetProtocol(reTransport)
+
+	test2 := fuzztest.NewFuzzTest()
+	err = test2.Read(context.Background(), reProtocol)
+	if err != nil {
+		return 0
+	}
+
+	// Verify equality
+	if !test1.Equals(test2) {
+		panic("Roundtrip failed: objects not equal after deserialization")
+	}
+
+	return 1
+}
+
+func FuzzRoundtripCompact(data []byte) int {
+	// Skip if input is too small
+	if len(data) < 1 {
+		return 0
+	}
+
+	config := &thrift.TConfiguration{
+		MaxMessageSize: FUZZ_MAX_MESSAGE_SIZE,
+	}
+
+	// First parse
+	transport := thrift.NewTMemoryBufferLen(len(data))
+	transport.Write(data)
+	protocol := thrift.NewTCompactProtocolFactoryConf(config).GetProtocol(transport)
+
+	// Try to read the FuzzTest structure
+	test1 := fuzztest.NewFuzzTest()
+	err := test1.Read(context.Background(), protocol)
+	if err != nil {
+		// Invalid input, but not a crash
+		return 0
+	}
+
+	// Serialize back
+	outTransport := thrift.NewTMemoryBuffer()
+	outProtocol := thrift.NewTCompactProtocolFactoryConf(config).GetProtocol(outTransport)
+	err = test1.Write(context.Background(), outProtocol)
+	if err != nil {
+		return 0
+	}
+
+	// Get serialized data and deserialize again
+	serialized := outTransport.Bytes()
+	reTransport := thrift.NewTMemoryBufferLen(len(serialized))
+	reTransport.Write(serialized)
+	reProtocol := thrift.NewTCompactProtocolFactoryConf(config).GetProtocol(reTransport)
+
+	test2 := fuzztest.NewFuzzTest()
+	err = test2.Read(context.Background(), reProtocol)
+	if err != nil {
+		return 0
+	}
+
+	// Verify equality
+	if !test1.Equals(test2) {
+		panic("Roundtrip failed: objects not equal after deserialization")
+	}
+
+	return 1
+}
+
+func FuzzRoundtripJson(data []byte) int {
+	// Skip if input is too small
+	if len(data) < 1 {
+		return 0
+	}
+
+	// First parse
+	transport := thrift.NewTMemoryBufferLen(len(data))
+	transport.Write(data)
+	protocol := thrift.NewTJSONProtocolFactory().GetProtocol(transport)
+
+	// Try to read the FuzzTest structure
+	test1 := fuzztest.NewFuzzTest()
+	err := test1.Read(context.Background(), protocol)
+	if err != nil {
+		// Invalid input, but not a crash
+		return 0
+	}
+
+	// Serialize back
+	outTransport := thrift.NewTMemoryBuffer()
+	outProtocol := thrift.NewTJSONProtocolFactory().GetProtocol(outTransport)
+	err = test1.Write(context.Background(), outProtocol)
+	if err != nil {
+		return 0
+	}
+
+	// Get serialized data and deserialize again
+	serialized := outTransport.Bytes()
+	reTransport := thrift.NewTMemoryBufferLen(len(serialized))
+	reTransport.Write(serialized)
+	reProtocol := thrift.NewTJSONProtocolFactory().GetProtocol(reTransport)
+
+	test2 := fuzztest.NewFuzzTest()
+	err = test2.Read(context.Background(), reProtocol)
+	if err != nil {
+		return 0
+	}
+
+	// Verify equality
+	if !test1.Equals(test2) {
+		panic("Roundtrip failed: objects not equal after deserialization")
+	}
+
+	return 1
+}