You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@thrift.apache.org by je...@apache.org on 2014/11/18 22:19:49 UTC

[1/3] thrift git commit: THRIFT-2817 Smarter buffer peeking for json protocols Client: Go Patch: Chi Vinh Le

Repository: thrift
Updated Branches:
  refs/heads/master 9c0316bbf -> 5f9bdffd2


THRIFT-2817 Smarter buffer peeking for json protocols
Client: Go
Patch: Chi Vinh Le <cv...@chinet.info>


Project: http://git-wip-us.apache.org/repos/asf/thrift/repo
Commit: http://git-wip-us.apache.org/repos/asf/thrift/commit/2f971e8f
Tree: http://git-wip-us.apache.org/repos/asf/thrift/tree/2f971e8f
Diff: http://git-wip-us.apache.org/repos/asf/thrift/diff/2f971e8f

Branch: refs/heads/master
Commit: 2f971e8f742fcaa0c84cfcc4f02eb844123e5819
Parents: 9c0316b
Author: Jens Geyer <je...@apache.org>
Authored: Tue Nov 18 21:53:17 2014 +0100
Committer: Jens Geyer <je...@apache.org>
Committed: Tue Nov 18 22:18:09 2014 +0100

----------------------------------------------------------------------
 lib/go/thrift/json_protocol.go             |  51 +++++++----
 lib/go/thrift/simple_json_protocol.go      | 112 ++++++++++++++++--------
 lib/go/thrift/simple_json_protocol_test.go |  83 ++++++++++++++++++
 3 files changed, 189 insertions(+), 57 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/thrift/blob/2f971e8f/lib/go/thrift/json_protocol.go
----------------------------------------------------------------------
diff --git a/lib/go/thrift/json_protocol.go b/lib/go/thrift/json_protocol.go
index 17fe530..78348ec 100644
--- a/lib/go/thrift/json_protocol.go
+++ b/lib/go/thrift/json_protocol.go
@@ -160,7 +160,7 @@ func (p *TJSONProtocol) WriteSetEnd() error {
 func (p *TJSONProtocol) WriteBool(b bool) error {
 	if b {
 		return p.WriteI32(1)
-    }
+	}
 	return p.WriteI32(0)
 }
 
@@ -196,18 +196,23 @@ func (p *TJSONProtocol) WriteBinary(v []byte) error {
 	if e := p.OutputPreValue(); e != nil {
 		return e
 	}
-	p.writer.Write(JSON_QUOTE_BYTES)
+	if _, e := p.writer.Write(JSON_QUOTE_BYTES); e != nil {
+		return NewTProtocolException(e)
+	}
 	writer := base64.NewEncoder(base64.StdEncoding, p.writer)
 	if _, e := writer.Write(v); e != nil {
 		return NewTProtocolException(e)
 	}
-	writer.Close()
-	p.writer.Write(JSON_QUOTE_BYTES)
+	if e := writer.Close(); e != nil {
+		return NewTProtocolException(e)
+	}
+	if _, e := p.writer.Write(JSON_QUOTE_BYTES); e != nil {
+		return NewTProtocolException(e)
+	}
 	return p.OutputPostValue()
 }
 
 // Reading methods.
-
 func (p *TJSONProtocol) ReadMessageBegin() (name string, typeId TMessageType, seqId int32, err error) {
 	if isNull, err := p.ParseListBegin(); isNull || err != nil {
 		return name, typeId, seqId, err
@@ -250,9 +255,6 @@ func (p *TJSONProtocol) ReadStructEnd() error {
 }
 
 func (p *TJSONProtocol) ReadFieldBegin() (string, TType, int16, error) {
-	if p.reader.Buffered() < 1 {
-		return "", STOP, -1, nil
-	}
 	b, _ := p.reader.Peek(1)
 	if len(b) < 1 || b[0] == JSON_RBRACE[0] || b[0] == JSON_RBRACKET[0] {
 		return "", STOP, -1, nil
@@ -328,7 +330,7 @@ func (p *TJSONProtocol) ReadSetEnd() error {
 }
 
 func (p *TJSONProtocol) ReadBool() (bool, error) {
-	value, err := p.ReadI32(); 
+	value, err := p.ReadI32()
 	return (value != 0), err
 }
 
@@ -362,21 +364,26 @@ func (p *TJSONProtocol) ReadString() (string, error) {
 	if err := p.ParsePreValue(); err != nil {
 		return v, err
 	}
-	b, _ := p.reader.Peek(len(JSON_NULL))
-	if len(b) > 0 && b[0] == JSON_QUOTE {
+	f, _ := p.reader.Peek(1)
+	if len(f) > 0 && f[0] == JSON_QUOTE {
 		p.reader.ReadByte()
 		value, err := p.ParseStringBody()
 		v = value
 		if err != nil {
 			return v, err
 		}
-	} else if len(b) >= len(JSON_NULL) && string(b[0:len(JSON_NULL)]) == string(JSON_NULL) {
-		_, err := p.reader.Read(b[0:len(JSON_NULL)])
+	} else if len(f) >= 0 && f[0] == JSON_NULL[0] {
+		b := make([]byte, len(JSON_NULL))
+		_, err := p.reader.Read(b)
 		if err != nil {
 			return v, NewTProtocolException(err)
 		}
+		if string(b) != string(JSON_NULL) {
+			e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(b))
+			return v, NewTProtocolExceptionWithType(INVALID_DATA, e)
+		}
 	} else {
-		e := fmt.Errorf("Expected a JSON string, found %s", string(b))
+		e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(f))
 		return v, NewTProtocolExceptionWithType(INVALID_DATA, e)
 	}
 	return v, p.ParsePostValue()
@@ -387,23 +394,29 @@ func (p *TJSONProtocol) ReadBinary() ([]byte, error) {
 	if err := p.ParsePreValue(); err != nil {
 		return nil, err
 	}
-	b, _ := p.reader.Peek(len(JSON_NULL))
-	if len(b) > 0 && b[0] == JSON_QUOTE {
+	f, _ := p.reader.Peek(1)
+	if len(f) > 0 && f[0] == JSON_QUOTE {
 		p.reader.ReadByte()
 		value, err := p.ParseBase64EncodedBody()
 		v = value
 		if err != nil {
 			return v, err
 		}
-	} else if len(b) >= len(JSON_NULL) && string(b[0:len(JSON_NULL)]) == string(JSON_NULL) {
-		_, err := p.reader.Read(b[0:len(JSON_NULL)])
+	} else if len(f) >= 0 && f[0] == JSON_NULL[0] {
+		b := make([]byte, len(JSON_NULL))
+		_, err := p.reader.Read(b)
 		if err != nil {
 			return v, NewTProtocolException(err)
 		}
+		if string(b) != string(JSON_NULL) {
+			e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(b))
+			return v, NewTProtocolExceptionWithType(INVALID_DATA, e)
+		}
 	} else {
-		e := fmt.Errorf("Expected a JSON string, found %s", string(b))
+		e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(f))
 		return v, NewTProtocolExceptionWithType(INVALID_DATA, e)
 	}
+
 	return v, p.ParsePostValue()
 }
 

http://git-wip-us.apache.org/repos/asf/thrift/blob/2f971e8f/lib/go/thrift/simple_json_protocol.go
----------------------------------------------------------------------
diff --git a/lib/go/thrift/simple_json_protocol.go b/lib/go/thrift/simple_json_protocol.go
index 71598ac..ab4e983 100644
--- a/lib/go/thrift/simple_json_protocol.go
+++ b/lib/go/thrift/simple_json_protocol.go
@@ -69,7 +69,7 @@ type TSimpleJSONProtocol struct {
 	trans TTransport
 
 	parseContextStack []int
-	dumpContext []int
+	dumpContext       []int
 
 	writer *bufio.Writer
 	reader *bufio.Reader
@@ -286,7 +286,6 @@ func (p *TSimpleJSONProtocol) WriteBinary(v []byte) error {
 }
 
 // Reading methods.
-
 func (p *TSimpleJSONProtocol) ReadMessageBegin() (name string, typeId TMessageType, seqId int32, err error) {
 	if isNull, err := p.ParseListBegin(); isNull || err != nil {
 		return name, typeId, seqId, err
@@ -330,9 +329,9 @@ func (p *TSimpleJSONProtocol) ReadFieldBegin() (string, TType, int16, error) {
 		case JSON_QUOTE:
 			p.reader.ReadByte()
 			name, err := p.ParseStringBody()
-            // simplejson is not meant to be read back into thrift 
-            // - see http://wiki.apache.org/thrift/ThriftUsageJava
-            // - use JSON instead
+			// simplejson is not meant to be read back into thrift
+			// - see http://wiki.apache.org/thrift/ThriftUsageJava
+			// - use JSON instead
 			if err != nil {
 				return name, STOP, 0, err
 			}
@@ -411,15 +410,20 @@ func (p *TSimpleJSONProtocol) ReadSetEnd() error {
 
 func (p *TSimpleJSONProtocol) ReadBool() (bool, error) {
 	var value bool
+
 	if err := p.ParsePreValue(); err != nil {
 		return value, err
 	}
-	b, _ := p.reader.Peek(len(JSON_TRUE))
-	if len(b) > 0 {
-		switch b[0] {
+	f, _ := p.reader.Peek(1)
+	if len(f) > 0 {
+		switch f[0] {
 		case JSON_TRUE[0]:
+			b := make([]byte, len(JSON_TRUE))
+			_, err := p.reader.Read(b)
+			if err != nil {
+				return false, NewTProtocolException(err)
+			}
 			if string(b) == string(JSON_TRUE) {
-				p.reader.Read(b[0:len(JSON_TRUE)])
 				value = true
 			} else {
 				e := fmt.Errorf("Expected \"true\" but found: %s", string(b))
@@ -427,8 +431,12 @@ func (p *TSimpleJSONProtocol) ReadBool() (bool, error) {
 			}
 			break
 		case JSON_FALSE[0]:
-			if string(b) == string(JSON_FALSE[:len(b)]) {
-				p.reader.Read(b[0:len(JSON_FALSE)])
+			b := make([]byte, len(JSON_FALSE))
+			_, err := p.reader.Read(b)
+			if err != nil {
+				return false, NewTProtocolException(err)
+			}
+			if string(b) == string(JSON_FALSE) {
 				value = false
 			} else {
 				e := fmt.Errorf("Expected \"false\" but found: %s", string(b))
@@ -436,15 +444,19 @@ func (p *TSimpleJSONProtocol) ReadBool() (bool, error) {
 			}
 			break
 		case JSON_NULL[0]:
+			b := make([]byte, len(JSON_NULL))
+			_, err := p.reader.Read(b)
+			if err != nil {
+				return false, NewTProtocolException(err)
+			}
 			if string(b) == string(JSON_NULL) {
-				p.reader.Read(b[0:len(JSON_NULL)])
 				value = false
 			} else {
 				e := fmt.Errorf("Expected \"null\" but found: %s", string(b))
 				return value, NewTProtocolExceptionWithType(INVALID_DATA, e)
 			}
 		default:
-			e := fmt.Errorf("Expected \"true\", \"false\", or \"null\" but found: %s", string(b))
+			e := fmt.Errorf("Expected \"true\", \"false\", or \"null\" but found: %s", string(f))
 			return value, NewTProtocolExceptionWithType(INVALID_DATA, e)
 		}
 	}
@@ -481,22 +493,26 @@ func (p *TSimpleJSONProtocol) ReadString() (string, error) {
 	if err := p.ParsePreValue(); err != nil {
 		return v, err
 	}
-	var b []byte
-	b, _ = p.reader.Peek(len(JSON_NULL))
-	if len(b) > 0 && b[0] == JSON_QUOTE {
+	f, _ := p.reader.Peek(1)
+	if len(f) > 0 && f[0] == JSON_QUOTE {
 		p.reader.ReadByte()
 		value, err := p.ParseStringBody()
 		v = value
 		if err != nil {
 			return v, err
 		}
-	} else if len(b) >= len(JSON_NULL) && string(b[0:len(JSON_NULL)]) == string(JSON_NULL) {
-		_, err := p.reader.Read(b[0:len(JSON_NULL)])
+	} else if len(f) >= 0 && f[0] == JSON_NULL[0] {
+		b := make([]byte, len(JSON_NULL))
+		_, err := p.reader.Read(b)
 		if err != nil {
 			return v, NewTProtocolException(err)
 		}
+		if string(b) != string(JSON_NULL) {
+			e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(b))
+			return v, NewTProtocolExceptionWithType(INVALID_DATA, e)
+		}
 	} else {
-		e := fmt.Errorf("Expected a JSON string, found %s", string(b))
+		e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(f))
 		return v, NewTProtocolExceptionWithType(INVALID_DATA, e)
 	}
 	return v, p.ParsePostValue()
@@ -507,23 +523,29 @@ func (p *TSimpleJSONProtocol) ReadBinary() ([]byte, error) {
 	if err := p.ParsePreValue(); err != nil {
 		return nil, err
 	}
-	b, _ := p.reader.Peek(len(JSON_NULL))
-	if len(b) > 0 && b[0] == JSON_QUOTE {
+	f, _ := p.reader.Peek(1)
+	if len(f) > 0 && f[0] == JSON_QUOTE {
 		p.reader.ReadByte()
 		value, err := p.ParseBase64EncodedBody()
 		v = value
 		if err != nil {
 			return v, err
 		}
-	} else if len(b) >= len(JSON_NULL) && string(b[0:len(JSON_NULL)]) == string(JSON_NULL) {
-		_, err := p.reader.Read(b[0:len(JSON_NULL)])
+	} else if len(f) >= 0 && f[0] == JSON_NULL[0] {
+		b := make([]byte, len(JSON_NULL))
+		_, err := p.reader.Read(b)
 		if err != nil {
 			return v, NewTProtocolException(err)
 		}
+		if string(b) != string(JSON_NULL) {
+			e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(b))
+			return v, NewTProtocolExceptionWithType(INVALID_DATA, e)
+		}
 	} else {
-		e := fmt.Errorf("Expected a JSON string, found %s", string(b))
+		e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(f))
 		return v, NewTProtocolExceptionWithType(INVALID_DATA, e)
 	}
+
 	return v, p.ParsePostValue()
 }
 
@@ -898,9 +920,8 @@ func (p *TSimpleJSONProtocol) ParseI64() (int64, bool, error) {
 	}
 	var value int64
 	var isnull bool
-	b, _ := p.reader.Peek(len(JSON_NULL))
-	if len(b) >= len(JSON_NULL) && string(b) == string(JSON_NULL) {
-		p.reader.Read(b[0:len(JSON_NULL)])
+	if p.safePeekContains(JSON_NULL) {
+		p.reader.Read(make([]byte, len(JSON_NULL)))
 		isnull = true
 	} else {
 		num, err := p.readNumeric()
@@ -921,9 +942,8 @@ func (p *TSimpleJSONProtocol) ParseF64() (float64, bool, error) {
 	}
 	var value float64
 	var isnull bool
-	b, _ := p.reader.Peek(len(JSON_NULL))
-	if len(b) >= len(JSON_NULL) && string(b) == string(JSON_NULL) {
-		p.reader.Read(b[0:len(JSON_NULL)])
+	if p.safePeekContains(JSON_NULL) {
+		p.reader.Read(make([]byte, len(JSON_NULL)))
 		isnull = true
 	} else {
 		num, err := p.readNumeric()
@@ -943,12 +963,15 @@ func (p *TSimpleJSONProtocol) ParseObjectStart() (bool, error) {
 		return false, err
 	}
 	var b []byte
-	b, _ = p.reader.Peek(len(JSON_NULL))
+	b, err := p.reader.Peek(1)
+	if err != nil {
+		return false, err
+	}
 	if len(b) > 0 && b[0] == JSON_LBRACE[0] {
 		p.reader.ReadByte()
 		p.parseContextStack = append(p.parseContextStack, int(_CONTEXT_IN_OBJECT_FIRST))
 		return false, nil
-	} else if len(b) >= len(JSON_NULL) && string(b[0:len(JSON_NULL)]) == string(JSON_NULL) {
+	} else if p.safePeekContains(JSON_NULL) {
 		return true, nil
 	}
 	e := fmt.Errorf("Expected '{' or null, but found '%s'", string(b))
@@ -986,7 +1009,7 @@ func (p *TSimpleJSONProtocol) ParseListBegin() (isNull bool, err error) {
 		return false, e
 	}
 	var b []byte
-	b, err = p.reader.Peek(len(JSON_NULL))
+	b, err = p.reader.Peek(1)
 	if err != nil {
 		return false, err
 	}
@@ -994,7 +1017,7 @@ func (p *TSimpleJSONProtocol) ParseListBegin() (isNull bool, err error) {
 		p.parseContextStack = append(p.parseContextStack, int(_CONTEXT_IN_LIST_FIRST))
 		p.reader.ReadByte()
 		isNull = false
-	} else if len(b) >= len(JSON_NULL) && string(b) == string(JSON_NULL) {
+	} else if p.safePeekContains(JSON_NULL) {
 		isNull = true
 	} else {
 		err = fmt.Errorf("Expected \"null\" or \"[\", received %q", b)
@@ -1038,6 +1061,9 @@ func (p *TSimpleJSONProtocol) ParseListEnd() error {
 		}
 	}
 	p.parseContextStack = p.parseContextStack[:len(p.parseContextStack)-1]
+	if _ParseContext(p.parseContextStack[len(p.parseContextStack)-1]) == _CONTEXT_IN_TOPLEVEL {
+		return nil
+	}
 	return p.ParsePostValue()
 }
 
@@ -1046,7 +1072,7 @@ func (p *TSimpleJSONProtocol) readSingleValue() (interface{}, TType, error) {
 	if e != nil {
 		return nil, VOID, NewTProtocolException(e)
 	}
-	b, e := p.reader.Peek(10)
+	b, e := p.reader.Peek(1)
 	if len(b) > 0 {
 		c := b[0]
 		switch c {
@@ -1135,9 +1161,8 @@ func (p *TSimpleJSONProtocol) readIfNull() (bool, error) {
 			break
 		}
 	}
-	b, _ := p.reader.Peek(len(JSON_NULL))
-	if string(b) == string(JSON_NULL) {
-		p.reader.Read(b[0:len(JSON_NULL)])
+	if p.safePeekContains(JSON_NULL) {
+		p.reader.Read(make([]byte, len(JSON_NULL)))
 		return true, nil
 	}
 	return false, nil
@@ -1275,3 +1300,14 @@ func (p *TSimpleJSONProtocol) readNumeric() (Numeric, error) {
 	}
 	return NewNumericFromJSONString(buf.String(), false), nil
 }
+
+// Safely peeks into the buffer, reading only what is necessary
+func (p *TSimpleJSONProtocol) safePeekContains(b []byte) bool {
+	for i := 0; i < len(b); i++ {
+		a, _ := p.reader.Peek(i + 1)
+		if len(a) == 0 || a[i] != b[i] {
+			return false
+		}
+	}
+	return true
+}

http://git-wip-us.apache.org/repos/asf/thrift/blob/2f971e8f/lib/go/thrift/simple_json_protocol_test.go
----------------------------------------------------------------------
diff --git a/lib/go/thrift/simple_json_protocol_test.go b/lib/go/thrift/simple_json_protocol_test.go
index 87a5c64..1abff75 100644
--- a/lib/go/thrift/simple_json_protocol_test.go
+++ b/lib/go/thrift/simple_json_protocol_test.go
@@ -221,6 +221,27 @@ func TestReadSimpleJSONProtocolI32(t *testing.T) {
 	}
 }
 
+func TestReadSimpleJSONProtocolI32Null(t *testing.T) {
+	thetype := "int32"
+	value := "null"
+
+	trans := NewTMemoryBuffer()
+	p := NewTSimpleJSONProtocol(trans)
+	trans.WriteString(value)
+	trans.Flush()
+	s := trans.String()
+	v, e := p.ReadI32()
+
+	if e != nil {
+		t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error())
+	}
+	if v != 0 {
+		t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v)
+	}
+	trans.Reset()
+	trans.Close()
+}
+
 func TestWriteSimpleJSONProtocolI64(t *testing.T) {
 	thetype := "int64"
 	trans := NewTMemoryBuffer()
@@ -268,6 +289,27 @@ func TestReadSimpleJSONProtocolI64(t *testing.T) {
 	}
 }
 
+func TestReadSimpleJSONProtocolI64Null(t *testing.T) {
+	thetype := "int32"
+	value := "null"
+
+	trans := NewTMemoryBuffer()
+	p := NewTSimpleJSONProtocol(trans)
+	trans.WriteString(value)
+	trans.Flush()
+	s := trans.String()
+	v, e := p.ReadI64()
+
+	if e != nil {
+		t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error())
+	}
+	if v != 0 {
+		t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v)
+	}
+	trans.Reset()
+	trans.Close()
+}
+
 func TestWriteSimpleJSONProtocolDouble(t *testing.T) {
 	thetype := "double"
 	trans := NewTMemoryBuffer()
@@ -391,6 +433,25 @@ func TestReadSimpleJSONProtocolString(t *testing.T) {
 		trans.Close()
 	}
 }
+func TestReadSimpleJSONProtocolStringNull(t *testing.T) {
+	thetype := "string"
+	value := "null"
+
+	trans := NewTMemoryBuffer()
+	p := NewTSimpleJSONProtocol(trans)
+	trans.WriteString(value)
+	trans.Flush()
+	s := trans.String()
+	v, e := p.ReadString()
+	if e != nil {
+		t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error())
+	}
+	if v != "" {
+		t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v)
+	}
+	trans.Reset()
+	trans.Close()
+}
 
 func TestWriteSimpleJSONProtocolBinary(t *testing.T) {
 	thetype := "binary"
@@ -448,6 +509,28 @@ func TestReadSimpleJSONProtocolBinary(t *testing.T) {
 	trans.Close()
 }
 
+func TestReadSimpleJSONProtocolBinaryNull(t *testing.T) {
+	thetype := "binary"
+	value := "null"
+
+	trans := NewTMemoryBuffer()
+	p := NewTSimpleJSONProtocol(trans)
+	trans.WriteString(value)
+	trans.Flush()
+	s := trans.String()
+	b, e := p.ReadBinary()
+	v := string(b)
+
+	if e != nil {
+		t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error())
+	}
+	if v != "" {
+		t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v)
+	}
+	trans.Reset()
+	trans.Close()
+}
+
 func TestWriteSimpleJSONProtocolList(t *testing.T) {
 	thetype := "list"
 	trans := NewTMemoryBuffer()


[2/3] thrift git commit: THRIFT-2839 TFramedTransport read bug Client: Go Patch: Chi Vinh Le

Posted by je...@apache.org.
THRIFT-2839 TFramedTransport read bug
Client: Go
Patch: Chi Vinh Le <cv...@chinet.info>


Project: http://git-wip-us.apache.org/repos/asf/thrift/repo
Commit: http://git-wip-us.apache.org/repos/asf/thrift/commit/0dd4801c
Tree: http://git-wip-us.apache.org/repos/asf/thrift/tree/0dd4801c
Diff: http://git-wip-us.apache.org/repos/asf/thrift/diff/0dd4801c

Branch: refs/heads/master
Commit: 0dd4801ce5cd45ca076b1c716fa6f94f418731a2
Parents: 2f971e8
Author: Jens Geyer <je...@apache.org>
Authored: Tue Nov 18 21:55:30 2014 +0100
Committer: Jens Geyer <je...@apache.org>
Committed: Tue Nov 18 22:18:13 2014 +0100

----------------------------------------------------------------------
 lib/go/thrift/framed_transport.go | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/thrift/blob/0dd4801c/lib/go/thrift/framed_transport.go
----------------------------------------------------------------------
diff --git a/lib/go/thrift/framed_transport.go b/lib/go/thrift/framed_transport.go
index bfecbe8..21c636d 100644
--- a/lib/go/thrift/framed_transport.go
+++ b/lib/go/thrift/framed_transport.go
@@ -79,7 +79,14 @@ func (p *TFramedTransport) Read(buf []byte) (l int, err error) {
 		}
 	}
 	if p.frameSize < len(buf) {
-		return 0, NewTTransportExceptionFromError(fmt.Errorf("Not enought frame size %d to read %d bytes", p.frameSize, len(buf)))
+		frameSize := p.frameSize
+		tmp := make([]byte, p.frameSize)
+		l, err = p.Read(tmp)
+		copy(buf, tmp)
+		if err == nil {
+			err = NewTTransportExceptionFromError(fmt.Errorf("Not enough frame size %d to read %d bytes", frameSize, len(buf)))
+			return
+		}
 	}
 	got, err := p.reader.Read(buf)
 	p.frameSize = p.frameSize - got
@@ -98,7 +105,7 @@ func (p *TFramedTransport) ReadByte() (c byte, err error) {
 		}
 	}
 	if p.frameSize < 1 {
-		return 0, NewTTransportExceptionFromError(fmt.Errorf("Not enought frame size %d to read %d bytes", p.frameSize, 1))
+		return 0, NewTTransportExceptionFromError(fmt.Errorf("Not enough frame size %d to read %d bytes", p.frameSize, 1))
 	}
 	c, err = p.reader.ReadByte()
 	if err == nil {


[3/3] thrift git commit: THRIFT-2841 Add comprehensive integration tests for the whole Go stack Client: Go Patch: Chi Vinh Le

Posted by je...@apache.org.
THRIFT-2841 Add comprehensive integration tests for the whole Go stack
Client: Go
Patch: Chi Vinh Le <cv...@chinet.info>

This closes #273


Project: http://git-wip-us.apache.org/repos/asf/thrift/repo
Commit: http://git-wip-us.apache.org/repos/asf/thrift/commit/5f9bdffd
Tree: http://git-wip-us.apache.org/repos/asf/thrift/tree/5f9bdffd
Diff: http://git-wip-us.apache.org/repos/asf/thrift/diff/5f9bdffd

Branch: refs/heads/master
Commit: 5f9bdffd2aefb3e1d1b0cc717f0e7dc5a2a16ad7
Parents: 0dd4801
Author: Jens Geyer <je...@apache.org>
Authored: Tue Nov 18 21:57:03 2014 +0100
Committer: Jens Geyer <je...@apache.org>
Committed: Tue Nov 18 22:18:15 2014 +0100

----------------------------------------------------------------------
 lib/go/test/tests/protocols_test.go     |  94 +++++++++++
 lib/go/test/tests/thrifttest_driver.go  | 234 +++++++++++++++++++++++++++
 lib/go/test/tests/thrifttest_handler.go | 201 +++++++++++++++++++++++
 3 files changed, 529 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/thrift/blob/5f9bdffd/lib/go/test/tests/protocols_test.go
----------------------------------------------------------------------
diff --git a/lib/go/test/tests/protocols_test.go b/lib/go/test/tests/protocols_test.go
new file mode 100644
index 0000000..422b5c8
--- /dev/null
+++ b/lib/go/test/tests/protocols_test.go
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package tests
+
+import (
+	"testing"
+	"thrift"
+	"thrifttest"
+)
+
+func RunSocketTestSuite(t *testing.T, protocolFactory thrift.TProtocolFactory,
+	transportFactory thrift.TTransportFactory) {
+	// server
+	var err error
+	addr = FindAvailableTCPServerPort()
+	serverTransport, err := thrift.NewTServerSocketTimeout(addr.String(), TIMEOUT)
+	if err != nil {
+		t.Fatal("Unable to create server socket", err)
+	}
+	processor := thrifttest.NewThriftTestProcessor(NewThriftTestHandler())
+	server = thrift.NewTSimpleServer4(processor, serverTransport, transportFactory, protocolFactory)
+	server.Listen()
+
+	go server.Serve()
+
+	// client
+	var transport thrift.TTransport = thrift.NewTSocketFromAddrTimeout(addr, TIMEOUT)
+	transport = transportFactory.GetTransport(transport)
+	var protocol thrift.TProtocol = protocolFactory.GetProtocol(transport)
+	thriftTestClient := thrifttest.NewThriftTestClientProtocol(transport, protocol, protocol)
+	err = transport.Open()
+	if err != nil {
+		t.Fatal("Unable to open client socket", err)
+	}
+
+	driver := NewThriftTestDriver(t, thriftTestClient)
+	driver.Start()
+}
+
+// Run test suite using TJSONProtocol
+func TestTJSONProtocol(t *testing.T) {
+	RunSocketTestSuite(t,
+		thrift.NewTJSONProtocolFactory(),
+		thrift.NewTTransportFactory())
+	RunSocketTestSuite(t,
+		thrift.NewTJSONProtocolFactory(),
+		thrift.NewTBufferedTransportFactory(8912))
+	RunSocketTestSuite(t,
+		thrift.NewTJSONProtocolFactory(),
+		thrift.NewTFramedTransportFactory(thrift.NewTTransportFactory()))
+}
+
+// Run test suite using TBinaryProtocol
+func TestTBinaryProtocol(t *testing.T) {
+	RunSocketTestSuite(t,
+		thrift.NewTBinaryProtocolFactoryDefault(),
+		thrift.NewTTransportFactory())
+	RunSocketTestSuite(t,
+		thrift.NewTBinaryProtocolFactoryDefault(),
+		thrift.NewTBufferedTransportFactory(8912))
+	RunSocketTestSuite(t,
+		thrift.NewTBinaryProtocolFactoryDefault(),
+		thrift.NewTFramedTransportFactory(thrift.NewTTransportFactory()))
+}
+
+// Run test suite using TCompactBinaryProtocol
+func TestTCompactProtocol(t *testing.T) {
+	RunSocketTestSuite(t,
+		thrift.NewTCompactProtocolFactory(),
+		thrift.NewTTransportFactory())
+	RunSocketTestSuite(t,
+		thrift.NewTCompactProtocolFactory(),
+		thrift.NewTBufferedTransportFactory(8912))
+	RunSocketTestSuite(t,
+		thrift.NewTCompactProtocolFactory(),
+		thrift.NewTFramedTransportFactory(thrift.NewTTransportFactory()))
+}

http://git-wip-us.apache.org/repos/asf/thrift/blob/5f9bdffd/lib/go/test/tests/thrifttest_driver.go
----------------------------------------------------------------------
diff --git a/lib/go/test/tests/thrifttest_driver.go b/lib/go/test/tests/thrifttest_driver.go
new file mode 100644
index 0000000..b6188e4
--- /dev/null
+++ b/lib/go/test/tests/thrifttest_driver.go
@@ -0,0 +1,234 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * 'License'); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package tests
+
+import (
+	"reflect"
+	"testing"
+	"thrifttest"
+)
+
+type ThriftTestDriver struct {
+	client thrifttest.ThriftTest
+	t      *testing.T
+}
+
+func NewThriftTestDriver(t *testing.T, client thrifttest.ThriftTest) *ThriftTestDriver {
+	return &ThriftTestDriver{client, t}
+}
+
+func (p *ThriftTestDriver) Start() {
+	client := p.client
+	t := p.t
+
+	if client.TestVoid() != nil {
+		t.Fatal("TestVoid failed")
+	}
+
+	if r, err := client.TestString("Test"); r != "Test" || err != nil {
+		t.Fatal("TestString with simple text failed")
+	}
+
+	if r, err := client.TestString(""); r != "" || err != nil {
+		t.Fatal("TestString with empty text failed")
+	}
+
+	stringTest := "Afrikaans, Alemannisch, Aragonés, العربية, مصرى, " +
+		"Asturianu, Aymar aru, Azərbaycan, Башҡорт, Boarisch, Žemaitėška, " +
+		"Беларуская, Беларуская (тарашкевіца), Български, Bamanankan, " +
+		"বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Нохчийн, " +
+		"Cebuano, ᏣᎳᎩ, Česky, Словѣ́ньскъ / ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ, Чӑвашла, Cymraeg, " +
+		"Dansk, Zazaki, ދިވެހިބަސް, Ελληνικά, Emiliàn e rumagnòl, English, " +
+		"Esperanto, Español, Eesti, Euskara, فارسی, Suomi, Võro, Føroyskt, " +
+		"Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, " +
+		"Avañe'ẽ, ગુજરાતી, Gaelg, עברית, हिन्दी, Fiji Hindi, Hrvatski, " +
+		"Kreyòl ayisyen, Magyar, Հայերեն, Interlingua, Bahasa Indonesia, " +
+		"Ilokano, Ido, Íslenska, Italiano, 日本語, Lojban, Basa Jawa, " +
+		"ქართული, Kongo, Kalaallisut, ಕನ್ನಡ, 한국어, Къарачай-Малкъар, " +
+		"Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, " +
+		"Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, Latviešu, Basa " +
+		"Banyumasan, Malagasy, Македонски, മലയാളം, मराठी, مازِرونی, Bahasa " +
+		"Melayu, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪" +
+		"Norsk (nynorsk)‬, ‪Norsk (bokmål)‬, Nouormand, Diné bizaad, " +
+		"Occitan, Иронау, Papiamentu, Deitsch, Polski, پنجابی, پښتو, " +
+		"Norfuk / Pitkern, Português, Runa Simi, Rumantsch, Romani, Română, " +
+		"Русский, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple " +
+		"English, Slovenčina, Slovenščina, Српски / Srpski, Seeltersk, " +
+		"Svenska, Kiswahili, தமிழ், తెలుగు, Тоҷикӣ, ไทย, Türkmençe, Tagalog, " +
+		"Türkçe, Татарча/Tatarça, Українська, اردو, Tiếng Việt, Volapük, " +
+		"Walon, Winaray, 吴语, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, " +
+		"Bân-lâm-gú, 粵語"
+
+	if r, err := client.TestString(stringTest); r != stringTest || err != nil {
+		t.Fatal("TestString with all languages failed")
+	}
+
+	specialCharacters := "quote: \" backslash:" +
+		" backspace: \b formfeed: \f newline: \n return: \r tab: " +
+		" now-all-of-them-together: '\\\b\n\r\t'" +
+		" now-a-bunch-of-junk: !@#$%&()(&%$#{}{}<><><" +
+		" char-to-test-json-parsing: ]] \"]] \\\" }}}{ [[[ "
+
+	if r, err := client.TestString(specialCharacters); r != specialCharacters || err != nil {
+		t.Fatal("TestString with specialCharacters failed")
+	}
+
+	if r, err := client.TestByte(1); r != 1 || err != nil {
+		t.Fatal("TestByte(1) failed")
+	}
+	if r, err := client.TestByte(0); r != 0 || err != nil {
+		t.Fatal("TestByte(0) failed")
+	}
+	if r, err := client.TestByte(-1); r != -1 || err != nil {
+		t.Fatal("TestByte(-1) failed")
+	}
+	if r, err := client.TestByte(-127); r != -127 || err != nil {
+		t.Fatal("TestByte(-127) failed")
+	}
+
+	if r, err := client.TestI32(-1); r != -1 || err != nil {
+		t.Fatal("TestI32(-1) failed")
+	}
+	if r, err := client.TestI32(1); r != 1 || err != nil {
+		t.Fatal("TestI32(1) failed")
+	}
+
+	if r, err := client.TestI64(-5); r != -5 || err != nil {
+		t.Fatal("TestI64(-5) failed")
+	}
+	if r, err := client.TestI64(5); r != 5 || err != nil {
+		t.Fatal("TestI64(5) failed")
+	}
+	if r, err := client.TestI64(-34359738368); r != -34359738368 || err != nil {
+		t.Fatal("TestI64(-34359738368) failed")
+	}
+
+	if r, err := client.TestDouble(-5.2098523); r != -5.2098523 || err != nil {
+		t.Fatal("TestDouble(-5.2098523) failed")
+	}
+	if r, err := client.TestDouble(-7.012052175215044); r != -7.012052175215044 || err != nil {
+		t.Fatal("TestDouble(-7.012052175215044) failed")
+	}
+
+	out := thrifttest.NewXtruct()
+	out.StringThing = "Zero"
+	out.ByteThing = 1
+	out.I32Thing = -3
+	out.I64Thing = 1000000
+	if r, err := client.TestStruct(out); !reflect.DeepEqual(r, out) || err != nil {
+		t.Fatal("TestStruct failed")
+	}
+
+	out2 := thrifttest.NewXtruct2()
+	out2.ByteThing = 1
+	out2.StructThing = out
+	out2.I32Thing = 5
+	if r, err := client.TestNest(out2); !reflect.DeepEqual(r, out2) || err != nil {
+		t.Fatal("TestNest failed")
+	}
+
+	mapout := make(map[int32]int32)
+	for i := int32(0); i < 5; i++ {
+		mapout[i] = i - 10
+	}
+	if r, err := client.TestMap(mapout); !reflect.DeepEqual(r, mapout) || err != nil {
+		t.Fatal("TestMap failed")
+	}
+
+	mapTestInput := map[string]string{
+		"a": "123", "a b": "with spaces ", "same": "same", "0": "numeric key",
+		"longValue": stringTest, stringTest: "long key",
+	}
+	if r, err := client.TestStringMap(mapTestInput); !reflect.DeepEqual(r, mapTestInput) || err != nil {
+		t.Fatal("TestStringMap failed")
+	}
+
+	setTestInput := map[int32]bool{1: true, 2: true, 3: true}
+	if r, err := client.TestSet(setTestInput); !reflect.DeepEqual(r, setTestInput) || err != nil {
+		t.Fatal("TestSet failed")
+	}
+
+	listTest := []int32{1, 2, 3}
+	if r, err := client.TestList(listTest); !reflect.DeepEqual(r, listTest) || err != nil {
+		t.Fatal("TestList failed")
+	}
+
+	if r, err := client.TestEnum(thrifttest.Numberz_ONE); r != thrifttest.Numberz_ONE || err != nil {
+		t.Fatal("TestEnum failed")
+	}
+
+	if r, err := client.TestTypedef(69); r != 69 || err != nil {
+		t.Fatal("TestTypedef failed")
+	}
+
+	mapMapTest := map[int32]map[int32]int32{
+		4:  {1: 1, 2: 2, 3: 3, 4: 4},
+		-4: {-4: -4, -3: -3, -2: -2, -1: -1},
+	}
+	if r, err := client.TestMapMap(1); !reflect.DeepEqual(r, mapMapTest) || err != nil {
+		t.Fatal("TestMapMap failed")
+	}
+
+	crazyX1 := thrifttest.NewXtruct()
+	crazyX1.StringThing = "Goodbye4"
+	crazyX1.ByteThing = 4
+	crazyX1.I32Thing = 4
+	crazyX1.I64Thing = 4
+
+	crazyX2 := thrifttest.NewXtruct()
+	crazyX2.StringThing = "Hello2"
+	crazyX2.ByteThing = 2
+	crazyX2.I32Thing = 2
+	crazyX2.I64Thing = 2
+
+	crazy := thrifttest.NewInsanity()
+	crazy.UserMap = map[thrifttest.Numberz]thrifttest.UserId{5: 5, 8: 8}
+	crazy.Xtructs = []*thrifttest.Xtruct{crazyX1, crazyX2}
+
+	crazyEmpty := thrifttest.NewInsanity()
+	crazyEmpty.UserMap = map[thrifttest.Numberz]thrifttest.UserId{}
+	crazyEmpty.Xtructs = []*thrifttest.Xtruct{}
+
+	insanity := map[thrifttest.UserId]map[thrifttest.Numberz]*thrifttest.Insanity{
+		1: {thrifttest.Numberz_TWO: crazy, thrifttest.Numberz_THREE: crazy},
+		2: {thrifttest.Numberz_SIX: crazyEmpty},
+	}
+	if r, err := client.TestInsanity(crazy); !reflect.DeepEqual(r, insanity) || err != nil {
+		t.Fatal("TestInsanity failed")
+	}
+
+	if err := client.TestException("TException"); err == nil {
+		t.Fatal("TestException TException failed")
+	}
+
+	if err, ok := client.TestException("Xception").(*thrifttest.Xception); ok == false || err == nil {
+		t.Fatal("TestException Xception failed")
+	} else if err.ErrorCode != 1001 || err.Message != "Xception" {
+		t.Fatal("TestException Xception failed")
+	}
+
+	if err := client.TestException("no Exception"); err != nil {
+		t.Fatal("TestException no Exception failed")
+	}
+
+	if err := client.TestOneway(0); err != nil {
+		t.Fatal("TestOneway failed")
+	}
+}

http://git-wip-us.apache.org/repos/asf/thrift/blob/5f9bdffd/lib/go/test/tests/thrifttest_handler.go
----------------------------------------------------------------------
diff --git a/lib/go/test/tests/thrifttest_handler.go b/lib/go/test/tests/thrifttest_handler.go
new file mode 100644
index 0000000..1bbd7de
--- /dev/null
+++ b/lib/go/test/tests/thrifttest_handler.go
@@ -0,0 +1,201 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * 'License'); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package tests
+
+import (
+	"errors"
+	"thrift"
+	"thrifttest"
+	"time"
+)
+
+type SecondServiceHandler struct {
+}
+
+func NewSecondServiceHandler() *SecondServiceHandler {
+	return &SecondServiceHandler{}
+}
+
+func (p *SecondServiceHandler) BlahBlah() (err error) {
+	return nil
+}
+
+func (p *SecondServiceHandler) SecondtestString(thing string) (r string, err error) {
+	return thing, nil
+}
+
+type ThriftTestHandler struct {
+}
+
+func NewThriftTestHandler() *ThriftTestHandler {
+	return &ThriftTestHandler{}
+}
+
+func (p *ThriftTestHandler) TestVoid() (err error) {
+	return nil
+}
+
+func (p *ThriftTestHandler) TestString(thing string) (r string, err error) {
+	return thing, nil
+}
+
+func (p *ThriftTestHandler) TestByte(thing int8) (r int8, err error) {
+	return thing, nil
+}
+
+func (p *ThriftTestHandler) TestI32(thing int32) (r int32, err error) {
+	return thing, nil
+}
+
+func (p *ThriftTestHandler) TestI64(thing int64) (r int64, err error) {
+	return thing, nil
+}
+
+func (p *ThriftTestHandler) TestDouble(thing float64) (r float64, err error) {
+	return thing, nil
+}
+
+func (p *ThriftTestHandler) TestStruct(thing *thrifttest.Xtruct) (r *thrifttest.Xtruct, err error) {
+	return thing, nil
+}
+
+func (p *ThriftTestHandler) TestNest(thing *thrifttest.Xtruct2) (r *thrifttest.Xtruct2, err error) {
+	return thing, nil
+}
+
+func (p *ThriftTestHandler) TestMap(thing map[int32]int32) (r map[int32]int32, err error) {
+	return thing, nil
+}
+
+func (p *ThriftTestHandler) TestStringMap(thing map[string]string) (r map[string]string, err error) {
+	return thing, nil
+}
+
+func (p *ThriftTestHandler) TestSet(thing map[int32]bool) (r map[int32]bool, err error) {
+	return thing, nil
+}
+
+func (p *ThriftTestHandler) TestList(thing []int32) (r []int32, err error) {
+	return thing, nil
+}
+
+func (p *ThriftTestHandler) TestEnum(thing thrifttest.Numberz) (r thrifttest.Numberz, err error) {
+	return thing, nil
+}
+
+func (p *ThriftTestHandler) TestTypedef(thing thrifttest.UserId) (r thrifttest.UserId, err error) {
+	return thing, nil
+}
+
+func (p *ThriftTestHandler) TestMapMap(hello int32) (r map[int32]map[int32]int32, err error) {
+	r = make(map[int32]map[int32]int32)
+	pos := make(map[int32]int32)
+	neg := make(map[int32]int32)
+
+	for i := int32(1); i < 5; i++ {
+		pos[i] = i
+		neg[-i] = -i
+	}
+	r[4] = pos
+	r[-4] = neg
+
+	return r, nil
+}
+
+func (p *ThriftTestHandler) TestInsanity(argument *thrifttest.Insanity) (r map[thrifttest.UserId]map[thrifttest.Numberz]*thrifttest.Insanity, err error) {
+	hello := thrifttest.NewXtruct()
+	hello.StringThing = "Hello2"
+	hello.ByteThing = 2
+	hello.I32Thing = 2
+	hello.I64Thing = 2
+
+	goodbye := thrifttest.NewXtruct()
+	goodbye.StringThing = "Goodbye4"
+	goodbye.ByteThing = 4
+	goodbye.I32Thing = 4
+	goodbye.I64Thing = 4
+
+	crazy := thrifttest.NewInsanity()
+	crazy.UserMap = make(map[thrifttest.Numberz]thrifttest.UserId)
+	crazy.UserMap[thrifttest.Numberz_EIGHT] = 8
+	crazy.UserMap[thrifttest.Numberz_FIVE] = 5
+	crazy.Xtructs = []*thrifttest.Xtruct{goodbye, hello}
+
+	first_map := make(map[thrifttest.Numberz]*thrifttest.Insanity)
+	second_map := make(map[thrifttest.Numberz]*thrifttest.Insanity)
+
+	first_map[thrifttest.Numberz_TWO] = crazy
+	first_map[thrifttest.Numberz_THREE] = crazy
+
+	looney := thrifttest.NewInsanity()
+	second_map[thrifttest.Numberz_SIX] = looney
+
+	var insane = make(map[thrifttest.UserId]map[thrifttest.Numberz]*thrifttest.Insanity)
+	insane[1] = first_map
+	insane[2] = second_map
+
+	return insane, nil
+}
+
+func (p *ThriftTestHandler) TestMulti(arg0 int8, arg1 int32, arg2 int64, arg3 map[int16]string, arg4 thrifttest.Numberz, arg5 thrifttest.UserId) (r *thrifttest.Xtruct, err error) {
+	r = thrifttest.NewXtruct()
+	r.StringThing = "Hello2"
+	r.ByteThing = arg0
+	r.I32Thing = arg1
+	r.I64Thing = arg2
+	return r, nil
+}
+
+func (p *ThriftTestHandler) TestException(arg string) (err error) {
+	if arg == "Xception" {
+		x := thrifttest.NewXception()
+		x.ErrorCode = 1001
+		x.Message = arg
+		return x
+	} else if arg == "TException" {
+		return thrift.TException(errors.New(arg))
+	} else {
+		return nil
+	}
+}
+
+func (p *ThriftTestHandler) TestMultiException(arg0 string, arg1 string) (r *thrifttest.Xtruct, err error) {
+	if arg0 == "Xception" {
+		x := thrifttest.NewXception()
+		x.ErrorCode = 1001
+		x.Message = "This is an Xception"
+		return nil, x
+	} else if arg0 == "Xception2" {
+		x2 := thrifttest.NewXception2()
+		x2.ErrorCode = 2002
+		x2.StructThing = thrifttest.NewXtruct()
+		x2.StructThing.StringThing = "This is an Xception2"
+		return nil, x2
+	}
+
+	res := thrifttest.NewXtruct()
+	res.StringThing = arg1
+	return res, nil
+}
+
+func (p *ThriftTestHandler) TestOneway(secondsToSleep int32) (err error) {
+	time.Sleep(time.Second * time.Duration(secondsToSleep))
+	return nil
+}