THRIFT-2841 Add comprehensive integration tests for the whole Go stack
Client: Go
Patch: Chi Vinh Le <cvl@chinet.info>
This closes #273
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()))
+}
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")
+ }
+}
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
+}