diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
commit | 19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch) | |
tree | 42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/jaegertracing/thrift/test | |
parent | Initial commit. (diff) | |
download | ceph-6d07fdb6bb33b1af39833b850bb6cf8af79fe293.tar.xz ceph-6d07fdb6bb33b1af39833b850bb6cf8af79fe293.zip |
Adding upstream version 16.2.11+ds.upstream/16.2.11+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
286 files changed, 43598 insertions, 0 deletions
diff --git a/src/jaegertracing/thrift/test/AnnotationTest.thrift b/src/jaegertracing/thrift/test/AnnotationTest.thrift new file mode 100644 index 000000000..7e24e1ccb --- /dev/null +++ b/src/jaegertracing/thrift/test/AnnotationTest.thrift @@ -0,0 +1,72 @@ +/* + * 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. + */ + +typedef list<i32> ( cpp.template = "std::list" ) int_linked_list + +struct foo { + 1: i32 bar ( presence = "required" ); + 2: i32 baz ( presence = "manual", cpp.use_pointer = "", ); + 3: i32 qux; + 4: i32 bop; +} ( + cpp.type = "DenseFoo", + python.type = "DenseFoo", + java.final = "", + annotation.without.value, +) + +exception foo_error { + 1: i32 error_code ( foo="bar" ) + 2: string error_msg +} (foo = "bar") + +typedef string ( unicode.encoding = "UTF-16" ) non_latin_string (foo="bar") +typedef list< double ( cpp.fixed_point = "16" ) > tiny_float_list + +enum weekdays { + SUNDAY ( weekend = "yes" ), + MONDAY, + TUESDAY, + WEDNESDAY, + THURSDAY, + FRIDAY, + SATURDAY ( weekend = "yes" ) +} (foo.bar="baz") + +/* Note that annotations on senum values are not supported. */ +senum seasons { + "Spring", + "Summer", + "Fall", + "Winter" +} ( foo = "bar" ) + +struct ostr_default { + 1: i32 bar; +} + +struct ostr_custom { + 1: i32 bar; +} (cpp.customostream) + + +service foo_service { + void foo() ( foo = "bar" ) +} (a.b="c") + diff --git a/src/jaegertracing/thrift/test/BrokenConstants.thrift b/src/jaegertracing/thrift/test/BrokenConstants.thrift new file mode 100644 index 000000000..c5aab4abe --- /dev/null +++ b/src/jaegertracing/thrift/test/BrokenConstants.thrift @@ -0,0 +1,25 @@ +/* + * 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. + */ + +const i64 myint = 68719476736 +const i64 broken = 9876543210987654321 // A little over 2^63 + +enum foo { + bar = 68719476736 +} diff --git a/src/jaegertracing/thrift/test/ConstantsDemo.thrift b/src/jaegertracing/thrift/test/ConstantsDemo.thrift new file mode 100644 index 000000000..a54534d51 --- /dev/null +++ b/src/jaegertracing/thrift/test/ConstantsDemo.thrift @@ -0,0 +1,75 @@ +/* + * 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. + */ + +namespace cpp yozone +namespace erl consts_ + +struct thing { + 1: i32 hello, + 2: i32 goodbye +} + +enum enumconstants { + ONE = 1, + TWO = 2 +} + +// struct thing2 { +// /** standard docstring */ +// 1: enumconstants val = TWO +// } + +typedef i32 myIntType +const myIntType myInt = 3 + +//const map<enumconstants,string> GEN_ENUM_NAMES = {ONE : "HOWDY", TWO: "PARTNER"} + +const i32 hex_const = 0x0001F +const i32 negative_hex_constant = -0x0001F + +const i32 GEN_ME = -3523553 +const double GEn_DUB = 325.532 +const double GEn_DU = 085.2355 +const string GEN_STRING = "asldkjasfd" + +const double e10 = 1e10 // fails with 0.9.3 and earlier +const double e11 = -1e10 + +const map<i32,i32> GEN_MAP = { 35532 : 233, 43523 : 853 } +const list<i32> GEN_LIST = [ 235235, 23598352, 3253523 ] + +const map<i32, map<i32, i32>> GEN_MAPMAP = { 235 : { 532 : 53255, 235:235}} + +const map<string,i32> GEN_MAP2 = { "hello" : 233, "lkj98d" : 853, 'lkjsdf' : 098325 } + +const thing GEN_THING = { 'hello' : 325, 'goodbye' : 325352 } + +const map<i32,thing> GEN_WHAT = { 35 : { 'hello' : 325, 'goodbye' : 325352 } } + +const set<i32> GEN_SET = [ 235, 235, 53235 ] + +exception Blah { + 1: i32 bing } + +exception Gak {} + +service yowza { + void blingity(), + i32 blangity() throws (1: Blah hoot ) +} diff --git a/src/jaegertracing/thrift/test/DebugProtoTest.thrift b/src/jaegertracing/thrift/test/DebugProtoTest.thrift new file mode 100644 index 000000000..de47ea717 --- /dev/null +++ b/src/jaegertracing/thrift/test/DebugProtoTest.thrift @@ -0,0 +1,387 @@ +/* + * 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. + */ + +namespace c_glib TTest +namespace cpp thrift.test.debug +namespace java thrift.test +namespace rb thrift.test + +struct Doubles { + 1: double nan, + 2: double inf, + 3: double neginf, + 4: double repeating, + 5: double big, + 6: double tiny, + 7: double zero, + 8: double negzero, +} + +struct OneOfEach { + 1: bool im_true, + 2: bool im_false, + 3: i8 a_bite = 0x7f, + 4: i16 integer16 = 0x7fff, + 5: i32 integer32, + 6: i64 integer64 = 10000000000, + 7: double double_precision, + 8: string some_characters, + 9: string zomg_unicode, + 10: bool what_who, + 11: binary base64, + 12: list<i8> byte_list = [1, 2, 3], + 13: list<i16> i16_list = [1,2,3], + 14: list<i64> i64_list = [1,2,3] +} + +struct Bonk { + 1: i32 type, + 2: string message, +} + +struct Nesting { + 1: Bonk my_bonk, + 2: OneOfEach my_ooe, +} + +struct HolyMoley { + 1: list<OneOfEach> big, + 2: set<list<string> (python.immutable = "")> contain, + 3: map<string,list<Bonk>> bonks, +} + +struct Backwards { + 2: i32 first_tag2, + 1: i32 second_tag1, +} + +struct Empty { +} ( + python.immutable = "", +) + +struct Wrapper { + 1: Empty foo +} ( + python.immutable = "", +) + +struct RandomStuff { + 1: i32 a, + 2: i32 b, + 3: i32 c, + 4: i32 d, + 5: list<i32> myintlist, + 6: map<i32,Wrapper> maps, + 7: i64 bigint, + 8: double triple, +} + +struct Base64 { + 1: i32 a, + 2: binary b1, + 3: binary b2, + 4: binary b3, + 5: binary b4, + 6: binary b5, + 7: binary b6, +} + +struct CompactProtoTestStruct { + // primitive fields + 1: i8 a_byte; + 2: i16 a_i16; + 3: i32 a_i32; + 4: i64 a_i64; + 5: double a_double; + 6: string a_string; + 7: binary a_binary; + 8: bool true_field; + 9: bool false_field; + 10: Empty empty_struct_field; + + // primitives in lists + 11: list<i8> byte_list; + 12: list<i16> i16_list; + 13: list<i32> i32_list; + 14: list<i64> i64_list; + 15: list<double> double_list; + 16: list<string> string_list; + 17: list<binary> binary_list; + 18: list<bool> boolean_list; + 19: list<Empty> struct_list; + + // primitives in sets + 20: set<i8> byte_set; + 21: set<i16> i16_set; + 22: set<i32> i32_set; + 23: set<i64> i64_set; + 24: set<double> double_set; + 25: set<string> string_set; + 26: set<binary> binary_set; + 27: set<bool> boolean_set; + 28: set<Empty> struct_set; + + // maps + // primitives as keys + 29: map<i8, i8> byte_byte_map; + 30: map<i16, i8> i16_byte_map; + 31: map<i32, i8> i32_byte_map; + 32: map<i64, i8> i64_byte_map; + 33: map<double, i8> double_byte_map; + 34: map<string, i8> string_byte_map; + 35: map<binary, i8> binary_byte_map; + 36: map<bool, i8> boolean_byte_map; + // primitives as values + 37: map<i8, i16> byte_i16_map; + 38: map<i8, i32> byte_i32_map; + 39: map<i8, i64> byte_i64_map; + 40: map<i8, double> byte_double_map; + 41: map<i8, string> byte_string_map; + 42: map<i8, binary> byte_binary_map; + 43: map<i8, bool> byte_boolean_map; + // collections as keys + 44: map<list<i8> (python.immutable = ""), i8> list_byte_map; + 45: map<set<i8> (python.immutable = ""), i8> set_byte_map; + 46: map<map<i8,i8> (python.immutable = ""), i8> map_byte_map; + // collections as values + 47: map<i8, map<i8,i8>> byte_map_map; + 48: map<i8, set<i8>> byte_set_map; + 49: map<i8, list<i8>> byte_list_map; + + // large field IDs + 500 : i64 field500; + 5000 : i64 field5000; + 20000 : i64 field20000; +} + +// To be used to test the serialization of an empty map +struct SingleMapTestStruct { + 1: required map<i32, i32> i32_map; +} + +const CompactProtoTestStruct COMPACT_TEST = { + 'a_byte' : 127, + 'a_i16' : 32000, + 'a_i32' : 1000000000, + 'a_i64' : 0xffffffffff, + 'a_double' : 5.6789, + 'a_string' : "my string", +//'a_binary,' + 'true_field' : 1, + 'false_field' : 0, + 'empty_struct_field' : {}, + 'byte_list' : [-127, -1, 0, 1, 127], + 'i16_list' : [-1, 0, 1, 0x7fff], + 'i32_list' : [-1, 0, 0xff, 0xffff, 0xffffff, 0x7fffffff], + 'i64_list' : [-1, 0, 0xff, 0xffff, 0xffffff, 0xffffffff, 0xffffffffff, 0xffffffffffff, 0xffffffffffffff, 0x7fffffffffffffff], + 'double_list' : [0.1, 0.2, 0.3], + 'string_list' : ["first", "second", "third"], +//'binary_list,' + 'boolean_list' : [1, 1, 1, 0, 0, 0], + 'struct_list' : [{}, {}], + 'byte_set' : [-127, -1, 0, 1, 127], + 'i16_set' : [-1, 0, 1, 0x7fff], + 'i32_set' : [1, 2, 3], + 'i64_set' : [-1, 0, 0xff, 0xffff, 0xffffff, 0xffffffff, 0xffffffffff, 0xffffffffffff, 0xffffffffffffff, 0x7fffffffffffffff], + 'double_set' : [0.1, 0.2, 0.3], + 'string_set' : ["first", "second", "third"], +//'binary_set,' + 'boolean_set' : [1, 0], + 'struct_set' : [{}], + 'byte_byte_map' : {1 : 2}, + 'i16_byte_map' : {1 : 1, -1 : 1, 0x7fff : 1}, + 'i32_byte_map' : {1 : 1, -1 : 1, 0x7fffffff : 1}, + 'i64_byte_map' : {0 : 1, 1 : 1, -1 : 1, 0x7fffffffffffffff : 1}, + 'double_byte_map' : {-1.1 : 1, 1.1 : 1}, + 'string_byte_map' : {"first" : 1, "second" : 2, "third" : 3, "" : 0}, +//'binary_byte_map,' + 'boolean_byte_map' : {1 : 1, 0 : 0}, + 'byte_i16_map' : {1 : 1, 2 : -1, 3 : 0x7fff}, + 'byte_i32_map' : {1 : 1, 2 : -1, 3 : 0x7fffffff}, + 'byte_i64_map' : {1 : 1, 2 : -1, 3 : 0x7fffffffffffffff}, + 'byte_double_map' : {1 : 0.1, 2 : -0.1, 3 : 1000000.1}, + 'byte_string_map' : {1 : "", 2 : "blah", 3 : "loooooooooooooong string"}, +//'byte_binary_map,' + 'byte_boolean_map' : {1 : 1, 2 : 0}, + 'list_byte_map' : {[1, 2, 3] : 1, [0, 1] : 2, [] : 0}, + 'set_byte_map' : {[1, 2, 3] : 1, [0, 1] : 2, [] : 0}, + 'map_byte_map' : {{1 : 1} : 1, {2 : 2} : 2, {} : 0}, + 'byte_map_map' : {0 : {}, 1 : {1 : 1}, 2 : {1 : 1, 2 : 2}}, + 'byte_set_map' : {0 : [], 1 : [1], 2 : [1, 2]}, + 'byte_list_map' : {0 : [], 1 : [1], 2 : [1, 2]}, + + 'field500' : 500, + 'field5000' : 5000, + 'field20000' : 20000, +} + + +const i32 MYCONST = 2 + + +exception ExceptionWithAMap { + 1: string blah; + 2: map<string, string> map_field; +} + +service ServiceForExceptionWithAMap { + void methodThatThrowsAnException() throws (1: ExceptionWithAMap xwamap); +} + +service Srv { + i32 Janky(1: i32 arg); + + // return type only methods + + void voidMethod(); + i32 primitiveMethod(); + CompactProtoTestStruct structMethod(); + + void methodWithDefaultArgs(1: i32 something = MYCONST); + + oneway void onewayMethod(); + + bool declaredExceptionMethod(1: bool shouldThrow) throws (1: ExceptionWithAMap xwamap); +} + +service Inherited extends Srv { + i32 identity(1: i32 arg) +} + +service EmptyService {} + +// The only purpose of this thing is to increase the size of the generated code +// so that ZlibTest has more highly compressible data to play with. +struct BlowUp { + 1: map<list<i32>(python.immutable = ""),set<map<i32,string> (python.immutable = "")>> b1; + 2: map<list<i32>(python.immutable = ""),set<map<i32,string> (python.immutable = "")>> b2; + 3: map<list<i32>(python.immutable = ""),set<map<i32,string> (python.immutable = "")>> b3; + 4: map<list<i32>(python.immutable = ""),set<map<i32,string> (python.immutable = "")>> b4; +} + + +struct ReverseOrderStruct { + 4: string first; + 3: i16 second; + 2: i32 third; + 1: i64 fourth; +} + +service ReverseOrderService { + void myMethod(4: string first, 3: i16 second, 2: i32 third, 1: i64 fourth); +} + +enum SomeEnum { + ONE = 1 + TWO = 2 +} + +/** This is a docstring on a constant! */ +const SomeEnum MY_SOME_ENUM = SomeEnum.ONE + +const SomeEnum MY_SOME_ENUM_1 = 1 +/*const SomeEnum MY_SOME_ENUM_2 = 7*/ + +const map<SomeEnum,SomeEnum> MY_ENUM_MAP = { + SomeEnum.ONE : SomeEnum.TWO +} + +struct StructWithSomeEnum { + 1: SomeEnum blah; +} + +const map<SomeEnum,StructWithSomeEnum> EXTRA_CRAZY_MAP = { + SomeEnum.ONE : {"blah" : SomeEnum.TWO} +} + +union TestUnion { + /** + * A doc string + */ + 1: string string_field; + 2: i32 i32_field; + 3: OneOfEach struct_field; + 4: list<RandomStuff> struct_list; + 5: i32 other_i32_field; + 6: SomeEnum enum_field; + 7: set<i32> i32_set; + 8: map<i32, i32> i32_map; +} + +union TestUnionMinusStringField { + 2: i32 i32_field; + 3: OneOfEach struct_field; + 4: list<RandomStuff> struct_list; + 5: i32 other_i32_field; + 6: SomeEnum enum_field; + 7: set<i32> i32_set; + 8: map<i32, i32> i32_map; +} + +union ComparableUnion { + 1: string string_field; + 2: binary binary_field; +} + +struct StructWithAUnion { + 1: TestUnion test_union; +} + +struct PrimitiveThenStruct { + 1: i32 blah; + 2: i32 blah2; + 3: Backwards bw; +} + +typedef map<i32,i32> SomeMap + +struct StructWithASomemap { + 1: required SomeMap somemap_field; +} + +struct BigFieldIdStruct { + 1: string field1; + 45: string field2; +} + +struct BreaksRubyCompactProtocol { + 1: string field1; + 2: BigFieldIdStruct field2; + 3: i32 field3; +} + +struct TupleProtocolTestStruct { + optional i32 field1; + optional i32 field2; + optional i32 field3; + optional i32 field4; + optional i32 field5; + optional i32 field6; + optional i32 field7; + optional i32 field8; + optional i32 field9; + optional i32 field10; + optional i32 field11; + optional i32 field12; +} + +struct ListDoublePerf { + 1: list<double> field; +} diff --git a/src/jaegertracing/thrift/test/DenseLinkingTest.thrift b/src/jaegertracing/thrift/test/DenseLinkingTest.thrift new file mode 100644 index 000000000..3a5b95741 --- /dev/null +++ b/src/jaegertracing/thrift/test/DenseLinkingTest.thrift @@ -0,0 +1,98 @@ +/* + * 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. + */ + +/* +../compiler/cpp/thrift -gen cpp:dense DebugProtoTest.thrift +../compiler/cpp/thrift -gen cpp:dense DenseLinkingTest.thrift +g++ -Wall -g -I../lib/cpp/src -I/usr/local/include/boost-1_33_1 \ + DebugProtoTest.cpp gen-cpp/DebugProtoTest_types.cpp \ + gen-cpp/DenseLinkingTest_types.cpp \ + ../lib/cpp/.libs/libthrift.a -o DebugProtoTest +./DebugProtoTest +*/ + +/* +The idea of this test is that everything is structurally identical to DebugProtoTest. +If I messed up the naming of the reflection local typespecs, +then compiling this should give errors because of doubly defined symbols. +*/ + +namespace cpp thrift.test +namespace java thrift.test + +struct OneOfEachZZ { + 1: bool im_true, + 2: bool im_false, + 3: byte a_bite, + 4: i16 integer16, + 5: i32 integer32, + 6: i64 integer64, + 7: double double_precision, + 8: string some_characters, + 9: string zomg_unicode, + 10: bool what_who, +} + +struct BonkZZ { + 1: i32 type, + 2: string message, +} + +struct NestingZZ { + 1: BonkZZ my_bonk, + 2: OneOfEachZZ my_ooe, +} + +struct HolyMoleyZZ { + 1: list<OneOfEachZZ> big, + 2: set<list<string>> contain, + 3: map<string,list<BonkZZ>> bonks, +} + +struct BackwardsZZ { + 2: i32 first_tag2, + 1: i32 second_tag1, +} + +struct EmptyZZ { +} + +struct WrapperZZ { + 1: EmptyZZ foo +} + +struct RandomStuffZZ { + 1: i32 a, + 2: i32 b, + 3: i32 c, + 4: i32 d, + 5: list<i32> myintlist, + 6: map<i32,WrapperZZ> maps, + 7: i64 bigint, + 8: double triple, +} + +service Srv { + i32 Janky(1: i32 arg) +} + +service UnderscoreSrv { + i64 some_rpc_call(1: string message) +} + diff --git a/src/jaegertracing/thrift/test/DocTest.thrift b/src/jaegertracing/thrift/test/DocTest.thrift new file mode 100644 index 000000000..d702b2c23 --- /dev/null +++ b/src/jaegertracing/thrift/test/DocTest.thrift @@ -0,0 +1,287 @@ +/* + * 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. + */ + +/** + * Program doctext. + * + * Seriously, this is the documentation for this whole program. + */ + +namespace java thrift.test +namespace cpp thrift.test + +// C++ comment +/* c style comment */ + +# the new unix comment + +/** Some doc text goes here. Wow I am [nesting these] (no more nesting.) */ +enum Numberz +{ + + /** This is how to document a parameter */ + ONE = 1, + + /** And this is a doc for a parameter that has no specific value assigned */ + TWO, + + THREE, + FIVE = 5, + SIX, + EIGHT = 8 +} + +/** This is how you would do a typedef doc */ +typedef i64 UserId + +/** And this is where you would document a struct */ +struct Xtruct +{ + + /** And the members of a struct */ + 1: string string_thing + + /** doct text goes before a comma */ + 4: i8 byte_thing, + + 9: i32 i32_thing, + 11: i64 i64_thing +} + +/** + * You can document constants now too. Yeehaw! + */ +const i32 INT32CONSTANT = 9853 +const i16 INT16CONSTANT = 1616 +/** Everyone get in on the docu-action! */ +const map<string,string> MAPCONSTANT = {'hello':'world', 'goodnight':'moon'} + +struct Xtruct2 +{ + 1: i8 byte_thing, + 2: Xtruct struct_thing, + 3: i32 i32_thing +} + +/** Struct insanity */ +struct Insanity +{ + + /** This is doc for field 1 */ + 1: map<Numberz, UserId> userMap, + + /** And this is doc for field 2 */ + 2: list<Xtruct> xtructs +} + +exception Xception { + 1: i32 errorCode, + 2: string message +} + +exception Xception2 { + 1: i32 errorCode, + 2: Xtruct struct_thing +} + +/* C1 */ +/** Doc */ +/* C2 */ +/* C3 */ +struct EmptyStruct {} + +struct OneField { + 1: EmptyStruct field +} + +/** This is where you would document a Service */ +service ThriftTest +{ + + /** And this is how you would document functions in a service */ + void testVoid(), + string testString(1: string thing), + i8 testByte(1: byte thing), + i32 testI32(1: i32 thing), + + /** Like this one */ + i64 testI64(1: i64 thing), + double testDouble(1: double thing), + Xtruct testStruct(1: Xtruct thing), + Xtruct2 testNest(1: Xtruct2 thing), + map<i32,i32> testMap(1: map<i32,i32> thing), + set<i32> testSet(1: set<i32> thing), + list<i32> testList(1: list<i32> thing), + + /** This is an example of a function with params documented */ + Numberz testEnum( + + /** This param is a thing */ + 1: Numberz thing + + ), + + UserId testTypedef(1: UserId thing), + + map<i32,map<i32,i32>> testMapMap(1: i32 hello), + + /* So you think you've got this all worked, out eh? */ + map<UserId, map<Numberz,Insanity>> testInsanity(1: Insanity argument), + +} + +/// This style of Doxy-comment doesn't work. +typedef i32 SorryNoGo + +/** + * This is a trivial example of a multiline docstring. + */ +typedef i32 TrivialMultiLine + +/** + * This is the canonical example + * of a multiline docstring. + */ +typedef i32 StandardMultiLine + +/** + * The last line is non-blank. + * I said non-blank! */ +typedef i32 LastLine + +/** Both the first line + * are non blank. ;-) + * and the last line */ +typedef i32 FirstAndLastLine + +/** + * INDENTED TITLE + * The text is less indented. + */ +typedef i32 IndentedTitle + +/** First line indented. + * Unfortunately, this does not get indented. + */ +typedef i32 FirstLineIndent + + +/** + * void code_in_comment() { + * printf("hooray code!"); + * } + */ +typedef i32 CodeInComment + + /** + * Indented Docstring. + * This whole docstring is indented. + * This line is indented further. + */ +typedef i32 IndentedDocstring + +/** Irregular docstring. + * We will have to punt + * on this thing */ +typedef i32 Irregular1 + +/** + * note the space + * before these lines +* but not this + * one + */ +typedef i32 Irregular2 + +/** +* Flush against +* the left. +*/ +typedef i32 Flush + +/** + No stars in this one. + It should still work fine, though. + Including indenting. + */ +typedef i32 NoStars + +/** Trailing whitespace +Sloppy trailing whitespace +is truncated. */ +typedef i32 TrailingWhitespace + +/** + * This is a big one. + * + * We'll have some blank lines in it. + * + * void as_well_as(some code) { + * puts("YEEHAW!"); + * } + */ +typedef i32 BigDog + +/** +* +* +*/ +typedef i32 TotallyDegenerate + +/**no room for newline here*/ + +/* * / */ +typedef i32 TestFor3501a + +/** + * / + */ +typedef i32 TestFor3501b + + +/* Comment-end tokens can of course have more than one asterisk */ +struct TestFor3709_00 { /* ? */ 1: i32 foo } +/* Comment-end tokens can of course have more than one asterisk **/ +struct TestFor3709_01 { /* ? */ 1: i32 foo } +/* Comment-end tokens can of course have more than one asterisk ***/ +struct TestFor3709_02 { /* ? */ 1: i32 foo } +/** Comment-end tokens can of course have more than one asterisk */ +struct TestFor3709_03 { /* ? */ 1: i32 foo } +/** Comment-end tokens can of course have more than one asterisk **/ +struct TestFor3709_04 { /* ? */ 1: i32 foo } +/** Comment-end tokens can of course have more than one asterisk ***/ +struct TestFor3709_05 { /* ? */ 1: i32 foo } +/*** Comment-end tokens can of course have more than one asterisk */ +struct TestFor3709_06 { /* ? */ 1: i32 foo } +/*** Comment-end tokens can of course have more than one asterisk **/ +struct TestFor3709_07 { /* ? */ 1: i32 foo } +/*** Comment-end tokens can of course have more than one asterisk ***/ +struct TestFor3709_08 { /* ? */ 1: i32 foo } + +struct TestFor3709 { + /** This is a comment */ + 1: required string id, + /** This is also a comment **/ + 2: required string typeId, + /** Yet another comment! */ + 3: required i32 endTimestamp +} + + +/* THE END */ diff --git a/src/jaegertracing/thrift/test/DoubleConstantsTest.thrift b/src/jaegertracing/thrift/test/DoubleConstantsTest.thrift new file mode 100644 index 000000000..c9212abbb --- /dev/null +++ b/src/jaegertracing/thrift/test/DoubleConstantsTest.thrift @@ -0,0 +1,17 @@ +namespace java thrift.test +namespace cpp thrift.test + +// more tests on double constants (precision and type checks) +const double DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST = 1 +const double DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST = -100 +const double DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST = 9223372036854775807 +const double DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST = -9223372036854775807 +const double DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST = 3.14159265359 +const double DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST = 1000000.1 +const double DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST = -1000000.1 +const double DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST = 1.7e+308 +const double DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST = 9223372036854775816.43 +const double DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST = -1.7e+308 +const double DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST = -9223372036854775816.43 + +const list<double> DOUBLE_LIST_TEST = [1,-100,100,9223372036854775807,-9223372036854775807,3.14159265359,1000000.1,-1000000.1,1.7e+308,-1.7e+308,9223372036854775816.43,-9223372036854775816.43] diff --git a/src/jaegertracing/thrift/test/EnumContainersTest.thrift b/src/jaegertracing/thrift/test/EnumContainersTest.thrift new file mode 100644 index 000000000..3b6408f45 --- /dev/null +++ b/src/jaegertracing/thrift/test/EnumContainersTest.thrift @@ -0,0 +1,46 @@ +/* + * 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. + */ + +namespace java thrift.test.enumcontainers + +enum GreekGodGoddess { + ARES, + APHRODITE, + ZEUS, + POSEIDON, + HERA, +} + +typedef GreekGodGoddess GreekGodGoddessType +typedef i32 Power + +struct GodBean { + 1: optional map<GreekGodGoddessType, Power> power, + 2: optional set<GreekGodGoddessType> goddess, + 3: optional map<string, GreekGodGoddess> byAlias, + 4: optional set<string> images, +} + +const map<GreekGodGoddessType, string> ATTRIBUTES = +{ + GreekGodGoddess.ZEUS: "lightning bolt", + GreekGodGoddess.POSEIDON: "trident", +} + +const set<GreekGodGoddessType> BEAUTY = [ GreekGodGoddess.APHRODITE, GreekGodGoddess.HERA ] diff --git a/src/jaegertracing/thrift/test/EnumTest.thrift b/src/jaegertracing/thrift/test/EnumTest.thrift new file mode 100644 index 000000000..7961f3841 --- /dev/null +++ b/src/jaegertracing/thrift/test/EnumTest.thrift @@ -0,0 +1,119 @@ +/* + * 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. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +namespace c_glib TTest + +enum MyEnum1 { + ME1_0 = 0, + ME1_1 = 1, + ME1_2, + ME1_3, + ME1_5 = 5, + ME1_6, +} + +enum MyEnum2 { + ME2_0, + ME2_1, + ME2_2, +} + +enum MyEnum2_again { + // enum value identifiers may appear again in another enum type + ME0_1, + ME1_1, + ME2_1, + ME3_1, +} + +enum MyEnum3 { + ME3_0, + ME3_1, + ME3_N2 = -2, + ME3_N1, + ME3_D0, + ME3_D1, + ME3_9 = 9, + ME3_10, +} + +enum MyEnum4 { + ME4_A = 0x7ffffffd + ME4_B + ME4_C + // attempting to define another enum value here fails + // with an overflow error, as we overflow values that can be + // represented with an i32. +} + +enum MyEnum5 { + e1 // fails with 0.9.3 and earlier + e2 = 42 // fails with 0.9.3 and earlier +} + +enum MyEnumWithCustomOstream { + custom1 = 1, + CustoM2 +} (cpp.customostream) + +struct MyStruct { + 1: MyEnum2 me2_2 = MyEnum1.ME2_2 + 2: MyEnum3 me3_n2 = MyEnum3.ME3_N2 + 3: MyEnum3 me3_d1 = MyEnum3.ME3_D1 +} + +struct EnumTestStruct { + 1: MyEnum3 a_enum; + 2: list<MyEnum3> enum_list; + 3: set<MyEnum3> enum_set; + 4: map<MyEnum3, MyEnum3> enum_enum_map; + // collections as keys + 44: map<list<MyEnum3> (python.immutable = ""), MyEnum3> list_enum_map; + 45: map<set<MyEnum3> (python.immutable = ""), MyEnum3> set_enum_map; + 46: map<map<MyEnum3,MyEnum3> (python.immutable = ""), MyEnum3> map_enum_map; + // collections as values + 47: map<MyEnum3, map<MyEnum3, MyEnum3>> enum_map_map; + 48: map<MyEnum3, set<MyEnum3>> enum_set_map; + 49: map<MyEnum3, list<MyEnum3>> enum_list_map; +} + +const EnumTestStruct ENUM_TEST = { + 'a_enum': MyEnum3.ME3_D1, + 'enum_list': [MyEnum3.ME3_D1, MyEnum3.ME3_0, MyEnum3.ME3_N2], + 'enum_set': [MyEnum3.ME3_D1, MyEnum3.ME3_N1], + 'enum_enum_map': {MyEnum3.ME3_D1: MyEnum3.ME3_0, MyEnum3.ME3_0: MyEnum3.ME3_D1}, + 'list_enum_map': {[MyEnum3.ME3_D1, MyEnum3.ME3_0]: MyEnum3.ME3_0, [MyEnum3.ME3_D1]: MyEnum3.ME3_0, [MyEnum3.ME3_0]: MyEnum3.ME3_D1}, + 'set_enum_map': {[MyEnum3.ME3_D1, MyEnum3.ME3_0]: MyEnum3.ME3_0, [MyEnum3.ME3_D1]: MyEnum3.ME3_0}, + 'map_enum_map': {{MyEnum3.ME3_N1: MyEnum3.ME3_10}: MyEnum3.ME3_1}, + 'enum_map_map': {MyEnum3.ME3_N1: {MyEnum3.ME3_D1: MyEnum3.ME3_D1}}, + 'enum_set_map': {MyEnum3.ME3_N2: [MyEnum3.ME3_D1, MyEnum3.ME3_N1], MyEnum3.ME3_10: [MyEnum3.ME3_D1, MyEnum3.ME3_N1]}, + 'enum_list_map': {MyEnum3.ME3_D1: [MyEnum3.ME3_10], MyEnum3.ME3_0: [MyEnum3.ME3_9, MyEnum3.ME3_10]}, +} + +service EnumTestService { + MyEnum3 testEnum(1: MyEnum3 enum1), + list<MyEnum3> testEnumList(1: list<MyEnum3> enum1), + set<MyEnum3> testEnumSet(1: set<MyEnum3> enum1), + map<MyEnum3, MyEnum3> testEnumMap(1: map<MyEnum3, MyEnum3> enum1), + EnumTestStruct testEnumStruct(1: EnumTestStruct enum1), +} diff --git a/src/jaegertracing/thrift/test/FullCamelTest.thrift b/src/jaegertracing/thrift/test/FullCamelTest.thrift new file mode 100644 index 000000000..cee4dd8fa --- /dev/null +++ b/src/jaegertracing/thrift/test/FullCamelTest.thrift @@ -0,0 +1,38 @@ +/* + * 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. + */ + +namespace java thrift.test.fullcamel + +struct OneOfEachZZ { + 1: bool im_true, + 2: bool im_false, + 3: byte a_bite, + 4: i16 integer16, + 5: i32 integer32, + 6: i64 integer64, + 7: double double_precision, + 8: string some_characters, + 9: string zomg_unicode, + 10: bool what_who, +} + +service UnderscoreSrv { + i64 some_rpc_call(1: string message) +} + diff --git a/src/jaegertracing/thrift/test/Identifiers.thrift b/src/jaegertracing/thrift/test/Identifiers.thrift new file mode 100644 index 000000000..aa3e4eac5 --- /dev/null +++ b/src/jaegertracing/thrift/test/Identifiers.thrift @@ -0,0 +1,6 @@ +// THRIFT-4953 +struct NoFieldIdentifiersTest { + string field_without_id1, + string field_without_id2, + 1: string field_with_id +}
\ No newline at end of file diff --git a/src/jaegertracing/thrift/test/Include.thrift b/src/jaegertracing/thrift/test/Include.thrift new file mode 100644 index 000000000..562319b2f --- /dev/null +++ b/src/jaegertracing/thrift/test/Include.thrift @@ -0,0 +1,24 @@ +/* + * 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. + */ + +include "ThriftTest.thrift" + +struct IncludeTest { + 1: required ThriftTest.Bools bools +}
\ No newline at end of file diff --git a/src/jaegertracing/thrift/test/Int64Test.thrift b/src/jaegertracing/thrift/test/Int64Test.thrift new file mode 100644 index 000000000..348cc9c47 --- /dev/null +++ b/src/jaegertracing/thrift/test/Int64Test.thrift @@ -0,0 +1,44 @@ +/* + * 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. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +namespace js Int64Test + +const i64 SMALL_INT64 = 42 +const i64 MAX_JS_SAFE_INT64 = 9007199254740991 +const i64 MIN_JS_SAFE_INT64 = -9007199254740991 +const i64 MAX_JS_SAFE_PLUS_ONE_INT64 = 9007199254740992 +const i64 MIN_JS_SAFE_MINUS_ONE_INT64 = -9007199254740992 +const i64 MAX_SIGNED_INT64 = 9223372036854775807 +const i64 MIN_SIGNED_INT64 = -9223372036854775808 + +const list<i64> INT64_LIST = [SMALL_INT64, MAX_JS_SAFE_INT64, MIN_JS_SAFE_INT64, MAX_JS_SAFE_PLUS_ONE_INT64, MIN_JS_SAFE_MINUS_ONE_INT64, MAX_SIGNED_INT64, MIN_SIGNED_INT64] + +const map<i64, i64> INT64_2_INT64_MAP = { + SMALL_INT64: SMALL_INT64, + MAX_JS_SAFE_INT64: MAX_JS_SAFE_INT64, + MIN_JS_SAFE_INT64: MIN_JS_SAFE_INT64, + MAX_JS_SAFE_PLUS_ONE_INT64: MAX_JS_SAFE_PLUS_ONE_INT64, + MIN_JS_SAFE_MINUS_ONE_INT64: MIN_JS_SAFE_MINUS_ONE_INT64, + MAX_SIGNED_INT64: MAX_SIGNED_INT64, + MIN_SIGNED_INT64: MIN_SIGNED_INT64 + } diff --git a/src/jaegertracing/thrift/test/JavaBeansTest.thrift b/src/jaegertracing/thrift/test/JavaBeansTest.thrift new file mode 100644 index 000000000..b6c3ea861 --- /dev/null +++ b/src/jaegertracing/thrift/test/JavaBeansTest.thrift @@ -0,0 +1,39 @@ +/* + * 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. + */ + +namespace java thrift.test + +struct OneOfEachBeans { + 1: bool boolean_field, + 2: byte a_bite, + 3: i16 integer16, + 4: i32 integer32, + 5: i64 integer64, + 6: double double_precision, + 7: string some_characters, + 8: binary base64, + 9: list<byte> byte_list, + 10: list<i16> i16_list, + 11: list<i64> i64_list +} + + +service Service { + i64 mymethod(i64 blah); +}
\ No newline at end of file diff --git a/src/jaegertracing/thrift/test/JavaBinaryDefault.thrift b/src/jaegertracing/thrift/test/JavaBinaryDefault.thrift new file mode 100644 index 000000000..5517802c7 --- /dev/null +++ b/src/jaegertracing/thrift/test/JavaBinaryDefault.thrift @@ -0,0 +1,25 @@ +/* + * 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. + */ + +namespace java thrift.test + +struct StringAndBinary { + 1: optional string strval = "" + 2: optional binary binval = "" +} diff --git a/src/jaegertracing/thrift/test/JavaDeepCopyTest.thrift b/src/jaegertracing/thrift/test/JavaDeepCopyTest.thrift new file mode 100644 index 000000000..fc974aefd --- /dev/null +++ b/src/jaegertracing/thrift/test/JavaDeepCopyTest.thrift @@ -0,0 +1,19 @@ +include "JavaTypes.thrift" + +namespace java thrift.test + +struct DeepCopyFoo { + 1: optional list<DeepCopyBar> l, + 2: optional set<DeepCopyBar> s, + 3: optional map<string, DeepCopyBar> m, + 4: optional list<JavaTypes.Object> li, + 5: optional set<JavaTypes.Object> si, + 6: optional map<string, JavaTypes.Object> mi, + 7: optional DeepCopyBar bar, +} + +struct DeepCopyBar { + 1: optional string a, + 2: optional i32 b, + 3: optional bool c, +} diff --git a/src/jaegertracing/thrift/test/JavaTypes.thrift b/src/jaegertracing/thrift/test/JavaTypes.thrift new file mode 100644 index 000000000..555334082 --- /dev/null +++ b/src/jaegertracing/thrift/test/JavaTypes.thrift @@ -0,0 +1,107 @@ +/* + * 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. + */ + +namespace java thrift.test + +struct Integer { + 1: i32 val +} + +struct String { + 1: string val +} + +struct Binary { + 1: binary val +} + +struct Boolean { + 1: bool val +} + +struct Double { + 1: double val +} + +struct Long { + 1: i64 val +} + +struct Byte { + 1: byte val +} + +struct Float { + 1: double val +} + +struct List { + 1: list<string> vals +} + +struct ArrayList { + 1: list<string> vals +} + +struct SortedMap { + 1: map<string, string> vals +} + +struct TreeMap { + 1: map<string, string> vals +} + +struct HashMap { + 1: map<string, String> vals +} + +struct Map { + 1: map<double, Double> vals +} + +struct Object { + 1: Integer integer, + 2: String str, + 3: Boolean boolean_field, + 4: Double dbl, + 5: Byte bite, + 6: map<i32, Integer> intmap, + 7: Map somemap, +} + +exception Exception { + 1: string msg +} + +service AsyncNonblockingService { + Object mymethod( + 1: Integer integer, + 2: String str, + 3: Boolean boolean_field, + 4: Double dbl, + 5: Byte bite, + 6: map<i32, Integer> intmap, + 7: Map somemap, + ) throws (1:Exception ex); +} + +struct SafeBytes { + 1: binary bytes; +} + diff --git a/src/jaegertracing/thrift/test/JsDeepConstructorTest.thrift b/src/jaegertracing/thrift/test/JsDeepConstructorTest.thrift new file mode 100644 index 000000000..ef5126fa4 --- /dev/null +++ b/src/jaegertracing/thrift/test/JsDeepConstructorTest.thrift @@ -0,0 +1,18 @@ +struct Simple { + 1: string value +} + +struct Complex { + 1: Simple struct_field + 2: list<Simple> struct_list_field + 3: set<Simple> struct_set_field + 4: map<string,Simple> struct_map_field + 5: list<set<map<string,list<Simple>>>> struct_nested_containers_field + 6: map<string, list<map<string,Simple>> > struct_nested_containers_field2 + 7: list<list<string>> list_of_list_field + 8: list<list<list<string>>> list_of_list_of_list_field +} + +struct ComplexList { + 1: list<Complex> struct_list_field; +} diff --git a/src/jaegertracing/thrift/test/Makefile.am b/src/jaegertracing/thrift/test/Makefile.am new file mode 100755 index 000000000..c2fbbd459 --- /dev/null +++ b/src/jaegertracing/thrift/test/Makefile.am @@ -0,0 +1,187 @@ +# +# 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. +# + +SUBDIRS = features +PRECROSS_TARGET = + +if WITH_C_GLIB +SUBDIRS += c_glib +PRECROSS_TARGET += precross-c_glib +endif + +if WITH_CL +SUBDIRS += cl +PRECROSS_TARGET += precross-cl +endif + +if WITH_MONO +SUBDIRS += csharp +PRECROSS_TARGET += precross-csharp +endif + +if WITH_CPP +SUBDIRS += cpp +PRECROSS_TARGET += precross-cpp +endif + +if WITH_PERL +SUBDIRS += perl +PRECROSS_TARGET += precross-perl +endif + +if WITH_PHP +SUBDIRS += php +PRECROSS_TARGET += precross-php +endif + +if WITH_DART +SUBDIRS += dart +PRECROSS_TARGET += precross-dart +endif + +if WITH_PYTHON +SUBDIRS += py +PRECROSS_TARGET += precross-py +SUBDIRS += py.tornado +if WITH_TWISTED_TEST +SUBDIRS += py.twisted +endif +endif + +if WITH_RUBY +SUBDIRS += rb +PRECROSS_TARGET += precross-rb +endif + +if WITH_HASKELL +SUBDIRS += hs +endif + +if WITH_HAXE +SUBDIRS += haxe +endif + +if WITH_DOTNET +SUBDIRS += netcore +SUBDIRS += netstd +endif + +if WITH_GO +SUBDIRS += go +PRECROSS_TARGET += precross-go +endif + +if WITH_ERLANG +SUBDIRS += erl +PRECROSS_TARGET += precross-erl +endif + +if WITH_LUA +SUBDIRS += lua +PRECROSS_TARGET += precross-lua +endif + +if WITH_RS +SUBDIRS += rs +PRECROSS_TARGET += precross-rs +endif + +# +# generate html for ThriftTest.thrift AND validate it! +# +if WITH_NODEJS +check-local: + $(top_builddir)/compiler/cpp/thrift --gen html -r $(top_srcdir)/test/ThriftTest.thrift + $(top_builddir)/node_modules/.bin/html-validator --file=gen-html/index.html --verbose + $(top_builddir)/node_modules/.bin/html-validator --file=gen-html/ThriftTest.html --verbose +else +check-local: + $(top_builddir)/compiler/cpp/thrift --gen html -r $(top_srcdir)/test/ThriftTest.thrift +endif + +clean-local: + $(RM) -r $(top_srcdir)/test/gen-html/ + find . -type d -name "__pycache__" | xargs rm -rf + find . -type f -name "*.pyc" | xargs rm -f + +dist-hook: + $(RM) -r $(distdir)/gen-html/ + find $(distdir) -type d -name "__pycache__" | xargs rm -rf + find $(distdir) -type f -name "*.pyc" | xargs rm -f + +EXTRA_DIST = \ + audit \ + c_glib \ + cl \ + cpp \ + crossrunner \ + dart \ + erl \ + hs \ + keys \ + lua \ + ocaml \ + perl \ + php \ + py \ + py.tornado \ + py.twisted \ + rb \ + rs \ + threads \ + AnnotationTest.thrift \ + BrokenConstants.thrift \ + ConstantsDemo.thrift \ + DebugProtoTest.thrift \ + DenseLinkingTest.thrift \ + DocTest.thrift \ + DoubleConstantsTest.thrift \ + EnumContainersTest.thrift \ + EnumTest.thrift \ + FullCamelTest.thrift \ + Include.thrift \ + Int64Test.thrift \ + JavaBeansTest.thrift \ + JavaBinaryDefault.thrift \ + JavaDeepCopyTest.thrift \ + JavaTypes.thrift \ + JsDeepConstructorTest.thrift \ + ManyOptionals.thrift \ + ManyTypedefs.thrift \ + NameConflictTest.thrift \ + OptionalRequiredTest.thrift \ + Recursive.thrift \ + ReuseObjects.thrift \ + SmallTest.thrift \ + StressTest.thrift \ + ThriftTest.thrift \ + TypedefTest.thrift \ + UnsafeTypes.thrift \ + known_failures_Linux.json \ + test.py \ + tests.json \ + rebuild_known_failures.sh \ + result.js \ + index.html \ + README.md \ + valgrind.suppress + +precross-%: + $(MAKE) -C $* precross +precross: $(PRECROSS_TARGET) diff --git a/src/jaegertracing/thrift/test/ManyOptionals.thrift b/src/jaegertracing/thrift/test/ManyOptionals.thrift new file mode 100644 index 000000000..3fb1d68b8 --- /dev/null +++ b/src/jaegertracing/thrift/test/ManyOptionals.thrift @@ -0,0 +1,231 @@ +/* + * 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. + */ + +// The java codegenerator has a few different codepaths depending +// on how many optionals the struct has; this attempts to exercise +// them. + +namespace java thrift.test + +struct Opt4 { + 1: i32 def1; + 2: i32 def2; + 3: i32 def3; + 4: i32 def4; +} + +struct Opt13 { + 1: i32 def1; + 2: i32 def2; + 3: i32 def3; + 4: i32 def4; + 5: i32 def5; + 6: i32 def6; + 7: i32 def7; + 8: i32 def8; + 9: i32 def9; + 10: i32 def10; + 11: i32 def11; + 12: i32 def12; + 13: i32 def13; +} + +struct Opt30 { + 1: i32 def1; + 2: i32 def2; + 3: i32 def3; + 4: i32 def4; + 5: i32 def5; + 6: i32 def6; + 7: i32 def7; + 8: i32 def8; + 9: i32 def9; + 10: i32 def10; + 11: i32 def11; + 12: i32 def12; + 13: i32 def13; + 14: i32 def14; + 15: i32 def15; + 16: i32 def16; + 17: i32 def17; + 18: i32 def18; + 19: i32 def19; + 20: i32 def20; + 21: i32 def21; + 22: i32 def22; + 23: i32 def23; + 24: i32 def24; + 25: i32 def25; + 26: i32 def26; + 27: i32 def27; + 28: i32 def28; + 29: i32 def29; + 30: i32 def30; +} + +struct Opt64 { + 1: i32 def1; + 2: i32 def2; + 3: i32 def3; + 4: i32 def4; + 5: i32 def5; + 6: i32 def6; + 7: i32 def7; + 8: i32 def8; + 9: i32 def9; + 10: i32 def10; + 11: i32 def11; + 12: i32 def12; + 13: i32 def13; + 14: i32 def14; + 15: i32 def15; + 16: i32 def16; + 17: i32 def17; + 18: i32 def18; + 19: i32 def19; + 20: i32 def20; + 21: i32 def21; + 22: i32 def22; + 23: i32 def23; + 24: i32 def24; + 25: i32 def25; + 26: i32 def26; + 27: i32 def27; + 28: i32 def28; + 29: i32 def29; + 30: i32 def30; + 31: i32 def31; + 32: i32 def32; + 33: i32 def33; + 34: i32 def34; + 35: i32 def35; + 36: i32 def36; + 37: i32 def37; + 38: i32 def38; + 39: i32 def39; + 40: i32 def40; + 41: i32 def41; + 42: i32 def42; + 43: i32 def43; + 44: i32 def44; + 45: i32 def45; + 46: i32 def46; + 47: i32 def47; + 48: i32 def48; + 49: i32 def49; + 50: i32 def50; + 51: i32 def51; + 52: i32 def52; + 53: i32 def53; + 54: i32 def54; + 55: i32 def55; + 56: i32 def56; + 57: i32 def57; + 58: i32 def58; + 59: i32 def59; + 60: i32 def60; + 61: i32 def61; + 62: i32 def62; + 63: i32 def63; + 64: i32 def64; +} + +struct Opt80 { + 1: i32 def1; + 2: i32 def2; + 3: i32 def3; + 4: i32 def4; + 5: i32 def5; + 6: i32 def6; + 7: i32 def7; + 8: i32 def8; + 9: i32 def9; + 10: i32 def10; + 11: i32 def11; + 12: i32 def12; + 13: i32 def13; + 14: i32 def14; + 15: i32 def15; + 16: i32 def16; + 17: i32 def17; + 18: i32 def18; + 19: i32 def19; + 20: i32 def20; + 21: i32 def21; + 22: i32 def22; + 23: i32 def23; + 24: i32 def24; + 25: i32 def25; + 26: i32 def26; + 27: i32 def27; + 28: i32 def28; + 29: i32 def29; + 30: i32 def30; + 31: i32 def31; + 32: i32 def32; + 33: i32 def33; + 34: i32 def34; + 35: i32 def35; + 36: i32 def36; + 37: i32 def37; + 38: i32 def38; + 39: i32 def39; + 40: i32 def40; + 41: i32 def41; + 42: i32 def42; + 43: i32 def43; + 44: i32 def44; + 45: i32 def45; + 46: i32 def46; + 47: i32 def47; + 48: i32 def48; + 49: i32 def49; + 50: i32 def50; + 51: i32 def51; + 52: i32 def52; + 53: i32 def53; + 54: i32 def54; + 55: i32 def55; + 56: i32 def56; + 57: i32 def57; + 58: i32 def58; + 59: i32 def59; + 60: i32 def60; + 61: i32 def61; + 62: i32 def62; + 63: i32 def63; + 64: i32 def64; + 65: i32 def65; + 66: i32 def66; + 67: i32 def67; + 68: i32 def68; + 69: i32 def69; + 70: i32 def70; + 71: i32 def71; + 72: i32 def72; + 73: i32 def73; + 74: i32 def74; + 75: i32 def75; + 76: i32 def76; + 77: i32 def77; + 78: i32 def78; + 79: i32 def79; + 80: i32 def80; +} + diff --git a/src/jaegertracing/thrift/test/ManyTypedefs.thrift b/src/jaegertracing/thrift/test/ManyTypedefs.thrift new file mode 100644 index 000000000..d194b63c2 --- /dev/null +++ b/src/jaegertracing/thrift/test/ManyTypedefs.thrift @@ -0,0 +1,50 @@ +/* + * 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. + */ + +// This is to make sure you don't mess something up when you change typedef code. +// Generate it with the old and new thrift and make sure they are the same. +/* +rm -rf gen-* orig-* +mkdir old new +thrift --gen cpp --gen java --gen php --gen phpi --gen py --gen rb --gen xsd --gen perl --gen ocaml --gen erl --gen hs --strict ManyTypedefs.thrift +mv gen-* old +../compiler/cpp/thrift --gen cpp --gen java --gen php --gen phpi --gen py --gen rb --gen xsd --gen perl --gen ocaml --gen erl --gen hs --strict ManyTypedefs.thrift +mv gen-* new +diff -ur old new +rm -rf old new +# There should be no output. +*/ + +typedef i32 int32 +typedef list<map<int32, string>> biglist + +struct struct1 { + 1: int32 myint; + 2: biglist mylist; +} + +exception exception1 { + 1: biglist alist; + 2: struct1 mystruct; +} + +service AService { + struct1 method1(1: int32 myint) throws (1: exception1 exn); + biglist method2(); +} diff --git a/src/jaegertracing/thrift/test/NameConflictTest.thrift b/src/jaegertracing/thrift/test/NameConflictTest.thrift new file mode 100644 index 000000000..d3efb474c --- /dev/null +++ b/src/jaegertracing/thrift/test/NameConflictTest.thrift @@ -0,0 +1,110 @@ +// Naming testcases, sepcifically for these tickets (but not limited to them) +// THRIFT-2508 Uncompileable C# code due to language keywords in IDL +// THRIFT-2557 error CS0542 member names cannot be the same as their enclosing type + + +struct using { + 1: double single + 2: double integer +} + +struct delegate { + 1: string partial + 2: delegate delegate +} + +struct get { + 1: bool sbyte +} + +struct partial { + 1: using using + 2: bool read + 3: bool write +} + +enum Maybe { + JUST = 1, + TRUE = 2, + FALSE = 3 +} + +enum Either { + LEFT = 1, + RIGHT = 2 +} + +struct foldr { + 1: string id +} + +struct of { + 1: string let + 2: string where +} + +struct ofOf { + 1: of Of +} + + +struct ClassAndProp { + 1: bool ClassAndProp + 2: bool ClassAndProp_ + 3: bool ClassAndProp__ + 4: bool ClassAndProper +} + +struct second_chance { + 1: bool SECOND_CHANCE + 2: bool SECOND_CHANCE_ + 3: bool SECOND_CHANCE__ + 4: bool SECOND_CHANCES +} + +struct NOW_EAT_THIS { + 1: bool now_eat_this + 2: bool now_eat_this_ + 3: bool now_eat_this__ + 4: bool now_eat_this_and_this +} + +struct TheEdgeCase { + 1: bool theEdgeCase + 2: bool theEdgeCase_ + 3: bool theEdgeCase__ + 4: bool TheEdgeCase + 5: bool TheEdgeCase_ + 6: bool TheEdgeCase__ +} + +struct Tricky_ { + 1: bool tricky + 2: bool Tricky +} + +struct Nested { + 1: ClassAndProp ClassAndProp + 2: second_chance second_chance + 3: NOW_EAT_THIS NOW_EAT_THIS + 4: TheEdgeCase TheEdgeCase + 5: Tricky_ Tricky_ + 6: Nested Nested +} + +exception Problem_ { + 1: bool problem + 2: bool Problem +} + + +service extern { + delegate event(1: partial get) + void Foo(1: Nested Foo_args) throws (1: Problem_ Foo_result) +} + +service qualified { + Maybe maybe(1: Maybe foldr) + Either either(1: foldr of) +} +// eof diff --git a/src/jaegertracing/thrift/test/OptionalRequiredTest.thrift b/src/jaegertracing/thrift/test/OptionalRequiredTest.thrift new file mode 100644 index 000000000..a608898f0 --- /dev/null +++ b/src/jaegertracing/thrift/test/OptionalRequiredTest.thrift @@ -0,0 +1,88 @@ +/* + * 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. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +namespace c_glib TTest +namespace cpp thrift.test +namespace java thrift.test + +struct OldSchool { + 1: i16 im_int; + 2: string im_str; + 3: list<map<i32,string>> im_big; +} + +struct Simple { + 1: /* :) */ i16 im_default; + 2: required i16 im_required; + 3: optional i16 im_optional; +} + +struct Tricky1 { + 1: /* :) */ i16 im_default; +} + +struct Tricky2 { + 1: optional i16 im_optional; +} + +struct Tricky3 { + 1: required i16 im_required; +} + +struct OptionalDefault { + 1: optional i16 opt_int = 1234; + 2: optional string opt_str = "default"; +} + +struct Complex { + 1: i16 cp_default; + 2: required i16 cp_required; + 3: optional i16 cp_optional; + 4: map<i16,Simple> the_map; + 5: required Simple req_simp; + 6: optional Simple opt_simp; +} + +struct ManyOpt { + 1: optional i32 opt1; + 2: optional i32 opt2; + 3: optional i32 opt3; + 4: i32 def4; + 5: optional i32 opt5; + 6: optional i32 opt6; +} + +struct JavaTestHelper { + 1: required i32 req_int; + 2: optional i32 opt_int; + 3: required string req_obj; + 4: optional string opt_obj; + 5: required binary req_bin; + 6: optional binary opt_bin; +} + +struct Binaries { + 4: binary bin; + 5: required binary req_bin; + 6: optional binary opt_bin; +} diff --git a/src/jaegertracing/thrift/test/README.md b/src/jaegertracing/thrift/test/README.md new file mode 100755 index 000000000..19cc2a1a7 --- /dev/null +++ b/src/jaegertracing/thrift/test/README.md @@ -0,0 +1,185 @@ +# Apache Thrift - integration test suite + +This is the cross everything integration test suite for Apache Thrift. + +## Run + +### A. Using Make + +The test can be executed by: + + make cross + +This starts the [test.py](test.py) script which does the real cross test with +different transports, protocols and languages. + +Note that this skips any language that is not built locally. It also skips +tests that are known to be failing. If you need more control over which tests +to run, read following section. + +### B. Using test script directly + +Alternatively, you can invoke [test.py](test.py) directly. You need to run`make +precross` once before executing it for the first time. + +For example, if you changed something in `nodejs` library and need to verify +the patch, you can skip everything except `nodejs` itself and some reference +implementation (currently `cpp` and `java` are recommended) like this: + + ./configure --without-c_glib -without-csharp --without-erlang --without-lua ... + make precross -j8 + test/test.py --server cpp,java --client nodejs + test/test.py --server nodejs --client cpp,java + +Another useful flag is --regex. For example, to run all tests that involve +Java TBinaryProtocol: + + test/test.py --regex "java.*binary" + +## Test case definition file + +The cross test cases are defined in [tests.json](tests.json). +The root element is collection of test target definitions. +Each test target definition looks like this: + + { + "name": "somelib", + + "client": { + "command": ["somelib_client_executable"], + "workdir": "somelib/bin", + "protocols": ["binary"], + "transports": ["buffered"], + "sockets": ["ip"], + }, + "server": { + "command": ["somelib_server_executable"], + "workdir": "somelib/bin", + "protocols": ["binary"], + "transports": ["buffered"], + "sockets": ["ip", "ip-ssl"], + } + } + +Either client or server definition or both should be present. + +Parameters that are common to both `client` and `server` can be put to target +definition root: + + { + "name": "somelib", + + "workdir": "somelib/bin", + "protocols": ["binary"], + "transports": ["buffered"], + "sockets": ["ip"], + + "client": { "command": ["somelib_client_executable"] }, + "server": { + "command": ["somelib_server_executable"], + "sockets": ["ip-ssl"] + } + } + +For the complete list of supported keys and their effect, see source code +comment at the opt of [crossrunner/collect.py](crossrunner/collect.py). + + +## List of known failures + +Since many cross tests currently fail (mainly due to partial incompatibility +around exception handling), the test script specifically report for "not known +before" failures. + +For this purpose, test cases known to (occasionally) fail are listed in +`known_failures_<platform>.json` where `<platform>` matches with python +`platform.system()` string. + +Currently, only Linux version is included. + +FYI, the file is initially generated by + + test/test.py --update-expected-failures=overwrite + +after a full test run, then repeatedly + + test/test.py --skip-known-failures + test/test.py --update-expected-failures=merge + +to update the known failures, run + + make fail + +## Test executable specification + +### Command line parameters + +Unit tests for languages are usually located under lib/<lang>/test/ +cross language tests according to [ThriftTest.thrift](ThriftTest.thrift) shall be +provided for every language including executables with the following command +line interface: + +**Server command line interface:** + + $ ./cpp/TestServer -h + Allowed options: + -h [ --help ] produce help message + --port arg (=9090) Port number to listen + --domain-socket arg Unix Domain Socket (e.g. /tmp/ThriftTest.thrift) + --named-pipe arg Windows Named Pipe (e.g. MyThriftPipe) + --server-type arg (=simple) type of server, "simple", "thread-pool", + "threaded", or "nonblocking" + --transport arg (=buffered) transport: buffered, framed, http, anonpipe + --protocol arg (=binary) protocol: binary, compact, json + --ssl Encrypted Transport using SSL + --processor-events processor-events + -n [ --workers ] arg (=4) Number of thread pools workers. Only valid for + thread-pool server type + +**Client command line interface:** + + $ ./cpp/TestClient -h + Allowed options: + -h [ --help ] produce help message + --host arg (=localhost) Host to connect + --port arg (=9090) Port number to connect + --domain-socket arg Domain Socket (e.g. /tmp/ThriftTest.thrift), + instead of host and port + --named-pipe arg Windows Named Pipe (e.g. MyThriftPipe) + --anon-pipes hRead hWrite Windows Anonymous Pipes pair (handles) + --transport arg (=buffered) Transport: buffered, framed, http, evhttp + --protocol arg (=binary) Protocol: binary, compact, json + --ssl Encrypted Transport using SSL + -n [ --testloops ] arg (=1) Number of Tests + -t [ --threads ] arg (=1) Number of Test threads + +If you have executed the **make check** or **make cross** then you will be able to browse +[gen-html/ThriftTest.html](gen-html/ThriftTest.html) with the test documentation. + +### Return code + +The return code (exit code) shall be 0 on success, or an integer in the range 1 - 255 on errors. +In order to signal failed tests, the return code shall be composed from these bits to indicate +failing tests: + + #define TEST_BASETYPES 1 // 0000 0001 + #define TEST_STRUCTS 2 // 0000 0010 + #define TEST_CONTAINERS 4 // 0000 0100 + #define TEST_EXCEPTIONS 8 // 0000 1000 + #define TEST_UNKNOWN 64 // 0100 0000 (Failed to prepare environment etc.) + #define TEST_TIMEOUT 128 // 1000 0000 + #define TEST_NOTUSED 48 // 0011 0000 (reserved bits) + +Tests that have not been executed at all count as errors. + +**Example:** + +During tests, the test client notices that some of the Struct tests fail. +Furthermore, due to some other problem none of the Exception tests is executed. +Therefore, the test client returns the code `10 = 2 | 8`, indicating the failure +of both test 2 (TEST_STRUCTS) and test 8 (TEST_EXCEPTIONS). + + +## SSL +Test Keys and Certificates are provided in multiple formats under the following +directory [test/keys](keys) diff --git a/src/jaegertracing/thrift/test/Recursive.thrift b/src/jaegertracing/thrift/test/Recursive.thrift new file mode 100644 index 000000000..c9825821c --- /dev/null +++ b/src/jaegertracing/thrift/test/Recursive.thrift @@ -0,0 +1,47 @@ +/* + * 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. + */ + +struct RecTree { + 1: list<RecTree> children + 2: i16 item +} + +struct RecList { + 1: RecList & nextitem + 3: i16 item +} + +struct CoRec { + 1: CoRec2 & other +} + +struct CoRec2 { + 1: CoRec other +} + +struct VectorTest { + 1: list<RecList> lister; +} + +service TestService +{ + RecTree echoTree(1:RecTree tree) + RecList echoList(1:RecList lst) + CoRec echoCoRec(1:CoRec item) +} diff --git a/src/jaegertracing/thrift/test/ReuseObjects.thrift b/src/jaegertracing/thrift/test/ReuseObjects.thrift new file mode 100644 index 000000000..2dd6c6ec3 --- /dev/null +++ b/src/jaegertracing/thrift/test/ReuseObjects.thrift @@ -0,0 +1,30 @@ +/* + * 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. + */ + +// The java codegenerator has option to reuse objects for deserialization + +namespace java thrift.test + +include "ThriftTest.thrift" + +struct Reuse { + 1: i32 val1; + 2: set<string> val2; +} + diff --git a/src/jaegertracing/thrift/test/Service.thrift b/src/jaegertracing/thrift/test/Service.thrift new file mode 100644 index 000000000..6f4c9c7a3 --- /dev/null +++ b/src/jaegertracing/thrift/test/Service.thrift @@ -0,0 +1,24 @@ +/* + * 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. + */ + +include "Types.thrift" + +service Service { + Types.Type1 testEpisode(1:Types.Type1 arg) +} diff --git a/src/jaegertracing/thrift/test/SmallTest.thrift b/src/jaegertracing/thrift/test/SmallTest.thrift new file mode 100644 index 000000000..d0821c7ff --- /dev/null +++ b/src/jaegertracing/thrift/test/SmallTest.thrift @@ -0,0 +1,60 @@ +/* + * 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. + */ + + +namespace rb TestNamespace + +struct Goodbyez { + 1: i32 val = 325; +} + +senum Thinger { + "ASDFKJ", + "r32)*F#@", + "ASDFLJASDF" +} + +struct BoolPasser { + 1: bool value = 1 +} + +struct Hello { + 1: i32 simple = 53, + 2: map<i32,i32> complex = {23:532, 6243:632, 2355:532}, + 3: map<i32, map<i32,i32>> complexer, + 4: string words = "words", + 5: Goodbyez thinz = {'val' : 36632} +} + +const map<i32,map<i32,i32>> CMAP = { 235: {235:235}, 53:{53:53} } +const i32 CINT = 325; +const Hello WHOA = {'simple' : 532} + +exception Goodbye { + 1: i32 simple, + 2: map<i32,i32> complex, + 3: map<i32, map<i32,i32>> complexer, +} + +service SmallService { + Thinger testThinger(1:Thinger bootz), + Hello testMe(1:i32 hello=64, 2: Hello wonk) throws (1: Goodbye g), + void testVoid() throws (1: Goodbye g), + i32 testI32(1:i32 boo) +} diff --git a/src/jaegertracing/thrift/test/StressTest.thrift b/src/jaegertracing/thrift/test/StressTest.thrift new file mode 100644 index 000000000..431811b87 --- /dev/null +++ b/src/jaegertracing/thrift/test/StressTest.thrift @@ -0,0 +1,35 @@ +/* + * 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. + */ + +namespace cpp test.stress +namespace d thrift.test.stress +namespace go stress + +service Service { + + void echoVoid(), + i8 echoByte(1: i8 arg), + i32 echoI32(1: i32 arg), + i64 echoI64(1: i64 arg), + string echoString(1: string arg), + list<i8> echoList(1: list<i8> arg), + set<i8> echoSet(1: set<i8> arg), + map<i8, i8> echoMap(1: map<i8, i8> arg), +} + diff --git a/src/jaegertracing/thrift/test/ThriftTest.thrift b/src/jaegertracing/thrift/test/ThriftTest.thrift new file mode 100644 index 000000000..cf28b2adf --- /dev/null +++ b/src/jaegertracing/thrift/test/ThriftTest.thrift @@ -0,0 +1,415 @@ +/* + * 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. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +namespace c_glib TTest +namespace cpp thrift.test +namespace csharp Thrift.Test +namespace delphi Thrift.Test +namespace go thrifttest +namespace java thrift.test +namespace js ThriftTest +namespace lua ThriftTest +namespace netcore ThriftTest +namespace netstd ThriftTest +namespace perl ThriftTest +namespace php ThriftTest +namespace py ThriftTest +namespace py.twisted ThriftTest +namespace rb Thrift.Test +namespace st ThriftTest +namespace xsd test (uri = 'http://thrift.apache.org/ns/ThriftTest') + +// Presence of namespaces and sub-namespaces for which there is +// no generator should compile with warnings only +namespace noexist ThriftTest +namespace cpp.noexist ThriftTest + +namespace * thrift.test + +/** + * Docstring! + */ +enum Numberz +{ + ONE = 1, + TWO, + THREE, + FIVE = 5, + SIX, + EIGHT = 8 +} + +const Numberz myNumberz = Numberz.ONE; +// the following is expected to fail: +// const Numberz urNumberz = ONE; + +typedef i64 UserId + +struct Bonk +{ + 1: string message, + 2: i32 type +} + +typedef map<string,Bonk> MapType + +struct Bools { + 1: bool im_true, + 2: bool im_false, +} + +struct Xtruct +{ + 1: string string_thing, + 4: i8 byte_thing, + 9: i32 i32_thing, + 11: i64 i64_thing +} + +struct Xtruct2 +{ + 1: i8 byte_thing, // used to be byte, hence the name + 2: Xtruct struct_thing, + 3: i32 i32_thing +} + +struct Xtruct3 +{ + 1: string string_thing, + 4: i32 changed, + 9: i32 i32_thing, + 11: i64 i64_thing +} + + +struct Insanity +{ + 1: map<Numberz, UserId> userMap, + 2: list<Xtruct> xtructs +} (python.immutable= "") + +struct CrazyNesting { + 1: string string_field, + 2: optional set<Insanity> set_field, + // Do not insert line break as test/go/Makefile.am is removing this line with pattern match + 3: required list<map<set<i32> (python.immutable = ""), map<i32,set<list<map<Insanity,string>(python.immutable = "")> (python.immutable = "")>>>> list_field, + 4: binary binary_field +} + +union SomeUnion { + 1: map<Numberz, UserId> map_thing, + 2: string string_thing, + 3: i32 i32_thing, + 4: Xtruct3 xtruct_thing, + 5: Insanity insanity_thing +} + +exception Xception { + 1: i32 errorCode, + 2: string message +} + +exception Xception2 { + 1: i32 errorCode, + 2: Xtruct struct_thing +} + +struct EmptyStruct {} + +struct OneField { + 1: EmptyStruct field +} + +service ThriftTest +{ + /** + * Prints "testVoid()" and returns nothing. + */ + void testVoid(), + + /** + * Prints 'testString("%s")' with thing as '%s' + * @param string thing - the string to print + * @return string - returns the string 'thing' + */ + string testString(1: string thing), + + /** + * Prints 'testBool("%s")' where '%s' with thing as 'true' or 'false' + * @param bool thing - the bool data to print + * @return bool - returns the bool 'thing' + */ + bool testBool(1: bool thing), + + /** + * Prints 'testByte("%d")' with thing as '%d' + * The types i8 and byte are synonyms, use of i8 is encouraged, byte still exists for the sake of compatibility. + * @param byte thing - the i8/byte to print + * @return i8 - returns the i8/byte 'thing' + */ + i8 testByte(1: i8 thing), + + /** + * Prints 'testI32("%d")' with thing as '%d' + * @param i32 thing - the i32 to print + * @return i32 - returns the i32 'thing' + */ + i32 testI32(1: i32 thing), + + /** + * Prints 'testI64("%d")' with thing as '%d' + * @param i64 thing - the i64 to print + * @return i64 - returns the i64 'thing' + */ + i64 testI64(1: i64 thing), + + /** + * Prints 'testDouble("%f")' with thing as '%f' + * @param double thing - the double to print + * @return double - returns the double 'thing' + */ + double testDouble(1: double thing), + + /** + * Prints 'testBinary("%s")' where '%s' is a hex-formatted string of thing's data + * @param binary thing - the binary data to print + * @return binary - returns the binary 'thing' + */ + binary testBinary(1: binary thing), + + /** + * Prints 'testStruct("{%s}")' where thing has been formatted into a string of comma separated values + * @param Xtruct thing - the Xtruct to print + * @return Xtruct - returns the Xtruct 'thing' + */ + Xtruct testStruct(1: Xtruct thing), + + /** + * Prints 'testNest("{%s}")' where thing has been formatted into a string of the nested struct + * @param Xtruct2 thing - the Xtruct2 to print + * @return Xtruct2 - returns the Xtruct2 'thing' + */ + Xtruct2 testNest(1: Xtruct2 thing), + + /** + * Prints 'testMap("{%s")' where thing has been formatted into a string of 'key => value' pairs + * separated by commas and new lines + * @param map<i32,i32> thing - the map<i32,i32> to print + * @return map<i32,i32> - returns the map<i32,i32> 'thing' + */ + map<i32,i32> testMap(1: map<i32,i32> thing), + + /** + * Prints 'testStringMap("{%s}")' where thing has been formatted into a string of 'key => value' pairs + * separated by commas and new lines + * @param map<string,string> thing - the map<string,string> to print + * @return map<string,string> - returns the map<string,string> 'thing' + */ + map<string,string> testStringMap(1: map<string,string> thing), + + /** + * Prints 'testSet("{%s}")' where thing has been formatted into a string of values + * separated by commas and new lines + * @param set<i32> thing - the set<i32> to print + * @return set<i32> - returns the set<i32> 'thing' + */ + set<i32> testSet(1: set<i32> thing), + + /** + * Prints 'testList("{%s}")' where thing has been formatted into a string of values + * separated by commas and new lines + * @param list<i32> thing - the list<i32> to print + * @return list<i32> - returns the list<i32> 'thing' + */ + list<i32> testList(1: list<i32> thing), + + /** + * Prints 'testEnum("%d")' where thing has been formatted into its numeric value + * @param Numberz thing - the Numberz to print + * @return Numberz - returns the Numberz 'thing' + */ + Numberz testEnum(1: Numberz thing), + + /** + * Prints 'testTypedef("%d")' with thing as '%d' + * @param UserId thing - the UserId to print + * @return UserId - returns the UserId 'thing' + */ + UserId testTypedef(1: UserId thing), + + /** + * Prints 'testMapMap("%d")' with hello as '%d' + * @param i32 hello - the i32 to print + * @return map<i32,map<i32,i32>> - returns a dictionary with these values: + * {-4 => {-4 => -4, -3 => -3, -2 => -2, -1 => -1, }, 4 => {1 => 1, 2 => 2, 3 => 3, 4 => 4, }, } + */ + map<i32,map<i32,i32>> testMapMap(1: i32 hello), + + /** + * So you think you've got this all worked out, eh? + * + * Creates a map with these values and prints it out: + * { 1 => { 2 => argument, + * 3 => argument, + * }, + * 2 => { 6 => <empty Insanity struct>, }, + * } + * @return map<UserId, map<Numberz,Insanity>> - a map with the above values + */ + map<UserId, map<Numberz,Insanity>> testInsanity(1: Insanity argument), + + /** + * Prints 'testMulti()' + * @param i8 arg0 - + * @param i32 arg1 - + * @param i64 arg2 - + * @param map<i16, string> arg3 - + * @param Numberz arg4 - + * @param UserId arg5 - + * @return Xtruct - returns an Xtruct with string_thing = "Hello2, byte_thing = arg0, i32_thing = arg1 + * and i64_thing = arg2 + */ + Xtruct testMulti(1: i8 arg0, 2: i32 arg1, 3: i64 arg2, 4: map<i16, string> arg3, 5: Numberz arg4, 6: UserId arg5), + + /** + * Print 'testException(%s)' with arg as '%s' + * @param string arg - a string indication what type of exception to throw + * if arg == "Xception" throw Xception with errorCode = 1001 and message = arg + * else if arg == "TException" throw TException + * else do not throw anything + */ + void testException(1: string arg) throws(1: Xception err1), + + /** + * Print 'testMultiException(%s, %s)' with arg0 as '%s' and arg1 as '%s' + * @param string arg - a string indicating what type of exception to throw + * if arg0 == "Xception" throw Xception with errorCode = 1001 and message = "This is an Xception" + * else if arg0 == "Xception2" throw Xception2 with errorCode = 2002 and struct_thing.string_thing = "This is an Xception2" + * else do not throw anything + * @return Xtruct - an Xtruct with string_thing = arg1 + */ + Xtruct testMultiException(1: string arg0, 2: string arg1) throws(1: Xception err1, 2: Xception2 err2) + + /** + * Print 'testOneway(%d): Sleeping...' with secondsToSleep as '%d' + * sleep 'secondsToSleep' + * Print 'testOneway(%d): done sleeping!' with secondsToSleep as '%d' + * @param i32 secondsToSleep - the number of seconds to sleep + */ + oneway void testOneway(1:i32 secondsToSleep) +} + +service SecondService +{ + /** + * Prints 'testString("%s")' with thing as '%s' + * @param string thing - the string to print + * @return string - returns the string 'thing' + */ + string secondtestString(1: string thing) +} + +struct VersioningTestV1 { + 1: i32 begin_in_both, + 3: string old_string, + 12: i32 end_in_both +} + +struct VersioningTestV2 { + 1: i32 begin_in_both, + + 2: i32 newint, + 3: i8 newbyte, + 4: i16 newshort, + 5: i64 newlong, + 6: double newdouble + 7: Bonk newstruct, + 8: list<i32> newlist, + 9: set<i32> newset, + 10: map<i32, i32> newmap, + 11: string newstring, + 12: i32 end_in_both +} + +struct ListTypeVersioningV1 { + 1: list<i32> myints; + 2: string hello; +} + +struct ListTypeVersioningV2 { + 1: list<string> strings; + 2: string hello; +} + +struct GuessProtocolStruct { + 7: map<string,string> map_field, +} + +struct LargeDeltas { + 1: Bools b1, + 10: Bools b10, + 100: Bools b100, + 500: bool check_true, + 1000: Bools b1000, + 1500: bool check_false, + 2000: VersioningTestV2 vertwo2000, + 2500: set<string> a_set2500, + 3000: VersioningTestV2 vertwo3000, + 4000: list<i32> big_numbers +} + +struct NestedListsI32x2 { + 1: list<list<i32>> integerlist +} +struct NestedListsI32x3 { + 1: list<list<list<i32>>> integerlist +} +struct NestedMixedx2 { + 1: list<set<i32>> int_set_list + 2: map<i32,set<string>> map_int_strset + 3: list<map<i32,set<string>>> map_int_strset_list +} +struct ListBonks { + 1: list<Bonk> bonk +} +struct NestedListsBonk { + 1: list<list<list<Bonk>>> bonk +} + +struct BoolTest { + 1: optional bool b = true; + 2: optional string s = "true"; +} + +struct StructA { + 1: required string s; +} + +struct StructB { + 1: optional StructA aa; + 2: required StructA ab; +} + +struct OptionalSetDefaultTest { + 1: optional set<string> with_default = [ "test" ] +} diff --git a/src/jaegertracing/thrift/test/TypedefTest.thrift b/src/jaegertracing/thrift/test/TypedefTest.thrift new file mode 100644 index 000000000..943747855 --- /dev/null +++ b/src/jaegertracing/thrift/test/TypedefTest.thrift @@ -0,0 +1,36 @@ +/* + * 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. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +namespace cpp thrift.test + +typedef i32 MyInt32 +typedef string MyString; + +struct TypedefTestStruct { + 1: MyInt32 field_MyInt32; + 2: MyString field_MyString; + 3: i32 field_Int32; + 4: string field_String; +} + +typedef TypedefTestStruct MyStruct,
\ No newline at end of file diff --git a/src/jaegertracing/thrift/test/Types.thrift b/src/jaegertracing/thrift/test/Types.thrift new file mode 100644 index 000000000..11069d998 --- /dev/null +++ b/src/jaegertracing/thrift/test/Types.thrift @@ -0,0 +1,23 @@ +/* + * 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. + */ + +struct Type1 { + 1: i32 number, + 2: string message, +}
\ No newline at end of file diff --git a/src/jaegertracing/thrift/test/UnsafeTypes.thrift b/src/jaegertracing/thrift/test/UnsafeTypes.thrift new file mode 100644 index 000000000..b38c905eb --- /dev/null +++ b/src/jaegertracing/thrift/test/UnsafeTypes.thrift @@ -0,0 +1,24 @@ +/* + * 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. + */ + +namespace java thrift.test + +struct UnsafeBytes { + 1: binary bytes; +} diff --git a/src/jaegertracing/thrift/test/audit/README.md b/src/jaegertracing/thrift/test/audit/README.md new file mode 100644 index 000000000..412f8d5b6 --- /dev/null +++ b/src/jaegertracing/thrift/test/audit/README.md @@ -0,0 +1,40 @@ +Typical usage +============= +``` +thrift.exe --audit <oldFile> <newFile> +``` +Example run +=========== +``` +> thrift.exe --audit test.thrift break1.thrift +[Thrift Audit Failure:break1.thrift] New Thrift File has missing function base_function3 +[Thrift Audit Warning:break1.thrift] Constant const3 has different value +``` + +Problems that the audit tool can catch +====================================== +Errors +* Removing an enum value +* Changing the type of a struct field +* Changing the required-ness of a struct field +* Removing a struct field +* Adding a required struct field +* Adding a struct field 'in the middle'. This usually indicates an old ID has been recycled +* Struct removed +* Oneway-ness change +* Return type change +* Missing function +* Missing service +* Change in service inheritance + +Warnings +* Removing a language namespace declaration +* Changing a namespace +* Changing an enum value's name +* Removing an enum class +* Default value changed +* Struct field name change +* Removed constant +* Type of constant changed +* Value of constant changed +
\ No newline at end of file diff --git a/src/jaegertracing/thrift/test/audit/break1.thrift b/src/jaegertracing/thrift/test/audit/break1.thrift new file mode 100644 index 000000000..f77f67224 --- /dev/null +++ b/src/jaegertracing/thrift/test/audit/break1.thrift @@ -0,0 +1,188 @@ +/* + * 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. + */ + +//Thrift Method removed from service base. + +namespace cpp test + +//constants +const i32 const1 = 123; +const double const2 = 23.3; +const map<string,string> const3 = {"hello":"world", "thrift":"audit"}; + +//Exception +exception test_exception1 { + 1: i32 code; + 2: string json; +} +exception test_exception2 { + 1: i32 code; + 2: string json; +} + +//Enums + +enum test_enum1 { + enum1_value0 = 0, + enum1_value1 = 1, + enum1_value2 = 2, + enum1_value5 = 5, + enum1_value7 = 7, + enum1_value8 = 8 +} + +enum test_enum2 { + enum2_value0 = 0, + enum2_value1 = 1, + enum2_value2 = 2, + enum2_value3 = 3 +} + +enum test_enum3 { + enum3_value1 = 0, + enum3_value2 = 1 +} + +struct test_struct1 { + 1: i16 struct1_member1, + 2: i32 struct1_member2, + 3: i64 struct1_member3, + 4: double struct1_member4 = 2.5, + 5: string struct1_member5 = "Audit test", + 6: bool struct1_member6, + 7: byte struct1_member7, + 8: binary struct1_member8, + 9: test_enum1 struct1_member9 +} + +struct test_struct2 { + 1: list<i16> struct2_member1, + 2: list<i32> struct2_member2, + 3: list<i64> struct2_member3= [23, 32], + 4: list<double> struct2_member4, + 5: list<string> struct2_member5, + 6: list<bool> struct2_member6, + 7: list<byte> struct2_member7, + 8: list<binary> struct2_member8, + 9: list<test_enum1> struct2_member9 +} + +struct test_struct3 { + 1: map<i16, i32> struct3_member1 = {1:2, 3:4}, + 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1}, + 3: map<string, bool> struct3_member3, + 4: map<byte, test_enum1> struct3_member4, + 5: map<test_enum2, test_enum3 > struct3_member5, + 7: map<double, string> struct3_member7 +} + +struct test_struct4 { + 1: i32 struct4_member1, + 2: optional i32 struct4_member2 +} + +struct test_struct5{ + 1: double struct5_member1, + 2: string struct5_member2 = "Thrift Audit Test" +} +struct test_struct6 { + 1: i32 struct6_member1, + 2: required i32 struct6_member2 +} + +service base { + oneway void base_oneway( + 1: i32 arg1), + + void base_function1( + 1: i16 function1_arg1, + 2: i32 function1_arg2, + 3: i64 function1_arg3, + 4: double function1_arg4, + 5: string function1_arg5, + 6: bool function1_arg6, + 7: test_enum1 function1_arg7, + 8: test_struct1 function1_arg8), + + void base_function2( + 1: list<i16> function2_arg1, + 2: list<i32> function2_arg2, + 3: list<i64> function2_arg3, + 4: list<double> function2_arg4, + 5: list<string> function2_arg5, + 6: list<bool> function2_arg6, + 7: list<byte> function2_arg7, + 8: list<test_enum1> function2_arg8, + 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e), + +} + +service derived1 extends base { + + test_enum1 derived1_function1( + 1: i64 function1_arg1, + 2: double function1_arg2, + 3: test_enum1 function1_arg3) throws (1:test_exception2 e), + + i64 derived1_function2( + 1: list<i64> function2_arg1, + 2: list<double> function2_arg2, + 3: list<string> function2_arg3, + 4: list<byte> function2_arg4, + 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e), + + double derived1_function3( + 1: string function3_arg1, + 2: bool function3_arg2) throws (1:test_exception2 e), + + string derived1_function4( + 1: string function4_arg1, + 2: bool function4_arg2) throws (1:test_exception2 e), + + + bool derived1_function5( + 1: map<i64, double> function5_arg1, + 2: map<string, bool> function5_arg2, + 3: map<test_enum1, test_enum2> function5_arg3) throws (1:test_exception2 e), + + test_struct1 derived1_function6( + 1: double function6_arg1) throws (1:test_exception2 e), +} + +service derived2 extends base { + + list<i32> derived2_function1( + 1: i32 function1_arg1) throws (1:test_exception2 e), + + list<test_enum1> derived2_function2( + 1:i64 function2_arg2) throws (1:test_exception2 e), + + list<test_struct1> derived2_function3( + 1:double function3_arg1) throws(1:test_exception2 e), + + map<double, string> derived2_function4( + 1:string function4_arg1) throws(1:test_exception2 e), + + map<test_enum1, test_enum2> derived2_function5( + 1:bool function5_arg1) throws(1:test_exception2 e), + + map<test_struct1, test_struct2> derived2_function6( + 1:bool function6_arg1) throws(1:test_exception2 e), + +} diff --git a/src/jaegertracing/thrift/test/audit/break10.thrift b/src/jaegertracing/thrift/test/audit/break10.thrift new file mode 100644 index 000000000..00690aaf5 --- /dev/null +++ b/src/jaegertracing/thrift/test/audit/break10.thrift @@ -0,0 +1,190 @@ +/* + * 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. + */ + +//break10 - Struct field removed from struct2 id =1 + +namespace cpp test + +//Constants +const i32 const1 = 123; +const double const2 = 23.3; +const map<string,string> const3 = {"hello":"world", "thrift":"audit"}; + + +//Exception +exception test_exception1 { + 1: i32 code; + 2: string json; +} +exception test_exception2 { + 1: i32 code; + 2: string json; +} + +//Enums + +enum test_enum1 { + enum1_value0 = 0, + enum1_value1 = 1, + enum1_value2 = 2, + enum1_value5 = 5, + enum1_value7 = 7, + enum1_value8 = 8 +} + +enum test_enum2 { + enum2_value0 = 0, + enum2_value1 = 1, + enum2_value2 = 2, + enum2_value3 = 3 +} + +enum test_enum3 { + enum3_value1 = 0, + enum3_value2 = 1 +} + +struct test_struct1 { + 1: i16 struct1_member1, + 2: i32 struct1_member2, + 3: i64 struct1_member3, + 4: double struct1_member4 = 2.5, + 5: string struct1_member5 = "Audit test", + 6: bool struct1_member6, + 7: byte struct1_member7, + 8: binary struct1_member8, + 9: test_enum1 struct1_member9 +} + +struct test_struct2 { + 2: list<i32> struct2_member2, + 3: list<i64> struct2_member3 = [23, 32], + 4: list<double> struct2_member4, + 5: list<string> struct2_member5, + 6: list<bool> struct2_member6, + 7: list<byte> struct2_member7, + 8: list<binary> struct2_member8, + 9: list<test_enum1> struct2_member9 +} + +struct test_struct3 { + 1: map<i16, i32> struct3_member1 = {1:2, 3:4}, + 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1}, + 3: map<string, bool> struct3_member3, + 4: map<byte, test_enum1> struct3_member4, + 5: map<test_enum2, test_enum3 > struct3_member5, + 7: map<double, string> struct3_member7 +} + +struct test_struct4 { + 1: i32 struct4_member1, + 2: optional i32 struct4_member2 +} + +struct test_struct5{ + 1: double struct5_member1, + 2: string struct5_member2 = "Thrift Audit Test" +} +struct test_struct6 { + 1: i32 struct6_member1, + 2: required i32 struct6_member2 +} + +service base { + oneway void base_oneway( + 1: i32 arg1), + + void base_function1( + 1: i16 function1_arg1, + 2: i32 function1_arg2, + 3: i64 function1_arg3, + 4: double function1_arg4, + 5: string function1_arg5, + 6: bool function1_arg6, + 7: test_enum1 function1_arg7, + 8: test_struct1 function1_arg8), + + void base_function2( + 1: list<i16> function2_arg1, + 2: list<i32> function2_arg2, + 3: list<i64> function2_arg3, + 4: list<double> function2_arg4, + 5: list<string> function2_arg5, + 6: list<bool> function2_arg6, + 7: list<byte> function2_arg7, + 8: list<test_enum1> function2_arg8, + 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e), + + void base_function3(), + +} + +service derived1 extends base { + + test_enum1 derived1_function1( + 1: i64 function1_arg1, + 2: double function1_arg2, + 3: test_enum1 function1_arg3) throws (1:test_exception2 e), + + i64 derived1_function2( + 1: list<i64> function2_arg1, + 2: list<double> function2_arg2, + 3: list<string> function2_arg3, + 4: list<byte> function2_arg4, + 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e), + + double derived1_function3( + 1: string function3_arg1, + 2: bool function3_arg2) throws (1:test_exception2 e), + + string derived1_function4( + 1: string function4_arg1, + 2: bool function4_arg2) throws (1:test_exception2 e), + + + bool derived1_function5( + 1: map<i64, double> function5_arg1, + 2: map<string, bool> function5_arg2, + 3: map<test_enum1, test_enum2> function5_arg3) throws (1:test_exception2 e), + + test_struct1 derived1_function6( + 1: double function6_arg1) throws (1:test_exception2 e), +} + +service derived2 extends base { + + list<i32> derived2_function1( + 1: i32 function1_arg1) throws (1:test_exception2 e), + + list<test_enum1> derived2_function2( + 1:i64 function2_arg2) throws (1:test_exception2 e), + + list<test_struct1> derived2_function3( + 1:double function3_arg1) throws(1:test_exception2 e), + + map<double, string> derived2_function4( + 1:string function4_arg1) throws(1:test_exception2 e), + + map<test_enum1, test_enum2> derived2_function5( + 1:bool function5_arg1) throws(1:test_exception2 e), + + map<test_struct1, test_struct2> derived2_function6( + 1:bool function6_arg1) throws(1:test_exception2 e), + +} diff --git a/src/jaegertracing/thrift/test/audit/break11.thrift b/src/jaegertracing/thrift/test/audit/break11.thrift new file mode 100644 index 000000000..a4e0a7d2f --- /dev/null +++ b/src/jaegertracing/thrift/test/audit/break11.thrift @@ -0,0 +1,190 @@ +/* + * 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. + */ + +//break11 - Struct field removed from struct3 id =7 + +namespace cpp test + +//Constants +const i32 const1 = 123; +const double const2 = 23.3; +const map<string,string> const3 = {"hello":"world", "thrift":"audit"}; + + +//Exception +exception test_exception1 { + 1: i32 code; + 2: string json; +} +exception test_exception2 { + 1: i32 code; + 2: string json; +} + +//Enums + +enum test_enum1 { + enum1_value0 = 0, + enum1_value1 = 1, + enum1_value2 = 2, + enum1_value5 = 5, + enum1_value7 = 7, + enum1_value8 = 8 +} + +enum test_enum2 { + enum2_value0 = 0, + enum2_value1 = 1, + enum2_value2 = 2, + enum2_value3 = 3 +} + +enum test_enum3 { + enum3_value1 = 0, + enum3_value2 = 1 +} + +struct test_struct1 { + 1: i16 struct1_member1, + 2: i32 struct1_member2, + 3: i64 struct1_member3, + 4: double struct1_member4 = 2.5, + 5: string struct1_member5 = "Audit test", + 6: bool struct1_member6, + 7: byte struct1_member7, + 8: binary struct1_member8, + 9: test_enum1 struct1_member9 +} + +struct test_struct2 { + 1: list<i16> struct2_member1, + 2: list<i32> struct2_member2, + 3: list<i64> struct2_member3 = [23, 32 ], + 4: list<double> struct2_member4, + 5: list<string> struct2_member5, + 6: list<bool> struct2_member6, + 7: list<byte> struct2_member7, + 8: list<binary> struct2_member8, + 9: list<test_enum1> struct2_member9 +} + +struct test_struct3 { + 1: map<i16, i32> struct3_member1 = {1:2, 3:4}, + 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1}, + 3: map<string, bool> struct3_member3, + 4: map<byte, test_enum1> struct3_member4, + 5: map<test_enum2, test_enum3 > struct3_member5, +} + +struct test_struct4 { + 1: i32 struct4_member1, + 2: optional i32 struct4_member2 +} + +struct test_struct5{ + 1: double struct5_member1, + 2: string struct5_member2 = "Thrift Audit Test" +} +struct test_struct6 { + 1: i32 struct6_member1, + 2: required i32 struct6_member2 +} + +service base { + oneway void base_oneway( + 1: i32 arg1), + + void base_function1( + 1: i16 function1_arg1, + 2: i32 function1_arg2, + 3: i64 function1_arg3, + 4: double function1_arg4, + 5: string function1_arg5, + 6: bool function1_arg6, + 7: test_enum1 function1_arg7, + 8: test_struct1 function1_arg8), + + void base_function2( + 1: list<i16> function2_arg1, + 2: list<i32> function2_arg2, + 3: list<i64> function2_arg3, + 4: list<double> function2_arg4, + 5: list<string> function2_arg5, + 6: list<bool> function2_arg6, + 7: list<byte> function2_arg7, + 8: list<test_enum1> function2_arg8, + 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e), + + void base_function3(), + +} + +service derived1 extends base { + + test_enum1 derived1_function1( + 1: i64 function1_arg1, + 2: double function1_arg2, + 3: test_enum1 function1_arg3) throws (1:test_exception2 e), + + i64 derived1_function2( + 1: list<i64> function2_arg1, + 2: list<double> function2_arg2, + 3: list<string> function2_arg3, + 4: list<byte> function2_arg4, + 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e), + + double derived1_function3( + 1: string function3_arg1, + 2: bool function3_arg2) throws (1:test_exception2 e), + + string derived1_function4( + 1: string function4_arg1, + 2: bool function4_arg2) throws (1:test_exception2 e), + + + bool derived1_function5( + 1: map<i64, double> function5_arg1, + 2: map<string, bool> function5_arg2, + 3: map<test_enum1, test_enum2> function5_arg3) throws (1:test_exception2 e), + + test_struct1 derived1_function6( + 1: double function6_arg1) throws (1:test_exception2 e), +} + +service derived2 extends base { + + list<i32> derived2_function1( + 1: i32 function1_arg1) throws (1:test_exception2 e), + + list<test_enum1> derived2_function2( + 1:i64 function2_arg2) throws (1:test_exception2 e), + + list<test_struct1> derived2_function3( + 1:double function3_arg1) throws(1:test_exception2 e), + + map<double, string> derived2_function4( + 1:string function4_arg1) throws(1:test_exception2 e), + + map<test_enum1, test_enum2> derived2_function5( + 1:bool function5_arg1) throws(1:test_exception2 e), + + map<test_struct1, test_struct2> derived2_function6( + 1:bool function6_arg1) throws(1:test_exception2 e), + +} diff --git a/src/jaegertracing/thrift/test/audit/break12.thrift b/src/jaegertracing/thrift/test/audit/break12.thrift new file mode 100644 index 000000000..e5522edc7 --- /dev/null +++ b/src/jaegertracing/thrift/test/audit/break12.thrift @@ -0,0 +1,191 @@ +/* + * 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. + */ + +// derived1_function1 return type changed from enum1 to enum2 + +namespace cpp test + +//Constants +const i32 const1 = 123; +const double const2 = 23.3; +const map<string,string> const3 = {"hello":"world", "thrift":"audit"}; + + +//Exception +exception test_exception1 { + 1: i32 code; + 2: string json; +} +exception test_exception2 { + 1: i32 code; + 2: string json; +} + +//Enums + +enum test_enum1 { + enum1_value0 = 0, + enum1_value1 = 1, + enum1_value2 = 2, + enum1_value5 = 5, + enum1_value7 = 7, + enum1_value8 = 8 +} + +enum test_enum2 { + enum2_value0 = 0, + enum2_value1 = 1, + enum2_value2 = 2, + enum2_value3 = 3 +} + +enum test_enum3 { + enum3_value1 = 0, + enum3_value2 = 1 +} + +struct test_struct1 { + 1: i16 struct1_member1, + 2: i32 struct1_member2, + 3: i64 struct1_member3, + 4: double struct1_member4 = 2.5, + 5: string struct1_member5 = "Audit test", + 6: bool struct1_member6, + 7: byte struct1_member7, + 8: binary struct1_member8, + 9: test_enum1 struct1_member9 +} + +struct test_struct2 { + 1: list<i16> struct2_member1, + 2: list<i32> struct2_member2, + 3: list<i64> struct2_member3 = [23, 32 ], + 4: list<double> struct2_member4, + 5: list<string> struct2_member5, + 6: list<bool> struct2_member6, + 7: list<byte> struct2_member7, + 8: list<binary> struct2_member8, + 9: list<test_enum1> struct2_member9 +} + +struct test_struct3 { + 1: map<i16, i32> struct3_member1 = {1:2, 3:4}, + 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1}, + 3: map<string, bool> struct3_member3, + 4: map<byte, test_enum1> struct3_member4, + 5: map<test_enum2, test_enum3 > struct3_member5, + 7: map<double, string> struct3_member7 +} + +struct test_struct4 { + 1: i32 struct4_member1, + 2: optional i32 struct4_member2 +} + +struct test_struct5{ + 1: double struct5_member1, + 2: string struct5_member2 = "Thrift Audit Test" +} +struct test_struct6 { + 1: i32 struct6_member1, + 2: required i32 struct6_member2 +} + +service base { + oneway void base_oneway( + 1: i32 arg1), + + void base_function1( + 1: i16 function1_arg1, + 2: i32 function1_arg2, + 3: i64 function1_arg3, + 4: double function1_arg4, + 5: string function1_arg5, + 6: bool function1_arg6, + 7: test_enum1 function1_arg7, + 8: test_struct1 function1_arg8), + + void base_function2( + 1: list<i16> function2_arg1, + 2: list<i32> function2_arg2, + 3: list<i64> function2_arg3, + 4: list<double> function2_arg4, + 5: list<string> function2_arg5, + 6: list<bool> function2_arg6, + 7: list<byte> function2_arg7, + 8: list<test_enum1> function2_arg8, + 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e), + + void base_function3(), + +} + +service derived1 extends base { + + test_enum2 derived1_function1( + 1: i64 function1_arg1, + 2: double function1_arg2, + 3: test_enum1 function1_arg3) throws (1:test_exception2 e), + + i64 derived1_function2( + 1: list<i64> function2_arg1, + 2: list<double> function2_arg2, + 3: list<string> function2_arg3, + 4: list<byte> function2_arg4, + 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e), + + double derived1_function3( + 1: string function3_arg1, + 2: bool function3_arg2) throws (1:test_exception2 e), + + string derived1_function4( + 1: string function4_arg1, + 2: bool function4_arg2) throws (1:test_exception2 e), + + + bool derived1_function5( + 1: map<i64, double> function5_arg1, + 2: map<string, bool> function5_arg2, + 3: map<test_enum1, test_enum2> function5_arg3) throws (1:test_exception2 e), + + test_struct1 derived1_function6( + 1: double function6_arg1) throws (1:test_exception2 e), +} + +service derived2 extends base { + + list<i32> derived2_function1( + 1: i32 function1_arg1) throws (1:test_exception2 e), + + list<test_enum1> derived2_function2( + 1:i64 function2_arg2) throws (1:test_exception2 e), + + list<test_struct1> derived2_function3( + 1:double function3_arg1) throws(1:test_exception2 e), + + map<double, string> derived2_function4( + 1:string function4_arg1) throws(1:test_exception2 e), + + map<test_enum1, test_enum2> derived2_function5( + 1:bool function5_arg1) throws(1:test_exception2 e), + + map<test_struct1, test_struct2> derived2_function6( + 1:bool function6_arg1) throws(1:test_exception2 e), + +} diff --git a/src/jaegertracing/thrift/test/audit/break13.thrift b/src/jaegertracing/thrift/test/audit/break13.thrift new file mode 100644 index 000000000..66975cd0f --- /dev/null +++ b/src/jaegertracing/thrift/test/audit/break13.thrift @@ -0,0 +1,191 @@ +/* + * 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. + */ + +// derived1_function6 return type changed from struct1 to struct2 + +namespace cpp test + +//Constants +const i32 const1 = 123; +const double const2 = 23.3; +const map<string,string> const3 = {"hello":"world", "thrift":"audit"}; + + +//Exception +exception test_exception1 { + 1: i32 code; + 2: string json; +} +exception test_exception2 { + 1: i32 code; + 2: string json; +} + +//Enums + +enum test_enum1 { + enum1_value0 = 0, + enum1_value1 = 1, + enum1_value2 = 2, + enum1_value5 = 5, + enum1_value7 = 7, + enum1_value8 = 8 +} + +enum test_enum2 { + enum2_value0 = 0, + enum2_value1 = 1, + enum2_value2 = 2, + enum2_value3 = 3 +} + +enum test_enum3 { + enum3_value1 = 0, + enum3_value2 = 1 +} + +struct test_struct1 { + 1: i16 struct1_member1, + 2: i32 struct1_member2, + 3: i64 struct1_member3, + 4: double struct1_member4 = 2.5, + 5: string struct1_member5 = "Audit test", + 6: bool struct1_member6, + 7: byte struct1_member7, + 8: binary struct1_member8, + 9: test_enum1 struct1_member9 +} + +struct test_struct2 { + 1: list<i16> struct2_member1, + 2: list<i32> struct2_member2, + 3: list<i64> struct2_member3 = [23, 32 ], + 4: list<double> struct2_member4, + 5: list<string> struct2_member5, + 6: list<bool> struct2_member6, + 7: list<byte> struct2_member7, + 8: list<binary> struct2_member8, + 9: list<test_enum1> struct2_member9 +} + +struct test_struct3 { + 1: map<i16, i32> struct3_member1 = {1:2, 3:4}, + 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1}, + 3: map<string, bool> struct3_member3, + 4: map<byte, test_enum1> struct3_member4, + 5: map<test_enum2, test_enum3 > struct3_member5, + 7: map<double, string> struct3_member7 +} + +struct test_struct4 { + 1: i32 struct4_member1, + 2: optional i32 struct4_member2 +} + +struct test_struct5{ + 1: double struct5_member1, + 2: string struct5_member2 = "Thrift Audit Test" +} +struct test_struct6 { + 1: i32 struct6_member1, + 2: required i32 struct6_member2 +} + +service base { + oneway void base_oneway( + 1: i32 arg1), + + void base_function1( + 1: i16 function1_arg1, + 2: i32 function1_arg2, + 3: i64 function1_arg3, + 4: double function1_arg4, + 5: string function1_arg5, + 6: bool function1_arg6, + 7: test_enum1 function1_arg7, + 8: test_struct1 function1_arg8), + + void base_function2( + 1: list<i16> function2_arg1, + 2: list<i32> function2_arg2, + 3: list<i64> function2_arg3, + 4: list<double> function2_arg4, + 5: list<string> function2_arg5, + 6: list<bool> function2_arg6, + 7: list<byte> function2_arg7, + 8: list<test_enum1> function2_arg8, + 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e), + + void base_function3(), + +} + +service derived1 extends base { + + test_enum1 derived1_function1( + 1: i64 function1_arg1, + 2: double function1_arg2, + 3: test_enum1 function1_arg3) throws (1:test_exception2 e), + + i64 derived1_function2( + 1: list<i64> function2_arg1, + 2: list<double> function2_arg2, + 3: list<string> function2_arg3, + 4: list<byte> function2_arg4, + 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e), + + double derived1_function3( + 1: string function3_arg1, + 2: bool function3_arg2) throws (1:test_exception2 e), + + string derived1_function4( + 1: string function4_arg1, + 2: bool function4_arg2) throws (1:test_exception2 e), + + + bool derived1_function5( + 1: map<i64, double> function5_arg1, + 2: map<string, bool> function5_arg2, + 3: map<test_enum1, test_enum2> function5_arg3) throws (1:test_exception2 e), + + test_struct2 derived1_function6( + 1: double function6_arg1) throws (1:test_exception2 e), +} + +service derived2 extends base { + + list<i32> derived2_function1( + 1: i32 function1_arg1) throws (1:test_exception2 e), + + list<test_enum1> derived2_function2( + 1:i64 function2_arg2) throws (1:test_exception2 e), + + list<test_struct1> derived2_function3( + 1:double function3_arg1) throws(1:test_exception2 e), + + map<double, string> derived2_function4( + 1:string function4_arg1) throws(1:test_exception2 e), + + map<test_enum1, test_enum2> derived2_function5( + 1:bool function5_arg1) throws(1:test_exception2 e), + + map<test_struct1, test_struct2> derived2_function6( + 1:bool function6_arg1) throws(1:test_exception2 e), + +} diff --git a/src/jaegertracing/thrift/test/audit/break14.thrift b/src/jaegertracing/thrift/test/audit/break14.thrift new file mode 100644 index 000000000..4ccd503c0 --- /dev/null +++ b/src/jaegertracing/thrift/test/audit/break14.thrift @@ -0,0 +1,190 @@ +/* + * 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. + */ + +// derived1_function6 return type changed from string to double + +namespace cpp test +//Constants +const i32 const1 = 123; +const double const2 = 23.3; +const map<string,string> const3 = {"hello":"world", "thrift":"audit"}; + + +//Exception +exception test_exception1 { + 1: i32 code; + 2: string json; +} +exception test_exception2 { + 1: i32 code; + 2: string json; +} + +//Enums + +enum test_enum1 { + enum1_value0 = 0, + enum1_value1 = 1, + enum1_value2 = 2, + enum1_value5 = 5, + enum1_value7 = 7, + enum1_value8 = 8 +} + +enum test_enum2 { + enum2_value0 = 0, + enum2_value1 = 1, + enum2_value2 = 2, + enum2_value3 = 3 +} + +enum test_enum3 { + enum3_value1 = 0, + enum3_value2 = 1 +} + +struct test_struct1 { + 1: i16 struct1_member1, + 2: i32 struct1_member2, + 3: i64 struct1_member3, + 4: double struct1_member4 = 2.5, + 5: string struct1_member5 = "Audit test", + 6: bool struct1_member6, + 7: byte struct1_member7, + 8: binary struct1_member8, + 9: test_enum1 struct1_member9 +} + +struct test_struct2 { + 1: list<i16> struct2_member1, + 2: list<i32> struct2_member2, + 3: list<i64> struct2_member3 = [23, 32 ], + 4: list<double> struct2_member4, + 5: list<string> struct2_member5, + 6: list<bool> struct2_member6, + 7: list<byte> struct2_member7, + 8: list<binary> struct2_member8, + 9: list<test_enum1> struct2_member9 +} + +struct test_struct3 { + 1: map<i16, i32> struct3_member1 = {1:2, 3:4}, + 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1}, + 3: map<string, bool> struct3_member3, + 4: map<byte, test_enum1> struct3_member4, + 5: map<test_enum2, test_enum3 > struct3_member5, + 7: map<double, string> struct3_member7 +} + +struct test_struct4 { + 1: i32 struct4_member1, + 2: optional i32 struct4_member2 +} + +struct test_struct5{ + 1: double struct5_member1, + 2: string struct5_member2 = "Thrift Audit Test" +} +struct test_struct6 { + 1: i32 struct6_member1, + 2: required i32 struct6_member2 +} + +service base { + oneway void base_oneway( + 1: i32 arg1), + + void base_function1( + 1: i16 function1_arg1, + 2: i32 function1_arg2, + 3: i64 function1_arg3, + 4: double function1_arg4, + 5: string function1_arg5, + 6: bool function1_arg6, + 7: test_enum1 function1_arg7, + 8: test_struct1 function1_arg8), + + void base_function2( + 1: list<i16> function2_arg1, + 2: list<i32> function2_arg2, + 3: list<i64> function2_arg3, + 4: list<double> function2_arg4, + 5: list<string> function2_arg5, + 6: list<bool> function2_arg6, + 7: list<byte> function2_arg7, + 8: list<test_enum1> function2_arg8, + 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e), + + void base_function3(), + +} + +service derived1 extends base { + + test_enum1 derived1_function1( + 1: i64 function1_arg1, + 2: double function1_arg2, + 3: test_enum1 function1_arg3) throws (1:test_exception2 e), + + i64 derived1_function2( + 1: list<i64> function2_arg1, + 2: list<double> function2_arg2, + 3: list<string> function2_arg3, + 4: list<byte> function2_arg4, + 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e), + + double derived1_function3( + 1: string function3_arg1, + 2: bool function3_arg2) throws (1:test_exception2 e), + + double derived1_function4( + 1: string function4_arg1, + 2: bool function4_arg2) throws (1:test_exception2 e), + + + bool derived1_function5( + 1: map<i64, double> function5_arg1, + 2: map<string, bool> function5_arg2, + 3: map<test_enum1, test_enum2> function5_arg3) throws (1:test_exception2 e), + + test_struct1 derived1_function6( + 1: double function6_arg1) throws (1:test_exception2 e), +} + +service derived2 extends base { + + list<i32> derived2_function1( + 1: i32 function1_arg1) throws (1:test_exception2 e), + + list<test_enum1> derived2_function2( + 1:i64 function2_arg2) throws (1:test_exception2 e), + + list<test_struct1> derived2_function3( + 1:double function3_arg1) throws(1:test_exception2 e), + + map<double, string> derived2_function4( + 1:string function4_arg1) throws(1:test_exception2 e), + + map<test_enum1, test_enum2> derived2_function5( + 1:bool function5_arg1) throws(1:test_exception2 e), + + map<test_struct1, test_struct2> derived2_function6( + 1:bool function6_arg1) throws(1:test_exception2 e), + +} diff --git a/src/jaegertracing/thrift/test/audit/break15.thrift b/src/jaegertracing/thrift/test/audit/break15.thrift new file mode 100644 index 000000000..95f69e6a4 --- /dev/null +++ b/src/jaegertracing/thrift/test/audit/break15.thrift @@ -0,0 +1,190 @@ +/* + * 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. + */ + +// break15 - derived2_function1 return type changed from list<i32> to list<i16> +namespace cpp test + +//Constants +const i32 const1 = 123; +const double const2 = 23.3; +const map<string,string> const3 = {"hello":"world", "thrift":"audit"}; + + +//Exception +exception test_exception1 { + 1: i32 code; + 2: string json; +} +exception test_exception2 { + 1: i32 code; + 2: string json; +} + +//Enums + +enum test_enum1 { + enum1_value0 = 0, + enum1_value1 = 1, + enum1_value2 = 2, + enum1_value5 = 5, + enum1_value7 = 7, + enum1_value8 = 8 +} + +enum test_enum2 { + enum2_value0 = 0, + enum2_value1 = 1, + enum2_value2 = 2, + enum2_value3 = 3 +} + +enum test_enum3 { + enum3_value1 = 0, + enum3_value2 = 1 +} + +struct test_struct1 { + 1: i16 struct1_member1, + 2: i32 struct1_member2, + 3: i64 struct1_member3, + 4: double struct1_member4 = 2.5, + 5: string struct1_member5 = "Audit test", + 6: bool struct1_member6, + 7: byte struct1_member7, + 8: binary struct1_member8, + 9: test_enum1 struct1_member9 +} + +struct test_struct2 { + 1: list<i16> struct2_member1, + 2: list<i32> struct2_member2, + 3: list<i64> struct2_member3 = [23, 32 ], + 4: list<double> struct2_member4, + 5: list<string> struct2_member5, + 6: list<bool> struct2_member6, + 7: list<byte> struct2_member7, + 8: list<binary> struct2_member8, + 9: list<test_enum1> struct2_member9 +} + +struct test_struct3 { + 1: map<i16, i32> struct3_member1 = {1:2, 3:4}, + 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1}, + 3: map<string, bool> struct3_member3, + 4: map<byte, test_enum1> struct3_member4, + 5: map<test_enum2, test_enum3 > struct3_member5, + 7: map<double, string> struct3_member7 +} + +struct test_struct4 { + 1: i32 struct4_member1, + 2: optional i32 struct4_member2 +} + +struct test_struct5{ + 1: double struct5_member1, + 2: string struct5_member2 = "Thrift Audit Test" +} +struct test_struct6 { + 1: i32 struct6_member1, + 2: required i32 struct6_member2 +} + +service base { + oneway void base_oneway( + 1: i32 arg1), + + void base_function1( + 1: i16 function1_arg1, + 2: i32 function1_arg2, + 3: i64 function1_arg3, + 4: double function1_arg4, + 5: string function1_arg5, + 6: bool function1_arg6, + 7: test_enum1 function1_arg7, + 8: test_struct1 function1_arg8), + + void base_function2( + 1: list<i16> function2_arg1, + 2: list<i32> function2_arg2, + 3: list<i64> function2_arg3, + 4: list<double> function2_arg4, + 5: list<string> function2_arg5, + 6: list<bool> function2_arg6, + 7: list<byte> function2_arg7, + 8: list<test_enum1> function2_arg8, + 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e), + + void base_function3(), + +} + +service derived1 extends base { + + test_enum1 derived1_function1( + 1: i64 function1_arg1, + 2: double function1_arg2, + 3: test_enum1 function1_arg3) throws (1:test_exception2 e), + + i64 derived1_function2( + 1: list<i64> function2_arg1, + 2: list<double> function2_arg2, + 3: list<string> function2_arg3, + 4: list<byte> function2_arg4, + 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e), + + double derived1_function3( + 1: string function3_arg1, + 2: bool function3_arg2) throws (1:test_exception2 e), + + string derived1_function4( + 1: string function4_arg1, + 2: bool function4_arg2) throws (1:test_exception2 e), + + + bool derived1_function5( + 1: map<i64, double> function5_arg1, + 2: map<string, bool> function5_arg2, + 3: map<test_enum1, test_enum2> function5_arg3) throws (1:test_exception2 e), + + test_struct1 derived1_function6( + 1: double function6_arg1) throws (1:test_exception2 e), +} + +service derived2 extends base { + + list<i16> derived2_function1( + 1: i32 function1_arg1) throws (1:test_exception2 e), + + list<test_enum1> derived2_function2( + 1:i64 function2_arg2) throws (1:test_exception2 e), + + list<test_struct1> derived2_function3( + 1:double function3_arg1) throws(1:test_exception2 e), + + map<double, string> derived2_function4( + 1:string function4_arg1) throws(1:test_exception2 e), + + map<test_enum1, test_enum2> derived2_function5( + 1:bool function5_arg1) throws(1:test_exception2 e), + + map<test_struct1, test_struct2> derived2_function6( + 1:bool function6_arg1) throws(1:test_exception2 e), + +} diff --git a/src/jaegertracing/thrift/test/audit/break16.thrift b/src/jaegertracing/thrift/test/audit/break16.thrift new file mode 100644 index 000000000..cdcff7d88 --- /dev/null +++ b/src/jaegertracing/thrift/test/audit/break16.thrift @@ -0,0 +1,191 @@ +/* + * 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. + */ + +// break 16 - derived2_function5 return type changed from map<test_enum1, test_enum2> to map<test_enum3, test_enum2> + +namespace cpp test + +//Constants +const i32 const1 = 123; +const double const2 = 23.3; +const map<string,string> const3 = {"hello":"world", "thrift":"audit"}; + + +//Exception +exception test_exception1 { + 1: i32 code; + 2: string json; +} +exception test_exception2 { + 1: i32 code; + 2: string json; +} + +//Enums + +enum test_enum1 { + enum1_value0 = 0, + enum1_value1 = 1, + enum1_value2 = 2, + enum1_value5 = 5, + enum1_value7 = 7, + enum1_value8 = 8 +} + +enum test_enum2 { + enum2_value0 = 0, + enum2_value1 = 1, + enum2_value2 = 2, + enum2_value3 = 3 +} + +enum test_enum3 { + enum3_value1 = 0, + enum3_value2 = 1 +} + +struct test_struct1 { + 1: i16 struct1_member1, + 2: i32 struct1_member2, + 3: i64 struct1_member3, + 4: double struct1_member4 = 2.5, + 5: string struct1_member5 = "Audit test", + 6: bool struct1_member6, + 7: byte struct1_member7, + 8: binary struct1_member8, + 9: test_enum1 struct1_member9 +} + +struct test_struct2 { + 1: list<i16> struct2_member1, + 2: list<i32> struct2_member2, + 3: list<i64> struct2_member3 = [23, 32 ], + 4: list<double> struct2_member4, + 5: list<string> struct2_member5, + 6: list<bool> struct2_member6, + 7: list<byte> struct2_member7, + 8: list<binary> struct2_member8, + 9: list<test_enum1> struct2_member9 +} + +struct test_struct3 { + 1: map<i16, i32> struct3_member1 = {1:2, 3:4}, + 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1}, + 3: map<string, bool> struct3_member3, + 4: map<byte, test_enum1> struct3_member4, + 5: map<test_enum2, test_enum3 > struct3_member5, + 7: map<double, string> struct3_member7 +} + +struct test_struct4 { + 1: i32 struct4_member1, + 2: optional i32 struct4_member2 +} + +struct test_struct5{ + 1: double struct5_member1, + 2: string struct5_member2 = "Thrift Audit Test" +} +struct test_struct6 { + 1: i32 struct6_member1, + 2: required i32 struct6_member2 +} + +service base { + oneway void base_oneway( + 1: i32 arg1), + + void base_function1( + 1: i16 function1_arg1, + 2: i32 function1_arg2, + 3: i64 function1_arg3, + 4: double function1_arg4, + 5: string function1_arg5, + 6: bool function1_arg6, + 7: test_enum1 function1_arg7, + 8: test_struct1 function1_arg8), + + void base_function2( + 1: list<i16> function2_arg1, + 2: list<i32> function2_arg2, + 3: list<i64> function2_arg3, + 4: list<double> function2_arg4, + 5: list<string> function2_arg5, + 6: list<bool> function2_arg6, + 7: list<byte> function2_arg7, + 8: list<test_enum1> function2_arg8, + 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e), + + void base_function3(), + +} + +service derived1 extends base { + + test_enum1 derived1_function1( + 1: i64 function1_arg1, + 2: double function1_arg2, + 3: test_enum1 function1_arg3) throws (1:test_exception2 e), + + i64 derived1_function2( + 1: list<i64> function2_arg1, + 2: list<double> function2_arg2, + 3: list<string> function2_arg3, + 4: list<byte> function2_arg4, + 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e), + + double derived1_function3( + 1: string function3_arg1, + 2: bool function3_arg2) throws (1:test_exception2 e), + + string derived1_function4( + 1: string function4_arg1, + 2: bool function4_arg2) throws (1:test_exception2 e), + + + bool derived1_function5( + 1: map<i64, double> function5_arg1, + 2: map<string, bool> function5_arg2, + 3: map<test_enum1, test_enum2> function5_arg3) throws (1:test_exception2 e), + + test_struct1 derived1_function6( + 1: double function6_arg1) throws (1:test_exception2 e), +} + +service derived2 extends base { + + list<i32> derived2_function1( + 1: i32 function1_arg1) throws (1:test_exception2 e), + + list<test_enum1> derived2_function2( + 1:i64 function2_arg2) throws (1:test_exception2 e), + + list<test_struct1> derived2_function3( + 1:double function3_arg1) throws(1:test_exception2 e), + + map<double, string> derived2_function4( + 1:string function4_arg1) throws(1:test_exception2 e), + + map<test_enum3, test_enum2> derived2_function5( + 1:bool function5_arg1) throws(1:test_exception2 e), + + map<test_struct1, test_struct2> derived2_function6( + 1:bool function6_arg1) throws(1:test_exception2 e), + +} diff --git a/src/jaegertracing/thrift/test/audit/break17.thrift b/src/jaegertracing/thrift/test/audit/break17.thrift new file mode 100644 index 000000000..353b1422c --- /dev/null +++ b/src/jaegertracing/thrift/test/audit/break17.thrift @@ -0,0 +1,191 @@ +/* + * 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. + */ + +//break17 - derived2_function6 return type changed from map<struct1,struct2> to map<struct1, struct3> + +namespace cpp test + +//Constants +const i32 const1 = 123; +const double const2 = 23.3; +const map<string,string> const3 = {"hello":"world", "thrift":"audit"}; + + +//Exception +exception test_exception1 { + 1: i32 code; + 2: string json; +} +exception test_exception2 { + 1: i32 code; + 2: string json; +} + +//Enums + +enum test_enum1 { + enum1_value0 = 0, + enum1_value1 = 1, + enum1_value2 = 2, + enum1_value5 = 5, + enum1_value7 = 7, + enum1_value8 = 8 +} + +enum test_enum2 { + enum2_value0 = 0, + enum2_value1 = 1, + enum2_value2 = 2, + enum2_value3 = 3 +} + +enum test_enum3 { + enum3_value1 = 0, + enum3_value2 = 1 +} + +struct test_struct1 { + 1: i16 struct1_member1, + 2: i32 struct1_member2, + 3: i64 struct1_member3, + 4: double struct1_member4 = 2.5, + 5: string struct1_member5 = "Audit test", + 6: bool struct1_member6, + 7: byte struct1_member7, + 8: binary struct1_member8, + 9: test_enum1 struct1_member9 +} + +struct test_struct2 { + 1: list<i16> struct2_member1, + 2: list<i32> struct2_member2, + 3: list<i64> struct2_member3 = [23, 32 ], + 4: list<double> struct2_member4, + 5: list<string> struct2_member5, + 6: list<bool> struct2_member6, + 7: list<byte> struct2_member7, + 8: list<binary> struct2_member8, + 9: list<test_enum1> struct2_member9 +} + +struct test_struct3 { + 1: map<i16, i32> struct3_member1 = {1:2, 3:4}, + 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1}, + 3: map<string, bool> struct3_member3, + 4: map<byte, test_enum1> struct3_member4, + 5: map<test_enum2, test_enum3 > struct3_member5, + 7: map<double, string> struct3_member7 +} + +struct test_struct4 { + 1: i32 struct4_member1, + 2: optional i32 struct4_member2 +} + +struct test_struct5{ + 1: double struct5_member1, + 2: string struct5_member2 = "Thrift Audit Test" +} +struct test_struct6 { + 1: i32 struct6_member1, + 2: required i32 struct6_member2 +} + +service base { + oneway void base_oneway( + 1: i32 arg1), + + void base_function1( + 1: i16 function1_arg1, + 2: i32 function1_arg2, + 3: i64 function1_arg3, + 4: double function1_arg4, + 5: string function1_arg5, + 6: bool function1_arg6, + 7: test_enum1 function1_arg7, + 8: test_struct1 function1_arg8), + + void base_function2( + 1: list<i16> function2_arg1, + 2: list<i32> function2_arg2, + 3: list<i64> function2_arg3, + 4: list<double> function2_arg4, + 5: list<string> function2_arg5, + 6: list<bool> function2_arg6, + 7: list<byte> function2_arg7, + 8: list<test_enum1> function2_arg8, + 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e), + + void base_function3(), + +} + +service derived1 extends base { + + test_enum1 derived1_function1( + 1: i64 function1_arg1, + 2: double function1_arg2, + 3: test_enum1 function1_arg3) throws (1:test_exception2 e), + + i64 derived1_function2( + 1: list<i64> function2_arg1, + 2: list<double> function2_arg2, + 3: list<string> function2_arg3, + 4: list<byte> function2_arg4, + 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e), + + double derived1_function3( + 1: string function3_arg1, + 2: bool function3_arg2) throws (1:test_exception2 e), + + string derived1_function4( + 1: string function4_arg1, + 2: bool function4_arg2) throws (1:test_exception2 e), + + + bool derived1_function5( + 1: map<i64, double> function5_arg1, + 2: map<string, bool> function5_arg2, + 3: map<test_enum1, test_enum2> function5_arg3) throws (1:test_exception2 e), + + test_struct1 derived1_function6( + 1: double function6_arg1) throws (1:test_exception2 e), +} + +service derived2 extends base { + + list<i32> derived2_function1( + 1: i32 function1_arg1) throws (1:test_exception2 e), + + list<test_enum1> derived2_function2( + 1:i64 function2_arg2) throws (1:test_exception2 e), + + list<test_struct1> derived2_function3( + 1:double function3_arg1) throws(1:test_exception2 e), + + map<double, string> derived2_function4( + 1:string function4_arg1) throws(1:test_exception2 e), + + map<test_enum1, test_enum2> derived2_function5( + 1:bool function5_arg1) throws(1:test_exception2 e), + + map<test_struct1, test_struct3> derived2_function6( + 1:bool function6_arg1) throws(1:test_exception2 e), + +} diff --git a/src/jaegertracing/thrift/test/audit/break18.thrift b/src/jaegertracing/thrift/test/audit/break18.thrift new file mode 100644 index 000000000..c778b6a0c --- /dev/null +++ b/src/jaegertracing/thrift/test/audit/break18.thrift @@ -0,0 +1,191 @@ +/* + * 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. + */ + +//break18- oneway removed from base_oneway + +namespace cpp test + +//Constants +const i32 const1 = 123; +const double const2 = 23.3; +const map<string,string> const3 = {"hello":"world", "thrift":"audit"}; + + +//Exception +exception test_exception1 { + 1: i32 code; + 2: string json; +} +exception test_exception2 { + 1: i32 code; + 2: string json; +} + +//Enums + +enum test_enum1 { + enum1_value0 = 0, + enum1_value1 = 1, + enum1_value2 = 2, + enum1_value5 = 5, + enum1_value7 = 7, + enum1_value8 = 8 +} + +enum test_enum2 { + enum2_value0 = 0, + enum2_value1 = 1, + enum2_value2 = 2, + enum2_value3 = 3 +} + +enum test_enum3 { + enum3_value1 = 0, + enum3_value2 = 1 +} + +struct test_struct1 { + 1: i16 struct1_member1, + 2: i32 struct1_member2, + 3: i64 struct1_member3, + 4: double struct1_member4 = 2.5, + 5: string struct1_member5 = "Audit test", + 6: bool struct1_member6, + 7: byte struct1_member7, + 8: binary struct1_member8, + 9: test_enum1 struct1_member9 +} + +struct test_struct2 { + 1: list<i16> struct2_member1, + 2: list<i32> struct2_member2, + 3: list<i64> struct2_member3 = [23, 32 ], + 4: list<double> struct2_member4, + 5: list<string> struct2_member5, + 6: list<bool> struct2_member6, + 7: list<byte> struct2_member7, + 8: list<binary> struct2_member8, + 9: list<test_enum1> struct2_member9 +} + +struct test_struct3 { + 1: map<i16, i32> struct3_member1 = {1:2, 3:4}, + 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1}, + 3: map<string, bool> struct3_member3, + 4: map<byte, test_enum1> struct3_member4, + 5: map<test_enum2, test_enum3 > struct3_member5, + 7: map<double, string> struct3_member7 +} + +struct test_struct4 { + 1: i32 struct4_member1, + 2: optional i32 struct4_member2 +} + +struct test_struct5{ + 1: double struct5_member1, + 2: string struct5_member2 = "Thrift Audit Test" +} +struct test_struct6 { + 1: i32 struct6_member1, + 2: required i32 struct6_member2 +} + +service base { + void base_oneway( + 1: i32 arg1), + + void base_function1( + 1: i16 function1_arg1, + 2: i32 function1_arg2, + 3: i64 function1_arg3, + 4: double function1_arg4, + 5: string function1_arg5, + 6: bool function1_arg6, + 7: test_enum1 function1_arg7, + 8: test_struct1 function1_arg8), + + void base_function2( + 1: list<i16> function2_arg1, + 2: list<i32> function2_arg2, + 3: list<i64> function2_arg3, + 4: list<double> function2_arg4, + 5: list<string> function2_arg5, + 6: list<bool> function2_arg6, + 7: list<byte> function2_arg7, + 8: list<test_enum1> function2_arg8, + 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e), + + void base_function3(), + +} + +service derived1 extends base { + + test_enum1 derived1_function1( + 1: i64 function1_arg1, + 2: double function1_arg2, + 3: test_enum1 function1_arg3) throws (1:test_exception2 e), + + i64 derived1_function2( + 1: list<i64> function2_arg1, + 2: list<double> function2_arg2, + 3: list<string> function2_arg3, + 4: list<byte> function2_arg4, + 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e), + + double derived1_function3( + 1: string function3_arg1, + 2: bool function3_arg2) throws (1:test_exception2 e), + + string derived1_function4( + 1: string function4_arg1, + 2: bool function4_arg2) throws (1:test_exception2 e), + + + bool derived1_function5( + 1: map<i64, double> function5_arg1, + 2: map<string, bool> function5_arg2, + 3: map<test_enum1, test_enum2> function5_arg3) throws (1:test_exception2 e), + + test_struct1 derived1_function6( + 1: double function6_arg1) throws (1:test_exception2 e), +} + +service derived2 extends base { + + list<i32> derived2_function1( + 1: i32 function1_arg1) throws (1:test_exception2 e), + + list<test_enum1> derived2_function2( + 1:i64 function2_arg2) throws (1:test_exception2 e), + + list<test_struct1> derived2_function3( + 1:double function3_arg1) throws(1:test_exception2 e), + + map<double, string> derived2_function4( + 1:string function4_arg1) throws(1:test_exception2 e), + + map<test_enum1, test_enum2> derived2_function5( + 1:bool function5_arg1) throws(1:test_exception2 e), + + map<test_struct1, test_struct2> derived2_function6( + 1:bool function6_arg1) throws(1:test_exception2 e), + +} diff --git a/src/jaegertracing/thrift/test/audit/break19.thrift b/src/jaegertracing/thrift/test/audit/break19.thrift new file mode 100644 index 000000000..1a0b2296d --- /dev/null +++ b/src/jaegertracing/thrift/test/audit/break19.thrift @@ -0,0 +1,191 @@ +/* + * 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. + */ + +//break19 - oneway added to base_function1 + +namespace cpp test + +//Constants +const i32 const1 = 123; +const double const2 = 23.3; +const map<string,string> const3 = {"hello":"world", "thrift":"audit"}; + + +//Exception +exception test_exception1 { + 1: i32 code; + 2: string json; +} +exception test_exception2 { + 1: i32 code; + 2: string json; +} + +//Enums + +enum test_enum1 { + enum1_value0 = 0, + enum1_value1 = 1, + enum1_value2 = 2, + enum1_value5 = 5, + enum1_value7 = 7, + enum1_value8 = 8 +} + +enum test_enum2 { + enum2_value0 = 0, + enum2_value1 = 1, + enum2_value2 = 2, + enum2_value3 = 3 +} + +enum test_enum3 { + enum3_value1 = 0, + enum3_value2 = 1 +} + +struct test_struct1 { + 1: i16 struct1_member1, + 2: i32 struct1_member2, + 3: i64 struct1_member3, + 4: double struct1_member4 = 2.5, + 5: string struct1_member5 = "Audit test", + 6: bool struct1_member6, + 7: byte struct1_member7, + 8: binary struct1_member8, + 9: test_enum1 struct1_member9 +} + +struct test_struct2 { + 1: list<i16> struct2_member1, + 2: list<i32> struct2_member2, + 3: list<i64> struct2_member3 = [23, 32 ], + 4: list<double> struct2_member4, + 5: list<string> struct2_member5, + 6: list<bool> struct2_member6, + 7: list<byte> struct2_member7, + 8: list<binary> struct2_member8, + 9: list<test_enum1> struct2_member9 +} + +struct test_struct3 { + 1: map<i16, i32> struct3_member1 = {1:2, 3:4}, + 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1}, + 3: map<string, bool> struct3_member3, + 4: map<byte, test_enum1> struct3_member4, + 5: map<test_enum2, test_enum3 > struct3_member5, + 7: map<double, string> struct3_member7 +} + +struct test_struct4 { + 1: i32 struct4_member1, + 2: optional i32 struct4_member2 +} + +struct test_struct5{ + 1: double struct5_member1, + 2: string struct5_member2 = "Thrift Audit Test" +} +struct test_struct6 { + 1: i32 struct6_member1, + 2: required i32 struct6_member2 +} + +service base { + oneway void base_oneway( + 1: i32 arg1), + + oneway void base_function1( + 1: i16 function1_arg1, + 2: i32 function1_arg2, + 3: i64 function1_arg3, + 4: double function1_arg4, + 5: string function1_arg5, + 6: bool function1_arg6, + 7: test_enum1 function1_arg7, + 8: test_struct1 function1_arg8), + + void base_function2( + 1: list<i16> function2_arg1, + 2: list<i32> function2_arg2, + 3: list<i64> function2_arg3, + 4: list<double> function2_arg4, + 5: list<string> function2_arg5, + 6: list<bool> function2_arg6, + 7: list<byte> function2_arg7, + 8: list<test_enum1> function2_arg8, + 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e), + + void base_function3(), + +} + +service derived1 extends base { + + test_enum1 derived1_function1( + 1: i64 function1_arg1, + 2: double function1_arg2, + 3: test_enum1 function1_arg3) throws (1:test_exception2 e), + + i64 derived1_function2( + 1: list<i64> function2_arg1, + 2: list<double> function2_arg2, + 3: list<string> function2_arg3, + 4: list<byte> function2_arg4, + 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e), + + double derived1_function3( + 1: string function3_arg1, + 2: bool function3_arg2) throws (1:test_exception2 e), + + string derived1_function4( + 1: string function4_arg1, + 2: bool function4_arg2) throws (1:test_exception2 e), + + + bool derived1_function5( + 1: map<i64, double> function5_arg1, + 2: map<string, bool> function5_arg2, + 3: map<test_enum1, test_enum2> function5_arg3) throws (1:test_exception2 e), + + test_struct1 derived1_function6( + 1: double function6_arg1) throws (1:test_exception2 e), +} + +service derived2 extends base { + + list<i32> derived2_function1( + 1: i32 function1_arg1) throws (1:test_exception2 e), + + list<test_enum1> derived2_function2( + 1:i64 function2_arg2) throws (1:test_exception2 e), + + list<test_struct1> derived2_function3( + 1:double function3_arg1) throws(1:test_exception2 e), + + map<double, string> derived2_function4( + 1:string function4_arg1) throws(1:test_exception2 e), + + map<test_enum1, test_enum2> derived2_function5( + 1:bool function5_arg1) throws(1:test_exception2 e), + + map<test_struct1, test_struct2> derived2_function6( + 1:bool function6_arg1) throws(1:test_exception2 e), + +} diff --git a/src/jaegertracing/thrift/test/audit/break2.thrift b/src/jaegertracing/thrift/test/audit/break2.thrift new file mode 100644 index 000000000..6f4fe2dd2 --- /dev/null +++ b/src/jaegertracing/thrift/test/audit/break2.thrift @@ -0,0 +1,190 @@ +/* + * 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. + */ + +//Struct field changed in test_struct1 + +namespace cpp test + +//Constants +const i32 const1 = 123; +const double const2 = 23.3; +const map<string,string> const3 = {"hello":"world", "thrift":"audit"}; + +//Exception +exception test_exception1 { + 1: i32 code; + 2: string json; +} +exception test_exception2 { + 1: i32 code; + 2: string json; +} + +//Enums + +enum test_enum1 { + enum1_value0 = 0, + enum1_value1 = 1, + enum1_value2 = 2, + enum1_value5 = 5, + enum1_value7 = 7, + enum1_value8 = 8 +} + +enum test_enum2 { + enum2_value0 = 0, + enum2_value1 = 1, + enum2_value2 = 2, + enum2_value3 = 3 +} + +enum test_enum3 { + enum3_value1 = 0, + enum3_value2 = 1 +} + +struct test_struct1 { + 1: i32 struct1_member1, + 2: i32 struct1_member2, + 3: i64 struct1_member3, + 4: double struct1_member4 = 2.5, + 5: string struct1_member5 = "Audit test", + 6: bool struct1_member6, + 7: byte struct1_member7, + 8: binary struct1_member8, + 9: test_enum1 struct1_member9 +} + +struct test_struct2 { + 1: list<i16> struct2_member1, + 2: list<i32> struct2_member2, + 3: list<i64> struct2_member3 = [23, 32], + 4: list<double> struct2_member4, + 5: list<string> struct2_member5, + 6: list<bool> struct2_member6, + 7: list<byte> struct2_member7, + 8: list<binary> struct2_member8, + 9: list<test_enum1> struct2_member9 +} + +struct test_struct3 { + 1: map<i16, i32> struct3_member1 = {1:2, 3:4}, + 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1}, + 3: map<string, bool> struct3_member3, + 4: map<byte, test_enum1> struct3_member4, + 5: map<test_enum2, test_enum3 > struct3_member5, + 7: map<double, string> struct3_member7 +} + +struct test_struct4 { + 1: i32 struct4_member1, + 2: optional i32 struct4_member2 +} + +struct test_struct5{ + 1: double struct5_member1, + 2: string struct5_member2 = "Thrift Audit Test" +} +struct test_struct6 { + 1: i32 struct6_member1, + 2: required i32 struct6_member2 +} + +service base { + oneway void base_oneway( + 1: i32 arg1), + + void base_function1( + 1: i16 function1_arg1, + 2: i32 function1_arg2, + 3: i64 function1_arg3, + 4: double function1_arg4, + 5: string function1_arg5, + 6: bool function1_arg6, + 7: test_enum1 function1_arg7, + 8: test_struct1 function1_arg8), + + void base_function2( + 1: list<i16> function2_arg1, + 2: list<i32> function2_arg2, + 3: list<i64> function2_arg3, + 4: list<double> function2_arg4, + 5: list<string> function2_arg5, + 6: list<bool> function2_arg6, + 7: list<byte> function2_arg7, + 8: list<test_enum1> function2_arg8, + 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e), + + void base_function3(), + +} + +service derived1 extends base { + + test_enum1 derived1_function1( + 1: i64 function1_arg1, + 2: double function1_arg2, + 3: test_enum1 function1_arg3) throws (1:test_exception2 e), + + i64 derived1_function2( + 1: list<i64> function2_arg1, + 2: list<double> function2_arg2, + 3: list<string> function2_arg3, + 4: list<byte> function2_arg4, + 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e), + + double derived1_function3( + 1: string function3_arg1, + 2: bool function3_arg2) throws (1:test_exception2 e), + + string derived1_function4( + 1: string function4_arg1, + 2: bool function4_arg2) throws (1:test_exception2 e), + + + bool derived1_function5( + 1: map<i64, double> function5_arg1, + 2: map<string, bool> function5_arg2, + 3: map<test_enum1, test_enum2> function5_arg3) throws (1:test_exception2 e), + + test_struct1 derived1_function6( + 1: double function6_arg1) throws (1:test_exception2 e), +} + +service derived2 extends base { + + list<i32> derived2_function1( + 1: i32 function1_arg1) throws (1:test_exception2 e), + + list<test_enum1> derived2_function2( + 1:i64 function2_arg2) throws (1:test_exception2 e), + + list<test_struct1> derived2_function3( + 1:double function3_arg1) throws(1:test_exception2 e), + + map<double, string> derived2_function4( + 1:string function4_arg1) throws(1:test_exception2 e), + + map<test_enum1, test_enum2> derived2_function5( + 1:bool function5_arg1) throws(1:test_exception2 e), + + map<test_struct1, test_struct2> derived2_function6( + 1:bool function6_arg1) throws(1:test_exception2 e), + +} diff --git a/src/jaegertracing/thrift/test/audit/break20.thrift b/src/jaegertracing/thrift/test/audit/break20.thrift new file mode 100644 index 000000000..9ae5f001e --- /dev/null +++ b/src/jaegertracing/thrift/test/audit/break20.thrift @@ -0,0 +1,190 @@ +/* + * 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. + */ + +// break 20 - first enum value removed from enum1 + +namespace cpp test + +//Constants +const i32 const1 = 123; +const double const2 = 23.3; +const map<string,string> const3 = {"hello":"world", "thrift":"audit"}; + + +//Exception +exception test_exception1 { + 1: i32 code; + 2: string json; +} +exception test_exception2 { + 1: i32 code; + 2: string json; +} + +//Enums + +enum test_enum1 { + enum1_value1 = 1, + enum1_value2 = 2, + enum1_value5 = 5, + enum1_value7 = 7, + enum1_value8 = 8 +} + +enum test_enum2 { + enum2_value0 = 0, + enum2_value1 = 1, + enum2_value2 = 2, + enum2_value3 = 3 +} + +enum test_enum3 { + enum3_value1 = 0, + enum3_value2 = 1 +} + +struct test_struct1 { + 1: i16 struct1_member1, + 2: i32 struct1_member2, + 3: i64 struct1_member3, + 4: double struct1_member4 = 2.5, + 5: string struct1_member5 = "Audit test", + 6: bool struct1_member6, + 7: byte struct1_member7, + 8: binary struct1_member8, + 9: test_enum1 struct1_member9 +} + +struct test_struct2 { + 1: list<i16> struct2_member1, + 2: list<i32> struct2_member2, + 3: list<i64> struct2_member3 = [23, 32 ], + 4: list<double> struct2_member4, + 5: list<string> struct2_member5, + 6: list<bool> struct2_member6, + 7: list<byte> struct2_member7, + 8: list<binary> struct2_member8, + 9: list<test_enum1> struct2_member9 +} + +struct test_struct3 { + 1: map<i16, i32> struct3_member1 = {1:2, 3:4}, + 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1}, + 3: map<string, bool> struct3_member3, + 4: map<byte, test_enum1> struct3_member4, + 5: map<test_enum2, test_enum3 > struct3_member5, + 7: map<double, string> struct3_member7 +} + +struct test_struct4 { + 1: i32 struct4_member1, + 2: optional i32 struct4_member2 +} + +struct test_struct5{ + 1: double struct5_member1, + 2: string struct5_member2 = "Thrift Audit Test" +} +struct test_struct6 { + 1: i32 struct6_member1, + 2: required i32 struct6_member2 +} + +service base { + oneway void base_oneway( + 1: i32 arg1), + + void base_function1( + 1: i16 function1_arg1, + 2: i32 function1_arg2, + 3: i64 function1_arg3, + 4: double function1_arg4, + 5: string function1_arg5, + 6: bool function1_arg6, + 7: test_enum1 function1_arg7, + 8: test_struct1 function1_arg8), + + void base_function2( + 1: list<i16> function2_arg1, + 2: list<i32> function2_arg2, + 3: list<i64> function2_arg3, + 4: list<double> function2_arg4, + 5: list<string> function2_arg5, + 6: list<bool> function2_arg6, + 7: list<byte> function2_arg7, + 8: list<test_enum1> function2_arg8, + 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e), + + void base_function3(), + +} + +service derived1 extends base { + + test_enum1 derived1_function1( + 1: i64 function1_arg1, + 2: double function1_arg2, + 3: test_enum1 function1_arg3) throws (1:test_exception2 e), + + i64 derived1_function2( + 1: list<i64> function2_arg1, + 2: list<double> function2_arg2, + 3: list<string> function2_arg3, + 4: list<byte> function2_arg4, + 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e), + + double derived1_function3( + 1: string function3_arg1, + 2: bool function3_arg2) throws (1:test_exception2 e), + + string derived1_function4( + 1: string function4_arg1, + 2: bool function4_arg2) throws (1:test_exception2 e), + + + bool derived1_function5( + 1: map<i64, double> function5_arg1, + 2: map<string, bool> function5_arg2, + 3: map<test_enum1, test_enum2> function5_arg3) throws (1:test_exception2 e), + + test_struct1 derived1_function6( + 1: double function6_arg1) throws (1:test_exception2 e), +} + +service derived2 extends base { + + list<i32> derived2_function1( + 1: i32 function1_arg1) throws (1:test_exception2 e), + + list<test_enum1> derived2_function2( + 1:i64 function2_arg2) throws (1:test_exception2 e), + + list<test_struct1> derived2_function3( + 1:double function3_arg1) throws(1:test_exception2 e), + + map<double, string> derived2_function4( + 1:string function4_arg1) throws(1:test_exception2 e), + + map<test_enum1, test_enum2> derived2_function5( + 1:bool function5_arg1) throws(1:test_exception2 e), + + map<test_struct1, test_struct2> derived2_function6( + 1:bool function6_arg1) throws(1:test_exception2 e), + +} diff --git a/src/jaegertracing/thrift/test/audit/break21.thrift b/src/jaegertracing/thrift/test/audit/break21.thrift new file mode 100644 index 000000000..f7da40022 --- /dev/null +++ b/src/jaegertracing/thrift/test/audit/break21.thrift @@ -0,0 +1,190 @@ +/* + * 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. + */ + +//break21- last enum value removed from enum2 + +namespace cpp test + +//Constants +const i32 const1 = 123; +const double const2 = 23.3; +const map<string,string> const3 = {"hello":"world", "thrift":"audit"}; + + +//Exception +exception test_exception1 { + 1: i32 code; + 2: string json; +} +exception test_exception2 { + 1: i32 code; + 2: string json; +} + +//Enums + +enum test_enum1 { + enum1_value0 = 0, + enum1_value1 = 1, + enum1_value2 = 2, + enum1_value5 = 5, + enum1_value7 = 7, + enum1_value8 = 8 +} + +enum test_enum2 { + enum2_value0 = 0, + enum2_value1 = 1, + enum2_value2 = 2, +} + +enum test_enum3 { + enum3_value1 = 0, + enum3_value2 = 1 +} + +struct test_struct1 { + 1: i16 struct1_member1, + 2: i32 struct1_member2, + 3: i64 struct1_member3, + 4: double struct1_member4 = 2.5, + 5: string struct1_member5 = "Audit test", + 6: bool struct1_member6, + 7: byte struct1_member7, + 8: binary struct1_member8, + 9: test_enum1 struct1_member9 +} + +struct test_struct2 { + 1: list<i16> struct2_member1, + 2: list<i32> struct2_member2, + 3: list<i64> struct2_member3 = [23, 32 ], + 4: list<double> struct2_member4, + 5: list<string> struct2_member5, + 6: list<bool> struct2_member6, + 7: list<byte> struct2_member7, + 8: list<binary> struct2_member8, + 9: list<test_enum1> struct2_member9 +} + +struct test_struct3 { + 1: map<i16, i32> struct3_member1 = {1:2, 3:4}, + 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1}, + 3: map<string, bool> struct3_member3, + 4: map<byte, test_enum1> struct3_member4, + 5: map<test_enum2, test_enum3 > struct3_member5, + 7: map<double, string> struct3_member7 +} + +struct test_struct4 { + 1: i32 struct4_member1, + 2: optional i32 struct4_member2 +} + +struct test_struct5{ + 1: double struct5_member1, + 2: string struct5_member2 = "Thrift Audit Test" +} +struct test_struct6 { + 1: i32 struct6_member1, + 2: required i32 struct6_member2 +} + +service base { + oneway void base_oneway( + 1: i32 arg1), + + void base_function1( + 1: i16 function1_arg1, + 2: i32 function1_arg2, + 3: i64 function1_arg3, + 4: double function1_arg4, + 5: string function1_arg5, + 6: bool function1_arg6, + 7: test_enum1 function1_arg7, + 8: test_struct1 function1_arg8), + + void base_function2( + 1: list<i16> function2_arg1, + 2: list<i32> function2_arg2, + 3: list<i64> function2_arg3, + 4: list<double> function2_arg4, + 5: list<string> function2_arg5, + 6: list<bool> function2_arg6, + 7: list<byte> function2_arg7, + 8: list<test_enum1> function2_arg8, + 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e), + + void base_function3(), + +} + +service derived1 extends base { + + test_enum1 derived1_function1( + 1: i64 function1_arg1, + 2: double function1_arg2, + 3: test_enum1 function1_arg3) throws (1:test_exception2 e), + + i64 derived1_function2( + 1: list<i64> function2_arg1, + 2: list<double> function2_arg2, + 3: list<string> function2_arg3, + 4: list<byte> function2_arg4, + 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e), + + double derived1_function3( + 1: string function3_arg1, + 2: bool function3_arg2) throws (1:test_exception2 e), + + string derived1_function4( + 1: string function4_arg1, + 2: bool function4_arg2) throws (1:test_exception2 e), + + + bool derived1_function5( + 1: map<i64, double> function5_arg1, + 2: map<string, bool> function5_arg2, + 3: map<test_enum1, test_enum2> function5_arg3) throws (1:test_exception2 e), + + test_struct1 derived1_function6( + 1: double function6_arg1) throws (1:test_exception2 e), +} + +service derived2 extends base { + + list<i32> derived2_function1( + 1: i32 function1_arg1) throws (1:test_exception2 e), + + list<test_enum1> derived2_function2( + 1:i64 function2_arg2) throws (1:test_exception2 e), + + list<test_struct1> derived2_function3( + 1:double function3_arg1) throws(1:test_exception2 e), + + map<double, string> derived2_function4( + 1:string function4_arg1) throws(1:test_exception2 e), + + map<test_enum1, test_enum2> derived2_function5( + 1:bool function5_arg1) throws(1:test_exception2 e), + + map<test_struct1, test_struct2> derived2_function6( + 1:bool function6_arg1) throws(1:test_exception2 e), + +} diff --git a/src/jaegertracing/thrift/test/audit/break22.thrift b/src/jaegertracing/thrift/test/audit/break22.thrift new file mode 100644 index 000000000..38083494d --- /dev/null +++ b/src/jaegertracing/thrift/test/audit/break22.thrift @@ -0,0 +1,190 @@ +/* + * 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. + */ + +//break22 - in-between enum value removed from enum1 + +namespace cpp test + +//Constants +const i32 const1 = 123; +const double const2 = 23.3; +const map<string,string> const3 = {"hello":"world", "thrift":"audit"}; + + +//Exception +exception test_exception1 { + 1: i32 code; + 2: string json; +} +exception test_exception2 { + 1: i32 code; + 2: string json; +} + +//Enums + +enum test_enum1 { + enum1_value0 = 0, + enum1_value1 = 1, + enum1_value5 = 5, + enum1_value7 = 7, + enum1_value8 = 8 +} + +enum test_enum2 { + enum2_value0 = 0, + enum2_value1 = 1, + enum2_value2 = 2, + enum2_value3 = 3 +} + +enum test_enum3 { + enum3_value1 = 0, + enum3_value2 = 1 +} + +struct test_struct1 { + 1: i16 struct1_member1, + 2: i32 struct1_member2, + 3: i64 struct1_member3, + 4: double struct1_member4 = 2.5, + 5: string struct1_member5 = "Audit test", + 6: bool struct1_member6, + 7: byte struct1_member7, + 8: binary struct1_member8, + 9: test_enum1 struct1_member9 +} + +struct test_struct2 { + 1: list<i16> struct2_member1, + 2: list<i32> struct2_member2, + 3: list<i64> struct2_member3 = [23, 32 ], + 4: list<double> struct2_member4, + 5: list<string> struct2_member5, + 6: list<bool> struct2_member6, + 7: list<byte> struct2_member7, + 8: list<binary> struct2_member8, + 9: list<test_enum1> struct2_member9 +} + +struct test_struct3 { + 1: map<i16, i32> struct3_member1 = {1:2, 3:4}, + 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1}, + 3: map<string, bool> struct3_member3, + 4: map<byte, test_enum1> struct3_member4, + 5: map<test_enum2, test_enum3 > struct3_member5, + 7: map<double, string> struct3_member7 +} + +struct test_struct4 { + 1: i32 struct4_member1, + 2: optional i32 struct4_member2 +} + +struct test_struct5{ + 1: double struct5_member1, + 2: string struct5_member2 = "Thrift Audit Test" +} +struct test_struct6 { + 1: i32 struct6_member1, + 2: required i32 struct6_member2 +} + +service base { + oneway void base_oneway( + 1: i32 arg1), + + void base_function1( + 1: i16 function1_arg1, + 2: i32 function1_arg2, + 3: i64 function1_arg3, + 4: double function1_arg4, + 5: string function1_arg5, + 6: bool function1_arg6, + 7: test_enum1 function1_arg7, + 8: test_struct1 function1_arg8), + + void base_function2( + 1: list<i16> function2_arg1, + 2: list<i32> function2_arg2, + 3: list<i64> function2_arg3, + 4: list<double> function2_arg4, + 5: list<string> function2_arg5, + 6: list<bool> function2_arg6, + 7: list<byte> function2_arg7, + 8: list<test_enum1> function2_arg8, + 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e), + + void base_function3(), + +} + +service derived1 extends base { + + test_enum1 derived1_function1( + 1: i64 function1_arg1, + 2: double function1_arg2, + 3: test_enum1 function1_arg3) throws (1:test_exception2 e), + + i64 derived1_function2( + 1: list<i64> function2_arg1, + 2: list<double> function2_arg2, + 3: list<string> function2_arg3, + 4: list<byte> function2_arg4, + 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e), + + double derived1_function3( + 1: string function3_arg1, + 2: bool function3_arg2) throws (1:test_exception2 e), + + string derived1_function4( + 1: string function4_arg1, + 2: bool function4_arg2) throws (1:test_exception2 e), + + + bool derived1_function5( + 1: map<i64, double> function5_arg1, + 2: map<string, bool> function5_arg2, + 3: map<test_enum1, test_enum2> function5_arg3) throws (1:test_exception2 e), + + test_struct1 derived1_function6( + 1: double function6_arg1) throws (1:test_exception2 e), +} + +service derived2 extends base { + + list<i32> derived2_function1( + 1: i32 function1_arg1) throws (1:test_exception2 e), + + list<test_enum1> derived2_function2( + 1:i64 function2_arg2) throws (1:test_exception2 e), + + list<test_struct1> derived2_function3( + 1:double function3_arg1) throws(1:test_exception2 e), + + map<double, string> derived2_function4( + 1:string function4_arg1) throws(1:test_exception2 e), + + map<test_enum1, test_enum2> derived2_function5( + 1:bool function5_arg1) throws(1:test_exception2 e), + + map<test_struct1, test_struct2> derived2_function6( + 1:bool function6_arg1) throws(1:test_exception2 e), + +} diff --git a/src/jaegertracing/thrift/test/audit/break23.thrift b/src/jaegertracing/thrift/test/audit/break23.thrift new file mode 100644 index 000000000..ff95a426f --- /dev/null +++ b/src/jaegertracing/thrift/test/audit/break23.thrift @@ -0,0 +1,192 @@ +/* + * 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. + */ + +//break23 - required struct field added to struct4 + +namespace cpp test + +//Constants +const i32 const1 = 123; +const double const2 = 23.3; +const map<string,string> const3 = {"hello":"world", "thrift":"audit"}; + + +//Exception +exception test_exception1 { + 1: i32 code; + 2: string json; +} +exception test_exception2 { + 1: i32 code; + 2: string json; +} + +//Enums + +enum test_enum1 { + enum1_value0 = 0, + enum1_value1 = 1, + enum1_value2 = 2, + enum1_value5 = 5, + enum1_value7 = 7, + enum1_value8 = 8 +} + +enum test_enum2 { + enum2_value0 = 0, + enum2_value1 = 1, + enum2_value2 = 2, + enum2_value3 = 3 +} + +enum test_enum3 { + enum3_value1 = 0, + enum3_value2 = 1 +} + +struct test_struct1 { + 1: i16 struct1_member1, + 2: i32 struct1_member2, + 3: i64 struct1_member3, + 4: double struct1_member4 = 2.5, + 5: string struct1_member5 = "Audit test", + 6: bool struct1_member6, + 7: byte struct1_member7, + 8: binary struct1_member8, + 9: test_enum1 struct1_member9 +} + +struct test_struct2 { + 1: list<i16> struct2_member1, + 2: list<i32> struct2_member2, + 3: list<i64> struct2_member3 = [23, 32 ], + 4: list<double> struct2_member4, + 5: list<string> struct2_member5, + 6: list<bool> struct2_member6, + 7: list<byte> struct2_member7, + 8: list<binary> struct2_member8, + 9: list<test_enum1> struct2_member9 +} + +struct test_struct3 { + 1: map<i16, i32> struct3_member1 = {1:2, 3:4}, + 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1}, + 3: map<string, bool> struct3_member3, + 4: map<byte, test_enum1> struct3_member4, + 5: map<test_enum2, test_enum3 > struct3_member5, + 7: map<double, string> struct3_member7 +} + +struct test_struct4 { + 1: i32 struct4_member1, + 2: optional i32 struct4_member2, + 3: required i64 struct4_member3 +} + +struct test_struct5{ + 1: double struct5_member1, + 2: string struct5_member2 = "Thrift Audit Test" +} +struct test_struct6 { + 1: i32 struct6_member1, + 2: required i32 struct6_member2 +} + +service base { + oneway void base_oneway( + 1: i32 arg1), + + void base_function1( + 1: i16 function1_arg1, + 2: i32 function1_arg2, + 3: i64 function1_arg3, + 4: double function1_arg4, + 5: string function1_arg5, + 6: bool function1_arg6, + 7: test_enum1 function1_arg7, + 8: test_struct1 function1_arg8), + + void base_function2( + 1: list<i16> function2_arg1, + 2: list<i32> function2_arg2, + 3: list<i64> function2_arg3, + 4: list<double> function2_arg4, + 5: list<string> function2_arg5, + 6: list<bool> function2_arg6, + 7: list<byte> function2_arg7, + 8: list<test_enum1> function2_arg8, + 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e), + + void base_function3(), + +} + +service derived1 extends base { + + test_enum1 derived1_function1( + 1: i64 function1_arg1, + 2: double function1_arg2, + 3: test_enum1 function1_arg3) throws (1:test_exception2 e), + + i64 derived1_function2( + 1: list<i64> function2_arg1, + 2: list<double> function2_arg2, + 3: list<string> function2_arg3, + 4: list<byte> function2_arg4, + 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e), + + double derived1_function3( + 1: string function3_arg1, + 2: bool function3_arg2) throws (1:test_exception2 e), + + string derived1_function4( + 1: string function4_arg1, + 2: bool function4_arg2) throws (1:test_exception2 e), + + + bool derived1_function5( + 1: map<i64, double> function5_arg1, + 2: map<string, bool> function5_arg2, + 3: map<test_enum1, test_enum2> function5_arg3) throws (1:test_exception2 e), + + test_struct1 derived1_function6( + 1: double function6_arg1) throws (1:test_exception2 e), +} + +service derived2 extends base { + + list<i32> derived2_function1( + 1: i32 function1_arg1) throws (1:test_exception2 e), + + list<test_enum1> derived2_function2( + 1:i64 function2_arg2) throws (1:test_exception2 e), + + list<test_struct1> derived2_function3( + 1:double function3_arg1) throws(1:test_exception2 e), + + map<double, string> derived2_function4( + 1:string function4_arg1) throws(1:test_exception2 e), + + map<test_enum1, test_enum2> derived2_function5( + 1:bool function5_arg1) throws(1:test_exception2 e), + + map<test_struct1, test_struct2> derived2_function6( + 1:bool function6_arg1) throws(1:test_exception2 e), + +} diff --git a/src/jaegertracing/thrift/test/audit/break24.thrift b/src/jaegertracing/thrift/test/audit/break24.thrift new file mode 100644 index 000000000..bb4d5b933 --- /dev/null +++ b/src/jaegertracing/thrift/test/audit/break24.thrift @@ -0,0 +1,191 @@ +/* + * 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. + */ + +//break24 - removed inheritance from derived1. + +namespace cpp test + +//Constants +const i32 const1 = 123; +const double const2 = 23.3; +const map<string,string> const3 = {"hello":"world", "thrift":"audit"}; + + +//Exception +exception test_exception1 { + 1: i32 code; + 2: string json; +} +exception test_exception2 { + 1: i32 code; + 2: string json; +} + +//Enums + +enum test_enum1 { + enum1_value0 = 0, + enum1_value1 = 1, + enum1_value2 = 2, + enum1_value5 = 5, + enum1_value7 = 7, + enum1_value8 = 8 +} + +enum test_enum2 { + enum2_value0 = 0, + enum2_value1 = 1, + enum2_value2 = 2, + enum2_value3 = 3 +} + +enum test_enum3 { + enum3_value1 = 0, + enum3_value2 = 1 +} + +struct test_struct1 { + 1: i16 struct1_member1, + 2: i32 struct1_member2, + 3: i64 struct1_member3, + 4: double struct1_member4 = 2.5, + 5: string struct1_member5 = "Audit test", + 6: bool struct1_member6, + 7: byte struct1_member7, + 8: binary struct1_member8, + 9: test_enum1 struct1_member9 +} + +struct test_struct2 { + 1: list<i16> struct2_member1, + 2: list<i32> struct2_member2, + 3: list<i64> struct2_member3 = [23, 32 ], + 4: list<double> struct2_member4, + 5: list<string> struct2_member5, + 6: list<bool> struct2_member6, + 7: list<byte> struct2_member7, + 8: list<binary> struct2_member8, + 9: list<test_enum1> struct2_member9 +} + +struct test_struct3 { + 1: map<i16, i32> struct3_member1 = {1:2, 3:4}, + 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1}, + 3: map<string, bool> struct3_member3, + 4: map<byte, test_enum1> struct3_member4, + 5: map<test_enum2, test_enum3 > struct3_member5, + 7: map<double, string> struct3_member7 +} + +struct test_struct4 { + 1: i32 struct4_member1, + 2: optional i32 struct4_member2 +} + +struct test_struct5{ + 1: double struct5_member1, + 2: string struct5_member2 = "Thrift Audit Test" +} +struct test_struct6 { + 1: i32 struct6_member1, + 2: required i32 struct6_member2 +} + +service base { + oneway void base_oneway( + 1: i32 arg1), + + void base_function1( + 1: i16 function1_arg1, + 2: i32 function1_arg2, + 3: i64 function1_arg3, + 4: double function1_arg4, + 5: string function1_arg5, + 6: bool function1_arg6, + 7: test_enum1 function1_arg7, + 8: test_struct1 function1_arg8), + + void base_function2( + 1: list<i16> function2_arg1, + 2: list<i32> function2_arg2, + 3: list<i64> function2_arg3, + 4: list<double> function2_arg4, + 5: list<string> function2_arg5, + 6: list<bool> function2_arg6, + 7: list<byte> function2_arg7, + 8: list<test_enum1> function2_arg8, + 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e), + + void base_function3(), + +} + +service derived1 { + + test_enum1 derived1_function1( + 1: i64 function1_arg1, + 2: double function1_arg2, + 3: test_enum1 function1_arg3) throws (1:test_exception2 e), + + i64 derived1_function2( + 1: list<i64> function2_arg1, + 2: list<double> function2_arg2, + 3: list<string> function2_arg3, + 4: list<byte> function2_arg4, + 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e), + + double derived1_function3( + 1: string function3_arg1, + 2: bool function3_arg2) throws (1:test_exception2 e), + + string derived1_function4( + 1: string function4_arg1, + 2: bool function4_arg2) throws (1:test_exception2 e), + + + bool derived1_function5( + 1: map<i64, double> function5_arg1, + 2: map<string, bool> function5_arg2, + 3: map<test_enum1, test_enum2> function5_arg3) throws (1:test_exception2 e), + + test_struct1 derived1_function6( + 1: double function6_arg1) throws (1:test_exception2 e), +} + +service derived2 extends base { + + list<i32> derived2_function1( + 1: i32 function1_arg1) throws (1:test_exception2 e), + + list<test_enum1> derived2_function2( + 1:i64 function2_arg2) throws (1:test_exception2 e), + + list<test_struct1> derived2_function3( + 1:double function3_arg1) throws(1:test_exception2 e), + + map<double, string> derived2_function4( + 1:string function4_arg1) throws(1:test_exception2 e), + + map<test_enum1, test_enum2> derived2_function5( + 1:bool function5_arg1) throws(1:test_exception2 e), + + map<test_struct1, test_struct2> derived2_function6( + 1:bool function6_arg1) throws(1:test_exception2 e), + +} diff --git a/src/jaegertracing/thrift/test/audit/break25.thrift b/src/jaegertracing/thrift/test/audit/break25.thrift new file mode 100644 index 000000000..6efe97e65 --- /dev/null +++ b/src/jaegertracing/thrift/test/audit/break25.thrift @@ -0,0 +1,191 @@ +/* + * 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. + */ + +//Changed inheritance of derived2 + +namespace cpp test + +//Constants +const i32 const1 = 123; +const double const2 = 23.3; +const map<string,string> const3 = {"hello":"world", "thrift":"audit"}; + + +//Exception +exception test_exception1 { + 1: i32 code; + 2: string json; +} +exception test_exception2 { + 1: i32 code; + 2: string json; +} + +//Enums + +enum test_enum1 { + enum1_value0 = 0, + enum1_value1 = 1, + enum1_value2 = 2, + enum1_value5 = 5, + enum1_value7 = 7, + enum1_value8 = 8 +} + +enum test_enum2 { + enum2_value0 = 0, + enum2_value1 = 1, + enum2_value2 = 2, + enum2_value3 = 3 +} + +enum test_enum3 { + enum3_value1 = 0, + enum3_value2 = 1 +} + +struct test_struct1 { + 1: i16 struct1_member1, + 2: i32 struct1_member2, + 3: i64 struct1_member3, + 4: double struct1_member4 = 2.5, + 5: string struct1_member5 = "Audit test", + 6: bool struct1_member6, + 7: byte struct1_member7, + 8: binary struct1_member8, + 9: test_enum1 struct1_member9 +} + +struct test_struct2 { + 1: list<i16> struct2_member1, + 2: list<i32> struct2_member2, + 3: list<i64> struct2_member3 = [23, 32 ], + 4: list<double> struct2_member4, + 5: list<string> struct2_member5, + 6: list<bool> struct2_member6, + 7: list<byte> struct2_member7, + 8: list<binary> struct2_member8, + 9: list<test_enum1> struct2_member9 +} + +struct test_struct3 { + 1: map<i16, i32> struct3_member1 = {1:2, 3:4}, + 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1}, + 3: map<string, bool> struct3_member3, + 4: map<byte, test_enum1> struct3_member4, + 5: map<test_enum2, test_enum3 > struct3_member5, + 7: map<double, string> struct3_member7 +} + +struct test_struct4 { + 1: i32 struct4_member1, + 2: optional i32 struct4_member2 +} + +struct test_struct5{ + 1: double struct5_member1, + 2: string struct5_member2 = "Thrift Audit Test" +} +struct test_struct6 { + 1: i32 struct6_member1, + 2: required i32 struct6_member2 +} + +service base { + oneway void base_oneway( + 1: i32 arg1), + + void base_function1( + 1: i16 function1_arg1, + 2: i32 function1_arg2, + 3: i64 function1_arg3, + 4: double function1_arg4, + 5: string function1_arg5, + 6: bool function1_arg6, + 7: test_enum1 function1_arg7, + 8: test_struct1 function1_arg8), + + void base_function2( + 1: list<i16> function2_arg1, + 2: list<i32> function2_arg2, + 3: list<i64> function2_arg3, + 4: list<double> function2_arg4, + 5: list<string> function2_arg5, + 6: list<bool> function2_arg6, + 7: list<byte> function2_arg7, + 8: list<test_enum1> function2_arg8, + 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e), + + void base_function3(), + +} + +service derived1 extends base { + + test_enum1 derived1_function1( + 1: i64 function1_arg1, + 2: double function1_arg2, + 3: test_enum1 function1_arg3) throws (1:test_exception2 e), + + i64 derived1_function2( + 1: list<i64> function2_arg1, + 2: list<double> function2_arg2, + 3: list<string> function2_arg3, + 4: list<byte> function2_arg4, + 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e), + + double derived1_function3( + 1: string function3_arg1, + 2: bool function3_arg2) throws (1:test_exception2 e), + + string derived1_function4( + 1: string function4_arg1, + 2: bool function4_arg2) throws (1:test_exception2 e), + + + bool derived1_function5( + 1: map<i64, double> function5_arg1, + 2: map<string, bool> function5_arg2, + 3: map<test_enum1, test_enum2> function5_arg3) throws (1:test_exception2 e), + + test_struct1 derived1_function6( + 1: double function6_arg1) throws (1:test_exception2 e), +} + +service derived2 extends derived1 { + + list<i32> derived2_function1( + 1: i32 function1_arg1) throws (1:test_exception2 e), + + list<test_enum1> derived2_function2( + 1:i64 function2_arg2) throws (1:test_exception2 e), + + list<test_struct1> derived2_function3( + 1:double function3_arg1) throws(1:test_exception2 e), + + map<double, string> derived2_function4( + 1:string function4_arg1) throws(1:test_exception2 e), + + map<test_enum1, test_enum2> derived2_function5( + 1:bool function5_arg1) throws(1:test_exception2 e), + + map<test_struct1, test_struct2> derived2_function6( + 1:bool function6_arg1) throws(1:test_exception2 e), + +} diff --git a/src/jaegertracing/thrift/test/audit/break26.thrift b/src/jaegertracing/thrift/test/audit/break26.thrift new file mode 100644 index 000000000..6576d9b62 --- /dev/null +++ b/src/jaegertracing/thrift/test/audit/break26.thrift @@ -0,0 +1,191 @@ +/* + * 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. + */ + +//break26 - Field type changed in base_function1 argument id=3 +namespace cpp test + +//Constants +const i32 const1 = 123; +const double const2 = 23.3; +const map<string,string> const3 = {"hello":"world", "thrift":"audit"}; + + +//Exception +exception test_exception1 { + 1: i32 code; + 2: string json; +} +exception test_exception2 { + 1: i32 code; + 2: string json; +} + +//Enums + +enum test_enum1 { + enum1_value0 = 0, + enum1_value1 = 1, + enum1_value2 = 2, + enum1_value5 = 5, + enum1_value7 = 7, + enum1_value8 = 8 +} + +enum test_enum2 { + enum2_value0 = 0, + enum2_value1 = 1, + enum2_value2 = 2, + enum2_value3 = 3 +} + +enum test_enum3 { + enum3_value1 = 0, + enum3_value2 = 1 +} + +struct test_struct1 { + 1: i16 struct1_member1, + 2: i32 struct1_member2, + 3: i64 struct1_member3, + 4: double struct1_member4 = 2.5, + 5: string struct1_member5 = "Audit test", + 6: bool struct1_member6, + 7: byte struct1_member7, + 8: binary struct1_member8, + 9: test_enum1 struct1_member9 +} + +struct test_struct2 { + 1: list<i16> struct2_member1, + 2: list<i32> struct2_member2, + 3: list<i64> struct2_member3 = [23, 32 ], + 4: list<double> struct2_member4, + 5: list<string> struct2_member5, + 6: list<bool> struct2_member6, + 7: list<byte> struct2_member7, + 8: list<binary> struct2_member8, + 9: list<test_enum1> struct2_member9 +} + +struct test_struct3 { + 1: map<i16, i32> struct3_member1 = {1:2, 3:4}, + 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1}, + 3: map<string, bool> struct3_member3, + 4: map<byte, test_enum1> struct3_member4, + 5: map<test_enum2, test_enum3 > struct3_member5, + 7: map<double, string> struct3_member7 +} + +struct test_struct4 { + 1: i32 struct4_member1, + 2: optional i32 struct4_member2 +} + +struct test_struct5{ + 1: double struct5_member1, + 2: string struct5_member2 = "Thrift Audit Test" +} +struct test_struct6 { + 1: i32 struct6_member1, + 2: required i32 struct6_member2 +} + +service base { + oneway void base_oneway( + 1: i32 arg1), + + void base_function1( + 1: i16 function1_arg1, + 2: i32 function1_arg2, + 3: double function1_arg3, + 4: double function1_arg4, + 5: string function1_arg5, + 6: bool function1_arg6, + 7: test_enum1 function1_arg7, + 8: test_struct1 function1_arg8), + + void base_function2( + 1: list<i16> function2_arg1, + 2: list<i32> function2_arg2, + 3: list<i64> function2_arg3, + 4: list<double> function2_arg4, + 5: list<string> function2_arg5, + 6: list<bool> function2_arg6, + 7: list<byte> function2_arg7, + 8: list<test_enum1> function2_arg8, + 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e), + + void base_function3(), + +} + +service derived1 extends base { + + test_enum1 derived1_function1( + 1: i64 function1_arg1, + 2: double function1_arg2, + 3: test_enum1 function1_arg3) throws (1:test_exception2 e), + + i64 derived1_function2( + 1: list<i64> function2_arg1, + 2: list<double> function2_arg2, + 3: list<string> function2_arg3, + 4: list<byte> function2_arg4, + 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e), + + double derived1_function3( + 1: string function3_arg1, + 2: bool function3_arg2) throws (1:test_exception2 e), + + string derived1_function4( + 1: string function4_arg1, + 2: bool function4_arg2) throws (1:test_exception2 e), + + + bool derived1_function5( + 1: map<i64, double> function5_arg1, + 2: map<string, bool> function5_arg2, + 3: map<test_enum1, test_enum2> function5_arg3) throws (1:test_exception2 e), + + test_struct1 derived1_function6( + 1: double function6_arg1) throws (1:test_exception2 e), +} + +service derived2 extends base { + + list<i32> derived2_function1( + 1: i32 function1_arg1) throws (1:test_exception2 e), + + list<test_enum1> derived2_function2( + 1:i64 function2_arg2) throws (1:test_exception2 e), + + list<test_struct1> derived2_function3( + 1:double function3_arg1) throws(1:test_exception2 e), + + map<double, string> derived2_function4( + 1:string function4_arg1) throws(1:test_exception2 e), + + map<test_enum1, test_enum2> derived2_function5( + 1:bool function5_arg1) throws(1:test_exception2 e), + + map<test_struct1, test_struct2> derived2_function6( + 1:bool function6_arg1) throws(1:test_exception2 e), + +} + diff --git a/src/jaegertracing/thrift/test/audit/break27.thrift b/src/jaegertracing/thrift/test/audit/break27.thrift new file mode 100644 index 000000000..b556706d8 --- /dev/null +++ b/src/jaegertracing/thrift/test/audit/break27.thrift @@ -0,0 +1,190 @@ +/* + * 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. + */ + +// break27 - argument changed base_function2 list<enum1> to list<enum3> id =8 +namespace cpp test + +//Constants +const i32 const1 = 123; +const double const2 = 23.3; +const map<string,string> const3 = {"hello":"world", "thrift":"audit"}; + + +//Exception +exception test_exception1 { + 1: i32 code; + 2: string json; +} +exception test_exception2 { + 1: i32 code; + 2: string json; +} + +//Enums + +enum test_enum1 { + enum1_value0 = 0, + enum1_value1 = 1, + enum1_value2 = 2, + enum1_value5 = 5, + enum1_value7 = 7, + enum1_value8 = 8 +} + +enum test_enum2 { + enum2_value0 = 0, + enum2_value1 = 1, + enum2_value2 = 2, + enum2_value3 = 3 +} + +enum test_enum3 { + enum3_value1 = 0, + enum3_value2 = 1 +} + +struct test_struct1 { + 1: i16 struct1_member1, + 2: i32 struct1_member2, + 3: i64 struct1_member3, + 4: double struct1_member4 = 2.5, + 5: string struct1_member5 = "Audit test", + 6: bool struct1_member6, + 7: byte struct1_member7, + 8: binary struct1_member8, + 9: test_enum1 struct1_member9 +} + +struct test_struct2 { + 1: list<i16> struct2_member1, + 2: list<i32> struct2_member2, + 3: list<i64> struct2_member3 = [23, 32 ], + 4: list<double> struct2_member4, + 5: list<string> struct2_member5, + 6: list<bool> struct2_member6, + 7: list<byte> struct2_member7, + 8: list<binary> struct2_member8, + 9: list<test_enum1> struct2_member9 +} + +struct test_struct3 { + 1: map<i16, i32> struct3_member1 = {1:2, 3:4}, + 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1}, + 3: map<string, bool> struct3_member3, + 4: map<byte, test_enum1> struct3_member4, + 5: map<test_enum2, test_enum3 > struct3_member5, + 7: map<double, string> struct3_member7 +} + +struct test_struct4 { + 1: i32 struct4_member1, + 2: optional i32 struct4_member2 +} + +struct test_struct5{ + 1: double struct5_member1, + 2: string struct5_member2 = "Thrift Audit Test" +} +struct test_struct6 { + 1: i32 struct6_member1, + 2: required i32 struct6_member2 +} + +service base { + oneway void base_oneway( + 1: i32 arg1), + + void base_function1( + 1: i16 function1_arg1, + 2: i32 function1_arg2, + 3: i64 function1_arg3, + 4: double function1_arg4, + 5: string function1_arg5, + 6: bool function1_arg6, + 7: test_enum1 function1_arg7, + 8: test_struct1 function1_arg8), + + void base_function2( + 1: list<i16> function2_arg1, + 2: list<i32> function2_arg2, + 3: list<i64> function2_arg3, + 4: list<double> function2_arg4, + 5: list<string> function2_arg5, + 6: list<bool> function2_arg6, + 7: list<byte> function2_arg7, + 8: list<test_enum3> function2_arg8, + 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e), + + void base_function3(), + +} + +service derived1 extends base { + + test_enum1 derived1_function1( + 1: i64 function1_arg1, + 2: double function1_arg2, + 3: test_enum1 function1_arg3) throws (1:test_exception2 e), + + i64 derived1_function2( + 1: list<i64> function2_arg1, + 2: list<double> function2_arg2, + 3: list<string> function2_arg3, + 4: list<byte> function2_arg4, + 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e), + + double derived1_function3( + 1: string function3_arg1, + 2: bool function3_arg2) throws (1:test_exception2 e), + + string derived1_function4( + 1: string function4_arg1, + 2: bool function4_arg2) throws (1:test_exception2 e), + + + bool derived1_function5( + 1: map<i64, double> function5_arg1, + 2: map<string, bool> function5_arg2, + 3: map<test_enum1, test_enum2> function5_arg3) throws (1:test_exception2 e), + + test_struct1 derived1_function6( + 1: double function6_arg1) throws (1:test_exception2 e), +} + +service derived2 extends base { + + list<i32> derived2_function1( + 1: i32 function1_arg1) throws (1:test_exception2 e), + + list<test_enum1> derived2_function2( + 1:i64 function2_arg2) throws (1:test_exception2 e), + + list<test_struct1> derived2_function3( + 1:double function3_arg1) throws(1:test_exception2 e), + + map<double, string> derived2_function4( + 1:string function4_arg1) throws(1:test_exception2 e), + + map<test_enum1, test_enum2> derived2_function5( + 1:bool function5_arg1) throws(1:test_exception2 e), + + map<test_struct1, test_struct2> derived2_function6( + 1:bool function6_arg1) throws(1:test_exception2 e), + +} diff --git a/src/jaegertracing/thrift/test/audit/break28.thrift b/src/jaegertracing/thrift/test/audit/break28.thrift new file mode 100644 index 000000000..c64e55808 --- /dev/null +++ b/src/jaegertracing/thrift/test/audit/break28.thrift @@ -0,0 +1,190 @@ +/* + * 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. + */ + +//break28- derived1_function5 arguement type changed map<i64, double> to list<i64> +namespace cpp test + +//Constants +const i32 const1 = 123; +const double const2 = 23.3; +const map<string,string> const3 = {"hello":"world", "thrift":"audit"}; + + +//Exception +exception test_exception1 { + 1: i32 code; + 2: string json; +} +exception test_exception2 { + 1: i32 code; + 2: string json; +} + +//Enums + +enum test_enum1 { + enum1_value0 = 0, + enum1_value1 = 1, + enum1_value2 = 2, + enum1_value5 = 5, + enum1_value7 = 7, + enum1_value8 = 8 +} + +enum test_enum2 { + enum2_value0 = 0, + enum2_value1 = 1, + enum2_value2 = 2, + enum2_value3 = 3 +} + +enum test_enum3 { + enum3_value1 = 0, + enum3_value2 = 1 +} + +struct test_struct1 { + 1: i16 struct1_member1, + 2: i32 struct1_member2, + 3: i64 struct1_member3, + 4: double struct1_member4 = 2.5, + 5: string struct1_member5 = "Audit test", + 6: bool struct1_member6, + 7: byte struct1_member7, + 8: binary struct1_member8, + 9: test_enum1 struct1_member9 +} + +struct test_struct2 { + 1: list<i16> struct2_member1, + 2: list<i32> struct2_member2, + 3: list<i64> struct2_member3 = [23, 32 ], + 4: list<double> struct2_member4, + 5: list<string> struct2_member5, + 6: list<bool> struct2_member6, + 7: list<byte> struct2_member7, + 8: list<binary> struct2_member8, + 9: list<test_enum1> struct2_member9 +} + +struct test_struct3 { + 1: map<i16, i32> struct3_member1 = {1:2, 3:4}, + 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1}, + 3: map<string, bool> struct3_member3, + 4: map<byte, test_enum1> struct3_member4, + 5: map<test_enum2, test_enum3 > struct3_member5, + 7: map<double, string> struct3_member7 +} + +struct test_struct4 { + 1: i32 struct4_member1, + 2: optional i32 struct4_member2 +} + +struct test_struct5{ + 1: double struct5_member1, + 2: string struct5_member2 = "Thrift Audit Test" +} +struct test_struct6 { + 1: i32 struct6_member1, + 2: required i32 struct6_member2 +} + +service base { + oneway void base_oneway( + 1: i32 arg1), + + void base_function1( + 1: i16 function1_arg1, + 2: i32 function1_arg2, + 3: i64 function1_arg3, + 4: double function1_arg4, + 5: string function1_arg5, + 6: bool function1_arg6, + 7: test_enum1 function1_arg7, + 8: test_struct1 function1_arg8), + + void base_function2( + 1: list<i16> function2_arg1, + 2: list<i32> function2_arg2, + 3: list<i64> function2_arg3, + 4: list<double> function2_arg4, + 5: list<string> function2_arg5, + 6: list<bool> function2_arg6, + 7: list<byte> function2_arg7, + 8: list<test_enum1> function2_arg8, + 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e), + + void base_function3(), + +} + +service derived1 extends base { + + test_enum1 derived1_function1( + 1: i64 function1_arg1, + 2: double function1_arg2, + 3: test_enum1 function1_arg3) throws (1:test_exception2 e), + + i64 derived1_function2( + 1: list<i64> function2_arg1, + 2: list<double> function2_arg2, + 3: list<string> function2_arg3, + 4: list<byte> function2_arg4, + 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e), + + double derived1_function3( + 1: string function3_arg1, + 2: bool function3_arg2) throws (1:test_exception2 e), + + string derived1_function4( + 1: string function4_arg1, + 2: bool function4_arg2) throws (1:test_exception2 e), + + + bool derived1_function5( + 1: list<i64> function5_arg1, + 2: map<string, bool> function5_arg2, + 3: map<test_enum1, test_enum2> function5_arg3) throws (1:test_exception2 e), + + test_struct1 derived1_function6( + 1: double function6_arg1) throws (1:test_exception2 e), +} + +service derived2 extends base { + + list<i32> derived2_function1( + 1: i32 function1_arg1) throws (1:test_exception2 e), + + list<test_enum1> derived2_function2( + 1:i64 function2_arg2) throws (1:test_exception2 e), + + list<test_struct1> derived2_function3( + 1:double function3_arg1) throws(1:test_exception2 e), + + map<double, string> derived2_function4( + 1:string function4_arg1) throws(1:test_exception2 e), + + map<test_enum1, test_enum2> derived2_function5( + 1:bool function5_arg1) throws(1:test_exception2 e), + + map<test_struct1, test_struct2> derived2_function6( + 1:bool function6_arg1) throws(1:test_exception2 e), + +} diff --git a/src/jaegertracing/thrift/test/audit/break29.thrift b/src/jaegertracing/thrift/test/audit/break29.thrift new file mode 100644 index 000000000..52f308113 --- /dev/null +++ b/src/jaegertracing/thrift/test/audit/break29.thrift @@ -0,0 +1,191 @@ +/* + * 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. + */ + +//break29 - base_function2 arguemnt type changed list<string> to string + +namespace cpp test + +//Constants +const i32 const1 = 123; +const double const2 = 23.3; +const map<string,string> const3 = {"hello":"world", "thrift":"audit"}; + + +//Exception +exception test_exception1 { + 1: i32 code; + 2: string json; +} +exception test_exception2 { + 1: i32 code; + 2: string json; +} + +//Enums + +enum test_enum1 { + enum1_value0 = 0, + enum1_value1 = 1, + enum1_value2 = 2, + enum1_value5 = 5, + enum1_value7 = 7, + enum1_value8 = 8 +} + +enum test_enum2 { + enum2_value0 = 0, + enum2_value1 = 1, + enum2_value2 = 2, + enum2_value3 = 3 +} + +enum test_enum3 { + enum3_value1 = 0, + enum3_value2 = 1 +} + +struct test_struct1 { + 1: i16 struct1_member1, + 2: i32 struct1_member2, + 3: i64 struct1_member3, + 4: double struct1_member4 = 2.5, + 5: string struct1_member5 = "Audit test", + 6: bool struct1_member6, + 7: byte struct1_member7, + 8: binary struct1_member8, + 9: test_enum1 struct1_member9 +} + +struct test_struct2 { + 1: list<i16> struct2_member1, + 2: list<i32> struct2_member2, + 3: list<i64> struct2_member3 = [23, 32 ], + 4: list<double> struct2_member4, + 5: list<string> struct2_member5, + 6: list<bool> struct2_member6, + 7: list<byte> struct2_member7, + 8: list<binary> struct2_member8, + 9: list<test_enum1> struct2_member9 +} + +struct test_struct3 { + 1: map<i16, i32> struct3_member1 = {1:2, 3:4}, + 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1}, + 3: map<string, bool> struct3_member3, + 4: map<byte, test_enum1> struct3_member4, + 5: map<test_enum2, test_enum3 > struct3_member5, + 7: map<double, string> struct3_member7 +} + +struct test_struct4 { + 1: i32 struct4_member1, + 2: optional i32 struct4_member2 +} + +struct test_struct5{ + 1: double struct5_member1, + 2: string struct5_member2 = "Thrift Audit Test" +} +struct test_struct6 { + 1: i32 struct6_member1, + 2: required i32 struct6_member2 +} + +service base { + oneway void base_oneway( + 1: i32 arg1), + + void base_function1( + 1: i16 function1_arg1, + 2: i32 function1_arg2, + 3: i64 function1_arg3, + 4: double function1_arg4, + 5: string function1_arg5, + 6: bool function1_arg6, + 7: test_enum1 function1_arg7, + 8: test_struct1 function1_arg8), + + void base_function2( + 1: list<i16> function2_arg1, + 2: list<i32> function2_arg2, + 3: list<i64> function2_arg3, + 4: list<double> function2_arg4, + 5: string function2_arg5, + 6: list<bool> function2_arg6, + 7: list<byte> function2_arg7, + 8: list<test_enum1> function2_arg8, + 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e), + + void base_function3(), + +} + +service derived1 extends base { + + test_enum1 derived1_function1( + 1: i64 function1_arg1, + 2: double function1_arg2, + 3: test_enum1 function1_arg3) throws (1:test_exception2 e), + + i64 derived1_function2( + 1: list<i64> function2_arg1, + 2: list<double> function2_arg2, + 3: list<string> function2_arg3, + 4: list<byte> function2_arg4, + 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e), + + double derived1_function3( + 1: string function3_arg1, + 2: bool function3_arg2) throws (1:test_exception2 e), + + string derived1_function4( + 1: string function4_arg1, + 2: bool function4_arg2) throws (1:test_exception2 e), + + + bool derived1_function5( + 1: map<i64, double> function5_arg1, + 2: map<string, bool> function5_arg2, + 3: map<test_enum1, test_enum2> function5_arg3) throws (1:test_exception2 e), + + test_struct1 derived1_function6( + 1: double function6_arg1) throws (1:test_exception2 e), +} + +service derived2 extends base { + + list<i32> derived2_function1( + 1: i32 function1_arg1) throws (1:test_exception2 e), + + list<test_enum1> derived2_function2( + 1:i64 function2_arg2) throws (1:test_exception2 e), + + list<test_struct1> derived2_function3( + 1:double function3_arg1) throws(1:test_exception2 e), + + map<double, string> derived2_function4( + 1:string function4_arg1) throws(1:test_exception2 e), + + map<test_enum1, test_enum2> derived2_function5( + 1:bool function5_arg1) throws(1:test_exception2 e), + + map<test_struct1, test_struct2> derived2_function6( + 1:bool function6_arg1) throws(1:test_exception2 e), + +} diff --git a/src/jaegertracing/thrift/test/audit/break3.thrift b/src/jaegertracing/thrift/test/audit/break3.thrift new file mode 100644 index 000000000..ded9972d8 --- /dev/null +++ b/src/jaegertracing/thrift/test/audit/break3.thrift @@ -0,0 +1,191 @@ +/* + * 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. + */ + +//break3 - Struct field changed in test_struct1(enum1 to enum2) + +namespace cpp test + +//Constants +const i32 const1 = 123; +const double const2 = 23.3; +const map<string,string> const3 = {"hello":"world", "thrift":"audit"}; + + +//Exception +exception test_exception1 { + 1: i32 code; + 2: string json; +} +exception test_exception2 { + 1: i32 code; + 2: string json; +} + +//Enums + +enum test_enum1 { + enum1_value0 = 0, + enum1_value1 = 1, + enum1_value2 = 2, + enum1_value5 = 5, + enum1_value7 = 7, + enum1_value8 = 8 +} + +enum test_enum2 { + enum2_value0 = 0, + enum2_value1 = 1, + enum2_value2 = 2, + enum2_value3 = 3 +} + +enum test_enum3 { + enum3_value1 = 0, + enum3_value2 = 1 +} + +struct test_struct1 { + 1: i16 struct1_member1, + 2: i32 struct1_member2, + 3: i64 struct1_member3, + 4: double struct1_member4 = 2.5, + 5: string struct1_member5 = "Audit test", + 6: bool struct1_member6, + 7: byte struct1_member7, + 8: binary struct1_member8, + 9: test_enum2 struct1_member9 +} + +struct test_struct2 { + 1: list<i16> struct2_member1, + 2: list<i32> struct2_member2, + 3: list<i64> struct2_member3 = [23, 32], + 4: list<double> struct2_member4, + 5: list<string> struct2_member5, + 6: list<bool> struct2_member6, + 7: list<byte> struct2_member7, + 8: list<binary> struct2_member8, + 9: list<test_enum1> struct2_member9 +} + +struct test_struct3 { + 1: map<i16, i32> struct3_member1 = {1:2, 3:4}, + 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1}, + 3: map<string, bool> struct3_member3, + 4: map<byte, test_enum1> struct3_member4, + 5: map<test_enum2, test_enum3 > struct3_member5, + 7: map<double, string> struct3_member7 +} + +struct test_struct4 { + 1: i32 struct4_member1, + 2: optional i32 struct4_member2 +} + +struct test_struct5{ + 1: double struct5_member1, + 2: string struct5_member2 = "Thrift Audit Test" +} +struct test_struct6 { + 1: i32 struct6_member1, + 2: required i32 struct6_member2 +} + +service base { + oneway void base_oneway( + 1: i32 arg1), + + void base_function1( + 1: i16 function1_arg1, + 2: i32 function1_arg2, + 3: i64 function1_arg3, + 4: double function1_arg4, + 5: string function1_arg5, + 6: bool function1_arg6, + 7: test_enum1 function1_arg7, + 8: test_struct1 function1_arg8), + + void base_function2( + 1: list<i16> function2_arg1, + 2: list<i32> function2_arg2, + 3: list<i64> function2_arg3, + 4: list<double> function2_arg4, + 5: list<string> function2_arg5, + 6: list<bool> function2_arg6, + 7: list<byte> function2_arg7, + 8: list<test_enum1> function2_arg8, + 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e), + + void base_function3(), + +} + +service derived1 extends base { + + test_enum1 derived1_function1( + 1: i64 function1_arg1, + 2: double function1_arg2, + 3: test_enum1 function1_arg3) throws (1:test_exception2 e), + + i64 derived1_function2( + 1: list<i64> function2_arg1, + 2: list<double> function2_arg2, + 3: list<string> function2_arg3, + 4: list<byte> function2_arg4, + 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e), + + double derived1_function3( + 1: string function3_arg1, + 2: bool function3_arg2) throws (1:test_exception2 e), + + string derived1_function4( + 1: string function4_arg1, + 2: bool function4_arg2) throws (1:test_exception2 e), + + + bool derived1_function5( + 1: map<i64, double> function5_arg1, + 2: map<string, bool> function5_arg2, + 3: map<test_enum1, test_enum2> function5_arg3) throws (1:test_exception2 e), + + test_struct1 derived1_function6( + 1: double function6_arg1) throws (1:test_exception2 e), +} + +service derived2 extends base { + + list<i32> derived2_function1( + 1: i32 function1_arg1) throws (1:test_exception2 e), + + list<test_enum1> derived2_function2( + 1:i64 function2_arg2) throws (1:test_exception2 e), + + list<test_struct1> derived2_function3( + 1:double function3_arg1) throws(1:test_exception2 e), + + map<double, string> derived2_function4( + 1:string function4_arg1) throws(1:test_exception2 e), + + map<test_enum1, test_enum2> derived2_function5( + 1:bool function5_arg1) throws(1:test_exception2 e), + + map<test_struct1, test_struct2> derived2_function6( + 1:bool function6_arg1) throws(1:test_exception2 e), + +} diff --git a/src/jaegertracing/thrift/test/audit/break30.thrift b/src/jaegertracing/thrift/test/audit/break30.thrift new file mode 100644 index 000000000..818dd6e47 --- /dev/null +++ b/src/jaegertracing/thrift/test/audit/break30.thrift @@ -0,0 +1,190 @@ +/* + * 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. + */ + +// break30- derived1_function6 argument changed struct1 to map<struct1,struct1> +namespace cpp test + +//Constants +const i32 const1 = 123; +const double const2 = 23.3; +const map<string,string> const3 = {"hello":"world", "thrift":"audit"}; + + +//Exception +exception test_exception1 { + 1: i32 code; + 2: string json; +} +exception test_exception2 { + 1: i32 code; + 2: string json; +} + +//Enums + +enum test_enum1 { + enum1_value0 = 0, + enum1_value1 = 1, + enum1_value2 = 2, + enum1_value5 = 5, + enum1_value7 = 7, + enum1_value8 = 8 +} + +enum test_enum2 { + enum2_value0 = 0, + enum2_value1 = 1, + enum2_value2 = 2, + enum2_value3 = 3 +} + +enum test_enum3 { + enum3_value1 = 0, + enum3_value2 = 1 +} + +struct test_struct1 { + 1: i16 struct1_member1, + 2: i32 struct1_member2, + 3: i64 struct1_member3, + 4: double struct1_member4 = 2.5, + 5: string struct1_member5 = "Audit test", + 6: bool struct1_member6, + 7: byte struct1_member7, + 8: binary struct1_member8, + 9: test_enum1 struct1_member9 +} + +struct test_struct2 { + 1: list<i16> struct2_member1, + 2: list<i32> struct2_member2, + 3: list<i64> struct2_member3 = [23, 32 ], + 4: list<double> struct2_member4, + 5: list<string> struct2_member5, + 6: list<bool> struct2_member6, + 7: list<byte> struct2_member7, + 8: list<binary> struct2_member8, + 9: list<test_enum1> struct2_member9 +} + +struct test_struct3 { + 1: map<i16, i32> struct3_member1 = {1:2, 3:4}, + 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1}, + 3: map<string, bool> struct3_member3, + 4: map<byte, test_enum1> struct3_member4, + 5: map<test_enum2, test_enum3 > struct3_member5, + 7: map<double, string> struct3_member7 +} + +struct test_struct4 { + 1: i32 struct4_member1, + 2: optional i32 struct4_member2 +} + +struct test_struct5{ + 1: double struct5_member1, + 2: string struct5_member2 = "Thrift Audit Test" +} +struct test_struct6 { + 1: i32 struct6_member1, + 2: required i32 struct6_member2 +} + +service base { + oneway void base_oneway( + 1: i32 arg1), + + void base_function1( + 1: i16 function1_arg1, + 2: i32 function1_arg2, + 3: i64 function1_arg3, + 4: double function1_arg4, + 5: string function1_arg5, + 6: bool function1_arg6, + 7: test_enum1 function1_arg7, + 8: test_struct1 function1_arg8), + + void base_function2( + 1: list<i16> function2_arg1, + 2: list<i32> function2_arg2, + 3: list<i64> function2_arg3, + 4: list<double> function2_arg4, + 5: list<string> function2_arg5, + 6: list<bool> function2_arg6, + 7: list<byte> function2_arg7, + 8: list<test_enum1> function2_arg8, + 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e), + + void base_function3(), + +} + +service derived1 extends base { + + test_enum1 derived1_function1( + 1: i64 function1_arg1, + 2: double function1_arg2, + 3: test_enum1 function1_arg3) throws (1:test_exception2 e), + + i64 derived1_function2( + 1: list<i64> function2_arg1, + 2: list<double> function2_arg2, + 3: list<string> function2_arg3, + 4: list<byte> function2_arg4, + 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e), + + double derived1_function3( + 1: string function3_arg1, + 2: bool function3_arg2) throws (1:test_exception2 e), + + string derived1_function4( + 1: string function4_arg1, + 2: bool function4_arg2) throws (1:test_exception2 e), + + + bool derived1_function5( + 1: map<i64, double> function5_arg1, + 2: map<string, bool> function5_arg2, + 3: map<test_enum1, test_enum2> function5_arg3) throws (1:test_exception2 e), + + map<test_struct1,test_struct1> derived1_function6( + 1: double function6_arg1) throws (1:test_exception2 e), +} + +service derived2 extends base { + + list<i32> derived2_function1( + 1: i32 function1_arg1) throws (1:test_exception2 e), + + list<test_enum1> derived2_function2( + 1:i64 function2_arg2) throws (1:test_exception2 e), + + list<test_struct1> derived2_function3( + 1:double function3_arg1) throws(1:test_exception2 e), + + map<double, string> derived2_function4( + 1:string function4_arg1) throws(1:test_exception2 e), + + map<test_enum1, test_enum2> derived2_function5( + 1:bool function5_arg1) throws(1:test_exception2 e), + + map<test_struct1, test_struct2> derived2_function6( + 1:bool function6_arg1) throws(1:test_exception2 e), + +} diff --git a/src/jaegertracing/thrift/test/audit/break31.thrift b/src/jaegertracing/thrift/test/audit/break31.thrift new file mode 100644 index 000000000..7ca380461 --- /dev/null +++ b/src/jaegertracing/thrift/test/audit/break31.thrift @@ -0,0 +1,191 @@ +/* + * 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. + */ + +//break31 - Exception removed to base_function2 + +namespace cpp test + +//Constants +const i32 const1 = 123; +const double const2 = 23.3; +const map<string,string> const3 = {"hello":"world", "thrift":"audit"}; + + +//Exception +exception test_exception1 { + 1: i32 code; + 2: string json; +} +exception test_exception2 { + 1: i32 code; + 2: string json; +} + +//Enums + +enum test_enum1 { + enum1_value0 = 0, + enum1_value1 = 1, + enum1_value2 = 2, + enum1_value5 = 5, + enum1_value7 = 7, + enum1_value8 = 8 +} + +enum test_enum2 { + enum2_value0 = 0, + enum2_value1 = 1, + enum2_value2 = 2, + enum2_value3 = 3 +} + +enum test_enum3 { + enum3_value1 = 0, + enum3_value2 = 1 +} + +struct test_struct1 { + 1: i16 struct1_member1, + 2: i32 struct1_member2, + 3: i64 struct1_member3, + 4: double struct1_member4 = 2.5, + 5: string struct1_member5 = "Audit test", + 6: bool struct1_member6, + 7: byte struct1_member7, + 8: binary struct1_member8, + 9: test_enum1 struct1_member9 +} + +struct test_struct2 { + 1: list<i16> struct2_member1, + 2: list<i32> struct2_member2, + 3: list<i64> struct2_member3 = [23, 32 ], + 4: list<double> struct2_member4, + 5: list<string> struct2_member5, + 6: list<bool> struct2_member6, + 7: list<byte> struct2_member7, + 8: list<binary> struct2_member8, + 9: list<test_enum1> struct2_member9 +} + +struct test_struct3 { + 1: map<i16, i32> struct3_member1 = {1:2, 3:4}, + 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1}, + 3: map<string, bool> struct3_member3, + 4: map<byte, test_enum1> struct3_member4, + 5: map<test_enum2, test_enum3 > struct3_member5, + 7: map<double, string> struct3_member7 +} + +struct test_struct4 { + 1: i32 struct4_member1, + 2: optional i32 struct4_member2 +} + +struct test_struct5{ + 1: double struct5_member1, + 2: string struct5_member2 = "Thrift Audit Test" +} +struct test_struct6 { + 1: i32 struct6_member1, + 2: required i32 struct6_member2 +} + +service base { + oneway void base_oneway( + 1: i32 arg1), + + void base_function1( + 1: i16 function1_arg1, + 2: i32 function1_arg2, + 3: i64 function1_arg3, + 4: double function1_arg4, + 5: string function1_arg5, + 6: bool function1_arg6, + 7: test_enum1 function1_arg7, + 8: test_struct1 function1_arg8), + + void base_function2( + 1: list<i16> function2_arg1, + 2: list<i32> function2_arg2, + 3: list<i64> function2_arg3, + 4: list<double> function2_arg4, + 5: list<string> function2_arg5, + 6: list<bool> function2_arg6, + 7: list<byte> function2_arg7, + 8: list<test_enum1> function2_arg8, + 9: list<test_struct1> function2_arg9), + + void base_function3(), + +} + +service derived1 extends base { + + test_enum1 derived1_function1( + 1: i64 function1_arg1, + 2: double function1_arg2, + 3: test_enum1 function1_arg3) throws (1:test_exception2 e), + + i64 derived1_function2( + 1: list<i64> function2_arg1, + 2: list<double> function2_arg2, + 3: list<string> function2_arg3, + 4: list<byte> function2_arg4, + 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e), + + double derived1_function3( + 1: string function3_arg1, + 2: bool function3_arg2) throws (1:test_exception2 e), + + string derived1_function4( + 1: string function4_arg1, + 2: bool function4_arg2) throws (1:test_exception2 e), + + + bool derived1_function5( + 1: map<i64, double> function5_arg1, + 2: map<string, bool> function5_arg2, + 3: map<test_enum1, test_enum2> function5_arg3) throws (1:test_exception2 e), + + test_struct1 derived1_function6( + 1: double function6_arg1) throws (1:test_exception2 e), +} + +service derived2 extends base { + + list<i32> derived2_function1( + 1: i32 function1_arg1) throws (1:test_exception2 e), + + list<test_enum1> derived2_function2( + 1:i64 function2_arg2) throws (1:test_exception2 e), + + list<test_struct1> derived2_function3( + 1:double function3_arg1) throws(1:test_exception2 e), + + map<double, string> derived2_function4( + 1:string function4_arg1) throws(1:test_exception2 e), + + map<test_enum1, test_enum2> derived2_function5( + 1:bool function5_arg1) throws(1:test_exception2 e), + + map<test_struct1, test_struct2> derived2_function6( + 1:bool function6_arg1) throws(1:test_exception2 e), + +} diff --git a/src/jaegertracing/thrift/test/audit/break32.thrift b/src/jaegertracing/thrift/test/audit/break32.thrift new file mode 100644 index 000000000..ca3f8a8b3 --- /dev/null +++ b/src/jaegertracing/thrift/test/audit/break32.thrift @@ -0,0 +1,191 @@ +/* + * 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. + */ + +//break32- Exception1 field type changed for id =1 + +namespace cpp test + +//Constants +const i32 const1 = 123; +const double const2 = 23.3; +const map<string,string> const3 = {"hello":"world", "thrift":"audit"}; + + +//Exception +exception test_exception1 { + 1: i64 code; + 2: string json; +} +exception test_exception2 { + 1: i32 code; + 2: string json; +} + +//Enums + +enum test_enum1 { + enum1_value0 = 0, + enum1_value1 = 1, + enum1_value2 = 2, + enum1_value5 = 5, + enum1_value7 = 7, + enum1_value8 = 8 +} + +enum test_enum2 { + enum2_value0 = 0, + enum2_value1 = 1, + enum2_value2 = 2, + enum2_value3 = 3 +} + +enum test_enum3 { + enum3_value1 = 0, + enum3_value2 = 1 +} + +struct test_struct1 { + 1: i16 struct1_member1, + 2: i32 struct1_member2, + 3: i64 struct1_member3, + 4: double struct1_member4 = 2.5, + 5: string struct1_member5 = "Audit test", + 6: bool struct1_member6, + 7: byte struct1_member7, + 8: binary struct1_member8, + 9: test_enum1 struct1_member9 +} + +struct test_struct2 { + 1: list<i16> struct2_member1, + 2: list<i32> struct2_member2, + 3: list<i64> struct2_member3 = [23, 32 ], + 4: list<double> struct2_member4, + 5: list<string> struct2_member5, + 6: list<bool> struct2_member6, + 7: list<byte> struct2_member7, + 8: list<binary> struct2_member8, + 9: list<test_enum1> struct2_member9 +} + +struct test_struct3 { + 1: map<i16, i32> struct3_member1 = {1:2, 3:4}, + 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1}, + 3: map<string, bool> struct3_member3, + 4: map<byte, test_enum1> struct3_member4, + 5: map<test_enum2, test_enum3 > struct3_member5, + 7: map<double, string> struct3_member7 +} + +struct test_struct4 { + 1: i32 struct4_member1, + 2: optional i32 struct4_member2 +} + +struct test_struct5{ + 1: double struct5_member1, + 2: string struct5_member2 = "Thrift Audit Test" +} +struct test_struct6 { + 1: i32 struct6_member1, + 2: required i32 struct6_member2 +} + +service base { + oneway void base_oneway( + 1: i32 arg1), + + void base_function1( + 1: i16 function1_arg1, + 2: i32 function1_arg2, + 3: i64 function1_arg3, + 4: double function1_arg4, + 5: string function1_arg5, + 6: bool function1_arg6, + 7: test_enum1 function1_arg7, + 8: test_struct1 function1_arg8), + + void base_function2( + 1: list<i16> function2_arg1, + 2: list<i32> function2_arg2, + 3: list<i64> function2_arg3, + 4: list<double> function2_arg4, + 5: list<string> function2_arg5, + 6: list<bool> function2_arg6, + 7: list<byte> function2_arg7, + 8: list<test_enum1> function2_arg8, + 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e), + + void base_function3(), + +} + +service derived1 extends base { + + test_enum1 derived1_function1( + 1: i64 function1_arg1, + 2: double function1_arg2, + 3: test_enum1 function1_arg3) throws (1:test_exception2 e), + + i64 derived1_function2( + 1: list<i64> function2_arg1, + 2: list<double> function2_arg2, + 3: list<string> function2_arg3, + 4: list<byte> function2_arg4, + 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e), + + double derived1_function3( + 1: string function3_arg1, + 2: bool function3_arg2) throws (1:test_exception2 e), + + string derived1_function4( + 1: string function4_arg1, + 2: bool function4_arg2) throws (1:test_exception2 e), + + + bool derived1_function5( + 1: map<i64, double> function5_arg1, + 2: map<string, bool> function5_arg2, + 3: map<test_enum1, test_enum2> function5_arg3) throws (1:test_exception2 e), + + test_struct1 derived1_function6( + 1: double function6_arg1) throws (1:test_exception2 e), +} + +service derived2 extends base { + + list<i32> derived2_function1( + 1: i32 function1_arg1) throws (1:test_exception2 e), + + list<test_enum1> derived2_function2( + 1:i64 function2_arg2) throws (1:test_exception2 e), + + list<test_struct1> derived2_function3( + 1:double function3_arg1) throws(1:test_exception2 e), + + map<double, string> derived2_function4( + 1:string function4_arg1) throws(1:test_exception2 e), + + map<test_enum1, test_enum2> derived2_function5( + 1:bool function5_arg1) throws(1:test_exception2 e), + + map<test_struct1, test_struct2> derived2_function6( + 1:bool function6_arg1) throws(1:test_exception2 e), + +} diff --git a/src/jaegertracing/thrift/test/audit/break33.thrift b/src/jaegertracing/thrift/test/audit/break33.thrift new file mode 100644 index 000000000..42dbb8247 --- /dev/null +++ b/src/jaegertracing/thrift/test/audit/break33.thrift @@ -0,0 +1,191 @@ +/* + * 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. + */ + +//break33 - derived1_function1 exception type changed. + +namespace cpp test + +//Constants +const i32 const1 = 123; +const double const2 = 23.3; +const map<string,string> const3 = {"hello":"world", "thrift":"audit"}; + + +//Exception +exception test_exception1 { + 1: i32 code; + 2: string json; +} +exception test_exception2 { + 1: i32 code; + 2: string json; +} + +//Enums + +enum test_enum1 { + enum1_value0 = 0, + enum1_value1 = 1, + enum1_value2 = 2, + enum1_value5 = 5, + enum1_value7 = 7, + enum1_value8 = 8 +} + +enum test_enum2 { + enum2_value0 = 0, + enum2_value1 = 1, + enum2_value2 = 2, + enum2_value3 = 3 +} + +enum test_enum3 { + enum3_value1 = 0, + enum3_value2 = 1 +} + +struct test_struct1 { + 1: i16 struct1_member1, + 2: i32 struct1_member2, + 3: i64 struct1_member3, + 4: double struct1_member4 = 2.5, + 5: string struct1_member5 = "Audit test", + 6: bool struct1_member6, + 7: byte struct1_member7, + 8: binary struct1_member8, + 9: test_enum1 struct1_member9 +} + +struct test_struct2 { + 1: list<i16> struct2_member1, + 2: list<i32> struct2_member2, + 3: list<i64> struct2_member3 = [23, 32 ], + 4: list<double> struct2_member4, + 5: list<string> struct2_member5, + 6: list<bool> struct2_member6, + 7: list<byte> struct2_member7, + 8: list<binary> struct2_member8, + 9: list<test_enum1> struct2_member9 +} + +struct test_struct3 { + 1: map<i16, i32> struct3_member1 = {1:2, 3:4}, + 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1}, + 3: map<string, bool> struct3_member3, + 4: map<byte, test_enum1> struct3_member4, + 5: map<test_enum2, test_enum3 > struct3_member5, + 7: map<double, string> struct3_member7 +} + +struct test_struct4 { + 1: i32 struct4_member1, + 2: optional i32 struct4_member2 +} + +struct test_struct5{ + 1: double struct5_member1, + 2: string struct5_member2 = "Thrift Audit Test" +} +struct test_struct6 { + 1: i32 struct6_member1, + 2: required i32 struct6_member2 +} + +service base { + oneway void base_oneway( + 1: i32 arg1), + + void base_function1( + 1: i16 function1_arg1, + 2: i32 function1_arg2, + 3: i64 function1_arg3, + 4: double function1_arg4, + 5: string function1_arg5, + 6: bool function1_arg6, + 7: test_enum1 function1_arg7, + 8: test_struct1 function1_arg8), + + void base_function2( + 1: list<i16> function2_arg1, + 2: list<i32> function2_arg2, + 3: list<i64> function2_arg3, + 4: list<double> function2_arg4, + 5: list<string> function2_arg5, + 6: list<bool> function2_arg6, + 7: list<byte> function2_arg7, + 8: list<test_enum1> function2_arg8, + 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e), + + void base_function3(), + +} + +service derived1 extends base { + + test_enum1 derived1_function1( + 1: i64 function1_arg1, + 2: double function1_arg2, + 3: test_enum1 function1_arg3) throws (1:test_exception1 e), + + i64 derived1_function2( + 1: list<i64> function2_arg1, + 2: list<double> function2_arg2, + 3: list<string> function2_arg3, + 4: list<byte> function2_arg4, + 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e), + + double derived1_function3( + 1: string function3_arg1, + 2: bool function3_arg2) throws (1:test_exception2 e), + + string derived1_function4( + 1: string function4_arg1, + 2: bool function4_arg2) throws (1:test_exception2 e), + + + bool derived1_function5( + 1: map<i64, double> function5_arg1, + 2: map<string, bool> function5_arg2, + 3: map<test_enum1, test_enum2> function5_arg3) throws (1:test_exception2 e), + + test_struct1 derived1_function6( + 1: double function6_arg1) throws (1:test_exception2 e), +} + +service derived2 extends base { + + list<i32> derived2_function1( + 1: i32 function1_arg1) throws (1:test_exception2 e), + + list<test_enum1> derived2_function2( + 1:i64 function2_arg2) throws (1:test_exception2 e), + + list<test_struct1> derived2_function3( + 1:double function3_arg1) throws(1:test_exception2 e), + + map<double, string> derived2_function4( + 1:string function4_arg1) throws(1:test_exception2 e), + + map<test_enum1, test_enum2> derived2_function5( + 1:bool function5_arg1) throws(1:test_exception2 e), + + map<test_struct1, test_struct2> derived2_function6( + 1:bool function6_arg1) throws(1:test_exception2 e), + +} diff --git a/src/jaegertracing/thrift/test/audit/break34.thrift b/src/jaegertracing/thrift/test/audit/break34.thrift new file mode 100644 index 000000000..af93e650d --- /dev/null +++ b/src/jaegertracing/thrift/test/audit/break34.thrift @@ -0,0 +1,192 @@ +/* + * 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. + */ + +//break34 - Field added to struct with Field ID being in between two existing field IDs + +namespace cpp test + +//Constants +const i32 const1 = 123; +const double const2 = 23.3; +const map<string,string> const3 = {"hello":"world", "thrift":"audit"}; + + +//Exception +exception test_exception1 { + 1: i32 code; + 2: string json; +} +exception test_exception2 { + 1: i32 code; + 2: string json; +} + +//Enums + +enum test_enum1 { + enum1_value0 = 0, + enum1_value1 = 1, + enum1_value2 = 2, + enum1_value5 = 5, + enum1_value7 = 7, + enum1_value8 = 8 +} + +enum test_enum2 { + enum2_value0 = 0, + enum2_value1 = 1, + enum2_value2 = 2, + enum2_value3 = 3 +} + +enum test_enum3 { + enum3_value1 = 0, + enum3_value2 = 1 +} + +struct test_struct1 { + 1: i16 struct1_member1, + 2: i32 struct1_member2, + 3: i64 struct1_member3, + 4: double struct1_member4 = 2.5, + 5: string struct1_member5 = "Audit test", + 6: bool struct1_member6, + 7: byte struct1_member7, + 8: binary struct1_member8, + 9: test_enum1 struct1_member9 +} + +struct test_struct2 { + 1: list<i16> struct2_member1, + 2: list<i32> struct2_member2, + 3: list<i64> struct2_member3 = [23, 32 ], + 4: list<double> struct2_member4, + 5: list<string> struct2_member5, + 6: list<bool> struct2_member6, + 7: list<byte> struct2_member7, + 8: list<binary> struct2_member8, + 9: list<test_enum1> struct2_member9 +} + +struct test_struct3 { + 1: map<i16, i32> struct3_member1 = {1:2, 3:4}, + 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1}, + 3: map<string, bool> struct3_member3, + 4: map<byte, test_enum1> struct3_member4, + 5: map<test_enum2, test_enum3 > struct3_member5, + 6: map<test_enum1, test_enum2> struct3_member6, + 7: map<double, string> struct3_member7 +} + +struct test_struct4 { + 1: i32 struct4_member1, + 2: optional i32 struct4_member2 +} + +struct test_struct5{ + 1: double struct5_member1, + 2: string struct5_member2 = "Thrift Audit Test" +} +struct test_struct6 { + 1: i32 struct6_member1, + 2: required i32 struct6_member2 +} + +service base { + oneway void base_oneway( + 1: i32 arg1), + + void base_function1( + 1: i16 function1_arg1, + 2: i32 function1_arg2, + 3: i64 function1_arg3, + 4: double function1_arg4, + 5: string function1_arg5, + 6: bool function1_arg6, + 7: test_enum1 function1_arg7, + 8: test_struct1 function1_arg8), + + void base_function2( + 1: list<i16> function2_arg1, + 2: list<i32> function2_arg2, + 3: list<i64> function2_arg3, + 4: list<double> function2_arg4, + 5: list<string> function2_arg5, + 6: list<bool> function2_arg6, + 7: list<byte> function2_arg7, + 8: list<test_enum1> function2_arg8, + 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e), + + void base_function3(), + +} + +service derived1 extends base { + + test_enum1 derived1_function1( + 1: i64 function1_arg1, + 2: double function1_arg2, + 3: test_enum1 function1_arg3) throws (1:test_exception2 e), + + i64 derived1_function2( + 1: list<i64> function2_arg1, + 2: list<double> function2_arg2, + 3: list<string> function2_arg3, + 4: list<byte> function2_arg4, + 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e), + + double derived1_function3( + 1: string function3_arg1, + 2: bool function3_arg2) throws (1:test_exception2 e), + + string derived1_function4( + 1: string function4_arg1, + 2: bool function4_arg2) throws (1:test_exception2 e), + + + bool derived1_function5( + 1: map<i64, double> function5_arg1, + 2: map<string, bool> function5_arg2, + 3: map<test_enum1, test_enum2> function5_arg3) throws (1:test_exception2 e), + + test_struct1 derived1_function6( + 1: double function6_arg1) throws (1:test_exception2 e), +} + +service derived2 extends base { + + list<i32> derived2_function1( + 1: i32 function1_arg1) throws (1:test_exception2 e), + + list<test_enum1> derived2_function2( + 1:i64 function2_arg2) throws (1:test_exception2 e), + + list<test_struct1> derived2_function3( + 1:double function3_arg1) throws(1:test_exception2 e), + + map<double, string> derived2_function4( + 1:string function4_arg1) throws(1:test_exception2 e), + + map<test_enum1, test_enum2> derived2_function5( + 1:bool function5_arg1) throws(1:test_exception2 e), + + map<test_struct1, test_struct2> derived2_function6( + 1:bool function6_arg1) throws(1:test_exception2 e), + +} diff --git a/src/jaegertracing/thrift/test/audit/break4.thrift b/src/jaegertracing/thrift/test/audit/break4.thrift new file mode 100644 index 000000000..6a28ec05b --- /dev/null +++ b/src/jaegertracing/thrift/test/audit/break4.thrift @@ -0,0 +1,190 @@ +/* + * 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. + */ + +//Field type changed in test_struct1(bool to string) +namespace cpp test + +//Constants +const i32 const1 = 123; +const double const2 = 23.3; +const map<string,string> const3 = {"hello":"world", "thrift":"audit"}; + + +//Exception +exception test_exception1 { + 1: i32 code; + 2: string json; +} +exception test_exception2 { + 1: i32 code; + 2: string json; +} + +//Enums + +enum test_enum1 { + enum1_value0 = 0, + enum1_value1 = 1, + enum1_value2 = 2, + enum1_value5 = 5, + enum1_value7 = 7, + enum1_value8 = 8 +} + +enum test_enum2 { + enum2_value0 = 0, + enum2_value1 = 1, + enum2_value2 = 2, + enum2_value3 = 3 +} + +enum test_enum3 { + enum3_value1 = 0, + enum3_value2 = 1 +} + +struct test_struct1 { + 1: i16 struct1_member1, + 2: i32 struct1_member2, + 3: i64 struct1_member3, + 4: double struct1_member4 = 2.5, + 5: string struct1_member5 = "Audit test", + 6: string struct1_member6, + 7: byte struct1_member7, + 8: binary struct1_member8, + 9: test_enum1 struct1_member9 +} + +struct test_struct2 { + 1: list<i16> struct2_member1, + 2: list<i32> struct2_member2, + 3: list<i64> struct2_member3 =[23, 32], + 4: list<double> struct2_member4, + 5: list<string> struct2_member5, + 6: list<bool> struct2_member6, + 7: list<byte> struct2_member7, + 8: list<binary> struct2_member8, + 9: list<test_enum1> struct2_member9 +} + +struct test_struct3 { + 1: map<i16, i32> struct3_member1 = {1:2, 3:4}, + 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1}, + 3: map<string, bool> struct3_member3, + 4: map<byte, test_enum1> struct3_member4, + 5: map<test_enum2, test_enum3 > struct3_member5, + 7: map<double, string> struct3_member7 +} + +struct test_struct4 { + 1: i32 struct4_member1, + 2: optional i32 struct4_member2 +} + +struct test_struct5{ + 1: double struct5_member1, + 2: string struct5_member2 = "Thrift Audit Test" +} +struct test_struct6 { + 1: i32 struct6_member1, + 2: required i32 struct6_member2 +} + +service base { + oneway void base_oneway( + 1: i32 arg1), + + void base_function1( + 1: i16 function1_arg1, + 2: i32 function1_arg2, + 3: i64 function1_arg3, + 4: double function1_arg4, + 5: string function1_arg5, + 6: bool function1_arg6, + 7: test_enum1 function1_arg7, + 8: test_struct1 function1_arg8), + + void base_function2( + 1: list<i16> function2_arg1, + 2: list<i32> function2_arg2, + 3: list<i64> function2_arg3, + 4: list<double> function2_arg4, + 5: list<string> function2_arg5, + 6: list<bool> function2_arg6, + 7: list<byte> function2_arg7, + 8: list<test_enum1> function2_arg8, + 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e), + + void base_function3(), + +} + +service derived1 extends base { + + test_enum1 derived1_function1( + 1: i64 function1_arg1, + 2: double function1_arg2, + 3: test_enum1 function1_arg3) throws (1:test_exception2 e), + + i64 derived1_function2( + 1: list<i64> function2_arg1, + 2: list<double> function2_arg2, + 3: list<string> function2_arg3, + 4: list<byte> function2_arg4, + 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e), + + double derived1_function3( + 1: string function3_arg1, + 2: bool function3_arg2) throws (1:test_exception2 e), + + string derived1_function4( + 1: string function4_arg1, + 2: bool function4_arg2) throws (1:test_exception2 e), + + + bool derived1_function5( + 1: map<i64, double> function5_arg1, + 2: map<string, bool> function5_arg2, + 3: map<test_enum1, test_enum2> function5_arg3) throws (1:test_exception2 e), + + test_struct1 derived1_function6( + 1: double function6_arg1) throws (1:test_exception2 e), +} + +service derived2 extends base { + + list<i32> derived2_function1( + 1: i32 function1_arg1) throws (1:test_exception2 e), + + list<test_enum1> derived2_function2( + 1:i64 function2_arg2) throws (1:test_exception2 e), + + list<test_struct1> derived2_function3( + 1:double function3_arg1) throws(1:test_exception2 e), + + map<double, string> derived2_function4( + 1:string function4_arg1) throws(1:test_exception2 e), + + map<test_enum1, test_enum2> derived2_function5( + 1:bool function5_arg1) throws(1:test_exception2 e), + + map<test_struct1, test_struct2> derived2_function6( + 1:bool function6_arg1) throws(1:test_exception2 e), + +} diff --git a/src/jaegertracing/thrift/test/audit/break5.thrift b/src/jaegertracing/thrift/test/audit/break5.thrift new file mode 100644 index 000000000..18c22d169 --- /dev/null +++ b/src/jaegertracing/thrift/test/audit/break5.thrift @@ -0,0 +1,190 @@ +/* + * 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. + */ + +// member field type changed in test_struct1(bool to list<bool>) + +namespace cpp test + +//Constants +const i32 const1 = 123; +const double const2 = 23.3; +const map<string,string> const3 = {"hello":"world", "thrift":"audit"}; + +//Exception +exception test_exception1 { + 1: i32 code; + 2: string json; +} +exception test_exception2 { + 1: i32 code; + 2: string json; +} + +//Enums + +enum test_enum1 { + enum1_value0 = 0, + enum1_value1 = 1, + enum1_value2 = 2, + enum1_value5 = 5, + enum1_value7 = 7, + enum1_value8 = 8 +} + +enum test_enum2 { + enum2_value0 = 0, + enum2_value1 = 1, + enum2_value2 = 2, + enum2_value3 = 3 +} + +enum test_enum3 { + enum3_value1 = 0, + enum3_value2 = 1 +} + +struct test_struct1 { + 1: i16 struct1_member1, + 2: i32 struct1_member2, + 3: i64 struct1_member3, + 4: double struct1_member4 = 2.5, + 5: string struct1_member5 = "Audit test", + 6: list<bool> struct1_member6, + 7: byte struct1_member7, + 8: binary struct1_member8, + 9: test_enum1 struct1_member9 +} + +struct test_struct2 { + 1: list<i16> struct2_member1, + 2: list<i32> struct2_member2, + 3: list<i64> struct2_member3 = [23, 32 ], + 4: list<double> struct2_member4, + 5: list<string> struct2_member5, + 6: list<bool> struct2_member6, + 7: list<byte> struct2_member7, + 8: list<binary> struct2_member8, + 9: list<test_enum1> struct2_member9 +} + +struct test_struct3 { + 1: map<i16, i32> struct3_member1 = {1:2, 3:4}, + 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1}, + 3: map<string, bool> struct3_member3, + 4: map<byte, test_enum1> struct3_member4, + 5: map<test_enum2, test_enum3 > struct3_member5, + 7: map<double, string> struct3_member7 +} + +struct test_struct4 { + 1: i32 struct4_member1, + 2: optional i32 struct4_member2 +} + +struct test_struct5{ + 1: double struct5_member1, + 2: string struct5_member2 = "Thrift Audit Test" +} +struct test_struct6 { + 1: i32 struct6_member1, + 2: required i32 struct6_member2 +} + +service base { + oneway void base_oneway( + 1: i32 arg1), + + void base_function1( + 1: i16 function1_arg1, + 2: i32 function1_arg2, + 3: i64 function1_arg3, + 4: double function1_arg4, + 5: string function1_arg5, + 6: bool function1_arg6, + 7: test_enum1 function1_arg7, + 8: test_struct1 function1_arg8), + + void base_function2( + 1: list<i16> function2_arg1, + 2: list<i32> function2_arg2, + 3: list<i64> function2_arg3, + 4: list<double> function2_arg4, + 5: list<string> function2_arg5, + 6: list<bool> function2_arg6, + 7: list<byte> function2_arg7, + 8: list<test_enum1> function2_arg8, + 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e), + + void base_function3(), + +} + +service derived1 extends base { + + test_enum1 derived1_function1( + 1: i64 function1_arg1, + 2: double function1_arg2, + 3: test_enum1 function1_arg3) throws (1:test_exception2 e), + + i64 derived1_function2( + 1: list<i64> function2_arg1, + 2: list<double> function2_arg2, + 3: list<string> function2_arg3, + 4: list<byte> function2_arg4, + 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e), + + double derived1_function3( + 1: string function3_arg1, + 2: bool function3_arg2) throws (1:test_exception2 e), + + string derived1_function4( + 1: string function4_arg1, + 2: bool function4_arg2) throws (1:test_exception2 e), + + + bool derived1_function5( + 1: map<i64, double> function5_arg1, + 2: map<string, bool> function5_arg2, + 3: map<test_enum1, test_enum2> function5_arg3) throws (1:test_exception2 e), + + test_struct1 derived1_function6( + 1: double function6_arg1) throws (1:test_exception2 e), +} + +service derived2 extends base { + + list<i32> derived2_function1( + 1: i32 function1_arg1) throws (1:test_exception2 e), + + list<test_enum1> derived2_function2( + 1:i64 function2_arg2) throws (1:test_exception2 e), + + list<test_struct1> derived2_function3( + 1:double function3_arg1) throws(1:test_exception2 e), + + map<double, string> derived2_function4( + 1:string function4_arg1) throws(1:test_exception2 e), + + map<test_enum1, test_enum2> derived2_function5( + 1:bool function5_arg1) throws(1:test_exception2 e), + + map<test_struct1, test_struct2> derived2_function6( + 1:bool function6_arg1) throws(1:test_exception2 e), + +} diff --git a/src/jaegertracing/thrift/test/audit/break6.thrift b/src/jaegertracing/thrift/test/audit/break6.thrift new file mode 100644 index 000000000..9b7a3004a --- /dev/null +++ b/src/jaegertracing/thrift/test/audit/break6.thrift @@ -0,0 +1,191 @@ +/* + * 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. + */ + +// Field type changed in test_struct2 (list<double> to list<i16>) + +namespace cpp test + +//Constants +const i32 const1 = 123; +const double const2 = 23.3; +const map<string,string> const3 = {"hello":"world", "thrift":"audit"}; + + +//Exception +exception test_exception1 { + 1: i32 code; + 2: string json; +} +exception test_exception2 { + 1: i32 code; + 2: string json; +} + +//Enums + +enum test_enum1 { + enum1_value0 = 0, + enum1_value1 = 1, + enum1_value2 = 2, + enum1_value5 = 5, + enum1_value7 = 7, + enum1_value8 = 8 +} + +enum test_enum2 { + enum2_value0 = 0, + enum2_value1 = 1, + enum2_value2 = 2, + enum2_value3 = 3 +} + +enum test_enum3 { + enum3_value1 = 0, + enum3_value2 = 1 +} + +struct test_struct1 { + 1: i16 struct1_member1, + 2: i32 struct1_member2, + 3: i64 struct1_member3, + 4: double struct1_member4 = 2.5, + 5: string struct1_member5 = "Audit test", + 6: bool struct1_member6, + 7: byte struct1_member7, + 8: binary struct1_member8, + 9: test_enum1 struct1_member9 +} + +struct test_struct2 { + 1: list<i16> struct2_member1, + 2: list<i32> struct2_member2, + 3: list<i64> struct2_member3 = [23, 32 ], + 4: list<i16> struct2_member4, + 5: list<string> struct2_member5, + 6: list<bool> struct2_member6, + 7: list<byte> struct2_member7, + 8: list<binary> struct2_member8, + 9: list<test_enum1> struct2_member9 +} + +struct test_struct3 { + 1: map<i16, i32> struct3_member1 = {1:2, 3:4}, + 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1}, + 3: map<string, bool> struct3_member3, + 4: map<byte, test_enum1> struct3_member4, + 5: map<test_enum2, test_enum3 > struct3_member5, + 7: map<double, string> struct3_member7 +} + +struct test_struct4 { + 1: i32 struct4_member1, + 2: optional i32 struct4_member2 +} + +struct test_struct5{ + 1: double struct5_member1, + 2: string struct5_member2 = "Thrift Audit Test" +} +struct test_struct6 { + 1: i32 struct6_member1, + 2: required i32 struct6_member2 +} + +service base { + oneway void base_oneway( + 1: i32 arg1), + + void base_function1( + 1: i16 function1_arg1, + 2: i32 function1_arg2, + 3: i64 function1_arg3, + 4: double function1_arg4, + 5: string function1_arg5, + 6: bool function1_arg6, + 7: test_enum1 function1_arg7, + 8: test_struct1 function1_arg8), + + void base_function2( + 1: list<i16> function2_arg1, + 2: list<i32> function2_arg2, + 3: list<i64> function2_arg3, + 4: list<double> function2_arg4, + 5: list<string> function2_arg5, + 6: list<bool> function2_arg6, + 7: list<byte> function2_arg7, + 8: list<test_enum1> function2_arg8, + 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e), + + void base_function3(), + +} + +service derived1 extends base { + + test_enum1 derived1_function1( + 1: i64 function1_arg1, + 2: double function1_arg2, + 3: test_enum1 function1_arg3) throws (1:test_exception2 e), + + i64 derived1_function2( + 1: list<i64> function2_arg1, + 2: list<double> function2_arg2, + 3: list<string> function2_arg3, + 4: list<byte> function2_arg4, + 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e), + + double derived1_function3( + 1: string function3_arg1, + 2: bool function3_arg2) throws (1:test_exception2 e), + + string derived1_function4( + 1: string function4_arg1, + 2: bool function4_arg2) throws (1:test_exception2 e), + + + bool derived1_function5( + 1: map<i64, double> function5_arg1, + 2: map<string, bool> function5_arg2, + 3: map<test_enum1, test_enum2> function5_arg3) throws (1:test_exception2 e), + + test_struct1 derived1_function6( + 1: double function6_arg1) throws (1:test_exception2 e), +} + +service derived2 extends base { + + list<i32> derived2_function1( + 1: i32 function1_arg1) throws (1:test_exception2 e), + + list<test_enum1> derived2_function2( + 1:i64 function2_arg2) throws (1:test_exception2 e), + + list<test_struct1> derived2_function3( + 1:double function3_arg1) throws(1:test_exception2 e), + + map<double, string> derived2_function4( + 1:string function4_arg1) throws(1:test_exception2 e), + + map<test_enum1, test_enum2> derived2_function5( + 1:bool function5_arg1) throws(1:test_exception2 e), + + map<test_struct1, test_struct2> derived2_function6( + 1:bool function6_arg1) throws(1:test_exception2 e), + +} diff --git a/src/jaegertracing/thrift/test/audit/break7.thrift b/src/jaegertracing/thrift/test/audit/break7.thrift new file mode 100644 index 000000000..b31c2dff1 --- /dev/null +++ b/src/jaegertracing/thrift/test/audit/break7.thrift @@ -0,0 +1,190 @@ +/* + * 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. + */ + +//break7 - requiredness removed in struct6 + +namespace cpp test +//Constants +const i32 const1 = 123; +const double const2 = 23.3; +const map<string,string> const3 = {"hello":"world", "thrift":"audit"}; + + +//Exception +exception test_exception1 { + 1: i32 code; + 2: string json; +} +exception test_exception2 { + 1: i32 code; + 2: string json; +} + +//Enums + +enum test_enum1 { + enum1_value0 = 0, + enum1_value1 = 1, + enum1_value2 = 2, + enum1_value5 = 5, + enum1_value7 = 7, + enum1_value8 = 8 +} + +enum test_enum2 { + enum2_value0 = 0, + enum2_value1 = 1, + enum2_value2 = 2, + enum2_value3 = 3 +} + +enum test_enum3 { + enum3_value1 = 0, + enum3_value2 = 1 +} + +struct test_struct1 { + 1: i16 struct1_member1, + 2: i32 struct1_member2, + 3: i64 struct1_member3, + 4: double struct1_member4 = 2.5, + 5: string struct1_member5 = "Audit test", + 6: bool struct1_member6, + 7: byte struct1_member7, + 8: binary struct1_member8, + 9: test_enum1 struct1_member9 +} + +struct test_struct2 { + 1: list<i16> struct2_member1, + 2: list<i32> struct2_member2, + 3: list<i64> struct2_member3 = [23, 32 ], + 4: list<double> struct2_member4, + 5: list<string> struct2_member5, + 6: list<bool> struct2_member6, + 7: list<byte> struct2_member7, + 8: list<binary> struct2_member8, + 9: list<test_enum1> struct2_member9 +} + +struct test_struct3 { + 1: map<i16, i32> struct3_member1 = {1:2, 3:4}, + 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1}, + 3: map<string, bool> struct3_member3, + 4: map<byte, test_enum1> struct3_member4, + 5: map<test_enum2, test_enum3 > struct3_member5, + 7: map<double, string> struct3_member7 +} + +struct test_struct4 { + 1: i32 struct4_member1, + 2: optional i32 struct4_member2 +} + +struct test_struct5{ + 1: double struct5_member1, + 2: string struct5_member2 = "Thrift Audit Test" +} +struct test_struct6 { + 1: i32 struct6_member1, + 2: i32 struct6_member2 +} + +service base { + oneway void base_oneway( + 1: i32 arg1), + + void base_function1( + 1: i16 function1_arg1, + 2: i32 function1_arg2, + 3: i64 function1_arg3, + 4: double function1_arg4, + 5: string function1_arg5, + 6: bool function1_arg6, + 7: test_enum1 function1_arg7, + 8: test_struct1 function1_arg8), + + void base_function2( + 1: list<i16> function2_arg1, + 2: list<i32> function2_arg2, + 3: list<i64> function2_arg3, + 4: list<double> function2_arg4, + 5: list<string> function2_arg5, + 6: list<bool> function2_arg6, + 7: list<byte> function2_arg7, + 8: list<test_enum1> function2_arg8, + 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e), + + void base_function3(), + +} + +service derived1 extends base { + + test_enum1 derived1_function1( + 1: i64 function1_arg1, + 2: double function1_arg2, + 3: test_enum1 function1_arg3) throws (1:test_exception2 e), + + i64 derived1_function2( + 1: list<i64> function2_arg1, + 2: list<double> function2_arg2, + 3: list<string> function2_arg3, + 4: list<byte> function2_arg4, + 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e), + + double derived1_function3( + 1: string function3_arg1, + 2: bool function3_arg2) throws (1:test_exception2 e), + + string derived1_function4( + 1: string function4_arg1, + 2: bool function4_arg2) throws (1:test_exception2 e), + + + bool derived1_function5( + 1: map<i64, double> function5_arg1, + 2: map<string, bool> function5_arg2, + 3: map<test_enum1, test_enum2> function5_arg3) throws (1:test_exception2 e), + + test_struct1 derived1_function6( + 1: double function6_arg1) throws (1:test_exception2 e), +} + +service derived2 extends base { + + list<i32> derived2_function1( + 1: i32 function1_arg1) throws (1:test_exception2 e), + + list<test_enum1> derived2_function2( + 1:i64 function2_arg2) throws (1:test_exception2 e), + + list<test_struct1> derived2_function3( + 1:double function3_arg1) throws(1:test_exception2 e), + + map<double, string> derived2_function4( + 1:string function4_arg1) throws(1:test_exception2 e), + + map<test_enum1, test_enum2> derived2_function5( + 1:bool function5_arg1) throws(1:test_exception2 e), + + map<test_struct1, test_struct2> derived2_function6( + 1:bool function6_arg1) throws(1:test_exception2 e), + +} diff --git a/src/jaegertracing/thrift/test/audit/break8.thrift b/src/jaegertracing/thrift/test/audit/break8.thrift new file mode 100644 index 000000000..9acac09eb --- /dev/null +++ b/src/jaegertracing/thrift/test/audit/break8.thrift @@ -0,0 +1,191 @@ +/* + * 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. + */ + +//break8 - requiredness addedd in struct5 + +namespace cpp test + +//Constants +const i32 const1 = 123; +const double const2 = 23.3; +const map<string,string> const3 = {"hello":"world", "thrift":"audit"}; + + +//Exception +exception test_exception1 { + 1: i32 code; + 2: string json; +} +exception test_exception2 { + 1: i32 code; + 2: string json; +} + +//Enums + +enum test_enum1 { + enum1_value0 = 0, + enum1_value1 = 1, + enum1_value2 = 2, + enum1_value5 = 5, + enum1_value7 = 7, + enum1_value8 = 8 +} + +enum test_enum2 { + enum2_value0 = 0, + enum2_value1 = 1, + enum2_value2 = 2, + enum2_value3 = 3 +} + +enum test_enum3 { + enum3_value1 = 0, + enum3_value2 = 1 +} + +struct test_struct1 { + 1: i16 struct1_member1, + 2: i32 struct1_member2, + 3: i64 struct1_member3, + 4: double struct1_member4 = 2.5, + 5: string struct1_member5 = "Audit test", + 6: bool struct1_member6, + 7: byte struct1_member7, + 8: binary struct1_member8, + 9: test_enum1 struct1_member9 +} + +struct test_struct2 { + 1: list<i16> struct2_member1, + 2: list<i32> struct2_member2, + 3: list<i64> struct2_member3 = [23, 32 ], + 4: list<double> struct2_member4, + 5: list<string> struct2_member5, + 6: list<bool> struct2_member6, + 7: list<byte> struct2_member7, + 8: list<binary> struct2_member8, + 9: list<test_enum1> struct2_member9 +} + +struct test_struct3 { + 1: map<i16, i32> struct3_member1 = {1:2, 3:4}, + 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1}, + 3: map<string, bool> struct3_member3, + 4: map<byte, test_enum1> struct3_member4, + 5: map<test_enum2, test_enum3 > struct3_member5, + 7: map<double, string> struct3_member7 +} + +struct test_struct4 { + 1: i32 struct4_member1, + 2: optional i32 struct4_member2 +} + +struct test_struct5{ + 1: double struct5_member1, + 2: required string struct5_member2 = "Thrift Audit Test" +} +struct test_struct6 { + 1: i32 struct6_member1, + 2: required i32 struct6_member2 +} + +service base { + oneway void base_oneway( + 1: i32 arg1), + + void base_function1( + 1: i16 function1_arg1, + 2: i32 function1_arg2, + 3: i64 function1_arg3, + 4: double function1_arg4, + 5: string function1_arg5, + 6: bool function1_arg6, + 7: test_enum1 function1_arg7, + 8: test_struct1 function1_arg8), + + void base_function2( + 1: list<i16> function2_arg1, + 2: list<i32> function2_arg2, + 3: list<i64> function2_arg3, + 4: list<double> function2_arg4, + 5: list<string> function2_arg5, + 6: list<bool> function2_arg6, + 7: list<byte> function2_arg7, + 8: list<test_enum1> function2_arg8, + 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e), + + void base_function3(), + +} + +service derived1 extends base { + + test_enum1 derived1_function1( + 1: i64 function1_arg1, + 2: double function1_arg2, + 3: test_enum1 function1_arg3) throws (1:test_exception2 e), + + i64 derived1_function2( + 1: list<i64> function2_arg1, + 2: list<double> function2_arg2, + 3: list<string> function2_arg3, + 4: list<byte> function2_arg4, + 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e), + + double derived1_function3( + 1: string function3_arg1, + 2: bool function3_arg2) throws (1:test_exception2 e), + + string derived1_function4( + 1: string function4_arg1, + 2: bool function4_arg2) throws (1:test_exception2 e), + + + bool derived1_function5( + 1: map<i64, double> function5_arg1, + 2: map<string, bool> function5_arg2, + 3: map<test_enum1, test_enum2> function5_arg3) throws (1:test_exception2 e), + + test_struct1 derived1_function6( + 1: double function6_arg1) throws (1:test_exception2 e), +} + +service derived2 extends base { + + list<i32> derived2_function1( + 1: i32 function1_arg1) throws (1:test_exception2 e), + + list<test_enum1> derived2_function2( + 1:i64 function2_arg2) throws (1:test_exception2 e), + + list<test_struct1> derived2_function3( + 1:double function3_arg1) throws(1:test_exception2 e), + + map<double, string> derived2_function4( + 1:string function4_arg1) throws(1:test_exception2 e), + + map<test_enum1, test_enum2> derived2_function5( + 1:bool function5_arg1) throws(1:test_exception2 e), + + map<test_struct1, test_struct2> derived2_function6( + 1:bool function6_arg1) throws(1:test_exception2 e), + +} diff --git a/src/jaegertracing/thrift/test/audit/break9.thrift b/src/jaegertracing/thrift/test/audit/break9.thrift new file mode 100644 index 000000000..62b319d6e --- /dev/null +++ b/src/jaegertracing/thrift/test/audit/break9.thrift @@ -0,0 +1,190 @@ +/* + * 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. + */ + +//break9 - Struct field removed from struct1 + + +namespace cpp test +//Constants + +const i32 const1 = 123; +const double const2 = 23.3; +const map<string,string> const3 = {"hello":"world", "thrift":"audit"}; + +//Exception +exception test_exception1 { + 1: i32 code; + 2: string json; +} +exception test_exception2 { + 1: i32 code; + 2: string json; +} + +//Enums + +enum test_enum1 { + enum1_value0 = 0, + enum1_value1 = 1, + enum1_value2 = 2, + enum1_value5 = 5, + enum1_value7 = 7, + enum1_value8 = 8 +} + +enum test_enum2 { + enum2_value0 = 0, + enum2_value1 = 1, + enum2_value2 = 2, + enum2_value3 = 3 +} + +enum test_enum3 { + enum3_value1 = 0, + enum3_value2 = 1 +} + +struct test_struct1 { + 1: i16 struct1_member1, + 2: i32 struct1_member2, + 3: i64 struct1_member3, + 4: double struct1_member4 = 2.5, + 5: string struct1_member5 = "Audit test", + 6: bool struct1_member6, + 8: binary struct1_member8, + 9: test_enum1 struct1_member9 +} + +struct test_struct2 { + 1: list<i16> struct2_member1, + 2: list<i32> struct2_member2, + 3: list<i64> struct2_member3 = [23, 32 ], + 4: list<double> struct2_member4, + 5: list<string> struct2_member5, + 6: list<bool> struct2_member6, + 7: list<byte> struct2_member7, + 8: list<binary> struct2_member8, + 9: list<test_enum1> struct2_member9 +} + +struct test_struct3 { + 1: map<i16, i32> struct3_member1 = {1:2, 3:4}, + 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1}, + 3: map<string, bool> struct3_member3, + 4: map<byte, test_enum1> struct3_member4, + 5: map<test_enum2, test_enum3 > struct3_member5, + 7: map<double, string> struct3_member7 +} + +struct test_struct4 { + 1: i32 struct4_member1, + 2: optional i32 struct4_member2 +} + +struct test_struct5{ + 1: double struct5_member1, + 2: string struct5_member2 = "Thrift Audit Test" +} +struct test_struct6 { + 1: i32 struct6_member1, + 2: required i32 struct6_member2 +} + +service base { + oneway void base_oneway( + 1: i32 arg1), + + void base_function1( + 1: i16 function1_arg1, + 2: i32 function1_arg2, + 3: i64 function1_arg3, + 4: double function1_arg4, + 5: string function1_arg5, + 6: bool function1_arg6, + 7: test_enum1 function1_arg7, + 8: test_struct1 function1_arg8), + + void base_function2( + 1: list<i16> function2_arg1, + 2: list<i32> function2_arg2, + 3: list<i64> function2_arg3, + 4: list<double> function2_arg4, + 5: list<string> function2_arg5, + 6: list<bool> function2_arg6, + 7: list<byte> function2_arg7, + 8: list<test_enum1> function2_arg8, + 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e), + + void base_function3(), + +} + +service derived1 extends base { + + test_enum1 derived1_function1( + 1: i64 function1_arg1, + 2: double function1_arg2, + 3: test_enum1 function1_arg3) throws (1:test_exception2 e), + + i64 derived1_function2( + 1: list<i64> function2_arg1, + 2: list<double> function2_arg2, + 3: list<string> function2_arg3, + 4: list<byte> function2_arg4, + 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e), + + double derived1_function3( + 1: string function3_arg1, + 2: bool function3_arg2) throws (1:test_exception2 e), + + string derived1_function4( + 1: string function4_arg1, + 2: bool function4_arg2) throws (1:test_exception2 e), + + + bool derived1_function5( + 1: map<i64, double> function5_arg1, + 2: map<string, bool> function5_arg2, + 3: map<test_enum1, test_enum2> function5_arg3) throws (1:test_exception2 e), + + test_struct1 derived1_function6( + 1: double function6_arg1) throws (1:test_exception2 e), +} + +service derived2 extends base { + + list<i32> derived2_function1( + 1: i32 function1_arg1) throws (1:test_exception2 e), + + list<test_enum1> derived2_function2( + 1:i64 function2_arg2) throws (1:test_exception2 e), + + list<test_struct1> derived2_function3( + 1:double function3_arg1) throws(1:test_exception2 e), + + map<double, string> derived2_function4( + 1:string function4_arg1) throws(1:test_exception2 e), + + map<test_enum1, test_enum2> derived2_function5( + 1:bool function5_arg1) throws(1:test_exception2 e), + + map<test_struct1, test_struct2> derived2_function6( + 1:bool function6_arg1) throws(1:test_exception2 e), + +} diff --git a/src/jaegertracing/thrift/test/audit/test.thrift b/src/jaegertracing/thrift/test/audit/test.thrift new file mode 100644 index 000000000..e9834b38f --- /dev/null +++ b/src/jaegertracing/thrift/test/audit/test.thrift @@ -0,0 +1,189 @@ +/* + * 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. + */ + +namespace cpp test + +//Constants +const i32 const1 = 123; +const double const2 = 23.3; +const map<string,string> const3 = {"hello":"world", "thrift":"audit"}; + + +//Exception +exception test_exception1 { + 1: i32 code; + 2: string json; +} +exception test_exception2 { + 1: i32 code; + 2: string json; +} + +//Enums + +enum test_enum1 { + enum1_value0 = 0, + enum1_value1 = 1, + enum1_value2 = 2, + enum1_value5 = 5, + enum1_value7 = 7, + enum1_value8 = 8 +} + +enum test_enum2 { + enum2_value0 = 0, + enum2_value1 = 1, + enum2_value2 = 2, + enum2_value3 = 3 +} + +enum test_enum3 { + enum3_value1 = 0, + enum3_value2 = 1 +} + +struct test_struct1 { + 1: i16 struct1_member1, + 2: i32 struct1_member2, + 3: i64 struct1_member3, + 4: double struct1_member4 = 2.5, + 5: string struct1_member5 = "Audit test", + 6: bool struct1_member6, + 7: byte struct1_member7, + 8: binary struct1_member8, + 9: test_enum1 struct1_member9 +} + +struct test_struct2 { + 1: list<i16> struct2_member1, + 2: list<i32> struct2_member2, + 3: list<i64> struct2_member3 = [23, 32 ], + 4: list<double> struct2_member4, + 5: list<string> struct2_member5, + 6: list<bool> struct2_member6, + 7: list<byte> struct2_member7, + 8: list<binary> struct2_member8, + 9: list<test_enum1> struct2_member9 +} + +struct test_struct3 { + 1: map<i16, i32> struct3_member1 = {1:2, 3:4}, + 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1}, + 3: map<string, bool> struct3_member3, + 4: map<byte, test_enum1> struct3_member4, + 5: map<test_enum2, test_enum3 > struct3_member5, + 7: map<double, string> struct3_member7 +} + +struct test_struct4 { + 1: i32 struct4_member1, + 2: optional i32 struct4_member2 +} + +struct test_struct5{ + 1: double struct5_member1, + 2: string struct5_member2 = "Thrift Audit Test" +} +struct test_struct6 { + 1: i32 struct6_member1, + 2: required i32 struct6_member2 +} + +service base { + oneway void base_oneway( + 1: i32 arg1), + + void base_function1( + 1: i16 function1_arg1, + 2: i32 function1_arg2, + 3: i64 function1_arg3, + 4: double function1_arg4, + 5: string function1_arg5, + 6: bool function1_arg6, + 7: test_enum1 function1_arg7, + 8: test_struct1 function1_arg8), + + void base_function2( + 1: list<i16> function2_arg1, + 2: list<i32> function2_arg2, + 3: list<i64> function2_arg3, + 4: list<double> function2_arg4, + 5: list<string> function2_arg5, + 6: list<bool> function2_arg6, + 7: list<byte> function2_arg7, + 8: list<test_enum1> function2_arg8, + 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e), + + void base_function3(), + +} + +service derived1 extends base { + + test_enum1 derived1_function1( + 1: i64 function1_arg1, + 2: double function1_arg2, + 3: test_enum1 function1_arg3) throws (1:test_exception2 e), + + i64 derived1_function2( + 1: list<i64> function2_arg1, + 2: list<double> function2_arg2, + 3: list<string> function2_arg3, + 4: list<byte> function2_arg4, + 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e), + + double derived1_function3( + 1: string function3_arg1, + 2: bool function3_arg2) throws (1:test_exception2 e), + + string derived1_function4( + 1: string function4_arg1, + 2: bool function4_arg2) throws (1:test_exception2 e), + + + bool derived1_function5( + 1: map<i64, double> function5_arg1, + 2: map<string, bool> function5_arg2, + 3: map<test_enum1, test_enum2> function5_arg3) throws (1:test_exception2 e), + + test_struct1 derived1_function6( + 1: double function6_arg1) throws (1:test_exception2 e), +} + +service derived2 extends base { + + list<i32> derived2_function1( + 1: i32 function1_arg1) throws (1:test_exception2 e), + + list<test_enum1> derived2_function2( + 1:i64 function2_arg2) throws (1:test_exception2 e), + + list<test_struct1> derived2_function3( + 1:double function3_arg1) throws(1:test_exception2 e), + + map<double, string> derived2_function4( + 1:string function4_arg1) throws(1:test_exception2 e), + + map<test_enum1, test_enum2> derived2_function5( + 1:bool function5_arg1) throws(1:test_exception2 e), + + map<test_struct1, test_struct2> derived2_function6( + 1:bool function6_arg1) throws(1:test_exception2 e), + +} diff --git a/src/jaegertracing/thrift/test/audit/thrift_audit_test.pl b/src/jaegertracing/thrift/test/audit/thrift_audit_test.pl new file mode 100644 index 000000000..69ed4dccc --- /dev/null +++ b/src/jaegertracing/thrift/test/audit/thrift_audit_test.pl @@ -0,0 +1,261 @@ +#!/usr/bin/perl -w + +# 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. + + +#break1 - Thrift method removed from service base +#break2 - Struct field changed in test_struct1(i16 to i32) +#break3 - Struct field changed in test_struct1(enum1 to enum2) +#break4 - Field type changed in test_struct1(bool to string) +#break5- member field type changed in test_struct1(bool to list<bool>) +#break6- Field type changed in test_struct2 (list<double> to list<i16>) +#break7 - requiredness removed in struct6 +#break8 - requiredness addedd in struct5 +#break9 - Struct field removed from struct1 +#break10 - Struct field removed from struct2 id = 1 +#break11 - Struct field removed from struct3 last id +#break12 - derived1_function1 return type changed from enum1 to enum2 +#break13 - derived1_function6 return type changed from struct1 to struct2 +#break14 - derived1_function4 return type changed from string to double +#break15 - derived2_function1 return type changed from list<i32> to list<i16> +#break16 - derived2_function5 return type changed from map<test_enum1,test_enum2> to map<test_enum3, test_enum2> +#break17 - derived2_function6 return type changed from map<struct1,struct2> to map<struct1, struct3> +#break18- oneway removed from base_oneway +#break19 - oneway added to base_function1 +#break20 - first enum value removed from enum1 +#break21- last enum value removed from enum2 +#break22 - in-between enum value removed from enum1 +#break23 - required struct field added to struct4 +#break24 - removed inheritance of derived1. +#break25 - changed inheritance of derived2. +#break26 - Field type changed in base_function1 argument id=3 +#break27 - argument changed base_function2 list<enum1> to list<enum3> id =8 +#break28- derived1_function5 arguement type changed map<i64, double> to list<i64> +#break29 - base_function2 arguemnt type changed list<string> to string +#break30- derived1_function6 argument changed struct1 to map<struct1,struct1> +#break31 - Exception removed to base_function2 +#break32- Exception1 field type changed for id =1 +#break33 - derived1_function1 exception type changed. +#break34 - Field added to struct with Field ID being in between two existing field IDs + +#warning.thrift +#Changing defaults +#Id=1 struct5 +#id=2 struct5 +#id=4 struct2(list<double>) +#id=3 struct2(list<i64> default values removed) +#id 4 struct1 change in double value +#id 5 struct1 (default string value removed) +#id=1 struct3 (change in map values) +#id2 struct3 (change in map keys) + +#change in inheritance for derived1 and derived2 + +#change in struct field names +#id9 struct1 +#id2 struct2 + +use strict; +use warnings; +use Getopt::Std; + +# globals +my $gArguments = ""; # arguments that will be passed to AuditTool +my $gAuditToolPath = ""; +my $gPreviousThriftPath; # previous thrift path +my $gCurrentThriftPath; # current thrift path +my $gThriftFileFolder; +my $gBreakingFilesCount =34; + +my $gVerbose = 0; +#functions +sub auditBreakingChanges; +sub auditNonBreakingChanges; + +main(); + +sub main +{ + parseOptions(); + auditBreakingChanges(); + auditNonBreakingChanges(); +} + +sub parseOptions +{ + my %options = (); + if ( getopts ('vf:o:t:',\%options) ) + { + # current (new) thrift folder + if ($options{'f'}) + { + $gThriftFileFolder = $options{'f'}; + $gPreviousThriftPath = $gThriftFileFolder."/test.thrift"; + } + else + { + die "Missing Folder containing thrift files\n"; + } + + if($options{'t'}) + { + $gAuditToolPath = $options{'t'}; + } + else + { + die "Audit Tool Path required \n"; + } + + if ($options{'v'}) + { + $gVerbose = 1; + } + + } +} + +sub auditBreakingChanges +{ + my $breakingFileBaseName = $gThriftFileFolder."/break"; + my $newThriftFile; + for(my $i=1; $i <= $gBreakingFilesCount; $i++) + { + $newThriftFile = $breakingFileBaseName."$i.thrift"; + my $arguments = $gPreviousThriftPath." ".$newThriftFile; + my ($exitCode, $output) = callThriftAuditTool($arguments); + print $output if $gVerbose eq 1; + + if($exitCode == 1) + { + # thrift_audit returns 1 when it is not able to find files or other non-audit failures + print "exiting with exit code =1 i = ".$i."\n"; + print $output; + exit $exitCode; + } + if($exitCode != 2) + { + # thrift-audit return 2 for audit failures. So for Breaking changes we should get 2 as return value. + print $output; + die "\nTEST FAILURE: Breaking Change not detected for thrift file $newThriftFile, code=$exitCode \n"; + } + if(index($output,getMessageSubString("break$i")) == -1) + { + #Audit tool detected failure, but not the expected one. The change in breaking thrift file does not match getMessageSubString() + print $output; + die "\nTest FAILURE: Audit tool detected failure, but not the expected one!\n"; + } + else + { + #Thrift audit tool has detected audit failure and has returned exited to status code 2 + print "Test Pass: Audit Failure detected for thrift file break$i.thrift \n"; + } + } + +} + +sub auditNonBreakingChanges +{ + my $breakingFileBaseName = $gThriftFileFolder."/warning"; + my $newThriftFile; + $newThriftFile = $breakingFileBaseName.".thrift"; + my $arguments = $gPreviousThriftPath." ".$newThriftFile; + my ($exitCode, $output) = callThriftAuditTool($arguments); + print $output if $gVerbose eq 1; + + if($exitCode == 1) + { + # thrift_audit returns 1 when it is not able to find files or other non-audit failures + print "exiting with exit code = 1 for file warning.thrift\n"; + exit $exitCode; + } + elsif($exitCode != 0) + { + # thrift-audit return 0 if there are no audit failures. + die "\nTEST FAILURE: Non Breaking changes returned failure for thrift file $newThriftFile \n"; + } + else + { + #Thrift audit tool has exited with status 0. + print "Test Pass: Audit tool exits with success for warnings \n"; + } + + +} + +# ----------------------------------------------------------------------------------------------------- +# call thriftAuditTool script +sub callThriftAuditTool ( $ ) +{ + my $args = shift; + + my $command = "$gAuditToolPath --audit $args"; + my $output = `$command 2>&1`; + my $exitCode = $? >> 8; + + return ($exitCode,$output); +} + +sub getMessageSubString( $ ) +{ + my $fileName = shift; + my %lookupTable = ( + "break1" => "base_function3", + "break2" => "test_struct1", + "break3" => "test_struct1", + "break4" => "test_struct1", + "break5" => "test_struct1", + "break6" => "test_struct2", + "break7" => "test_struct6", + "break8" => "test_struct5", + "break9" => "test_struct1", + "break10" => "test_struct2", + "break11" => "test_struct3", + "break12" => "derived1_function1", + "break13" => "derived1_function6", + "break14" => "derived1_function4", + "break15" => "derived2_function1", + "break16" => "derived2_function5", + "break17" => "derived2_function6", + "break18" => "base_oneway", + "break19" => "base_function1", + "break20" => "test_enum1", + "break21" => "test_enum2", + "break22" => "test_enum1", + "break23" => "test_struct4", + "break24" => "derived1", + "break25" => "derived2", + "break26" => "base_function1", + "break27" => "base_function2_args", + "break28" => "derived1_function5_args", + "break29" => "base_function2_args", + "break30" => "derived1_function6", + "break31" => "base_function2_exception", + "break32" => "test_exception1", + "break33" => "derived1_function1_exception", + "break34" => "test_struct3", + ); + if (not exists $lookupTable{ $fileName }) + { + print "in the null case\n"; + return "NULL"; + } + + my $retval = $lookupTable{ $fileName }; + print "$fileName => $retval\n"; + return $lookupTable{ $fileName }; +} diff --git a/src/jaegertracing/thrift/test/audit/warning.thrift b/src/jaegertracing/thrift/test/audit/warning.thrift new file mode 100644 index 000000000..5392d5cc5 --- /dev/null +++ b/src/jaegertracing/thrift/test/audit/warning.thrift @@ -0,0 +1,190 @@ +/* + * 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. + */ + + +namespace cpp test + +//Constants + +const i32 const1 = 123; +const double const2 = 23.2; +const map<string,string> const3 = {"hello":"class", "thrift":"audit"}; + +//Exception +exception test_exception1 { + 1: i32 code; + 2: string json; +} +exception test_exception2 { + 1: i32 code; + 2: string json; +} + +//Enums + +enum test_enum1 { + enum1_value0 = 0, + enum1_value1 = 1, + enum1_value2 = 2, + enum1_value5 = 5, + enum1_value7 = 7, + enum1_value8 = 8 +} + +enum test_enum2 { + enum2_value0 = 0, + enum2_value1 = 1, + enum2_value2 = 2, + enum2_value3 = 3 +} + +enum test_enum3 { + enum3_value1 = 0, + enum3_value2 = 1 +} + +struct test_struct1 { + 1: i16 struct1_member1, + 2: i32 struct1_member2, + 3: i64 struct1_member3, + 4: double struct1_member4 = 2.4, + 5: string struct1_member5, + 6: bool struct1_member6, + 7: byte struct1_member7, + 8: binary struct1_member8, + 9: test_enum1 changed19 +} + +struct test_struct2 { + 1: list<i16> struct2_member1, + 2: list<i32> changed22, + 3: list<i64> struct2_member3, + 4: list<double> struct2_member4 =[1.0, 2.1], + 5: list<string> struct2_member5, + 6: list<bool> struct2_member6, + 7: list<byte> struct2_member7, + 8: list<binary> struct2_member8, + 9: list<test_enum1> struct2_member9 +} + +struct test_struct3 { + 1: map<i16, i32> struct3_member1 = {1:10, 2:20}, + 2: map<i64, double> struct3_member2 = {1:1.1, 2:2.1}, + 3: map<string, bool> struct3_member3, + 4: map<byte, test_enum1> struct3_member4, + 5: map<test_enum2, test_enum3 > struct3_member5, + 7: map<double, string> struct3_member7 +} + +struct test_struct4 { + 1: i32 struct4_member1, + 2: optional i32 struct4_member2 +} + +struct test_struct5{ + 1: double struct5_member1 = 1.1, + 2: string struct5_member2 = "Thrift Audit Tess" +} +struct test_struct6 { + 1: i32 struct6_member1, + 2: required i32 struct6_member2 +} + +service base { + oneway void base_oneway( + 1: i32 arg1), + + void base_function1( + 1: i16 function1_arg1, + 2: i32 function1_arg2, + 3: i64 function1_arg3, + 4: double function1_arg4, + 5: string function1_arg5, + 6: bool function1_arg6, + 7: test_enum1 function1_arg7, + 8: test_struct1 function1_arg8), + + void base_function2( + 1: list<i16> function2_arg1, + 2: list<i32> function2_arg2, + 3: list<i64> function2_arg3, + 4: list<double> function2_arg4, + 5: list<string> function2_arg5, + 6: list<bool> function2_arg6, + 7: list<byte> function2_arg7, + 8: list<test_enum1> function2_arg8, + 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e), + + void base_function3(), + +} + +service derived1 extends base{ + + test_enum1 derived1_function1( + 1: i64 function1_arg1, + 2: double function1_arg2, + 3: test_enum1 function1_arg3) throws (1:test_exception2 e), + + i64 derived1_function2( + 1: list<i64> function2_arg1, + 2: list<double> function2_arg2, + 3: list<string> function2_arg3, + 4: list<byte> function2_arg4, + 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e), + + double derived1_function3( + 1: string function3_arg1, + 2: bool function3_arg2) throws (1:test_exception2 e), + + string derived1_function4( + 1: string function4_arg1, + 2: bool function4_arg2) throws (1:test_exception2 e), + + + bool derived1_function5( + 1: map<i64, double> function5_arg1, + 2: map<string, bool> function5_arg2, + 3: map<test_enum1, test_enum2> function5_arg3) throws (1:test_exception2 e), + + test_struct1 derived1_function6( + 1: double function6_arg1) throws (1:test_exception2 e), +} + +service derived2 extends base { + + list<i32> derived2_function1( + 1: i32 function1_arg1) throws (1:test_exception2 e), + + list<test_enum1> derived2_function2( + 1:i64 function2_arg2) throws (1:test_exception2 e), + + list<test_struct1> derived2_function3( + 1:double function3_arg1) throws(1:test_exception2 e), + + map<double, string> derived2_function4( + 1:string function4_arg1) throws(1:test_exception2 e), + + map<test_enum1, test_enum2> derived2_function5( + 1:bool function5_arg1) throws(1:test_exception2 e), + + map<test_struct1, test_struct2> derived2_function6( + 1:bool function6_arg1) throws(1:test_exception2 e), + +} diff --git a/src/jaegertracing/thrift/test/c_glib/CMakeLists.txt b/src/jaegertracing/thrift/test/c_glib/CMakeLists.txt new file mode 100644 index 000000000..98173155b --- /dev/null +++ b/src/jaegertracing/thrift/test/c_glib/CMakeLists.txt @@ -0,0 +1,55 @@ +# +# 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. +# + +# Contains the thrift specific LINK_AGAINST_THRIFT_LIBRARY +include(ThriftMacros) + +find_package(GLIB REQUIRED COMPONENTS gobject) +include_directories(SYSTEM "${GLIB_INCLUDE_DIR}") +include_directories(SYSTEM "${GLIBCONFIG_INCLUDE_DIR}") + +#Make sure gen-c_glib files can be included +include_directories("${CMAKE_CURRENT_BINARY_DIR}") +include_directories("${CMAKE_CURRENT_BINARY_DIR}/gen-c_glib") +include_directories("${PROJECT_SOURCE_DIR}/lib/c_glib/src") + +set(crosstestgencglib_SOURCES + gen-c_glib/t_test_second_service.c + gen-c_glib/t_test_second_service.h + gen-c_glib/t_test_thrift_test.c + gen-c_glib/t_test_thrift_test.h + gen-c_glib/t_test_thrift_test_types.c + gen-c_glib/t_test_thrift_test_types.h +) +add_library(crosstestgencglib STATIC ${crosstestgencglib_SOURCES}) +LINK_AGAINST_THRIFT_LIBRARY(crosstestgencglib thrift_c_glib) + +add_executable(test_server src/test_server.c src/thrift_test_handler.c src/thrift_second_service_handler.c) +target_link_libraries(test_server crosstestgencglib) + +add_executable(test_client src/test_client.c) +target_link_libraries(test_client crosstestgencglib) + +# +# Common thrift code generation rules +# + +add_custom_command(OUTPUT gen-c_glib/t_test_second_service.c gen-c_glib/t_test_second_service.h gen-c_glib/t_test_thrift_test.c gen-c_glib/t_test_thrift_test.h gen-c_glib/t_test_thrift_test_types.c gen-c_glib/t_test_thrift_test_types.h + COMMAND ${THRIFT_COMPILER} --gen c_glib -r ${PROJECT_SOURCE_DIR}/test/ThriftTest.thrift +) diff --git a/src/jaegertracing/thrift/test/c_glib/Makefile.am b/src/jaegertracing/thrift/test/c_glib/Makefile.am new file mode 100755 index 000000000..98a373498 --- /dev/null +++ b/src/jaegertracing/thrift/test/c_glib/Makefile.am @@ -0,0 +1,82 @@ +# +# 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. +# +AUTOMAKE_OPTIONS = subdir-objects serial-tests nostdinc + +noinst_LTLIBRARIES = libtestcglib.la +nodist_libtestcglib_la_SOURCES = \ + gen-c_glib/t_test_second_service.c \ + gen-c_glib/t_test_second_service.h \ + gen-c_glib/t_test_thrift_test.c \ + gen-c_glib/t_test_thrift_test.h \ + gen-c_glib/t_test_thrift_test_types.c \ + gen-c_glib/t_test_thrift_test_types.h + +libtestcglib_la_LIBADD = $(top_builddir)/lib/c_glib/libthrift_c_glib.la + +precross: libtestcglib.la test_client test_server + +check_PROGRAMS = \ + test_client \ + test_server + +test_client_SOURCES = \ + src/test_client.c + +test_client_LDADD = \ + libtestcglib.la \ + $(top_builddir)/lib/c_glib/libthrift_c_glib.la + +test_server_SOURCES = \ + src/thrift_test_handler.c \ + src/thrift_test_handler.h \ + src/thrift_second_service_handler.c \ + src/thrift_second_service_handler.h \ + src/test_server.c + +test_server_LDADD = \ + libtestcglib.la \ + $(top_builddir)/lib/c_glib/libthrift_c_glib.la + +# +# Common thrift code generation rules +# +gen-c_glib/t_test_second_service.c gen-c_glib/t_test_second_service.h gen-c_glib/t_test_thrift_test.c gen-c_glib/t_test_thrift_test.h gen-c_glib/t_test_thrift_test_types.c gen-c_glib/t_test_thrift_test_types.h: $(top_srcdir)/test/ThriftTest.thrift $(THRIFT) + $(THRIFT) --gen c_glib -r $< + +AM_CFLAGS = -g -Wall -Wextra $(GLIB_CFLAGS) $(GOBJECT_CFLAGS) +AM_CXXFLAGS = $(AM_CFLAGS) +AM_CPPFLAGS = -I$(top_srcdir)/lib/c_glib/src -Igen-c_glib -I$(top_builddir)/lib/c_glib/src/thrift +AM_LDFLAGS = $(GLIB_LIBS) $(GOBJECT_LIBS) @GCOV_LDFLAGS@ + +clean-local: + $(RM) -r gen-c_glib/ + $(RM) test_client + $(RM) test_server + $(RM) libtestcglib.la + find . -type f -iname "*.o" | xargs rm -f + +dist-hook: + $(RM) -r $(distdir)/gen-c_glib/ + $(RM) $(distdir)/test_client + $(RM) $(distdir)/test_server + $(RM) $(distdir)/libtestcglib.la + find $(distdir) -type f -iname "*.o" | xargs rm -f + +EXTRA_DIST = \ + src diff --git a/src/jaegertracing/thrift/test/c_glib/src/test_client.c b/src/jaegertracing/thrift/test/c_glib/src/test_client.c new file mode 100644 index 000000000..7126a86d8 --- /dev/null +++ b/src/jaegertracing/thrift/test/c_glib/src/test_client.c @@ -0,0 +1,1825 @@ +/* + * 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. + */ + +#include <glib-object.h> +#include <inttypes.h> +#include <signal.h> +#include <stdio.h> +#include <string.h> + +#include <sys/time.h> + +#include <thrift/c_glib/thrift.h> +#include <thrift/c_glib/protocol/thrift_binary_protocol.h> +#include <thrift/c_glib/protocol/thrift_compact_protocol.h> +#include <thrift/c_glib/protocol/thrift_multiplexed_protocol.h> +#include <thrift/c_glib/transport/thrift_buffered_transport.h> +#include <thrift/c_glib/transport/thrift_framed_transport.h> +#include <thrift/c_glib/transport/thrift_ssl_socket.h> +#include <thrift/c_glib/transport/thrift_socket.h> +#include <thrift/c_glib/transport/thrift_transport.h> + +#include "../gen-c_glib/t_test_second_service.h" +#include "../gen-c_glib/t_test_thrift_test.h" + +/* Handle SIGPIPE signals (indicating the server has closed the + connection prematurely) by outputting an error message before + exiting. */ +static void +sigpipe_handler (int signal_number) +{ + THRIFT_UNUSED_VAR (signal_number); + + /* Flush standard output to make sure the test results so far are + logged */ + fflush (stdout); + + fputs ("Broken pipe (server closed connection prematurely)\n", stderr); + fflush (stderr); + + /* Re-raise the signal, this time invoking the default signal + handler, to terminate the program */ + raise (SIGPIPE); +} + +/* Compare two gint32 values. Used for sorting and finding integer + values within a GList. */ +static gint +gint32_compare (gconstpointer a, gconstpointer b) +{ + gint32 int32_a = *(gint32 *)a; + gint32 int32_b = *(gint32 *)b; + int result = 0; + + if (int32_a < int32_b) + result = -1; + else if (int32_a > int32_b) + result = 1; + + return result; +} + +/** + * It gets a multiplexed protocol which uses a concrete protocol underneath + * @param protocol_name the fully qualified protocol path (e.g. "binary:multi") + * @param transport the underlying transport + * @param service_name the single supported service name + * @todo need to allow multiple services to fully test multiplexed + * @return a multiplexed protocol wrapping the correct underlying protocol + */ +ThriftProtocol * +get_multiplexed_protocol(gchar *protocol_name, ThriftTransport *transport, gchar *service_name) +{ + ThriftProtocol * multiplexed_protocol = NULL; + + if ( strncmp(protocol_name, "binary:", 7) == 0) { + multiplexed_protocol = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, + "transport", transport, + NULL); + } else if ( strncmp(protocol_name, "compact:", 8) == 0) { + multiplexed_protocol = g_object_new (THRIFT_TYPE_COMPACT_PROTOCOL, + "transport", transport, + NULL); + } else { + fprintf(stderr, "Unknown multiplex protocol name: %s\n", protocol_name); + return NULL; + } + + return g_object_new (THRIFT_TYPE_MULTIPLEXED_PROTOCOL, + "transport", transport, + "protocol", multiplexed_protocol, + "service-name", service_name, + NULL); +} + +int +main (int argc, char **argv) +{ + static gchar * host = NULL; + static gint port = 9090; + static gchar * path = NULL; + static gboolean ssl = FALSE; + static gchar * transport_option = NULL; + static gchar * protocol_option = NULL; + static gint num_tests = 1; + + static + GOptionEntry option_entries[] ={ + { "host", 'h', 0, G_OPTION_ARG_STRING, &host, + "Host to connect (=localhost)", NULL }, + { "port", 'p', 0, G_OPTION_ARG_INT, &port, + "Port number to connect (=9090)", NULL }, + { "domain-socket", 0, 0, G_OPTION_ARG_STRING, &path, + "Unix socket domain path to connect", NULL }, + { "ssl", 's', 0, G_OPTION_ARG_NONE, &ssl, + "Enable SSL", NULL }, + { "transport", 't', 0, G_OPTION_ARG_STRING, &transport_option, + "Transport: buffered, framed (=buffered)", NULL }, + { "protocol", 'r', 0, G_OPTION_ARG_STRING, &protocol_option, + "Protocol: binary, compact, multi, multic (=binary)", NULL }, + { "testloops", 'n', 0, G_OPTION_ARG_INT, &num_tests, + "Number of tests (=1)", NULL }, + { NULL } + }; + + struct sigaction sigpipe_action; + + GType socket_type = THRIFT_TYPE_SOCKET; + gchar *socket_name = "ip"; + GType transport_type = THRIFT_TYPE_BUFFERED_TRANSPORT; + gchar *transport_name = "buffered"; + GType protocol_type = THRIFT_TYPE_BINARY_PROTOCOL; + gchar *protocol_name = "binary"; + + ThriftSocket *socket = NULL; + ThriftTransport *transport = NULL; + ThriftProtocol *protocol = NULL; + ThriftProtocol *protocol2 = NULL; // for multiplexed tests + + TTestThriftTestIf *test_client = NULL; + TTestSecondServiceIf *second_service = NULL; // for multiplexed tests + + struct timeval time_start, time_stop, time_elapsed; + guint64 time_elapsed_usec, time_total_usec = 0; + guint64 time_min_usec = G_MAXUINT64, time_max_usec = 0, time_avg_usec; + + GOptionContext *option_context; + gboolean options_valid = TRUE; + int test_num = 0; + int fail_count = 0; + GError *error = NULL; + +#if (!GLIB_CHECK_VERSION (2, 36, 0)) + g_type_init (); +#endif + + /* Configure and parse our command-line options */ + option_context = g_option_context_new (NULL); + g_option_context_add_main_entries (option_context, + option_entries, + NULL); + if (!g_option_context_parse (option_context, + &argc, + &argv, + &error)) { + fprintf (stderr, "%s\n", error->message); + return 255; + } + g_option_context_free (option_context); + + /* Set remaining default values for unspecified options */ + if (host == NULL) + host = g_strdup ("localhost"); + + /* Validate the parsed options */ + if (protocol_option != NULL) { + if (strncmp (protocol_option, "compact", 8) == 0) { + protocol_type = THRIFT_TYPE_COMPACT_PROTOCOL; + protocol_name = "compact"; + } + else if (strncmp (protocol_option, "multi", 6) == 0) { + protocol_type = THRIFT_TYPE_MULTIPLEXED_PROTOCOL; + protocol_name = "binary:multi"; + } + else if (strncmp (protocol_option, "multic", 7) == 0) { + protocol_type = THRIFT_TYPE_MULTIPLEXED_PROTOCOL; + protocol_name = "compact:multic"; + } + else if (strncmp (protocol_option, "binary", 7) == 0) { + printf("We are going with default protocol\n"); + } + else { + fprintf (stderr, "Unknown protocol type %s\n", protocol_option); + options_valid = FALSE; + } + } + + if (transport_option != NULL) { + if (strncmp (transport_option, "framed", 7) == 0) { + transport_type = THRIFT_TYPE_FRAMED_TRANSPORT; + transport_name = "framed"; + } + else if (strncmp (transport_option, "buffered", 9) != 0) { + fprintf (stderr, "Unknown transport type %s\n", transport_option); + options_valid = FALSE; + } + } + + if (ssl) { + socket_type = THRIFT_TYPE_SSL_SOCKET; + socket_name = "ip-ssl"; + printf("Type name %s\n", g_type_name (socket_type)); + } + + if (!options_valid) + return 254; + + if (path) { + printf ("Connecting (%s/%s) to: %s/%s\n", + transport_name, + protocol_name, + socket_name, + path); + } else { + printf ("Connecting (%s/%s) to: %s/%s:%d\n", + transport_name, + protocol_name, + socket_name, + host, + port); + } + + /* Install our SIGPIPE handler, which outputs an error message to + standard error before exiting so testers can know what + happened */ + memset (&sigpipe_action, 0, sizeof (sigpipe_action)); + sigpipe_action.sa_handler = sigpipe_handler; + sigpipe_action.sa_flags = SA_RESETHAND; + sigaction (SIGPIPE, &sigpipe_action, NULL); + + if (ssl) { + thrift_ssl_socket_initialize_openssl(); + } + + /* Establish all our connection objects */ + if (path) { + socket = g_object_new (socket_type, + "path", path, + NULL); + } else { + socket = g_object_new (socket_type, + "hostname", host, + "port", port, + NULL); + } + + if (ssl && !thrift_ssl_load_cert_from_file(THRIFT_SSL_SOCKET(socket), "../keys/CA.pem")) { + fprintf(stderr, "Unable to load validation certificate ../keys/CA.pem - did you run in the test/c_glib directory?\n"); + g_clear_object (&socket); + return 253; + } + + transport = g_object_new (transport_type, + "transport", socket, + NULL); + + if(protocol_type==THRIFT_TYPE_MULTIPLEXED_PROTOCOL) { + // TODO: A multiplexed test should also test "Second" (see Java TestServer) + // The context comes from the name of the thrift file. If multiple thrift + // schemas are used we have to redo the way this is done. + protocol = get_multiplexed_protocol(protocol_name, transport, "ThriftTest"); + if (NULL == protocol) { + g_clear_object (&transport); + g_clear_object (&socket); + return 252; + } + + // Make a second protocol and client running on the same multiplexed transport + protocol2 = get_multiplexed_protocol(protocol_name, transport, "SecondService"); + second_service = g_object_new (T_TEST_TYPE_SECOND_SERVICE_CLIENT, + "input_protocol", protocol2, + "output_protocol", protocol2, + NULL); + + }else{ + protocol = g_object_new (protocol_type, + "transport", transport, + NULL); + } + + test_client = g_object_new (T_TEST_TYPE_THRIFT_TEST_CLIENT, + "input_protocol", protocol, + "output_protocol", protocol, + NULL); + + /* Execute the actual tests */ + for (test_num = 0; test_num < num_tests; ++test_num) { + if (thrift_transport_open (transport, &error)) { + gchar *string = NULL; + gboolean boolean = 0; + gint8 byte = 0; + gint32 int32 = 0; + gint64 int64 = 0; + gdouble dub = 0; + + gint byte_thing, i32_thing, inner_byte_thing, inner_i32_thing; + gint64 i64_thing, inner_i64_thing; + + TTestXtruct *xtruct_out, *xtruct_out2, *xtruct_in, *inner_xtruct_in; + TTestXtruct2 *xtruct2_out, *xtruct2_in; + + GHashTable *map_out, *map_in, *inner_map_in; + GHashTable *set_out, *set_in; + gpointer key, value; + gint32 *i32_key_ptr, *i32_value_ptr; + GHashTableIter hash_table_iter, inner_hash_table_iter; + GList *keys_out, *keys_in, *keys_elem; + + GArray *list_out, *list_in; + + TTestNumberz numberz; + TTestNumberz numberz2; + + TTestUserId user_id, *user_id_ptr, *user_id_ptr2; + + TTestInsanity *insanity_out, *insanity_in; + GHashTable *user_map; + GHashTableIter user_map_iter; + GPtrArray *xtructs; + + TTestXception *xception = NULL; + TTestXception2 *xception2 = NULL; + + gboolean oneway_result; + struct timeval oneway_start, oneway_end, oneway_elapsed; + gint oneway_elapsed_usec; + + gboolean first; + gint32 i, j; + + if (path) { + printf ("Test #%d, connect %s\n", test_num + 1, path); + } else { + printf ("Test #%d, connect %s:%d\n", test_num + 1, host, port); + } + gettimeofday (&time_start, NULL); + + /* These test routines have been ported from the C++ test + client, care being taken to ensure their output remains as + close as possible to the original to facilitate diffs. + + For simplicity comments have been omitted, but every routine + has the same basic structure: + + - Create and populate data structures as necessary. + + - Format and output (to the console) a representation of the + outgoing data. + + - Issue the remote method call to the server. + + - Format and output a representation of the returned data. + + - Verify the returned data matches what was expected. + + - Deallocate any created data structures. + + Note the recognized values and expected behaviour of each + remote method are described in ThriftTest.thrift, which + you'll find in the top-level "test" folder. */ + + /** + * VOID TEST + */ + printf ("testVoid()"); + if (t_test_thrift_test_if_test_void (test_client, &error)) { + printf (" = void\n"); + } + else { + if(error!=NULL){ + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + } + fail_count++; + } + + /** + * STRING TEST + */ + printf ("testString(\"Test\")"); + if (t_test_thrift_test_if_test_string (test_client, + &string, + "Test", + &error)) { + printf (" = \"%s\"\n", string); + if (strncmp (string, "Test", 5) != 0) + fail_count++; + + g_free (string); + string = NULL; + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + + /** + * Multiplexed Test - do this right in the middle of the normal Test Client run + */ + if (second_service) { + printf ("testSecondServiceMultiplexSecondTestString(\"2nd\")"); + if (t_test_second_service_if_secondtest_string (second_service, + &string, + "2nd", + &error)) { + printf (" = \"%s\"\n", string); + if (strcmp (string, "testString(\"2nd\")") != 0) { + ++fail_count; + } + + g_free (string); + string = NULL; + } else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + ++fail_count; + } + } + + /** + * BOOL TEST + */ + printf ("testByte(true)"); + if (t_test_thrift_test_if_test_bool (test_client, + &boolean, + 1, + &error)) { + printf (" = %s\n", boolean ? "true" : "false"); + if (boolean != 1) + fail_count++; + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + printf ("testByte(false)"); + if (t_test_thrift_test_if_test_bool (test_client, + &boolean, + 0, + &error)) { + printf (" = %s\n", boolean ? "true" : "false"); + if (boolean != 0) + fail_count++; + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + + /** + * BYTE TEST + */ + printf ("testByte(1)"); + if (t_test_thrift_test_if_test_byte (test_client, + &byte, + 1, + &error)) { + printf (" = %d\n", byte); + if (byte != 1) + fail_count++; + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + printf ("testByte(-1)"); + if (t_test_thrift_test_if_test_byte (test_client, + &byte, + -1, + &error)) { + printf (" = %d\n", byte); + if (byte != -1) + fail_count++; + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + + /** + * I32 TEST + */ + printf ("testI32(-1)"); + if (t_test_thrift_test_if_test_i32 (test_client, + &int32, + -1, + &error)) { + printf (" = %d\n", int32); + if (int32 != -1) + fail_count++; + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + + /** + * I64 TEST + */ + printf ("testI64(-34359738368)"); + if (t_test_thrift_test_if_test_i64 (test_client, + &int64, + (gint64)-34359738368, + &error)) { + printf (" = %" PRId64 "\n", int64); + if (int64 != (gint64)-34359738368) + fail_count++; + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + + /** + * DOUBLE TEST + */ + printf("testDouble(-5.2098523)"); + if (t_test_thrift_test_if_test_double (test_client, + &dub, + -5.2098523, + &error)) { + printf (" = %f\n", dub); + if ((dub - (-5.2098523)) > 0.001) + fail_count++; + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + + /** + * BINARY TEST + */ + printf ("testBinary(empty)"); + GByteArray *emptyArray = g_byte_array_new(); + GByteArray *result = NULL; + if (t_test_thrift_test_if_test_binary (test_client, + &result, + emptyArray, + &error)) { + GBytes *response = g_byte_array_free_to_bytes(result); // frees result + result = NULL; + gsize siz = g_bytes_get_size(response); + if (siz == 0) { + printf(" = empty\n"); + } else { + printf(" = not empty (%ld bytes)\n", (long)siz); + ++fail_count; + } + g_bytes_unref(response); + } else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + g_byte_array_unref(emptyArray); + emptyArray = NULL; + + // TODO: add testBinary() with data + printf ("testBinary([-128..127]) = {"); + const signed char bin_data[256] + = {-128, -127, -126, -125, -124, -123, -122, -121, -120, -119, -118, -117, -116, -115, -114, + -113, -112, -111, -110, -109, -108, -107, -106, -105, -104, -103, -102, -101, -100, -99, + -98, -97, -96, -95, -94, -93, -92, -91, -90, -89, -88, -87, -86, -85, -84, + -83, -82, -81, -80, -79, -78, -77, -76, -75, -74, -73, -72, -71, -70, -69, + -68, -67, -66, -65, -64, -63, -62, -61, -60, -59, -58, -57, -56, -55, -54, + -53, -52, -51, -50, -49, -48, -47, -46, -45, -44, -43, -42, -41, -40, -39, + -38, -37, -36, -35, -34, -33, -32, -31, -30, -29, -28, -27, -26, -25, -24, + -23, -22, -21, -20, -19, -18, -17, -16, -15, -14, -13, -12, -11, -10, -9, + -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, + 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, + 127}; + GByteArray *fullArray = g_byte_array_new(); + g_byte_array_append(fullArray, (guint8 *)(&bin_data[0]), 256); + if (t_test_thrift_test_if_test_binary (test_client, + &result, + fullArray, + &error)) { + GBytes *response = g_byte_array_free_to_bytes(result); // frees result + result = NULL; + gsize siz = g_bytes_get_size(response); + gconstpointer ptr = g_bytes_get_data(response, &siz); + if (siz == 256) { + gboolean first = 1; + gboolean failed = 0; + int i; + + for (i = 0; i < 256; ++i) { + if (!first) + printf(","); + else + first = 0; + int val = ((signed char *)ptr)[i]; + printf("%d", val); + if (!failed && val != i - 128) { + failed = 1; + } + } + printf("} "); + if (failed) { + printf("FAIL (bad content) size %ld OK\n", (long)siz); + ++fail_count; + } else { + printf("OK size %ld OK\n", (long)siz); + } + } else { + printf(" = bad size %ld\n", (long)siz); + ++fail_count; + } + g_bytes_unref(response); + } else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + g_byte_array_unref(fullArray); + fullArray = NULL; + + /** + * STRUCT TEST + */ + printf ("testStruct({\"Zero\", 1, -3, -5})"); + xtruct_out = g_object_new (T_TEST_TYPE_XTRUCT, + "string_thing", "Zero", + "byte_thing", 1, + "i32_thing", -3, + "i64_thing", -5LL, + NULL); + xtruct_in = g_object_new (T_TEST_TYPE_XTRUCT, NULL); + + if (t_test_thrift_test_if_test_struct (test_client, + &xtruct_in, + xtruct_out, + &error)) { + g_object_get (xtruct_in, + "string_thing", &string, + "byte_thing", &byte_thing, + "i32_thing", &i32_thing, + "i64_thing", &i64_thing, + NULL); + + printf (" = {\"%s\", %d, %d, %" PRId64 "}\n", + string, + byte_thing, + i32_thing, + i64_thing); + if ((string == NULL || strncmp (string, "Zero", 5) != 0) || + byte_thing != 1 || + i32_thing != -3 || + i64_thing != (gint64)-5) + fail_count++; + + if (string) { + g_free (string); + string = NULL; + } + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + // g_clear_object(&xtruct_out); used below + g_clear_object(&xtruct_in); + + /** + * NESTED STRUCT TEST + */ + printf ("testNest({1, {\"Zero\", 1, -3, -5}), 5}"); + xtruct2_out = g_object_new (T_TEST_TYPE_XTRUCT2, + "byte_thing", 1, + "struct_thing", xtruct_out, + "i32_thing", 5, + NULL); + xtruct2_in = g_object_new (T_TEST_TYPE_XTRUCT2, NULL); + + if (t_test_thrift_test_if_test_nest (test_client, + &xtruct2_in, + xtruct2_out, + &error)) { + g_object_get (xtruct2_in, + "byte_thing", &byte_thing, + "struct_thing", &xtruct_in, + "i32_thing", &i32_thing, + NULL); + g_object_get (xtruct_in, + "string_thing", &string, + "byte_thing", &inner_byte_thing, + "i32_thing", &inner_i32_thing, + "i64_thing", &inner_i64_thing, + NULL); + + printf (" = {%d, {\"%s\", %d, %d, %" PRId64 "}, %d}\n", + byte_thing, + string, + inner_byte_thing, + inner_i32_thing, + inner_i64_thing, + i32_thing); + if (byte_thing != 1 || + (string == NULL || strncmp (string, "Zero", 5) != 0) || + inner_byte_thing != 1 || + inner_i32_thing != -3 || + inner_i64_thing != (gint64)-5 || + i32_thing != 5) + fail_count++; + + if (string) { + g_free(string); + string = NULL; + } + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + + g_clear_object(&xtruct_in); + g_clear_object(&xtruct2_in); + g_clear_object(&xtruct2_out); + g_clear_object(&xtruct_out); + + /** + * MAP TEST + */ + map_out = g_hash_table_new_full (g_int_hash, + g_int_equal, + g_free, + g_free); + for (i = 0; i < 5; ++i) { + i32_key_ptr = g_malloc (sizeof *i32_key_ptr); + i32_value_ptr = g_malloc (sizeof *i32_value_ptr); + + *i32_key_ptr = i; + *i32_value_ptr = i - 10; + + g_hash_table_insert (map_out, i32_key_ptr, i32_value_ptr); + } + printf ("testMap({"); + first = TRUE; + g_hash_table_iter_init (&hash_table_iter, map_out); + while (g_hash_table_iter_next (&hash_table_iter, + &key, + &value)) { + if (first) + first = FALSE; + else + printf (", "); + + printf ("%d => %d", *(gint32 *)key, *(gint32 *)value); + } + printf ("})"); + + map_in = g_hash_table_new_full (g_int_hash, + g_int_equal, + g_free, + g_free); + + if (t_test_thrift_test_if_test_map (test_client, + &map_in, + map_out, + &error)) { + printf (" = {"); + first = TRUE; + g_hash_table_iter_init (&hash_table_iter, map_in); + while (g_hash_table_iter_next (&hash_table_iter, + &key, + &value)) { + if (first) + first = FALSE; + else + printf (", "); + + printf ("%d => %d", *(gint32 *)key, *(gint32 *)value); + } + printf ("}\n"); + + if (g_hash_table_size (map_in) != g_hash_table_size (map_out)) + fail_count++; + else { + g_hash_table_iter_init (&hash_table_iter, map_out); + while (g_hash_table_iter_next (&hash_table_iter, + &key, + &value)) { + gpointer in_value = g_hash_table_lookup (map_in, key); + if (in_value == NULL || + *(gint32 *)in_value != *(gint32 *)value) { + fail_count++; + break; + } + } + } + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + + g_hash_table_unref (map_in); + g_hash_table_unref (map_out); + + /** + * STRING MAP TEST + */ + map_out = g_hash_table_new_full (g_str_hash, + g_str_equal, + NULL, + NULL); + g_hash_table_insert (map_out, "a", "2"); + g_hash_table_insert (map_out, "b", "blah"); + g_hash_table_insert (map_out, "some", "thing"); + printf ("testStringMap({"); + first = TRUE; + g_hash_table_iter_init (&hash_table_iter, map_out); + while (g_hash_table_iter_next (&hash_table_iter, + &key, + &value)) { + if (first) + first = FALSE; + else + printf (", "); + + printf ("\"%s\" => \"%s\"", (gchar *)key, (gchar *)value); + } + printf (")}"); + + map_in = g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + g_free); + + if (t_test_thrift_test_if_test_string_map (test_client, + &map_in, + map_out, + &error)) { + printf (" = {"); + first = TRUE; + g_hash_table_iter_init (&hash_table_iter, map_in); + while (g_hash_table_iter_next (&hash_table_iter, + &key, + &value)) { + if (first) + first = FALSE; + else + printf (", "); + + printf ("\"%s\" => \"%s\"", (gchar *)key, (gchar *)value); + } + printf ("}\n"); + + if (g_hash_table_size (map_in) != g_hash_table_size (map_out)) + fail_count++; + else { + g_hash_table_iter_init (&hash_table_iter, map_out); + while (g_hash_table_iter_next (&hash_table_iter, + &key, + &value)) { + gpointer in_value = g_hash_table_lookup (map_in, key); + if (in_value == NULL || + strcmp ((gchar *)in_value, (gchar *)value) != 0) { + fail_count++; + break; + } + } + } + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + + g_hash_table_unref (map_in); + g_hash_table_unref (map_out); + + /** + * SET TEST + */ + set_out = g_hash_table_new_full (g_int_hash, g_int_equal, g_free, NULL); + for (i = -2; i < 3; ++i) { + i32_key_ptr = g_malloc (sizeof *i32_key_ptr); + *i32_key_ptr = i; + + g_hash_table_insert (set_out, i32_key_ptr, NULL); + } + printf ("testSet({"); + first = TRUE; + keys_out = g_hash_table_get_keys (set_out); + keys_elem = keys_out; + while (keys_elem != NULL) { + if (first) + first = FALSE; + else + printf (", "); + + printf ("%d", *(gint32 *)keys_elem->data); + + keys_elem = keys_elem->next; + } + printf ("})"); + + set_in = g_hash_table_new_full (g_int_hash, g_int_equal, g_free, NULL); + + if (t_test_thrift_test_if_test_set (test_client, + &set_in, + set_out, + &error)) { + printf(" = {"); + first = TRUE; + keys_in = g_hash_table_get_keys (set_in); + keys_elem = keys_in; + while (keys_elem != NULL) { + if (first) + first = FALSE; + else + printf (", "); + + printf ("%d", *(gint32 *)keys_elem->data); + + keys_elem = keys_elem->next; + } + printf ("}\n"); + + if (g_list_length (keys_in) != g_list_length (keys_out)) + fail_count++; + else { + keys_elem = keys_out; + while (keys_elem != NULL) { + if (g_list_find_custom (keys_in, + keys_elem->data, + gint32_compare) == NULL) { + fail_count++; + break; + } + + keys_elem = keys_elem->next; + } + } + + g_list_free (keys_in); + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + + g_hash_table_unref (set_in); + g_list_free (keys_out); + g_hash_table_unref (set_out); + + /** + * LIST TEST + */ + list_out = g_array_new (FALSE, TRUE, sizeof (gint32)); + for (i = -2; i < 3; ++i) { + g_array_append_val (list_out, i); + } + printf ("testList({"); + first = TRUE; + for (i = 0; i < (gint32)list_out->len; ++i) { + if (first) + first = FALSE; + else + printf (", "); + + printf ("%d", g_array_index (list_out, gint32, i)); + } + printf ("})"); + + list_in = g_array_new (FALSE, TRUE, sizeof (gint32)); + + if (t_test_thrift_test_if_test_list (test_client, + &list_in, + list_out, + &error)) { + printf (" = {"); + first = TRUE; + for (i = 0; i < (gint32)list_in->len; ++i) { + if (first) + first = FALSE; + else + printf (", "); + + printf ("%d", g_array_index (list_in, gint32, i)); + } + printf ("}\n"); + + if (list_in->len != list_out->len || + memcmp (list_in->data, + list_out->data, + list_in->len * sizeof (gint32)) != 0) + fail_count++; + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + + g_array_unref (list_in); + g_array_unref (list_out); + + /** + * ENUM TEST + */ + printf("testEnum(ONE)"); + if (t_test_thrift_test_if_test_enum (test_client, + &numberz, + T_TEST_NUMBERZ_ONE, + &error)) { + printf(" = %d\n", numberz); + if (numberz != T_TEST_NUMBERZ_ONE) + fail_count++; + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + + printf("testEnum(TWO)"); + if (t_test_thrift_test_if_test_enum (test_client, + &numberz, + T_TEST_NUMBERZ_TWO, + &error)) { + printf(" = %d\n", numberz); + if (numberz != T_TEST_NUMBERZ_TWO) + fail_count++; + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + + printf("testEnum(THREE)"); + if (t_test_thrift_test_if_test_enum (test_client, + &numberz, + T_TEST_NUMBERZ_THREE, + &error)) { + printf(" = %d\n", numberz); + if (numberz != T_TEST_NUMBERZ_THREE) + fail_count++; + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + + printf("testEnum(FIVE)"); + if (t_test_thrift_test_if_test_enum (test_client, + &numberz, + T_TEST_NUMBERZ_FIVE, + &error)) { + printf(" = %d\n", numberz); + if (numberz != T_TEST_NUMBERZ_FIVE) + fail_count++; + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + + printf("testEnum(EIGHT)"); + if (t_test_thrift_test_if_test_enum (test_client, + &numberz, + T_TEST_NUMBERZ_EIGHT, + &error)) { + printf(" = %d\n", numberz); + if (numberz != T_TEST_NUMBERZ_EIGHT) + fail_count++; + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + + /** + * TYPEDEF TEST + */ + printf ("testTypedef(309858235082523)"); + if (t_test_thrift_test_if_test_typedef (test_client, + &user_id, + 309858235082523LL, + &error)) { + printf(" = %" PRId64 "\n", user_id); + if (user_id != 309858235082523LL) + fail_count++; + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + + /** + * NESTED MAP TEST + */ + printf ("testMapMap(1)"); + map_in = g_hash_table_new_full (g_int_hash, + g_int_equal, + g_free, + (GDestroyNotify)g_hash_table_unref); + if (t_test_thrift_test_if_test_map_map (test_client, + &map_in, + 1, + &error)) { + g_hash_table_iter_init (&hash_table_iter, map_in); + + printf (" = {"); + while (g_hash_table_iter_next (&hash_table_iter, + &key, + &value)) { + printf ("%d => {", *(gint32 *)key); + + g_hash_table_iter_init (&inner_hash_table_iter, + (GHashTable *)value); + while (g_hash_table_iter_next (&inner_hash_table_iter, + &key, + &value)) { + printf ("%d => %d, ", *(gint32 *)key, *(gint32 *)value); + } + + printf ("}, "); + } + printf ("}\n"); + + if (g_hash_table_size (map_in) != 2) + fail_count++; + else { + gint32 inner_keys[] = {1, 2, 3, 4}; + gint32 i32_key; + + i32_key = -4; + inner_map_in = g_hash_table_lookup (map_in, &i32_key); + if (inner_map_in == NULL || + g_hash_table_size (inner_map_in) != 4) + fail_count++; + else { + keys_in = g_hash_table_get_keys (inner_map_in); + keys_in = g_list_sort (keys_in, gint32_compare); + + for (i = 0; i < 4; i++) { + keys_elem = g_list_nth (keys_in, 3 - i); + + if (*(gint32 *)keys_elem->data != (-1 * inner_keys[i]) || + *(gint32 *)g_hash_table_lookup (inner_map_in, + keys_elem->data) != + (-1 * inner_keys[i])) { + fail_count++; + break; + } + } + + g_list_free (keys_in); + } + + i32_key = 4; + inner_map_in = g_hash_table_lookup (map_in, &i32_key); + if (inner_map_in == NULL || + g_hash_table_size (inner_map_in) != 4) + fail_count++; + else { + keys_in = g_hash_table_get_keys (inner_map_in); + keys_in = g_list_sort (keys_in, gint32_compare); + + for (i = 0; i < 4; i++) { + keys_elem = g_list_nth (keys_in, i); + + if (*(gint32 *)keys_elem->data != inner_keys[i] || + *(gint32 *)g_hash_table_lookup (inner_map_in, + keys_elem->data) != + inner_keys[i]) { + fail_count++; + break; + } + } + + g_list_free (keys_in); + } + } + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + + g_hash_table_unref (map_in); + + /** + * INSANITY TEST + */ + insanity_out = g_object_new (T_TEST_TYPE_INSANITY, NULL); + g_object_get (insanity_out, + "userMap", &user_map, + "xtructs", &xtructs, + NULL); + + numberz = T_TEST_NUMBERZ_FIVE; + numberz2 = T_TEST_NUMBERZ_EIGHT; + user_id_ptr = g_malloc (sizeof *user_id_ptr); + *user_id_ptr = 5; + user_id_ptr2 = g_malloc (sizeof *user_id_ptr); + *user_id_ptr2 = 8; + g_hash_table_insert (user_map, (gpointer)numberz, user_id_ptr); + g_hash_table_insert (user_map, (gpointer)numberz2, user_id_ptr2); + g_hash_table_unref (user_map); + + xtruct_out = g_object_new (T_TEST_TYPE_XTRUCT, + "string_thing", "Hello2", + "byte_thing", 2, + "i32_thing", 2, + "i64_thing", 2LL, + NULL); + xtruct_out2 = g_object_new (T_TEST_TYPE_XTRUCT, + "string_thing", "Goodbye4", + "byte_thing", 4, + "i32_thing", 4, + "i64_thing", 4LL, + NULL); + g_ptr_array_add (xtructs, xtruct_out2); + g_ptr_array_add (xtructs, xtruct_out); + g_ptr_array_unref (xtructs); + + map_in = g_hash_table_new_full (g_int64_hash, + g_int64_equal, + g_free, + (GDestroyNotify)g_hash_table_unref); + + printf("testInsanity()"); + if (t_test_thrift_test_if_test_insanity (test_client, + &map_in, + insanity_out, + &error)) { + printf (" = {"); + g_hash_table_iter_init (&hash_table_iter, map_in); + while (g_hash_table_iter_next (&hash_table_iter, + &key, + &value)) { + printf ("%" PRId64 " => {", *(TTestUserId *)key); + + g_hash_table_iter_init (&inner_hash_table_iter, + (GHashTable *)value); + while (g_hash_table_iter_next (&inner_hash_table_iter, + &key, + &value)) { + printf ("%d => {", (TTestNumberz)key); + + g_object_get ((TTestInsanity *)value, + "userMap", &user_map, + "xtructs", &xtructs, + NULL); + + printf ("{"); + g_hash_table_iter_init (&user_map_iter, user_map); + while (g_hash_table_iter_next (&user_map_iter, + &key, + &value)) { + printf ("%d => %" PRId64 ", ", + (TTestNumberz)key, + *(TTestUserId *)value); + } + printf ("}, "); + g_hash_table_unref (user_map); + + printf("{"); + for (i = 0; i < (gint32)xtructs->len; ++i) { + xtruct_in = g_ptr_array_index (xtructs, i); + g_object_get (xtruct_in, + "string_thing", &string, + "byte_thing", &byte_thing, + "i32_thing", &i32_thing, + "i64_thing", &i64_thing, + NULL); + + printf ("{\"%s\", %d, %d, %" PRId64 "}, ", + string, + byte_thing, + i32_thing, + i64_thing); + } + printf ("}"); + g_ptr_array_unref (xtructs); + + printf ("}, "); + } + printf("}, "); + } + printf("}\n"); + + if (g_hash_table_size (map_in) != 2) + fail_count++; + else { + TTestNumberz numberz_key_values[] = { + T_TEST_NUMBERZ_TWO, T_TEST_NUMBERZ_THREE + }; + gint user_map_values[] = { 5, 8 }; + TTestUserId user_id_key; + + user_id_key = 1; + inner_map_in = g_hash_table_lookup (map_in, &user_id_key); + if (inner_map_in == NULL || + g_hash_table_size (inner_map_in) != 2) + fail_count++; + else { + TTestNumberz numberz_key; + + for (i = 0; i < 2; ++i) { + numberz_key = numberz_key_values[i]; + insanity_in = + g_hash_table_lookup (inner_map_in, + (gconstpointer)numberz_key); + if (insanity_in == NULL) + fail_count++; + else { + g_object_get (insanity_in, + "userMap", &user_map, + "xtructs", &xtructs, + NULL); + + if (user_map == NULL) + fail_count++; + else { + if (g_hash_table_size (user_map) != 2) + fail_count++; + else { + for (j = 0; j < 2; ++j) { + numberz_key = (TTestNumberz)user_map_values[j]; + + value = + g_hash_table_lookup (user_map, + (gconstpointer)numberz_key); + if (value == NULL || + *(TTestUserId *)value != (TTestUserId)user_map_values[j]) + fail_count++; + } + } + + g_hash_table_unref (user_map); + } + + if (xtructs == NULL) + fail_count++; + else { + if (xtructs->len != 2) + fail_count++; + else { + xtruct_in = g_ptr_array_index (xtructs, 0); + g_object_get (xtruct_in, + "string_thing", &string, + "byte_thing", &byte_thing, + "i32_thing", &i32_thing, + "i64_thing", &i64_thing, + NULL); + if ((string == NULL || + strncmp (string, "Goodbye4", 9) != 0) || + byte_thing != 4 || + i32_thing != 4 || + i64_thing != 4) + fail_count++; + + if (string != NULL) + g_free (string); + + xtruct_in = g_ptr_array_index (xtructs, 1); + g_object_get (xtruct_in, + "string_thing", &string, + "byte_thing", &byte_thing, + "i32_thing", &i32_thing, + "i64_thing", &i64_thing, + NULL); + if ((string == NULL || + strncmp (string, "Hello2", 7) != 0) || + byte_thing != 2 || + i32_thing != 2 || + i64_thing != 2) + fail_count++; + + if (string != NULL) + g_free (string); + } + + g_ptr_array_unref (xtructs); + } + } + } + } + + user_id_key = 2; + inner_map_in = g_hash_table_lookup (map_in, &user_id_key); + if (inner_map_in == NULL || + g_hash_table_size (inner_map_in) != 1) + fail_count++; + else { + insanity_in = + g_hash_table_lookup (inner_map_in, + (gconstpointer)T_TEST_NUMBERZ_SIX); + if (insanity_in == NULL) + fail_count++; + else { + g_object_get (insanity_in, + "userMap", &user_map, + "xtructs", &xtructs, + NULL); + + if (user_map == NULL) + fail_count++; + else { + if (g_hash_table_size (user_map) != 0) + fail_count++; + + g_hash_table_unref (user_map); + } + + if (xtructs == NULL) + fail_count++; + else { + if (xtructs->len != 0) + fail_count++; + + g_ptr_array_unref (xtructs); + } + } + } + } + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + + g_hash_table_unref (map_in); + g_clear_object (&insanity_out); + + /* test exception */ + printf ("testClient.testException(\"Xception\") =>"); + if (!t_test_thrift_test_if_test_exception (test_client, + "Xception", + &xception, + &error) && + xception != NULL) { + g_object_get (xception, + "errorCode", &int32, + "message", &string, + NULL); + printf (" {%u, \"%s\"}\n", int32, string); + g_free (string); + + g_clear_object (&xception); + + g_error_free (error); + error = NULL; + } + else { + printf (" void\nFAILURE\n"); + fail_count++; + + if (xception != NULL) { + g_object_unref (xception); + xception = NULL; + } + + if (error != NULL) { + g_error_free (error); + error = NULL; + } + } + + printf ("testClient.testException(\"TException\") =>"); + if (!t_test_thrift_test_if_test_exception (test_client, + "TException", + &xception, + &error) && + xception == NULL && + error != NULL) { + printf (" Caught TException\n"); + + g_error_free (error); + error = NULL; + } + else { + printf (" void\nFAILURE\n"); + fail_count++; + + g_clear_object (&xception); + + if (error != NULL) { + g_error_free (error); + error = NULL; + } + } + + printf ("testClient.testException(\"success\") =>"); + if (t_test_thrift_test_if_test_exception (test_client, + "success", + &xception, + &error)) + printf (" void\n"); + else { + printf (" void\nFAILURE\n"); + fail_count++; + + g_clear_object (&xception); + + g_error_free (error); + error = NULL; + } + + g_assert (error == NULL); + + /* test multi exception */ + printf ("testClient.testMultiException(\"Xception\", \"test 1\") =>"); + xtruct_in = g_object_new (T_TEST_TYPE_XTRUCT, NULL); + if (!t_test_thrift_test_if_test_multi_exception (test_client, + &xtruct_in, + "Xception", + "test 1", + &xception, + &xception2, + &error) && + xception != NULL && + xception2 == NULL) { + g_object_get (xception, + "errorCode", &int32, + "message", &string, + NULL); + printf (" {%u, \"%s\"}\n", int32, string); + g_free (string); + + g_object_unref (xception); + xception = NULL; + + g_error_free (error); + error = NULL; + } + else { + printf (" result\nFAILURE\n"); + fail_count++; + + g_clear_object (&xception); + g_clear_object (&xception2); + + if (error != NULL) { + g_error_free (error); + error = NULL; + } + } + g_object_unref (xtruct_in); + + printf ("testClient.testMultiException(\"Xception2\", \"test 2\") =>"); + xtruct_in = g_object_new (T_TEST_TYPE_XTRUCT, NULL); + if (!t_test_thrift_test_if_test_multi_exception (test_client, + &xtruct_in, + "Xception2", + "test 2", + &xception, + &xception2, + &error) && + xception == NULL && + xception2 != NULL) { + g_object_get (xception2, + "errorCode", &int32, + "struct_thing", &inner_xtruct_in, + NULL); + g_object_get (inner_xtruct_in, + "string_thing", &string, + NULL); + printf (" {%u, {\"%s\"}}\n", int32, string); + g_free (string); + + g_clear_object (&inner_xtruct_in); + g_clear_object (&xception2); + + g_error_free (error); + error = NULL; + } + else { + printf (" result\nFAILURE\n"); + fail_count++; + + g_clear_object (&xception); + g_clear_object (&xception2); + + if (error != NULL) { + g_error_free (error); + error = NULL; + } + } + g_clear_object (&xtruct_in); + + printf ("testClient.testMultiException(\"success\", \"test 3\") =>"); + xtruct_in = g_object_new (T_TEST_TYPE_XTRUCT, NULL); + if (t_test_thrift_test_if_test_multi_exception (test_client, + &xtruct_in, + "success", + "test 3", + &xception, + &xception2, + &error) && + xception == NULL && + xception2 == NULL) { + g_object_get (xtruct_in, + "string_thing", &string, + NULL); + printf (" {{\"%s\"}}\n", string); + g_free (string); + } + else { + printf (" result\nFAILURE\n"); + fail_count++; + + g_clear_object (&xception); + g_clear_object (&xception2); + + if (error != NULL) { + g_error_free (error); + error = NULL; + } + } + g_clear_object (&xtruct_in); + + /* test oneway void */ + printf ("testClient.testOneway(1) =>"); + gettimeofday (&oneway_start, NULL); + oneway_result = t_test_thrift_test_if_test_oneway (test_client, + 1, + &error); + gettimeofday (&oneway_end, NULL); + timersub (&oneway_end, &oneway_start, &oneway_elapsed); + oneway_elapsed_usec = + oneway_elapsed.tv_sec * 1000 * 1000 + oneway_elapsed.tv_usec; + + if (oneway_result) { + if (oneway_elapsed_usec > 200 * 1000) { + printf (" FAILURE - took %.2f ms\n", + (double)oneway_elapsed_usec / 1000.0); + fail_count++; + } + else + printf (" success - took %.2f ms\n", + (double)oneway_elapsed_usec / 1000.0); + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + + /** + * redo a simple test after the oneway to make sure we aren't "off by + * one" -- if the server treated oneway void like normal void, this next + * test will fail since it will get the void confirmation rather than + * the correct result. In this circumstance, the client will receive the + * error: + * + * application error: Wrong method name + */ + /** + * I32 TEST + */ + printf ("re-test testI32(-1)"); + if (t_test_thrift_test_if_test_i32 (test_client, + &int32, + -1, + &error)) { + printf (" = %d\n", int32); + if (int32 != -1) + fail_count++; + } + else { + printf ("%s\n", error->message); + g_error_free (error); + error = NULL; + + fail_count++; + } + + gettimeofday (&time_stop, NULL); + timersub (&time_stop, &time_start, &time_elapsed); + time_elapsed_usec = + time_elapsed.tv_sec * 1000 * 1000 + time_elapsed.tv_usec; + + printf("Total time: %" PRIu64 " us\n", time_elapsed_usec); + + time_total_usec += time_elapsed_usec; + if (time_elapsed_usec < time_min_usec) + time_min_usec = time_elapsed_usec; + if (time_elapsed_usec > time_max_usec) + time_max_usec = time_elapsed_usec; + + thrift_transport_close (transport, &error); + } + else { + printf ("Connect failed: %s\n", error->message); + g_error_free (error); + error = NULL; + + return 1; + } + } + + /* All done---output statistics */ + puts ("\nAll tests done."); + printf("Number of failures: %d\n", fail_count); + + time_avg_usec = time_total_usec / num_tests; + + printf ("Min time: %" PRIu64 " us\n", time_min_usec); + printf ("Max time: %" PRIu64 " us\n", time_max_usec); + printf ("Avg time: %" PRIu64 " us\n", time_avg_usec); + + g_clear_object(&second_service); + g_clear_object(&protocol2); + g_clear_object(&test_client); + g_clear_object(&protocol); + g_clear_object(&transport); + g_clear_object(&socket); + + if (ssl) { + thrift_ssl_socket_finalize_openssl(); + } + + return fail_count; +} diff --git a/src/jaegertracing/thrift/test/c_glib/src/test_server.c b/src/jaegertracing/thrift/test/c_glib/src/test_server.c new file mode 100644 index 000000000..0819b8ca5 --- /dev/null +++ b/src/jaegertracing/thrift/test/c_glib/src/test_server.c @@ -0,0 +1,307 @@ +/* + * 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. + */ + +#include <glib-object.h> +#include <signal.h> +#include <stdio.h> +#include <string.h> + +#include <thrift/c_glib/thrift.h> +#include <thrift/c_glib/processor/thrift_multiplexed_processor.h> +#include <thrift/c_glib/protocol/thrift_binary_protocol_factory.h> +#include <thrift/c_glib/protocol/thrift_compact_protocol_factory.h> +#include <thrift/c_glib/server/thrift_server.h> +#include <thrift/c_glib/server/thrift_simple_server.h> +#include <thrift/c_glib/transport/thrift_buffered_transport.h> +#include <thrift/c_glib/transport/thrift_buffered_transport_factory.h> +#include <thrift/c_glib/transport/thrift_framed_transport.h> +#include <thrift/c_glib/transport/thrift_framed_transport_factory.h> +#include <thrift/c_glib/transport/thrift_server_socket.h> +#include <thrift/c_glib/transport/thrift_server_transport.h> +#include <thrift/c_glib/transport/thrift_transport.h> +#include <thrift/c_glib/transport/thrift_transport_factory.h> + +#include "../gen-c_glib/t_test_thrift_test.h" +#include "../gen-c_glib/t_test_second_service.h" + +#include "thrift_test_handler.h" +#include "thrift_second_service_handler.h" + +/* Our server object, declared globally so it is accessible within the SIGINT + signal handler */ +ThriftServer *server = NULL; + +/* A flag that indicates whether the server was interrupted with SIGINT + (i.e. Ctrl-C) so we can tell whether its termination was abnormal */ +gboolean sigint_received = FALSE; + +/* Handle SIGINT ("Ctrl-C") signals by gracefully stopping the server */ +static void +sigint_handler (int signal_number) +{ + THRIFT_UNUSED_VAR (signal_number); + + /* Take note we were called */ + sigint_received = TRUE; + + /* Shut down the server gracefully */ + if (server != NULL) + thrift_server_stop (server); +} + +int +main (int argc, char **argv) +{ + static gint port = 9090; + static gchar *path_option = NULL; + static gchar *server_type_option = NULL; + static gchar *transport_option = NULL; + static gchar *protocol_option = NULL; + static gint string_limit = 0; + static gint container_limit = 0; + + static + GOptionEntry option_entries[] = { + { "port", 0, 0, G_OPTION_ARG_INT, &port, + "Port number to connect (=9090)", NULL }, + { "domain-socket", 0, 0, G_OPTION_ARG_STRING, &path_option, + "Unix socket domain path to connect", NULL }, + { "server-type", 0, 0, G_OPTION_ARG_STRING, &server_type_option, + "Type of server: simple (=simple)", NULL }, + { "transport", 0, 0, G_OPTION_ARG_STRING, &transport_option, + "Transport: buffered, framed (=buffered)", NULL }, + { "protocol", 0, 0, G_OPTION_ARG_STRING, &protocol_option, + "Protocol: binary, compact (=binary)", NULL }, + { "string-limit", 0, 0, G_OPTION_ARG_INT, &string_limit, + "Max string length (=none)", NULL }, + { "container-limit", 0, 0, G_OPTION_ARG_INT, &container_limit, + "Max container length (=none)", NULL }, + { NULL } + }; + + gchar *server_name = "simple"; + gchar *transport_name = "buffered"; + GType transport_factory_type = THRIFT_TYPE_BUFFERED_TRANSPORT_FACTORY; + gchar *protocol_name = "binary"; + GType protocol_factory_type = THRIFT_TYPE_BINARY_PROTOCOL_FACTORY; + + TTestThriftTestHandler *handler; + TTestThriftTestHandler *handler_second_service = NULL; + ThriftProcessor *processor; + ThriftProcessor *processor_test = NULL; + ThriftProcessor *processor_second_service = NULL; + ThriftServerTransport *server_transport; + ThriftTransportFactory *transport_factory; + ThriftProtocolFactory *protocol_factory; + + struct sigaction sigint_action; + + GOptionContext *option_context; + gboolean options_valid = TRUE; + + GError *error = NULL; + +#if (!GLIB_CHECK_VERSION (2, 36, 0)) + g_type_init (); +#endif + + /* Configure and parse our command-line options */ + option_context = g_option_context_new (NULL); + g_option_context_add_main_entries (option_context, + option_entries, + NULL); + if (g_option_context_parse (option_context, + &argc, + &argv, + &error) == FALSE) { + fprintf (stderr, "%s\n", error->message); + return 255; + } + g_option_context_free (option_context); + + /* Validate the parsed options */ + if (server_type_option != NULL && + strncmp (server_type_option, "simple", 7) != 0) { + fprintf (stderr, "Unknown server type %s\n", protocol_option); + options_valid = FALSE; + } + + if (protocol_option != NULL) { + if (strncmp (protocol_option, "compact", 8) == 0) { + protocol_factory_type = THRIFT_TYPE_COMPACT_PROTOCOL_FACTORY; + protocol_name = "compact"; + } + else if (strncmp (protocol_option, "multi", 6) == 0) { + protocol_name = "binary:multi"; + } + else if (strncmp (protocol_option, "multic", 7) == 0) { + protocol_factory_type = THRIFT_TYPE_COMPACT_PROTOCOL_FACTORY; + protocol_name = "compact:multic"; + } + else if (strncmp (protocol_option, "binary", 7) != 0) { + fprintf (stderr, "Unknown protocol type %s\n", protocol_option); + options_valid = FALSE; + } + } + + if (transport_option != NULL) { + if (strncmp (transport_option, "framed", 7) == 0) { + transport_factory_type = THRIFT_TYPE_FRAMED_TRANSPORT_FACTORY; + transport_name = "framed"; + } + else if (strncmp (transport_option, "buffered", 9) != 0) { + fprintf (stderr, "Unknown transport type %s\n", transport_option); + options_valid = FALSE; + } + } + + if (!options_valid) + return 254; + + /* Establish all our connection objects */ + handler = g_object_new (TYPE_THRIFT_TEST_HANDLER, + NULL); + + + + if(strstr(protocol_name, ":multi")){ + /* When a multiplexed processor is involved the handler is not + registered as usual. We create the processor and the real + processor is registered. Multiple processors can be registered + at once. This is why we don't have a constructor property */ + processor = g_object_new (THRIFT_TYPE_MULTIPLEXED_PROCESSOR, + NULL); + + handler_second_service = g_object_new (TYPE_SECOND_SERVICE_HANDLER, + NULL); + + processor_test = g_object_new (T_TEST_TYPE_THRIFT_TEST_PROCESSOR, + "handler", handler, + NULL); + processor_second_service = g_object_new (T_TEST_TYPE_SECOND_SERVICE_PROCESSOR, + "handler", handler_second_service, + NULL); + + /* We register a test processor with Multiplexed name ThriftTest */ + if(!thrift_multiplexed_processor_register_processor(processor, + "ThriftTest", processor_test, + &error)){ + g_message ("thrift_server_serve: %s", + error != NULL ? error->message : "(null)"); + g_clear_error (&error); + } + /* We register a second test processor with Multiplexed name SecondService + * we are responsible of freeing the processor when it's not used anymore */ + if(!thrift_multiplexed_processor_register_processor(processor, + "SecondService", processor_second_service, + &error)){ + g_message ("thrift_server_serve: %s", + error != NULL ? error->message : "(null)"); + g_clear_error (&error); + } + + }else{ + processor = g_object_new (T_TEST_TYPE_THRIFT_TEST_PROCESSOR, + "handler", handler, + NULL); + } + if (path_option) { + server_transport = g_object_new (THRIFT_TYPE_SERVER_SOCKET, + "path", path_option, + NULL); + } else { + server_transport = g_object_new (THRIFT_TYPE_SERVER_SOCKET, + "port", port, + NULL); + } + transport_factory = g_object_new (transport_factory_type, + NULL); + + if (strstr (protocol_name, "compact") != NULL) { + protocol_factory = g_object_new (protocol_factory_type, + "string_limit", string_limit, + "container_limit", container_limit, + NULL); + } else { + protocol_factory = g_object_new (protocol_factory_type, + NULL); + } + + server = g_object_new (THRIFT_TYPE_SIMPLE_SERVER, + "processor", processor, + "server_transport", server_transport, + "input_transport_factory", transport_factory, + "output_transport_factory", transport_factory, + "input_protocol_factory", protocol_factory, + "output_protocol_factory", protocol_factory, + NULL); + + /* Install our SIGINT handler, which handles Ctrl-C being pressed by stopping + the server gracefully */ + memset (&sigint_action, 0, sizeof (sigint_action)); + sigint_action.sa_handler = sigint_handler; + sigint_action.sa_flags = SA_RESETHAND; + sigaction (SIGINT, &sigint_action, NULL); + + if (path_option) { + printf ("Starting \"%s\" server (%s/%s) listen on: %s\n", + server_name, + transport_name, + protocol_name, + path_option); + } else { + printf ("Starting \"%s\" server (%s/%s) listen on: %d\n", + server_name, + transport_name, + protocol_name, + port); + } + fflush (stdout); + + /* Serve clients until SIGINT is received (Ctrl-C is pressed) */ + thrift_server_serve (server, &error); + + /* If the server stopped for any reason other than being interrupted by the + user, report the error */ + if (!sigint_received) { + g_message ("thrift_server_serve: %s", + error != NULL ? error->message : "(null)"); + g_clear_error (&error); + } + + puts ("done."); + + g_object_unref (server); + g_object_unref (protocol_factory); + g_object_unref (transport_factory); + g_object_unref (server_transport); + g_object_unref (processor); + g_object_unref (handler); + if(handler_second_service){ + g_object_unref (handler_second_service); + } + if(processor_test){ + g_object_unref (processor_test); + } + if(processor_second_service){ + g_object_unref (processor_second_service); + } + + return 0; +} diff --git a/src/jaegertracing/thrift/test/c_glib/src/thrift_second_service_handler.c b/src/jaegertracing/thrift/test/c_glib/src/thrift_second_service_handler.c new file mode 100644 index 000000000..66ac7bca2 --- /dev/null +++ b/src/jaegertracing/thrift/test/c_glib/src/thrift_second_service_handler.c @@ -0,0 +1,69 @@ +/* + * 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. + */ + +#include <inttypes.h> +#include <string.h> +#include <unistd.h> + +#include <thrift/c_glib/thrift.h> +#include <thrift/c_glib/thrift_application_exception.h> + +#include "thrift_second_service_handler.h" + +/* A handler that implements the TTestSecondServiceIf interface */ + +G_DEFINE_TYPE (SecondServiceHandler, + second_service_handler, + T_TEST_TYPE_SECOND_SERVICE_HANDLER); + + +gboolean +second_service_handler_secondtest_string (TTestSecondServiceIf *iface, + gchar **_return, + const gchar *thing, + GError **error) +{ + THRIFT_UNUSED_VAR (iface); + THRIFT_UNUSED_VAR (error); + gchar buffer[256]; + + printf ("testSecondServiceMultiplexSecondTestString(\"%s\")\n", thing); + snprintf(buffer, 255, "testString(\"%s\")", thing); + *_return = g_strdup (buffer); + + return TRUE; +} + +static void +second_service_handler_init (SecondServiceHandler *self) +{ + THRIFT_UNUSED_VAR (self); +} + +static void +second_service_handler_class_init (SecondServiceHandlerClass *klass) +{ + TTestSecondServiceHandlerClass *base_class = + T_TEST_SECOND_SERVICE_HANDLER_CLASS (klass); + + + base_class->secondtest_string = + second_service_handler_secondtest_string; + +} diff --git a/src/jaegertracing/thrift/test/c_glib/src/thrift_second_service_handler.h b/src/jaegertracing/thrift/test/c_glib/src/thrift_second_service_handler.h new file mode 100644 index 000000000..bbe048cec --- /dev/null +++ b/src/jaegertracing/thrift/test/c_glib/src/thrift_second_service_handler.h @@ -0,0 +1,73 @@ +/* + * 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. + */ + +#ifndef _SECOND_SERVICE_HANDLER_H +#define _SECOND_SERVICE_HANDLER_H + +#include <glib-object.h> +#include <stdio.h> + +#include "../gen-c_glib/t_test_second_service.h" + +G_BEGIN_DECLS + +/* A handler that implements the TTestSecondServiceIf interface */ + +#define TYPE_SECOND_SERVICE_HANDLER (second_service_handler_get_type ()) + +#define SECOND_SERVICE_HANDLER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + TYPE_SECOND_SERVICE_HANDLER, \ + SecondServiceHandler)) +#define IS_SECOND_SERVICE_HANDLER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + TYPE_SECOND_SERVICE_HANDLER)) +#define SECOND_SERVICE_HANDLER_CLASS(c) \ + (G_TYPE_CHECK_CLASS_CAST ((c), \ + TYPE_SECOND_SERVICE_HANDLER, \ + SecondServiceHandlerClass)) +#define IS_SECOND_SERVICE_HANDLER_CLASS(c) \ + (G_TYPE_CHECK_CLASS_TYPE ((c), \ + TYPE_SECOND_SERVICE_HANDLER)) +#define SECOND_SERVICE_HANDLER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + TYPE_SECOND_SERVICE_HANDLER, \ + SecondServiceHandlerClass)) + +typedef struct _SecondServiceHandler SecondServiceHandler; +typedef struct _SecondServiceHandlerClass SecondServiceHandlerClass; + +struct _SecondServiceHandler { + TTestSecondServiceHandler parent; +}; + +struct _SecondServiceHandlerClass { + TTestSecondServiceHandlerClass parent; + +}; + +/* Used by SECOND_SERVICE_HANDLER_GET_TYPE */ +GType second_service_handler_get_type (void); + +gboolean second_service_handler_blah_blah (TTestSecondServiceIf *iface, GError **error); +gboolean second_service_handler_secondtest_string (TTestSecondServiceIf *iface, gchar ** _return, const gchar * thing, GError **error); + +G_END_DECLS + +#endif /* _SECOND_SERVICE_HANDLER_H */ diff --git a/src/jaegertracing/thrift/test/c_glib/src/thrift_test_handler.c b/src/jaegertracing/thrift/test/c_glib/src/thrift_test_handler.c new file mode 100644 index 000000000..f6c759e1a --- /dev/null +++ b/src/jaegertracing/thrift/test/c_glib/src/thrift_test_handler.c @@ -0,0 +1,837 @@ +/* + * 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. + */ + +#include <inttypes.h> +#include <string.h> +#include <unistd.h> + +#include <thrift/c_glib/thrift.h> +#include <thrift/c_glib/thrift_application_exception.h> + +#include "thrift_test_handler.h" + +/* A handler that implements the TTestThriftTestIf interface */ + +G_DEFINE_TYPE (ThriftTestHandler, + thrift_test_handler, + T_TEST_TYPE_THRIFT_TEST_HANDLER) + +gboolean +thrift_test_handler_test_void (TTestThriftTestIf *iface, + GError **error) +{ + THRIFT_UNUSED_VAR (iface); + THRIFT_UNUSED_VAR (error); + + printf ("testVoid()\n"); + + return TRUE; +} + +gboolean +thrift_test_handler_test_string (TTestThriftTestIf *iface, + gchar **_return, + const gchar *thing, + GError **error) +{ + THRIFT_UNUSED_VAR (iface); + THRIFT_UNUSED_VAR (error); + + printf ("testString(\"%s\")\n", thing); + *_return = g_strdup (thing); + + return TRUE; +} + +gboolean +thrift_test_handler_test_bool (TTestThriftTestIf *iface, + gboolean *_return, + const gboolean thing, + GError **error) +{ + THRIFT_UNUSED_VAR (iface); + THRIFT_UNUSED_VAR (error); + + printf ("testBool(%s)\n", thing ? "true" : "false"); + *_return = thing; + + return TRUE; +} + +gboolean +thrift_test_handler_test_byte (TTestThriftTestIf *iface, + gint8 *_return, + const gint8 thing, + GError **error) +{ + THRIFT_UNUSED_VAR (iface); + THRIFT_UNUSED_VAR (error); + + printf ("testByte(%d)\n", (gint)thing); + *_return = thing; + + return TRUE; +} + +gboolean +thrift_test_handler_test_i32 (TTestThriftTestIf *iface, + gint32 *_return, + const gint32 thing, + GError **error) +{ + THRIFT_UNUSED_VAR (iface); + THRIFT_UNUSED_VAR (error); + + printf ("testI32(%d)\n", thing); + *_return = thing; + + return TRUE; +} + +gboolean +thrift_test_handler_test_i64 (TTestThriftTestIf *iface, + gint64 *_return, + const gint64 thing, + GError **error) +{ + THRIFT_UNUSED_VAR (iface); + THRIFT_UNUSED_VAR (error); + + printf ("testI64(%" PRId64 ")\n", thing); + *_return = thing; + + return TRUE; +} + +gboolean +thrift_test_handler_test_double (TTestThriftTestIf *iface, + gdouble *_return, + const gdouble thing, + GError **error) +{ + THRIFT_UNUSED_VAR (iface); + THRIFT_UNUSED_VAR (error); + + printf ("testDouble(%f)\n", thing); + *_return = thing; + + return TRUE; +} + +gboolean +thrift_test_handler_test_binary (TTestThriftTestIf *iface, + GByteArray ** _return, + const GByteArray * thing, + GError **error) +{ + THRIFT_UNUSED_VAR (iface); + THRIFT_UNUSED_VAR (error); + + printf ("testBinary()\n"); // TODO: hex output + g_byte_array_ref((GByteArray *)thing); + *_return = (GByteArray *)thing; + + return TRUE; +} + +gboolean +thrift_test_handler_test_struct (TTestThriftTestIf *iface, + TTestXtruct **_return, + const TTestXtruct *thing, + GError **error) +{ + gchar *string_thing = NULL; + gint byte_thing; + gint i32_thing; + gint64 i64_thing; + + THRIFT_UNUSED_VAR (iface); + THRIFT_UNUSED_VAR (error); + + g_object_get ((TTestXtruct *)thing, + "string_thing", &string_thing, + "byte_thing", &byte_thing, + "i32_thing", &i32_thing, + "i64_thing", &i64_thing, + NULL); + + printf ("testStruct({\"%s\", %d, %d, %" PRId64 "})\n", + string_thing, + (gint)byte_thing, + i32_thing, + i64_thing); + + g_object_set (*_return, + "string_thing", string_thing, + "byte_thing", byte_thing, + "i32_thing", i32_thing, + "i64_thing", i64_thing, + NULL); + + if (string_thing != NULL) + g_free (string_thing); + + return TRUE; +} + +gboolean +thrift_test_handler_test_nest (TTestThriftTestIf *iface, + TTestXtruct2 **_return, + const TTestXtruct2 *thing, + GError **error) +{ + gchar *inner_string_thing = NULL; + gint byte_thing, inner_byte_thing; + gint i32_thing, inner_i32_thing; + gint64 inner_i64_thing; + TTestXtruct *struct_thing; + + THRIFT_UNUSED_VAR (iface); + THRIFT_UNUSED_VAR (error); + + g_object_get ((TTestXtruct2 *)thing, + "byte_thing", &byte_thing, + "struct_thing", &struct_thing, + "i32_thing", &i32_thing, + NULL); + g_object_get (struct_thing, + "string_thing", &inner_string_thing, + "byte_thing", &inner_byte_thing, + "i32_thing", &inner_i32_thing, + "i64_thing", &inner_i64_thing, + NULL); + + printf ("testNest({%d, {\"%s\", %d, %d, %" PRId64 "}, %d})\n", + byte_thing, + inner_string_thing, + inner_byte_thing, + inner_i32_thing, + inner_i64_thing, + i32_thing); + + g_object_set (*_return, + "byte_thing", byte_thing, + "struct_thing", struct_thing, + "i32_thing", i32_thing, + NULL); + + if (inner_string_thing != NULL) + g_free (inner_string_thing); + g_object_unref (struct_thing); + + return TRUE; +} + +gboolean +thrift_test_handler_test_map (TTestThriftTestIf *iface, + GHashTable **_return, + const GHashTable *thing, + GError **error) +{ + GHashTableIter hash_table_iter; + gpointer key; + gpointer value; + gboolean first = TRUE; + + THRIFT_UNUSED_VAR (iface); + THRIFT_UNUSED_VAR (error); + + printf ("testMap({"); + g_hash_table_iter_init (&hash_table_iter, (GHashTable *)thing); + while (g_hash_table_iter_next (&hash_table_iter, + &key, + &value)) { + gint32 *new_key; + gint32 *new_value; + + if (first) + first = FALSE; + else + printf (", "); + + printf ("%d => %d", *(gint32 *)key, *(gint32 *)value); + + new_key = g_malloc (sizeof *new_key); + *new_key = *(gint32 *)key; + new_value = g_malloc (sizeof *new_value); + *new_value = *(gint32 *)value; + g_hash_table_insert (*_return, new_key, new_value); + } + printf ("})\n"); + + return TRUE; +} + +gboolean +thrift_test_handler_test_string_map (TTestThriftTestIf *iface, + GHashTable **_return, + const GHashTable *thing, + GError **error) +{ + GHashTableIter hash_table_iter; + gpointer key; + gpointer value; + gboolean first = TRUE; + + THRIFT_UNUSED_VAR (iface); + THRIFT_UNUSED_VAR (error); + + printf ("testStringMap({"); + g_hash_table_iter_init (&hash_table_iter, (GHashTable *)thing); + while (g_hash_table_iter_next (&hash_table_iter, + &key, + &value)) { + gchar *new_key; + gchar *new_value; + + if (first) + first = FALSE; + else + printf (", "); + + printf ("%s => %s", (gchar *)key, (gchar *)value); + + new_key = g_strdup ((gchar *)key); + new_value = g_strdup ((gchar *)value); + g_hash_table_insert (*_return, new_key, new_value); + } + printf ("})\n"); + + return TRUE; +} + +gboolean +thrift_test_handler_test_set (TTestThriftTestIf *iface, + GHashTable **_return, + const GHashTable *thing, + GError **error) +{ + GHashTableIter hash_table_iter; + gpointer key; + gboolean first = TRUE; + + THRIFT_UNUSED_VAR (iface); + THRIFT_UNUSED_VAR (error); + + printf ("testSet({"); + g_hash_table_iter_init (&hash_table_iter, (GHashTable *)thing); + while (g_hash_table_iter_next (&hash_table_iter, + &key, + NULL)) { + gint32 *new_key; + + if (first) + first = FALSE; + else + printf (", "); + + printf ("%d", *(gint32 *)key); + + new_key = g_malloc (sizeof *new_key); + *new_key = *(gint32 *)key; + g_hash_table_insert (*_return, new_key, NULL); + } + printf ("})\n"); + + return TRUE; +} + +gboolean +thrift_test_handler_test_list (TTestThriftTestIf *iface, + GArray **_return, + const GArray *thing, + GError **error) +{ + guint i; + gboolean first = TRUE; + + THRIFT_UNUSED_VAR (iface); + THRIFT_UNUSED_VAR (error); + + printf ("testList({"); + for (i = 0; i < thing->len; i += 1) { + gint32 value; + gint32 *new_value; + + if (first) + first = FALSE; + else + printf (", "); + + value = g_array_index (thing, gint32, i); + printf ("%d", value); + + new_value = g_malloc (sizeof *new_value); + *new_value = value; + g_array_append_val (*_return, *new_value); + } + printf ("})\n"); + + return TRUE; +} + +gboolean +thrift_test_handler_test_enum (TTestThriftTestIf *iface, + TTestNumberz *_return, + const TTestNumberz thing, + GError **error) +{ + THRIFT_UNUSED_VAR (iface); + THRIFT_UNUSED_VAR (error); + + printf ("testEnum(%d)\n", thing); + *_return = thing; + + return TRUE; +} + +gboolean +thrift_test_handler_test_typedef (TTestThriftTestIf *iface, + TTestUserId *_return, + const TTestUserId thing, + GError **error) +{ + THRIFT_UNUSED_VAR (iface); + THRIFT_UNUSED_VAR (error); + + printf ("testTypedef(%" PRId64 ")\n", thing); + *_return = thing; + + return TRUE; +} + +gboolean +thrift_test_handler_test_map_map (TTestThriftTestIf *iface, + GHashTable **_return, + const gint32 hello, + GError **error) +{ + GHashTable *positive; + GHashTable *negative; + gint32 *key; + gint32 *value; + guint i; + + THRIFT_UNUSED_VAR (iface); + THRIFT_UNUSED_VAR (error); + + printf ("testMapMap(%d)\n", hello); + + positive = g_hash_table_new_full (g_int_hash, + g_int_equal, + g_free, + g_free); + negative = g_hash_table_new_full (g_int_hash, + g_int_equal, + g_free, + g_free); + + for (i = 1; i < 5; i += 1) { + key = g_malloc (sizeof *key); + value = g_malloc (sizeof *value); + *key = i; + *value = i; + g_hash_table_insert (positive, key, value); + + key = g_malloc (sizeof *key); + value = g_malloc (sizeof *value); + *key = -i; + *value = -i; + g_hash_table_insert (negative, key, value); + } + + key = g_malloc (sizeof *key); + *key = 4; + g_hash_table_insert (*_return, key, positive); + + key = g_malloc (sizeof *key); + *key = -4; + g_hash_table_insert (*_return, key, negative); + + return TRUE; +} + +gboolean +thrift_test_handler_test_insanity (TTestThriftTestIf *iface, + GHashTable **_return, + const TTestInsanity *argument, + GError **error) +{ + TTestXtruct *xtruct_in; + + gchar *string_thing = NULL; + gint byte_thing; + gint i32_thing; + gint64 i64_thing; + + GPtrArray *xtructs; + + TTestInsanity *looney; + + GHashTable *user_map; + GHashTable *first_map; + GHashTable *second_map; + + GHashTableIter hash_table_iter; + GHashTableIter inner_hash_table_iter; + GHashTableIter user_map_iter; + + gpointer key; + gpointer value; + + TTestUserId *user_id; + + guint i; + + THRIFT_UNUSED_VAR (iface); + THRIFT_UNUSED_VAR (error); + + printf ("testInsanity()\n"); + + first_map = g_hash_table_new_full (g_direct_hash, + g_direct_equal, + NULL, + g_object_unref); + second_map = g_hash_table_new_full (g_direct_hash, + g_direct_equal, + NULL, + g_object_unref); + + g_hash_table_insert (first_map, + GINT_TO_POINTER (T_TEST_NUMBERZ_TWO), + (gpointer)argument); + g_hash_table_insert (first_map, + GINT_TO_POINTER (T_TEST_NUMBERZ_THREE), + (gpointer)argument); + + /* Increment argument's ref count by two because first_map now holds + two references to it and the caller is not aware we have made any + additional references to argument. (That is, caller owns argument + and will unref it explicitly in addition to unref-ing *_return.) + + We do this instead of creating a copy of argument in order to mimic + the C++ implementation (and since, frankly, the world needs less + argument, not more). */ + g_object_ref ((gpointer)argument); + g_object_ref ((gpointer)argument); + + looney = g_object_new (T_TEST_TYPE_INSANITY, NULL); + g_hash_table_insert (second_map, + GINT_TO_POINTER (T_TEST_NUMBERZ_SIX), + looney); + + user_id = g_malloc (sizeof *user_id); + *user_id = 1; + g_hash_table_insert (*_return, user_id, first_map); + + user_id = g_malloc (sizeof *user_id); + *user_id = 2; + g_hash_table_insert (*_return, user_id, second_map); + + printf ("return"); + printf (" = {"); + g_hash_table_iter_init (&hash_table_iter, *_return); + while (g_hash_table_iter_next (&hash_table_iter, + &key, + &value)) { + printf ("%" PRId64 " => {", *(TTestUserId *)key); + + g_hash_table_iter_init (&inner_hash_table_iter, + (GHashTable *)value); + while (g_hash_table_iter_next (&inner_hash_table_iter, + &key, + &value)) { + printf ("%d => {", (TTestNumberz)key); + + g_object_get ((TTestInsanity *)value, + "userMap", &user_map, + "xtructs", &xtructs, + NULL); + + printf ("{"); + g_hash_table_iter_init (&user_map_iter, user_map); + while (g_hash_table_iter_next (&user_map_iter, + &key, + &value)) { + printf ("%d => %" PRId64 ", ", + (TTestNumberz)key, + *(TTestUserId *)value); + } + printf ("}, "); + g_hash_table_unref (user_map); + + printf ("{"); + for (i = 0; i < xtructs->len; ++i) { + xtruct_in = g_ptr_array_index (xtructs, i); + g_object_get (xtruct_in, + "string_thing", &string_thing, + "byte_thing", &byte_thing, + "i32_thing", &i32_thing, + "i64_thing", &i64_thing, + NULL); + + printf ("{\"%s\", %d, %d, %" PRId64 "}, ", + string_thing, + byte_thing, + i32_thing, + i64_thing); + } + printf ("}"); + g_ptr_array_unref (xtructs); + + printf ("}, "); + } + printf ("}, "); + } + printf ("}\n"); + + return TRUE; +} + +gboolean +thrift_test_handler_test_multi (TTestThriftTestIf *iface, + TTestXtruct **_return, + const gint8 arg0, + const gint32 arg1, + const gint64 arg2, + const GHashTable *arg3, + const TTestNumberz arg4, + const TTestUserId arg5, + GError **error) +{ + THRIFT_UNUSED_VAR (iface); + THRIFT_UNUSED_VAR (error); + THRIFT_UNUSED_VAR (arg3); + THRIFT_UNUSED_VAR (arg4); + THRIFT_UNUSED_VAR (arg5); + + printf ("testMulti()\n"); + + g_object_set (*_return, + "string_thing", g_strdup ("Hello2"), + "byte_thing", arg0, + "i32_thing", arg1, + "i64_thing", arg2, + NULL); + + return TRUE; +} + +gboolean +thrift_test_handler_test_exception (TTestThriftTestIf *iface, + const gchar *arg, + TTestXception **err1, + GError **error) +{ + THRIFT_UNUSED_VAR (iface); + + TTestXtruct *xtruct; + gboolean result; + + printf ("testException(%s)\n", arg); + + /* Unlike argument objects, exception objects are not pre-created */ + g_assert (*err1 == NULL); + + if (strncmp (arg, "Xception", 9) == 0) { + /* "Throw" a custom exception: Set the corresponding exception + argument, set *error to NULL and return FALSE */ + *err1 = g_object_new (T_TEST_TYPE_XCEPTION, + "errorCode", 1001, + "message", g_strdup (arg), + NULL); + *error = NULL; + result = FALSE; + } + else if (strncmp (arg, "TException", 11) == 0) { + /* "Throw" a generic TException (ThriftApplicationException): Set + all exception arguments to NULL, set *error and return FALSE */ + *err1 = NULL; + g_set_error (error, + thrift_application_exception_error_quark (), + THRIFT_APPLICATION_EXCEPTION_ERROR_UNKNOWN, + "Default TException."); + result = FALSE; + } + else { + *err1 = NULL; + *error = NULL; + + /* This code is duplicated from the C++ test suite, though it + appears to serve no purpose */ + xtruct = g_object_new (T_TEST_TYPE_XTRUCT, + "string_thing", g_strdup (arg), + NULL); + g_object_unref (xtruct); + + result = TRUE; + } + + return result; +} + +gboolean +thrift_test_handler_test_multi_exception (TTestThriftTestIf *iface, + TTestXtruct **_return, + const gchar *arg0, + const gchar *arg1, + TTestXception **err1, + TTestXception2 **err2, + GError **error) +{ + THRIFT_UNUSED_VAR (iface); + THRIFT_UNUSED_VAR (error); + + TTestXtruct *struct_thing; + gboolean result; + + printf ("testMultiException(%s, %s)\n", arg0, arg1); + + g_assert (*err1 == NULL); + g_assert (*err2 == NULL); + + if (strncmp (arg0, "Xception", 8) == 0 && strlen(arg0) == 8) { + *err1 = g_object_new (T_TEST_TYPE_XCEPTION, + "errorCode", 1001, + "message", g_strdup ("This is an Xception"), + NULL); + result = FALSE; + } + else if (strncmp (arg0, "Xception2", 9) == 0) { + *err2 = g_object_new (T_TEST_TYPE_XCEPTION2, + "errorCode", 2002, + NULL); + + g_object_get (*err2, + "struct_thing", &struct_thing, + NULL); + g_object_set (struct_thing, + "string_thing", g_strdup ("This is an Xception2"), + NULL); + g_object_set (*err2, + "struct_thing", struct_thing, + NULL); + g_object_unref (struct_thing); + + result = FALSE; + } + else { + g_object_set (*_return, + "string_thing", g_strdup (arg1), + NULL); + result = TRUE; + } + + return result; +} + +gboolean +thrift_test_handler_test_oneway (TTestThriftTestIf *iface, + const gint32 secondsToSleep, + GError **error) +{ + THRIFT_UNUSED_VAR (iface); + THRIFT_UNUSED_VAR (error); + + printf ("testOneway(%d): Sleeping...\n", secondsToSleep); + sleep (secondsToSleep); + printf ("testOneway(%d): done sleeping!\n", secondsToSleep); + + return TRUE; +} + +static void +thrift_test_handler_init (ThriftTestHandler *self) +{ + THRIFT_UNUSED_VAR (self); +} + +static void +thrift_test_handler_class_init (ThriftTestHandlerClass *klass) +{ + TTestThriftTestHandlerClass *base_class = + T_TEST_THRIFT_TEST_HANDLER_CLASS (klass); + + base_class->test_void = + klass->test_void = + thrift_test_handler_test_void; + base_class->test_string = + klass->test_string = + thrift_test_handler_test_string; + base_class->test_bool = + klass->test_bool = + thrift_test_handler_test_bool; + base_class->test_byte = + klass->test_byte = + thrift_test_handler_test_byte; + base_class->test_i32 = + klass->test_i32 = + thrift_test_handler_test_i32; + base_class->test_i64 = + klass->test_i64 = + thrift_test_handler_test_i64; + base_class->test_double = + klass->test_double = + thrift_test_handler_test_double; + base_class->test_binary = + klass->test_binary = + thrift_test_handler_test_binary; + base_class->test_struct = + klass->test_struct = + thrift_test_handler_test_struct; + base_class->test_nest = + klass->test_nest = + thrift_test_handler_test_nest; + base_class->test_map = + klass->test_map = + thrift_test_handler_test_map; + base_class->test_string_map = + klass->test_string_map = + thrift_test_handler_test_string_map; + base_class->test_set = + klass->test_set = + thrift_test_handler_test_set; + base_class->test_list = + klass->test_list = + thrift_test_handler_test_list; + base_class->test_enum = + klass->test_enum = + thrift_test_handler_test_enum; + base_class->test_typedef = + klass->test_typedef = + thrift_test_handler_test_typedef; + base_class->test_map_map = + klass->test_map_map = + thrift_test_handler_test_map_map; + base_class->test_insanity = + klass->test_insanity = + thrift_test_handler_test_insanity; + base_class->test_multi = + klass->test_multi = + thrift_test_handler_test_multi; + base_class->test_exception = + klass->test_exception = + thrift_test_handler_test_exception; + base_class->test_multi_exception = + klass->test_multi_exception = + thrift_test_handler_test_multi_exception; + base_class->test_oneway = + klass->test_oneway = + thrift_test_handler_test_oneway; +} diff --git a/src/jaegertracing/thrift/test/c_glib/src/thrift_test_handler.h b/src/jaegertracing/thrift/test/c_glib/src/thrift_test_handler.h new file mode 100644 index 000000000..b64cb16f2 --- /dev/null +++ b/src/jaegertracing/thrift/test/c_glib/src/thrift_test_handler.h @@ -0,0 +1,245 @@ +/* + * 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. + */ + +#ifndef _THRIFT_TEST_HANDLER_H +#define _THRIFT_TEST_HANDLER_H + +#include <glib-object.h> +#include <stdio.h> + +#include "../gen-c_glib/t_test_thrift_test.h" + +G_BEGIN_DECLS + +/* A handler that implements the TTestThriftTestIf interface */ + +#define TYPE_THRIFT_TEST_HANDLER (thrift_test_handler_get_type ()) + +#define THRIFT_TEST_HANDLER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + TYPE_THRIFT_TEST_HANDLER, \ + ThriftTestHandler)) +#define IS_THRIFT_TEST_HANDLER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + TYPE_THRIFT_TEST_HANDLER)) +#define THRIFT_TEST_HANDLER_CLASS(c) \ + (G_TYPE_CHECK_CLASS_CAST ((c), \ + TYPE_THRIFT_TEST_HANDLER, \ + ThriftTestHandlerClass)) +#define IS_THRIFT_TEST_HANDLER_CLASS(c) \ + (G_TYPE_CHECK_CLASS_TYPE ((c), \ + TYPE_THRIFT_TEST_HANDLER)) +#define THRIFT_TEST_HANDLER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + TYPE_THRIFT_TEST_HANDLER, \ + ThriftTestHandlerClass)) + +typedef struct _ThriftTestHandler ThriftTestHandler; +typedef struct _ThriftTestHandlerClass ThriftTestHandlerClass; + +struct _ThriftTestHandler { + TTestThriftTestHandler parent; +}; + +struct _ThriftTestHandlerClass { + TTestThriftTestHandlerClass parent; + + gboolean (*test_void) (TTestThriftTestIf *iface, + GError **error); + gboolean (*test_string) (TTestThriftTestIf *iface, + gchar **_return, + const gchar *thing, + GError **error); + gboolean (*test_bool) (TTestThriftTestIf *iface, + gboolean*_return, + const gboolean thing, + GError **error); + gboolean (*test_byte) (TTestThriftTestIf *iface, + gint8*_return, + const gint8 thing, + GError **error); + gboolean (*test_i32) (TTestThriftTestIf *iface, + gint32*_return, + const gint32 thing, + GError **error); + gboolean (*test_i64) (TTestThriftTestIf *iface, + gint64*_return, + const gint64 thing, + GError **error); + gboolean (*test_double) (TTestThriftTestIf *iface, + gdouble*_return, + const gdouble thing, + GError **error); + gboolean (*test_binary) (TTestThriftTestIf *iface, + GByteArray **_return, + const GByteArray *thing, + GError **error); + gboolean (*test_struct) (TTestThriftTestIf *iface, + TTestXtruct **_return, + const TTestXtruct *thing, + GError **error); + gboolean (*test_nest) (TTestThriftTestIf *iface, + TTestXtruct2 **_return, + const TTestXtruct2 *thing, + GError **error); + gboolean (*test_map) (TTestThriftTestIf *iface, + GHashTable **_return, + const GHashTable *thing, + GError **error); + gboolean (*test_string_map) (TTestThriftTestIf *iface, + GHashTable **_return, + const GHashTable *thing, + GError **error); + gboolean (*test_set) (TTestThriftTestIf *iface, + GHashTable **_return, + const GHashTable *thing, + GError **error); + gboolean (*test_list) (TTestThriftTestIf *iface, + GArray **_return, + const GArray *thing, + GError **error); + gboolean (*test_enum) (TTestThriftTestIf *iface, + TTestNumberz*_return, + const TTestNumberz thing, + GError **error); + gboolean (*test_typedef) (TTestThriftTestIf *iface, + TTestUserId*_return, + const TTestUserId thing, + GError **error); + gboolean (*test_map_map) (TTestThriftTestIf *iface, + GHashTable **_return, + const gint32 hello, + GError **error); + gboolean (*test_insanity) (TTestThriftTestIf *iface, + GHashTable **_return, + const TTestInsanity *argument, + GError **error); + gboolean (*test_multi) (TTestThriftTestIf *iface, + TTestXtruct **_return, + const gint8 arg0, + const gint32 arg1, + const gint64 arg2, + const GHashTable *arg3, + const TTestNumberz arg4, + const TTestUserId arg5, + GError **error); + gboolean (*test_exception) (TTestThriftTestIf *iface, + const gchar *arg, + TTestXception **err1, + GError **error); + gboolean (*test_multi_exception) (TTestThriftTestIf *iface, + TTestXtruct **_return, + const gchar *arg0, + const gchar *arg1, + TTestXception **err1, + TTestXception2 **err2, + GError **error); + gboolean (*test_oneway) (TTestThriftTestIf *iface, + const gint32 secondsToSleep, + GError **error); +}; + +/* Used by THRIFT_TEST_HANDLER_GET_TYPE */ +GType thrift_test_handler_get_type (void); + +gboolean thrift_test_handler_test_void (TTestThriftTestIf *iface, + GError **error); +gboolean thrift_test_handler_test_string (TTestThriftTestIf *iface, + gchar **_return, + const gchar *thing, + GError **error); +gboolean thrift_test_handler_test_byte (TTestThriftTestIf *iface, + gint8*_return, + const gint8 thing, + GError **error); +gboolean t_test_thrift_test_if_test_i32 (TTestThriftTestIf *iface, + gint32*_return, + const gint32 thing, + GError **error); +gboolean thrift_test_handler_test_i64 (TTestThriftTestIf *iface, + gint64*_return, + const gint64 thing, + GError **error); +gboolean thrift_test_handler_test_double (TTestThriftTestIf *iface, + gdouble*_return, + const gdouble thing, + GError **error); +gboolean thrift_test_handler_test_struct (TTestThriftTestIf *iface, + TTestXtruct **_return, + const TTestXtruct *thing, + GError **error); +gboolean thrift_test_handler_test_nest (TTestThriftTestIf *iface, + TTestXtruct2 **_return, + const TTestXtruct2 *thing, + GError **error); +gboolean thrift_test_handler_test_map (TTestThriftTestIf *iface, + GHashTable **_return, + const GHashTable *thing, + GError **error); +gboolean thrift_test_handler_test_string_map (TTestThriftTestIf *iface, + GHashTable **_return, + const GHashTable *thing, + GError **error); +gboolean thrift_test_handler_test_set (TTestThriftTestIf *iface, + GHashTable **_return, + const GHashTable *thing, + GError **error); +gboolean thrift_test_handler_test_list (TTestThriftTestIf *iface, + GArray **_return, + const GArray *thing, + GError **error); +gboolean thrift_test_handler_test_typedef (TTestThriftTestIf *iface, + TTestUserId*_return, + const TTestUserId thing, + GError **error); +gboolean thrift_test_handler_test_map_map (TTestThriftTestIf *iface, + GHashTable **_return, + const gint32 hello, + GError **error); +gboolean thrift_test_handler_test_insanity (TTestThriftTestIf *iface, + GHashTable **_return, + const TTestInsanity *argument, + GError **error); +gboolean thrift_test_handler_test_multi (TTestThriftTestIf *iface, + TTestXtruct **_return, + const gint8 arg0, + const gint32 arg1, + const gint64 arg2, + const GHashTable *arg3, + const TTestNumberz arg4, + const TTestUserId arg5, + GError **error); +gboolean thrift_test_handler_test_exception (TTestThriftTestIf *iface, + const gchar *arg, + TTestXception **err1, + GError **error); +gboolean thrift_test_handler_test_multi_exception (TTestThriftTestIf *iface, + TTestXtruct **_return, + const gchar *arg0, + const gchar *arg1, + TTestXception **err1, + TTestXception2 **err2, + GError **error); +gboolean thrift_test_handler_test_oneway (TTestThriftTestIf *iface, + const gint32 secondsToSleep, + GError **error); + +G_END_DECLS + +#endif /* _THRIFT_TEST_HANDLER_H */ diff --git a/src/jaegertracing/thrift/test/cl/Makefile.am b/src/jaegertracing/thrift/test/cl/Makefile.am new file mode 100755 index 000000000..b5e72bcbb --- /dev/null +++ b/src/jaegertracing/thrift/test/cl/Makefile.am @@ -0,0 +1,42 @@ +# +# 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. +# + +THRIFT = $(top_builddir)/compiler/cpp/thrift + +stubs: ../ThriftTest.thrift + $(THRIFT) --gen cl ../ThriftTest.thrift + +TestServer: make-test-server.lisp + $(SBCL) --script make-test-server.lisp + +TestClient: make-test-client.lisp + $(SBCL) --script make-test-client.lisp + +precross: stubs TestServer TestClient + +clean-local: + $(RM) -r gen-cl + $(RM) TestServer + $(RM) TestClient + +EXTRA_DIST = \ + implementation.lisp \ + make-test-client.lisp \ + make-test-server.lisp \ + tests.lisp diff --git a/src/jaegertracing/thrift/test/cl/implementation.lisp b/src/jaegertracing/thrift/test/cl/implementation.lisp new file mode 100644 index 000000000..0caf7beb5 --- /dev/null +++ b/src/jaegertracing/thrift/test/cl/implementation.lisp @@ -0,0 +1,136 @@ +(in-package #:thrift.test-implementation) + +;;;; Licensed 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. + +(defun thrift.test.thrift-test-implementation:test-void () + (format t "testVoid()~%")) + +(defun thrift.test.thrift-test-implementation:test-string (thing) + (format t "testString(~a)~%" thing) + thing) + +(defun thrift.test.thrift-test-implementation:test-bool (thing) + (format t "testBool(~a)~%" (if thing "true" "false")) + thing) + +(defun thrift.test.thrift-test-implementation:test-byte (thing) + (format t "testByte(~a)~%" thing) + thing) + +(defun thrift.test.thrift-test-implementation:test-i32 (thing) + (format t "testI32(~a)~%" thing) + thing) + +(defun thrift.test.thrift-test-implementation:test-i64 (thing) + (format t "testI64(~a)~%" thing) + thing) + +(defun thrift.test.thrift-test-implementation:test-double (thing) + (format t "testDouble(~a)~%" thing) + thing) + +(defun thrift.test.thrift-test-implementation:test-binary (thing) + (format t "testBinary(~a)~%" thing) + thing) + +(defun thrift.test.thrift-test-implementation:test-struct (thing) + (format t "testStruct(~a)~%" thing) + thing) + +(defun thrift.test.thrift-test-implementation:test-nest (thing) + (format t "testNest(~a)~%" thing) + thing) + +(defun thrift.test.thrift-test-implementation:test-map (thing) + (format t "testMap(~a)~%" thing) + thing) + +(defun thrift.test.thrift-test-implementation:test-string-map (thing) + (format t "testStringMap(~a)~%" thing) + thing) + +(defun thrift.test.thrift-test-implementation:test-set (thing) + (format t "testSet(~a)~%" thing) + thing) + +(defun thrift.test.thrift-test-implementation:test-list (thing) + (format t "testList(~a)~%" thing) + thing) + +(defun thrift.test.thrift-test-implementation:test-enum (thing) + (format t "testEnum(~a)~%" thing) + thing) + +(defun thrift.test.thrift-test-implementation:test-typedef (thing) + (format t "testTypedef(~a)~%" thing) + thing) + +(defun thrift.test.thrift-test-implementation:test-map-map (hello) + (format t "testMapMap(~a)~%" hello) + '((-4 . ((-4 . -4) (-3 . -3) (-2 . -2) (-1 . -1))) (4 . ((1 . 1) (2 . 2) (3 . 3) (4 . 4))))) + +(defun thrift.test.thrift-test-implementation:test-insanity (argument) + (let ((result `((1 . ((2 . ,argument) (3 . ,argument))) + (2 . ((6 . ,(thrift.test::make-insanity :user-map nil :xtructs nil))))))) + (format t "~a~%" result) + result)) + +(defun thrift.test.thrift-test-implementation:test-multi (arg0 arg1 arg2 arg3 arg4 arg5) + (declare (ignorable arg3 arg4 arg5)) + (format t "testMulti()~%") + (thrift.test:make-xtruct :string-thing "Hello2" + :byte-thing arg0 + :i32-thing arg1 + :i64-thing arg2)) + +(defun thrift.test.thrift-test-implementation:test-exception (arg) + (format t "testException(~a)~%" arg) + (cond + ((string= arg "Xception") (error 'thrift.test:xception + :error-code 1001 + :message arg)) + ((string= arg "TException") (error 'thrift.test:xception + :error-code 0 + :message "Stuff!")))) + +(defun thrift.test.thrift-test-implementation:test-multi-exception (arg0 arg1) + (format t "testMultiException(~a, ~a)~%" arg0 arg1) + (cond + ((string= arg0 "Xception") (error 'thrift.test:xception + :error-code 1001 + :message "This is an Xception")) + ((string= arg0 "Xception2") (error 'thrift.test:xception2 + :error-code 2002 + :struct-thing (thrift.test:make-xtruct :string-thing "This is an Xception2" + :byte-thing 0 + :i32-thing 0 + :i64-thing 0)))) + (thrift.test:make-xtruct :string-thing arg1 + :byte-thing 0 + :i32-thing 0 + :i64-thing 0)) + +(defun thrift.test.thrift-test-implementation:test-oneway (seconds) + (format t "testOneway(~a): Sleeping...~%" seconds) + (sleep seconds) + (format t "testOneway(~a): done sleeping!~%" seconds)) + +;;; Removed from the IDL definition. +#+(or) +(defun thrift.test.second-service-implementation:blah-blah () + (format t "blahBlah()~%")) + +(defun thrift.test.second-service-implementation:secondtest-string (thing) + (format t "secondtestString(~a)~%" thing) + (concatenate 'string "testString(\"" thing "\")")) + diff --git a/src/jaegertracing/thrift/test/cl/make-test-client.lisp b/src/jaegertracing/thrift/test/cl/make-test-client.lisp new file mode 100644 index 000000000..509669dd8 --- /dev/null +++ b/src/jaegertracing/thrift/test/cl/make-test-client.lisp @@ -0,0 +1,93 @@ +(in-package #:cl-user) + +;;;; Licensed 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. + +#+(or) (when (not (boundp 'sb-impl::default-external-format) + (setf sb-impl::default-external-format :UTF-8))) + +(require "asdf") +(load (merge-pathnames "../../lib/cl/load-locally.lisp" *load-truename*)) +(asdf:load-system :net.didierverna.clon) +(asdf:load-system :fiasco) +(asdf:load-asd (merge-pathnames "gen-cl/ThriftTest/thrift-gen-ThriftTest.asd" *load-truename*)) +(asdf:load-system :thrift-gen-thrifttest) + +(net.didierverna.clon:nickname-package) + +(defpackage #:thrift-cross + (:use #:common-lisp #:fiasco) + (:export #:cross-test)) + +(in-package #:thrift-cross) + +(defparameter *prot* nil) + +(load (merge-pathnames "tests.lisp" *load-truename*) :external-format :UTF-8) + +(clon:defsynopsis () + (text :contents "The Common Lisp client for Thrift's cross-language test suite.") + (group (:header "Allowed options:") + (flag :short-name "h" :long-name "help" + :description "Print this help and exit.") + (stropt :long-name "host" + :description "The host to connect to." + :default-value "localhost" + :argument-name "ARG") + (stropt :long-name "port" + :description "Number of the port to listen for connections on." + :default-value "9090" + :argument-name "ARG" + :argument-type :optional) + (stropt :long-name "transport" + :description "Transport: transport to use (\"buffered\", \"framed\")" + :default-value "buffered" + :argument-name "ARG") + (stropt :long-name "protocol" + :description "Protocol: protocol to use (\"binary\", \"multi\")" + :default-value "binary" + :argument-name "ARG"))) + +(defun main () + "Entry point for our standalone application." + (clon:make-context) + (when (clon:getopt :short-name "h") + (clon:help) + (clon:exit)) + (let ((port "9090") + (host "localhost") + (framed nil) + (multiplexed nil)) + (clon:do-cmdline-options (option name value source) + (print (list option name value source)) + (if (string= name "host") + (setf host value)) + (if (string= name "port") + (setf port value)) + (if (string= name "transport") + (cond ((string= value "buffered") (setf framed nil)) + ((string= value "framed") (setf framed t)) + (t (error "Unsupported transport.")))) + (if (string= name "protocol") + (cond ((string= value "binary") (setf multiplexed nil)) + ((string= value "multi") (setf multiplexed t)) + (t (error "Unsupported protocol."))))) + (terpri) + (setf *prot* (thrift.implementation::client (puri:parse-uri + (concatenate 'string "thrift://" host ":" port)) + :framed framed + :multiplexed multiplexed)) + (let ((result (cross-test :multiplexed multiplexed))) + (thrift.implementation::close *prot*) + (clon:exit result)))) + +(clon:dump "TestClient" main) diff --git a/src/jaegertracing/thrift/test/cl/make-test-server.lisp b/src/jaegertracing/thrift/test/cl/make-test-server.lisp new file mode 100644 index 000000000..293c87928 --- /dev/null +++ b/src/jaegertracing/thrift/test/cl/make-test-server.lisp @@ -0,0 +1,80 @@ +(in-package #:cl-user) + +;;;; Licensed 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. + +(require "asdf") +(load (merge-pathnames "../../lib/cl/load-locally.lisp" *load-truename*)) +(asdf:load-system :net.didierverna.clon) +(asdf:load-asd (merge-pathnames "gen-cl/ThriftTest/thrift-gen-ThriftTest.asd" *load-truename*)) +(asdf:load-system :thrift-gen-thrifttest) +(load (merge-pathnames "implementation.lisp" *load-truename*)) + +(net.didierverna.clon:nickname-package) + +(clon:defsynopsis () + (text :contents "The Common Lisp server for Thrift's cross-language test suite.") + (group (:header "Allowed options:") + (flag :short-name "h" :long-name "help" + :description "Print this help and exit.") + (stropt :long-name "port" + :description "Number of the port to listen for connections on." + :default-value "9090" + :argument-name "ARG" + :argument-type :optional) + (stropt :long-name "server-type" + :description "The type of server, currently only \"simple\" is available." + :default-value "simple" + :argument-name "ARG") + (stropt :long-name "transport" + :description "Transport: transport to use (\"buffered\" or \"framed\")" + :default-value "buffered" + :argument-name "ARG") + (stropt :long-name "protocol" + :description "Protocol: protocol to use (\"binary\" or \"multi\")" + :default-value "binary" + :argument-name "ARG"))) + +(defun main () + "Entry point for our standalone application." + (clon:make-context) + (when (clon:getopt :short-name "h") + (clon:help) + (clon:exit)) + (let ((port "9090") + (framed nil) + (multiplexed nil)) + (clon:do-cmdline-options (option name value source) + (print (list option name value source)) + (if (string= name "port") + (setf port value)) + (if (string= name "transport") + (cond ((string= value "buffered") (setf framed nil)) + ((string= value "framed") (setf framed t)) + (t (error "Unsupported transport.")))) + (if (string= name "protocol") + (cond ((string= value "binary") (setf multiplexed nil)) + ((string= value "multi") (setf multiplexed t)) + (t (error "Unsupported protocol."))))) + (terpri) + (let ((services (if multiplexed + (list thrift.test:thrift-test thrift.test:second-service) + thrift.test:thrift-test))) + (thrift:serve (puri:parse-uri (concatenate 'string + "thrift://127.0.0.1:" + port)) + services + :framed framed + :multiplexed multiplexed))) + (clon:exit)) + +(clon:dump "TestServer" main) diff --git a/src/jaegertracing/thrift/test/cl/tests.lisp b/src/jaegertracing/thrift/test/cl/tests.lisp new file mode 100644 index 000000000..c5035fd98 --- /dev/null +++ b/src/jaegertracing/thrift/test/cl/tests.lisp @@ -0,0 +1,240 @@ +(in-package #:thrift-cross) + +;;;; Licensed 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. + +;;;; The tests here only make sense in the context of a TestServer +;;;; running and the dynamic variable thrift-cross::*prot* +;;;; being set with a client connection to the TestServer. Normally, +;;;; this is handled in make-test-client.lisp. + + +;;; Standard Thrift cross-test error codes +(defparameter *test_basetypes* 1) +(defparameter *test_structs* 2) +(defparameter *test_containers* 4) +(defparameter *test_exceptions* 8) +(defparameter *test_unknown* 64) +(defparameter *test_timeout* 128) + +(defun cross-test (&key (multiplexed nil)) + "The main cross-test runner." + (let ((result nil)) + (handler-case + (progn + (unless (run-package-tests :package :base-types) + (pushnew *test_basetypes* result)) + (unless (run-package-tests :package :structs) + (pushnew *test_structs* result)) + (unless (run-package-tests :package :containers) + (pushnew *test_containers* result)) + (unless (run-package-tests :package :exceptions) + (pushnew *test_exceptions* result)) + (unless (run-package-tests :package :misc) + (pushnew *test_unknown* result)) + + ;; It doesn't seem like anyone actually uses + ;; the second test service when testing multiplexing, + ;; so this would fail against servers in other + ;; languages. For now, anyway. + #+(or) + (when multiplexed + (unless (run-package-tests :package :multiplex) + (pushnew *test_unknown* result)))) + (error (e) (pushnew *test_unknown* result))) + (apply #'+ result))) + +(fiasco:define-test-package #:base-types) + +(in-package #:base-types) + +(defconstant *lang-string* "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ú, 粵語") + +(defparameter *trick-string* (format nil "quote: \" backslash: \\ newline: ~% backspace: ~C ~ + tab: ~T junk: !@#$%&()(&%$#{}{}<><><" #\backspace)) + +(defconstant *binary-sequence* #(128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127)) + +(deftest void-test () + (is (null (thrift.test.thrift-test:test-void thrift-cross::*prot*)))) + +(deftest boolean-test () + (is (thrift.test.thrift-test:test-bool thrift-cross::*prot* t)) + (is (not (thrift.test.thrift-test:test-bool thrift-cross::*prot* nil)))) + +(deftest integer-test () + (is (= (thrift.test.thrift-test:test-byte thrift-cross::*prot* 127) 127)) + (is (= (thrift.test.thrift-test:test-byte thrift-cross::*prot* -128) -128)) + (is (= (thrift.test.thrift-test:test-byte thrift-cross::*prot* 42) 42)) + (is (= (thrift.test.thrift-test:test-byte thrift-cross::*prot* 0) 0)) + (is (= (thrift.test.thrift-test:test-i32 thrift-cross::*prot* 0) 0)) + (is (= (thrift.test.thrift-test:test-i32 thrift-cross::*prot* 2147483647) 2147483647)) + (is (= (thrift.test.thrift-test:test-i32 thrift-cross::*prot* -2147483648) -2147483648)) + (is (= (thrift.test.thrift-test:test-i64 thrift-cross::*prot* 0) 0)) + (is (= (thrift.test.thrift-test:test-i64 thrift-cross::*prot* 9223372036854775807) 9223372036854775807)) + (is (= (thrift.test.thrift-test:test-i64 thrift-cross::*prot* -9223372036854775808) -9223372036854775808))) + +(deftest double-test () + (is (= (thrift.test.thrift-test:test-double thrift-cross::*prot* 0.0) 0)) + (is (= (thrift.test.thrift-test:test-double thrift-cross::*prot* 42.0) 42)) + (is (= (thrift.test.thrift-test:test-double thrift-cross::*prot* -555.0) -555)) + (is (= (thrift.test.thrift-test:test-double thrift-cross::*prot* -52.3678) -52.3678))) + +(deftest string-test () + (is (string= (thrift.test.thrift-test:test-string thrift-cross::*prot* "") "")) + (is (string= (thrift.test.thrift-test:test-string thrift-cross::*prot* "(defun botsbuildbots () (botsbuilsbots))") + "(defun botsbuildbots () (botsbuilsbots))")) + (is (string= (thrift.test.thrift-test:test-string thrift-cross::*prot* *lang-string*) *lang-string*)) + (is (string= (thrift.test.thrift-test:test-string thrift-cross::*prot* *trick-string*) *trick-string*))) + +(deftest binary-test () + (is (equalp (thrift.test.thrift-test:test-binary thrift-cross::*prot* #()) #())) + (is (equalp (thrift.test.thrift-test:test-binary thrift-cross::*prot* *binary-sequence*) *binary-sequence*))) + +(deftest enum-test () + (is (= (thrift.test.thrift-test:test-enum thrift-cross::*prot* thrift.test:numberz.five) thrift.test:numberz.five)) + (is (= (thrift.test.thrift-test:test-enum thrift-cross::*prot* thrift.test:numberz.eight) thrift.test:numberz.eight)) + (is (= (thrift.test.thrift-test:test-enum thrift-cross::*prot* thrift.test:numberz.one) thrift.test:numberz.one))) + +(deftest typedef-test () + (is (= (thrift.test.thrift-test:test-typedef thrift-cross::*prot* 309858235082523) 309858235082523))) + +(fiasco:define-test-package #:structs) + +(in-package #:structs) + +(defparameter *test-struct* (thrift.test:make-xtruct :string-thing "Hell is empty." + :byte-thing -2 + :i32-thing 42 + :i64-thing 42424242)) + +(defparameter *test-nest* (thrift.test:make-xtruct2 :byte-thing 42 + :struct-thing *test-struct* + :i32-thing -42)) + +(deftest struct-test () + (let ((rec-struct (thrift.test.thrift-test:test-struct thrift-cross::*prot* *test-struct*))) + (is (string= (thrift.test:xtruct-string-thing *test-struct*) + (thrift.test:xtruct-string-thing rec-struct))) + (is (= (thrift.test:xtruct-byte-thing *test-struct*) + (thrift.test:xtruct-byte-thing rec-struct))) + (is (= (thrift.test:xtruct-i32-thing *test-struct*) + (thrift.test:xtruct-i32-thing rec-struct))) + (is (= (thrift.test:xtruct-i64-thing *test-struct*) + (thrift.test:xtruct-i64-thing rec-struct))))) + +(deftest nest-test () + (let* ((rec-nest (thrift.test.thrift-test:test-nest thrift-cross::*prot* *test-nest*)) + (rec-struct (thrift.test:xtruct2-struct-thing rec-nest))) + (is (string= (thrift.test:xtruct-string-thing *test-struct*) + (thrift.test:xtruct-string-thing rec-struct))) + (is (= (thrift.test:xtruct-byte-thing *test-struct*) + (thrift.test:xtruct-byte-thing rec-struct))) + (is (= (thrift.test:xtruct-i32-thing *test-struct*) + (thrift.test:xtruct-i32-thing rec-struct))) + (is (= (thrift.test:xtruct-i64-thing *test-struct*) + (thrift.test:xtruct-i64-thing rec-struct))) + (is (= (thrift.test:xtruct2-byte-thing *test-nest*) + (thrift.test:xtruct2-byte-thing rec-nest))) + (is (= (thrift.test:xtruct2-i32-thing *test-nest*) + (thrift.test:xtruct2-i32-thing rec-nest))))) + +(fiasco:define-test-package #:containers) + +(in-package #:containers) + +(deftest list-test () + (is (null (thrift.test.thrift-test:test-list thrift-cross::*prot* nil))) + (is (equal (thrift.test.thrift-test:test-list thrift-cross::*prot* '(42 -42 0 5)) '(42 -42 0 5)))) + +(deftest set-test () + (is (null (thrift.test.thrift-test:test-set thrift-cross::*prot* nil))) + (is (equal (sort (thrift.test.thrift-test:test-set thrift-cross::*prot* (list 42 -42 0 5)) #'<) + '(-42 0 5 42)))) + +(defun map= (map1 map2 &key (car-predicate #'equal) (cdr-predicate #'equal)) + "Compare two assoc maps according to the predicates given." + (not (set-exclusive-or map1 map2 :test (lambda (el1 el2) + (and (funcall car-predicate + (car el1) + (car el2)) + (funcall cdr-predicate + (cdr el1) + (cdr el2))))))) + +(deftest map-test () + (is (null (thrift.test.thrift-test:test-map thrift-cross::*prot* nil))) + (is (map= (thrift.test.thrift-test:test-map thrift-cross::*prot* '((0 . 1) (42 . -42) (5 . 5))) + '((0 . 1) (42 . -42) (5 . 5)))) + (is (map= (thrift.test.thrift-test:test-map-map thrift-cross::*prot* 42) + '((-4 . ((-4 . -4) (-3 . -3) (-2 . -2) (-1 . -1))) + (4 . ((1 . 1) (2 . 2) (3 . 3) (4 . 4)))) + :cdr-predicate #'map=))) + +(fiasco:define-test-package #:exceptions) + +(in-package #:exceptions) + +(defun test-xception (expected-code expected-message function &rest args) + "A helper function to test whether xception is signalled, and whether its fields have the expected values." + (handler-case (progn (apply function args) + nil) + (thrift.test:xception (ex) (and (= (thrift.test::xception-error-code ex) expected-code) + (string= (thrift.test::xception-message ex) expected-message))))) + +(defun test-xception2 (expected-code expected-message function &rest args) + "A helper function to test whether xception2 is signalled, and whether its fields have the expected values." + (handler-case (progn (apply function args) + nil) + (thrift.test:xception2 (ex) (and (= (thrift.test::xception2-error-code ex) expected-code) + (string= (thrift.test::xtruct-string-thing + (thrift.test::xception2-struct-thing ex)) + expected-message))))) + +(deftest exception-test () + (is (test-xception 1001 "Xception" #'thrift.test.thrift-test:test-exception thrift-cross::*prot* "Xception")) + (signals thrift:application-error (thrift.test.thrift-test:test-exception thrift-cross::*prot* "TException")) + (finishes (thrift.test.thrift-test:test-exception thrift-cross::*prot* "success"))) + +(deftest multi-exception-test () + (is (test-xception 1001 + "This is an Xception" + #'thrift.test.thrift-test:test-multi-exception + thrift-cross::*prot* + "Xception" + "meaningless")) + (is (test-xception2 2002 + "This is an Xception2" + #'thrift.test.thrift-test:test-multi-exception + thrift-cross::*prot* + "Xception2" + "meaningless too!")) + (is (string= "foobar" (thrift.test:xtruct-string-thing + (thrift.test.thrift-test:test-multi-exception thrift-cross::*prot* + "success!" + "foobar"))))) + +(fiasco:define-test-package #:misc) + +(in-package #:misc) + +(deftest oneway-test () + (is (null (thrift.test.thrift-test:test-oneway thrift-cross::*prot* 1)))) + +(fiasco:define-test-package #:multiplex) + +(in-package #:multiplex) + +(deftest multiplex-test () + ;; Removed from the IDL definition. + ;; (finishes (thrift.test.second-service:blah-blah thrift-cross::*prot*)) + (is (string= "asd" (thrift.test.second-service:secondtest-string thrift-cross::*prot* "asd")))) diff --git a/src/jaegertracing/thrift/test/cpp/CMakeLists.txt b/src/jaegertracing/thrift/test/cpp/CMakeLists.txt new file mode 100755 index 000000000..90af7826c --- /dev/null +++ b/src/jaegertracing/thrift/test/cpp/CMakeLists.txt @@ -0,0 +1,97 @@ +# +# 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. +# + +# The test executables still depend on Boost +include(BoostMacros) +REQUIRE_BOOST_HEADERS() +set(BOOST_COMPONENTS filesystem program_options random) +REQUIRE_BOOST_LIBRARIES(BOOST_COMPONENTS) + +# Contains the thrift specific LINK_AGAINST_THRIFT_LIBRARY +include(ThriftMacros) + +find_package(OpenSSL REQUIRED) +include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}") + +find_package(Libevent REQUIRED) # Libevent comes with CMake support from upstream +include_directories(SYSTEM ${LIBEVENT_INCLUDE_DIRS}) + +find_package(ZLIB REQUIRED) +include_directories(SYSTEM ${ZLIB_INCLUDE_DIRS}) + +#Make sure gen-cpp files can be included +include_directories("${CMAKE_CURRENT_BINARY_DIR}") +include_directories("${CMAKE_CURRENT_BINARY_DIR}/gen-cpp") +include_directories("${PROJECT_SOURCE_DIR}/lib/cpp/src") + +set(crosstestgencpp_SOURCES + gen-cpp/SecondService.cpp + gen-cpp/ThriftTest.cpp + gen-cpp/ThriftTest_types.cpp + gen-cpp/ThriftTest_constants.cpp + src/ThriftTest_extras.cpp +) +add_library(crosstestgencpp STATIC ${crosstestgencpp_SOURCES}) +LINK_AGAINST_THRIFT_LIBRARY(crosstestgencpp thrift) + +set(crossstressgencpp_SOURCES + gen-cpp/Service.cpp + gen-cpp/StressTest_types.cpp + gen-cpp/StressTest_constants.cpp +) +add_library(crossstressgencpp STATIC ${crossstressgencpp_SOURCES}) +LINK_AGAINST_THRIFT_LIBRARY(crossstressgencpp thrift) + +add_executable(TestServer src/TestServer.cpp) +target_link_libraries(TestServer crosstestgencpp ${Boost_LIBRARIES} ${LIBEVENT_LIB}) +LINK_AGAINST_THRIFT_LIBRARY(TestServer thrift) +LINK_AGAINST_THRIFT_LIBRARY(TestServer thriftnb) +LINK_AGAINST_THRIFT_LIBRARY(TestServer thriftz) + +add_executable(TestClient src/TestClient.cpp) +target_link_libraries(TestClient crosstestgencpp ${Boost_LIBRARIES} ${LIBEVENT_LIB}) +LINK_AGAINST_THRIFT_LIBRARY(TestClient thrift) +LINK_AGAINST_THRIFT_LIBRARY(TestClient thriftnb) +LINK_AGAINST_THRIFT_LIBRARY(TestClient thriftz) + +add_executable(StressTest src/StressTest.cpp) +target_link_libraries(StressTest crossstressgencpp ${Boost_LIBRARIES} ${LIBEVENT_LIB}) +LINK_AGAINST_THRIFT_LIBRARY(StressTest thrift) +LINK_AGAINST_THRIFT_LIBRARY(StressTest thriftnb) +add_test(NAME StressTest COMMAND StressTest) +add_test(NAME StressTestConcurrent COMMAND StressTest --client-type=concurrent) + +add_executable(StressTestNonBlocking src/StressTestNonBlocking.cpp) +target_link_libraries(StressTestNonBlocking crossstressgencpp ${Boost_LIBRARIES} ${LIBEVENT_LIB}) +LINK_AGAINST_THRIFT_LIBRARY(StressTestNonBlocking thrift) +LINK_AGAINST_THRIFT_LIBRARY(StressTestNonBlocking thriftnb) +LINK_AGAINST_THRIFT_LIBRARY(StressTestNonBlocking thriftz) +add_test(NAME StressTestNonBlocking COMMAND StressTestNonBlocking) + +# +# Common thrift code generation rules +# + +add_custom_command(OUTPUT gen-cpp/SecondService.cpp gen-cpp/SecondService.h gen-cpp/ThriftTest.cpp gen-cpp/ThriftTest.h gen-cpp/ThriftTest_types.cpp gen-cpp/ThriftTest_constants.cpp + COMMAND ${THRIFT_COMPILER} --gen cpp:templates,cob_style -r ${PROJECT_SOURCE_DIR}/test/ThriftTest.thrift +) + +add_custom_command(OUTPUT gen-cpp/StressTest_types.cpp gen-cpp/StressTest_constants.cpp gen-cpp/Service.cpp + COMMAND ${THRIFT_COMPILER} --gen cpp ${PROJECT_SOURCE_DIR}/test/StressTest.thrift +) diff --git a/src/jaegertracing/thrift/test/cpp/Makefile.am b/src/jaegertracing/thrift/test/cpp/Makefile.am new file mode 100755 index 000000000..76ae82bfb --- /dev/null +++ b/src/jaegertracing/thrift/test/cpp/Makefile.am @@ -0,0 +1,125 @@ +# +# 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. +# +AUTOMAKE_OPTIONS = subdir-objects serial-tests nostdinc + +BUILT_SOURCES = gen-cpp/ThriftTest.cpp \ + gen-cpp/ThriftTest_types.cpp \ + gen-cpp/ThriftTest_constants.cpp \ + gen-cpp/SecondService.cpp \ + gen-cpp/StressTest_types.cpp \ + gen-cpp/StressTest_constants.cpp \ + gen-cpp/Service.cpp + +noinst_LTLIBRARIES = libtestgencpp.la libstresstestgencpp.la +nodist_libtestgencpp_la_SOURCES = \ + gen-cpp/SecondService.cpp \ + gen-cpp/SecondService.h \ + gen-cpp/SecondService.tcc \ + gen-cpp/ThriftTest_constants.cpp \ + gen-cpp/ThriftTest_constants.h \ + gen-cpp/ThriftTest_types.cpp \ + gen-cpp/ThriftTest_types.h \ + gen-cpp/ThriftTest_types.tcc \ + gen-cpp/ThriftTest.cpp \ + gen-cpp/ThriftTest.h \ + gen-cpp/ThriftTest.tcc \ + src/ThriftTest_extras.cpp + +libtestgencpp_la_LIBADD = $(top_builddir)/lib/cpp/libthrift.la + +nodist_libstresstestgencpp_la_SOURCES = \ + gen-cpp/StressTest_constants.cpp \ + gen-cpp/StressTest_types.cpp \ + gen-cpp/StressTest_constants.h \ + gen-cpp/StressTest_types.h \ + gen-cpp/Service.cpp \ + gen-cpp/Service.h + +libstresstestgencpp_la_LIBADD = $(top_builddir)/lib/cpp/libthrift.la + +precross: TestServer TestClient + +check_PROGRAMS = \ + TestServer \ + TestClient \ + StressTest \ + StressTestNonBlocking + +# we currently do not run the testsuite, stop c++ server issue +# TESTS = \ +# $(check_PROGRAMS) + +TestServer_SOURCES = \ + src/TestServer.cpp + +TestServer_LDADD = \ + libtestgencpp.la \ + $(top_builddir)/lib/cpp/libthrift.la \ + $(top_builddir)/lib/cpp/libthriftz.la \ + $(top_builddir)/lib/cpp/libthriftnb.la \ + -levent -lboost_program_options -lboost_system -lboost_filesystem $(ZLIB_LIBS) + +TestClient_SOURCES = \ + src/TestClient.cpp + +TestClient_LDADD = \ + libtestgencpp.la \ + $(top_builddir)/lib/cpp/libthrift.la \ + $(top_builddir)/lib/cpp/libthriftz.la \ + $(top_builddir)/lib/cpp/libthriftnb.la \ + -levent -lboost_program_options -lboost_system -lboost_filesystem $(ZLIB_LIBS) + +StressTest_SOURCES = \ + src/StressTest.cpp + +StressTest_LDADD = \ + libstresstestgencpp.la \ + $(top_builddir)/lib/cpp/libthrift.la + +StressTestNonBlocking_SOURCES = \ + src/StressTestNonBlocking.cpp + +StressTestNonBlocking_LDADD = \ + libstresstestgencpp.la \ + $(top_builddir)/lib/cpp/libthriftnb.la \ + -levent +# +# Common thrift code generation rules +# +gen-cpp/ThriftTest.cpp gen-cpp/ThriftTest_types.cpp gen-cpp/ThriftTest_constants.cpp gen-cpp/SecondService.cpp gen-cpp/SecondService.h gen-cpp/SecondService.tcc: $(top_srcdir)/test/ThriftTest.thrift $(THRIFT) + $(THRIFT) --gen cpp:templates,cob_style -r $< + +gen-cpp/StressTest_types.cpp gen-cpp/StressTest_constants.cpp gen-cpp/Service.cpp: $(top_srcdir)/test/StressTest.thrift $(THRIFT) + $(THRIFT) --gen cpp $< + +AM_CPPFLAGS = $(BOOST_CPPFLAGS) $(LIBEVENT_CPPFLAGS) -I$(top_srcdir)/lib/cpp/src -Igen-cpp -I. +AM_CXXFLAGS = -Wall -Wextra -pedantic -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS +AM_LDFLAGS = $(BOOST_LDFLAGS) $(LIBEVENT_LDFLAGS) $(ZLIB_LIBS) + +clean-local: + $(RM) -r gen-cpp/ + +style-local: + $(CPPSTYLE_CMD) + +EXTRA_DIST = \ + src/TestClient.cpp \ + src/TestServer.cpp \ + src/StressTest.cpp \ + src/StressTestNonBlocking.cpp diff --git a/src/jaegertracing/thrift/test/cpp/src/StressTest.cpp b/src/jaegertracing/thrift/test/cpp/src/StressTest.cpp new file mode 100644 index 000000000..79a708e8f --- /dev/null +++ b/src/jaegertracing/thrift/test/cpp/src/StressTest.cpp @@ -0,0 +1,605 @@ +/* + * 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. + */ + +#include <thrift/concurrency/ThreadManager.h> +#include <thrift/concurrency/ThreadFactory.h> +#include <thrift/concurrency/Monitor.h> +#include <thrift/concurrency/Mutex.h> +#include <thrift/protocol/TBinaryProtocol.h> +#include <thrift/server/TSimpleServer.h> +#include <thrift/server/TThreadPoolServer.h> +#include <thrift/server/TThreadedServer.h> +#include <thrift/transport/TServerSocket.h> +#include <thrift/transport/TSocket.h> +#include <thrift/transport/TTransportUtils.h> +#include <thrift/transport/TFileTransport.h> +#include <thrift/TLogging.h> + +#include "Service.h" +#include <iostream> +#include <set> +#include <stdexcept> +#include <sstream> +#include <map> +#if _WIN32 +#include <thrift/windows/TWinsockSingleton.h> +#endif + +using namespace std; + +using namespace apache::thrift; +using namespace apache::thrift::async; +using namespace apache::thrift::protocol; +using namespace apache::thrift::transport; +using namespace apache::thrift::server; +using namespace apache::thrift::concurrency; + +using namespace test::stress; + +struct eqstr { + bool operator()(const char* s1, const char* s2) const { return strcmp(s1, s2) == 0; } +}; + +struct ltstr { + bool operator()(const char* s1, const char* s2) const { return strcmp(s1, s2) < 0; } +}; + +// typedef hash_map<const char*, int, hash<const char*>, eqstr> count_map; +typedef map<const char*, int, ltstr> count_map; + +class Server : public ServiceIf { +public: + Server() = default; + + void count(const char* method) { + Guard m(lock_); + int ct = counts_[method]; + counts_[method] = ++ct; + } + + void echoVoid() override { + count("echoVoid"); + return; + } + + count_map getCount() { + Guard m(lock_); + return counts_; + } + + int8_t echoByte(const int8_t arg) override { return arg; } + int32_t echoI32(const int32_t arg) override { return arg; } + int64_t echoI64(const int64_t arg) override { return arg; } + void echoString(string& out, const string& arg) override { + if (arg != "hello") { + T_ERROR_ABORT("WRONG STRING (%s)!!!!", arg.c_str()); + } + out = arg; + } + void echoList(vector<int8_t>& out, const vector<int8_t>& arg) override { out = arg; } + void echoSet(set<int8_t>& out, const set<int8_t>& arg) override { out = arg; } + void echoMap(map<int8_t, int8_t>& out, const map<int8_t, int8_t>& arg) override { out = arg; } + +private: + count_map counts_; + Mutex lock_; +}; + +enum TransportOpenCloseBehavior { + OpenAndCloseTransportInThread, + DontOpenAndCloseTransportInThread +}; +class ClientThread : public Runnable { +public: + ClientThread(std::shared_ptr<TTransport> transport, + std::shared_ptr<ServiceIf> client, + Monitor& monitor, + size_t& workerCount, + size_t loopCount, + TType loopType, + TransportOpenCloseBehavior behavior) + : _transport(transport), + _client(client), + _monitor(monitor), + _workerCount(workerCount), + _loopCount(loopCount), + _loopType(loopType), + _behavior(behavior) {} + + void run() override { + + // Wait for all worker threads to start + + { + Synchronized s(_monitor); + while (_workerCount == 0) { + _monitor.wait(); + } + } + + _startTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count(); + if(_behavior == OpenAndCloseTransportInThread) { + _transport->open(); + } + + switch (_loopType) { + case T_VOID: + loopEchoVoid(); + break; + case T_BYTE: + loopEchoByte(); + break; + case T_I32: + loopEchoI32(); + break; + case T_I64: + loopEchoI64(); + break; + case T_STRING: + loopEchoString(); + break; + default: + cerr << "Unexpected loop type" << _loopType << endl; + break; + } + + _endTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count(); + + if(_behavior == OpenAndCloseTransportInThread) { + _transport->close(); + } + + _done = true; + + { + Synchronized s(_monitor); + + _workerCount--; + + if (_workerCount == 0) { + + _monitor.notify(); + } + } + } + + void loopEchoVoid() { + for (size_t ix = 0; ix < _loopCount; ix++) { + _client->echoVoid(); + } + } + + void loopEchoByte() { + for (size_t ix = 0; ix < _loopCount; ix++) { + int8_t arg = 1; + int8_t result; + result = _client->echoByte(arg); + (void)result; + assert(result == arg); + } + } + + void loopEchoI32() { + for (size_t ix = 0; ix < _loopCount; ix++) { + int32_t arg = 1; + int32_t result; + result = _client->echoI32(arg); + (void)result; + assert(result == arg); + } + } + + void loopEchoI64() { + for (size_t ix = 0; ix < _loopCount; ix++) { + int64_t arg = 1; + int64_t result; + result = _client->echoI64(arg); + (void)result; + assert(result == arg); + } + } + + void loopEchoString() { + for (size_t ix = 0; ix < _loopCount; ix++) { + string arg = "hello"; + string result; + _client->echoString(result, arg); + assert(result == arg); + } + } + + std::shared_ptr<TTransport> _transport; + std::shared_ptr<ServiceIf> _client; + Monitor& _monitor; + size_t& _workerCount; + size_t _loopCount; + TType _loopType; + int64_t _startTime; + int64_t _endTime; + bool _done; + Monitor _sleep; + TransportOpenCloseBehavior _behavior; +}; + +class TStartObserver : public apache::thrift::server::TServerEventHandler { +public: + TStartObserver() : awake_(false) {} + void preServe() override { + apache::thrift::concurrency::Synchronized s(m_); + awake_ = true; + m_.notifyAll(); + } + void waitForService() { + apache::thrift::concurrency::Synchronized s(m_); + while (!awake_) + m_.waitForever(); + } + +private: + apache::thrift::concurrency::Monitor m_; + bool awake_; +}; + +int main(int argc, char** argv) { +#if _WIN32 + transport::TWinsockSingleton::create(); +#endif + + int port = 9091; + string clientType = "regular"; + string serverType = "thread-pool"; + string protocolType = "binary"; + size_t workerCount = 8; + size_t clientCount = 4; + size_t loopCount = 50000; + TType loopType = T_VOID; + string callName = "echoVoid"; + bool runServer = true; + bool logRequests = false; + string requestLogPath = "./requestlog.tlog"; + bool replayRequests = false; + + ostringstream usage; + + usage << argv[0] << " [--port=<port number>] [--server] [--server-type=<server-type>] " + "[--protocol-type=<protocol-type>] [--workers=<worker-count>] " + "[--clients=<client-count>] [--loop=<loop-count>] " + "[--client-type=<client-type>]" << endl + << "\tclients Number of client threads to create - 0 implies no clients, i.e. " + "server only. Default is " << clientCount << endl + << "\thelp Prints this help text." << endl + << "\tcall Service method to call. Default is " << callName << endl + << "\tloop The number of remote thrift calls each client makes. Default is " << loopCount << endl + << "\tport The port the server and clients should bind to " + "for thrift network connections. Default is " << port << endl + << "\tserver Run the Thrift server in this process. Default is " << runServer << endl + << "\tserver-type Type of server, \"simple\" or \"thread-pool\". Default is " << serverType << endl + << "\tprotocol-type Type of protocol, \"binary\", \"ascii\", or \"xml\". Default is " << protocolType << endl + << "\tlog-request Log all request to ./requestlog.tlog. Default is " << logRequests << endl + << "\treplay-request Replay requests from log file (./requestlog.tlog) Default is " << replayRequests << endl + << "\tworkers Number of thread pools workers. Only valid " + "for thread-pool server type. Default is " << workerCount << endl + << "\tclient-type Type of client, \"regular\" or \"concurrent\". Default is " << clientType << endl + << endl; + + map<string, string> args; + + for (int ix = 1; ix < argc; ix++) { + + string arg(argv[ix]); + + if (arg.compare(0, 2, "--") == 0) { + + size_t end = arg.find_first_of("=", 2); + + string key = string(arg, 2, end - 2); + + if (end != string::npos) { + args[key] = string(arg, end + 1); + } else { + args[key] = "true"; + } + } else { + throw invalid_argument("Unexcepted command line token: " + arg); + } + } + + try { + + if (!args["clients"].empty()) { + clientCount = atoi(args["clients"].c_str()); + } + + if (!args["help"].empty()) { + cerr << usage.str(); + return 0; + } + + if (!args["loop"].empty()) { + loopCount = atoi(args["loop"].c_str()); + } + + if (!args["call"].empty()) { + callName = args["call"]; + } + + if (!args["port"].empty()) { + port = atoi(args["port"].c_str()); + } + + if (!args["server"].empty()) { + runServer = args["server"] == "true"; + } + + if (!args["log-request"].empty()) { + logRequests = args["log-request"] == "true"; + } + + if (!args["replay-request"].empty()) { + replayRequests = args["replay-request"] == "true"; + } + + if (!args["server-type"].empty()) { + serverType = args["server-type"]; + + if (serverType == "simple") { + + } else if (serverType == "thread-pool") { + + } else if (serverType == "threaded") { + + } else { + + throw invalid_argument("Unknown server type " + serverType); + } + } + if (!args["client-type"].empty()) { + clientType = args["client-type"]; + + if (clientType == "regular") { + + } else if (clientType == "concurrent") { + + } else { + + throw invalid_argument("Unknown client type " + clientType); + } + } + if (!args["workers"].empty()) { + workerCount = atoi(args["workers"].c_str()); + } + + } catch (std::exception& e) { + cerr << e.what() << endl; + cerr << usage.str(); + } + + std::shared_ptr<ThreadFactory> threadFactory + = std::shared_ptr<ThreadFactory>(new ThreadFactory()); + + // Dispatcher + std::shared_ptr<Server> serviceHandler(new Server()); + + if (replayRequests) { + std::shared_ptr<Server> serviceHandler(new Server()); + std::shared_ptr<ServiceProcessor> serviceProcessor(new ServiceProcessor(serviceHandler)); + + // Transports + std::shared_ptr<TFileTransport> fileTransport(new TFileTransport(requestLogPath)); + fileTransport->setChunkSize(2 * 1024 * 1024); + fileTransport->setMaxEventSize(1024 * 16); + fileTransport->seekToEnd(); + + // Protocol Factory + std::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory()); + + TFileProcessor fileProcessor(serviceProcessor, protocolFactory, fileTransport); + + fileProcessor.process(0, true); + exit(0); + } + + if (runServer) { + + std::shared_ptr<ServiceProcessor> serviceProcessor(new ServiceProcessor(serviceHandler)); + + // Transport + std::shared_ptr<TServerSocket> serverSocket(new TServerSocket(port)); + + // Transport Factory + std::shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory()); + + // Protocol Factory + std::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory()); + + if (logRequests) { + // initialize the log file + std::shared_ptr<TFileTransport> fileTransport(new TFileTransport(requestLogPath)); + fileTransport->setChunkSize(2 * 1024 * 1024); + fileTransport->setMaxEventSize(1024 * 16); + + transportFactory + = std::shared_ptr<TTransportFactory>(new TPipedTransportFactory(fileTransport)); + } + + std::shared_ptr<TServer> server; + + if (serverType == "simple") { + + server.reset( + new TSimpleServer(serviceProcessor, serverSocket, transportFactory, protocolFactory)); + + } else if (serverType == "threaded") { + + server.reset( + new TThreadedServer(serviceProcessor, serverSocket, transportFactory, protocolFactory)); + + } else if (serverType == "thread-pool") { + + std::shared_ptr<ThreadManager> threadManager + = ThreadManager::newSimpleThreadManager(workerCount); + + threadManager->threadFactory(threadFactory); + threadManager->start(); + server.reset(new TThreadPoolServer(serviceProcessor, + serverSocket, + transportFactory, + protocolFactory, + threadManager)); + } + + std::shared_ptr<TStartObserver> observer(new TStartObserver); + server->setServerEventHandler(observer); + std::shared_ptr<Thread> serverThread = threadFactory->newThread(server); + + cerr << "Starting the server on port " << port << endl; + + serverThread->start(); + observer->waitForService(); + + // If we aren't running clients, just wait forever for external clients + if (clientCount == 0) { + serverThread->join(); + } + } + + if (clientCount > 0) { //FIXME: start here for client type? + + Monitor monitor; + + size_t threadCount = 0; + + set<std::shared_ptr<Thread> > clientThreads; + + if (callName == "echoVoid") { + loopType = T_VOID; + } else if (callName == "echoByte") { + loopType = T_BYTE; + } else if (callName == "echoI32") { + loopType = T_I32; + } else if (callName == "echoI64") { + loopType = T_I64; + } else if (callName == "echoString") { + loopType = T_STRING; + } else { + throw invalid_argument("Unknown service call " + callName); + } + + if(clientType == "regular") { + for (size_t ix = 0; ix < clientCount; ix++) { + + std::shared_ptr<TSocket> socket(new TSocket("127.0.0.1", port)); + std::shared_ptr<TBufferedTransport> bufferedSocket(new TBufferedTransport(socket, 2048)); + std::shared_ptr<TProtocol> protocol(new TBinaryProtocol(bufferedSocket)); + std::shared_ptr<ServiceClient> serviceClient(new ServiceClient(protocol)); + + clientThreads.insert(threadFactory->newThread(std::shared_ptr<ClientThread>( + new ClientThread(socket, serviceClient, monitor, threadCount, loopCount, loopType, OpenAndCloseTransportInThread)))); + } + } else if(clientType == "concurrent") { + std::shared_ptr<TSocket> socket(new TSocket("127.0.0.1", port)); + std::shared_ptr<TBufferedTransport> bufferedSocket(new TBufferedTransport(socket, 2048)); + std::shared_ptr<TProtocol> protocol(new TBinaryProtocol(bufferedSocket)); + auto sync = std::make_shared<TConcurrentClientSyncInfo>(); + std::shared_ptr<ServiceConcurrentClient> serviceClient(new ServiceConcurrentClient(protocol, sync)); + socket->open(); + for (size_t ix = 0; ix < clientCount; ix++) { + clientThreads.insert(threadFactory->newThread(std::shared_ptr<ClientThread>( + new ClientThread(socket, serviceClient, monitor, threadCount, loopCount, loopType, DontOpenAndCloseTransportInThread)))); + } + } + + for (auto thread = clientThreads.begin(); + thread != clientThreads.end(); + thread++) { + (*thread)->start(); + } + + int64_t time00; + int64_t time01; + + { + Synchronized s(monitor); + threadCount = clientCount; + + cerr << "Launch " << clientCount << " " << clientType << " client threads" << endl; + + time00 = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count(); + + monitor.notifyAll(); + + while (threadCount > 0) { + monitor.wait(); + } + + time01 = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count(); + } + + int64_t firstTime = 9223372036854775807LL; + int64_t lastTime = 0; + + double averageTime = 0; + int64_t minTime = 9223372036854775807LL; + int64_t maxTime = 0; + + for (auto ix = clientThreads.begin(); + ix != clientThreads.end(); + ix++) { + + std::shared_ptr<ClientThread> client + = std::dynamic_pointer_cast<ClientThread>((*ix)->runnable()); + + int64_t delta = client->_endTime - client->_startTime; + + assert(delta > 0); + + if (client->_startTime < firstTime) { + firstTime = client->_startTime; + } + + if (client->_endTime > lastTime) { + lastTime = client->_endTime; + } + + if (delta < minTime) { + minTime = delta; + } + + if (delta > maxTime) { + maxTime = delta; + } + + averageTime += delta; + } + + averageTime /= clientCount; + + cout << "workers :" << workerCount << ", client : " << clientCount << ", loops : " << loopCount + << ", rate : " << (clientCount * loopCount * 1000) / ((double)(time01 - time00)) << endl; + + count_map count = serviceHandler->getCount(); + count_map::iterator iter; + for (iter = count.begin(); iter != count.end(); ++iter) { + printf("%s => %d\n", iter->first, iter->second); + } + cerr << "done." << endl; + } + + return 0; +} diff --git a/src/jaegertracing/thrift/test/cpp/src/StressTestNonBlocking.cpp b/src/jaegertracing/thrift/test/cpp/src/StressTestNonBlocking.cpp new file mode 100644 index 000000000..e94ecb2db --- /dev/null +++ b/src/jaegertracing/thrift/test/cpp/src/StressTestNonBlocking.cpp @@ -0,0 +1,542 @@ +/* + * 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. + */ + +#include <thrift/concurrency/ThreadManager.h> +#include <thrift/concurrency/ThreadFactory.h> +#include <thrift/concurrency/Monitor.h> +#include <thrift/concurrency/Mutex.h> +#include <thrift/protocol/TBinaryProtocol.h> +#include <thrift/server/TSimpleServer.h> +#include <thrift/server/TThreadPoolServer.h> +#include <thrift/server/TThreadedServer.h> +#include <thrift/server/TNonblockingServer.h> +#include <thrift/transport/TServerSocket.h> +#include <thrift/transport/TSocket.h> +#include <thrift/transport/TNonblockingServerSocket.h> +#include <thrift/transport/TTransportUtils.h> +#include <thrift/transport/TFileTransport.h> +#include <thrift/TLogging.h> + +#include "Service.h" + +#include <iostream> +#include <set> +#include <stdexcept> +#include <sstream> +#include <map> +#if _WIN32 +#include <thrift/windows/TWinsockSingleton.h> +#endif + +using namespace std; + +using namespace apache::thrift; +using namespace apache::thrift::protocol; +using namespace apache::thrift::transport; +using namespace apache::thrift::server; +using namespace apache::thrift::concurrency; + +using namespace test::stress; + +struct eqstr { + bool operator()(const char* s1, const char* s2) const { return strcmp(s1, s2) == 0; } +}; + +struct ltstr { + bool operator()(const char* s1, const char* s2) const { return strcmp(s1, s2) < 0; } +}; + +// typedef hash_map<const char*, int, hash<const char*>, eqstr> count_map; +typedef map<const char*, int, ltstr> count_map; + +class Server : public ServiceIf { +public: + Server() = default; + + void count(const char* method) { + Guard m(lock_); + int ct = counts_[method]; + counts_[method] = ++ct; + } + + void echoVoid() override { + count("echoVoid"); + // Sleep to simulate work + THRIFT_SLEEP_USEC(1); + return; + } + + count_map getCount() { + Guard m(lock_); + return counts_; + } + + int8_t echoByte(const int8_t arg) override { return arg; } + int32_t echoI32(const int32_t arg) override { return arg; } + int64_t echoI64(const int64_t arg) override { return arg; } + void echoString(string& out, const string& arg) override { + if (arg != "hello") { + T_ERROR_ABORT("WRONG STRING (%s)!!!!", arg.c_str()); + } + out = arg; + } + void echoList(vector<int8_t>& out, const vector<int8_t>& arg) override { out = arg; } + void echoSet(set<int8_t>& out, const set<int8_t>& arg) override { out = arg; } + void echoMap(map<int8_t, int8_t>& out, const map<int8_t, int8_t>& arg) override { out = arg; } + +private: + count_map counts_; + Mutex lock_; +}; + +class ClientThread : public Runnable { +public: + ClientThread(std::shared_ptr<TTransport> transport, + std::shared_ptr<ServiceClient> client, + Monitor& monitor, + size_t& workerCount, + size_t loopCount, + TType loopType) + : _transport(transport), + _client(client), + _monitor(monitor), + _workerCount(workerCount), + _loopCount(loopCount), + _loopType(loopType) {} + + void run() override { + + // Wait for all worker threads to start + + { + Synchronized s(_monitor); + while (_workerCount == 0) { + _monitor.wait(); + } + } + + _startTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count(); + + _transport->open(); + + switch (_loopType) { + case T_VOID: + loopEchoVoid(); + break; + case T_BYTE: + loopEchoByte(); + break; + case T_I32: + loopEchoI32(); + break; + case T_I64: + loopEchoI64(); + break; + case T_STRING: + loopEchoString(); + break; + default: + cerr << "Unexpected loop type" << _loopType << endl; + break; + } + + _endTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count(); + + _transport->close(); + + _done = true; + + { + Synchronized s(_monitor); + + _workerCount--; + + if (_workerCount == 0) { + + _monitor.notify(); + } + } + } + + void loopEchoVoid() { + for (size_t ix = 0; ix < _loopCount; ix++) { + _client->echoVoid(); + } + } + + void loopEchoByte() { + for (size_t ix = 0; ix < _loopCount; ix++) { + int8_t arg = 1; + int8_t result; + result = _client->echoByte(arg); + (void)result; + assert(result == arg); + } + } + + void loopEchoI32() { + for (size_t ix = 0; ix < _loopCount; ix++) { + int32_t arg = 1; + int32_t result; + result = _client->echoI32(arg); + (void)result; + assert(result == arg); + } + } + + void loopEchoI64() { + for (size_t ix = 0; ix < _loopCount; ix++) { + int64_t arg = 1; + int64_t result; + result = _client->echoI64(arg); + (void)result; + assert(result == arg); + } + } + + void loopEchoString() { + for (size_t ix = 0; ix < _loopCount; ix++) { + string arg = "hello"; + string result; + _client->echoString(result, arg); + assert(result == arg); + } + } + + std::shared_ptr<TTransport> _transport; + std::shared_ptr<ServiceClient> _client; + Monitor& _monitor; + size_t& _workerCount; + size_t _loopCount; + TType _loopType; + int64_t _startTime; + int64_t _endTime; + bool _done; + Monitor _sleep; +}; + +int main(int argc, char** argv) { +#if _WIN32 + transport::TWinsockSingleton::create(); +#endif + + int port = 9091; + string serverType = "simple"; + string protocolType = "binary"; + uint32_t workerCount = 4; + uint32_t clientCount = 20; + uint32_t loopCount = 1000; + TType loopType = T_VOID; + string callName = "echoVoid"; + bool runServer = true; + bool logRequests = false; + string requestLogPath = "./requestlog.tlog"; + bool replayRequests = false; + + ostringstream usage; + + usage << argv[0] << " [--port=<port number>] [--server] [--server-type=<server-type>] " + "[--protocol-type=<protocol-type>] [--workers=<worker-count>] " + "[--clients=<client-count>] [--loop=<loop-count>]" << endl + << "\tclients Number of client threads to create - 0 implies no clients, i.e. " + "server only. Default is " << clientCount << endl + << "\thelp Prints this help text." << endl + << "\tcall Service method to call. Default is " << callName << endl + << "\tloop The number of remote thrift calls each client makes. Default is " + << loopCount << endl << "\tport The port the server and clients should bind to " + "for thrift network connections. Default is " << port << endl + << "\tserver Run the Thrift server in this process. Default is " << runServer + << endl << "\tserver-type Type of server, \"simple\" or \"thread-pool\". Default is " + << serverType << endl + << "\tprotocol-type Type of protocol, \"binary\", \"ascii\", or \"xml\". Default is " + << protocolType << endl + << "\tlog-request Log all request to ./requestlog.tlog. Default is " << logRequests + << endl << "\treplay-request Replay requests from log file (./requestlog.tlog) Default is " + << replayRequests << endl << "\tworkers Number of thread pools workers. Only valid " + "for thread-pool server type. Default is " << workerCount + << endl; + + map<string, string> args; + + for (int ix = 1; ix < argc; ix++) { + + string arg(argv[ix]); + + if (arg.compare(0, 2, "--") == 0) { + + size_t end = arg.find_first_of("=", 2); + + string key = string(arg, 2, end - 2); + + if (end != string::npos) { + args[key] = string(arg, end + 1); + } else { + args[key] = "true"; + } + } else { + throw invalid_argument("Unexcepted command line token: " + arg); + } + } + + try { + + if (!args["clients"].empty()) { + clientCount = atoi(args["clients"].c_str()); + } + + if (!args["help"].empty()) { + cerr << usage.str(); + return 0; + } + + if (!args["loop"].empty()) { + loopCount = atoi(args["loop"].c_str()); + } + + if (!args["call"].empty()) { + callName = args["call"]; + } + + if (!args["port"].empty()) { + port = atoi(args["port"].c_str()); + } + + if (!args["server"].empty()) { + runServer = args["server"] == "true"; + } + + if (!args["log-request"].empty()) { + logRequests = args["log-request"] == "true"; + } + + if (!args["replay-request"].empty()) { + replayRequests = args["replay-request"] == "true"; + } + + if (!args["server-type"].empty()) { + serverType = args["server-type"]; + } + + if (!args["workers"].empty()) { + workerCount = atoi(args["workers"].c_str()); + } + + } catch (std::exception& e) { + cerr << e.what() << endl; + cerr << usage.str(); + } + + std::shared_ptr<ThreadFactory> threadFactory + = std::shared_ptr<ThreadFactory>(new ThreadFactory()); + + // Dispatcher + std::shared_ptr<Server> serviceHandler(new Server()); + + if (replayRequests) { + std::shared_ptr<Server> serviceHandler(new Server()); + std::shared_ptr<ServiceProcessor> serviceProcessor(new ServiceProcessor(serviceHandler)); + + // Transports + std::shared_ptr<TFileTransport> fileTransport(new TFileTransport(requestLogPath)); + fileTransport->setChunkSize(2 * 1024 * 1024); + fileTransport->setMaxEventSize(1024 * 16); + fileTransport->seekToEnd(); + + // Protocol Factory + std::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory()); + + TFileProcessor fileProcessor(serviceProcessor, protocolFactory, fileTransport); + + fileProcessor.process(0, true); + exit(0); + } + + if (runServer) { + + std::shared_ptr<ServiceProcessor> serviceProcessor(new ServiceProcessor(serviceHandler)); + + // Protocol Factory + std::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory()); + + // Transport Factory + std::shared_ptr<TTransportFactory> transportFactory; + + if (logRequests) { + // initialize the log file + std::shared_ptr<TFileTransport> fileTransport(new TFileTransport(requestLogPath)); + fileTransport->setChunkSize(2 * 1024 * 1024); + fileTransport->setMaxEventSize(1024 * 16); + + transportFactory + = std::shared_ptr<TTransportFactory>(new TPipedTransportFactory(fileTransport)); + } + + std::shared_ptr<Thread> serverThread; + std::shared_ptr<Thread> serverThread2; + std::shared_ptr<transport::TNonblockingServerSocket> nbSocket1; + std::shared_ptr<transport::TNonblockingServerSocket> nbSocket2; + + if (serverType == "simple") { + + nbSocket1.reset(new transport::TNonblockingServerSocket(port)); + serverThread = threadFactory->newThread(std::shared_ptr<TServer>( + new TNonblockingServer(serviceProcessor, protocolFactory, nbSocket1))); + nbSocket2.reset(new transport::TNonblockingServerSocket(port + 1)); + serverThread2 = threadFactory->newThread(std::shared_ptr<TServer>( + new TNonblockingServer(serviceProcessor, protocolFactory, nbSocket2))); + + } else if (serverType == "thread-pool") { + + std::shared_ptr<ThreadManager> threadManager + = ThreadManager::newSimpleThreadManager(workerCount); + + threadManager->threadFactory(threadFactory); + threadManager->start(); + nbSocket1.reset(new transport::TNonblockingServerSocket(port)); + serverThread = threadFactory->newThread(std::shared_ptr<TServer>( + new TNonblockingServer(serviceProcessor, protocolFactory, nbSocket1, threadManager))); + nbSocket2.reset(new transport::TNonblockingServerSocket(port + 1)); + serverThread2 = threadFactory->newThread(std::shared_ptr<TServer>( + new TNonblockingServer(serviceProcessor, protocolFactory, nbSocket2, threadManager))); + } + + cerr << "Starting the server on port " << port << " and " << (port + 1) << endl; + serverThread->start(); + serverThread2->start(); + + // If we aren't running clients, just wait forever for external clients + + if (clientCount == 0) { + serverThread->join(); + serverThread2->join(); + } + } + THRIFT_SLEEP_SEC(1); + + if (clientCount > 0) { + + Monitor monitor; + + size_t threadCount = 0; + + set<std::shared_ptr<Thread> > clientThreads; + + if (callName == "echoVoid") { + loopType = T_VOID; + } else if (callName == "echoByte") { + loopType = T_BYTE; + } else if (callName == "echoI32") { + loopType = T_I32; + } else if (callName == "echoI64") { + loopType = T_I64; + } else if (callName == "echoString") { + loopType = T_STRING; + } else { + throw invalid_argument("Unknown service call " + callName); + } + + for (uint32_t ix = 0; ix < clientCount; ix++) { + + std::shared_ptr<TSocket> socket(new TSocket("127.0.0.1", port + (ix % 2))); + std::shared_ptr<TFramedTransport> framedSocket(new TFramedTransport(socket)); + std::shared_ptr<TProtocol> protocol(new TBinaryProtocol(framedSocket)); + std::shared_ptr<ServiceClient> serviceClient(new ServiceClient(protocol)); + + clientThreads.insert(threadFactory->newThread(std::shared_ptr<ClientThread>( + new ClientThread(socket, serviceClient, monitor, threadCount, loopCount, loopType)))); + } + + for (auto thread = clientThreads.begin(); + thread != clientThreads.end(); + thread++) { + (*thread)->start(); + } + + int64_t time00; + int64_t time01; + + { + Synchronized s(monitor); + threadCount = clientCount; + + cerr << "Launch " << clientCount << " client threads" << endl; + + time00 = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count(); + + monitor.notifyAll(); + + while (threadCount > 0) { + monitor.wait(); + } + + time01 = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count(); + } + + int64_t firstTime = 9223372036854775807LL; + int64_t lastTime = 0; + + double averageTime = 0; + int64_t minTime = 9223372036854775807LL; + int64_t maxTime = 0; + + for (auto ix = clientThreads.begin(); + ix != clientThreads.end(); + ix++) { + + std::shared_ptr<ClientThread> client + = std::dynamic_pointer_cast<ClientThread>((*ix)->runnable()); + + int64_t delta = client->_endTime - client->_startTime; + + assert(delta > 0); + + if (client->_startTime < firstTime) { + firstTime = client->_startTime; + } + + if (client->_endTime > lastTime) { + lastTime = client->_endTime; + } + + if (delta < minTime) { + minTime = delta; + } + + if (delta > maxTime) { + maxTime = delta; + } + + averageTime += delta; + } + + averageTime /= clientCount; + + cout << "workers :" << workerCount << ", client : " << clientCount << ", loops : " << loopCount + << ", rate : " << (clientCount * loopCount * 1000) / ((double)(time01 - time00)) << endl; + + count_map count = serviceHandler->getCount(); + count_map::iterator iter; + for (iter = count.begin(); iter != count.end(); ++iter) { + printf("%s => %d\n", iter->first, iter->second); + } + cerr << "done." << endl; + } + + return 0; +} diff --git a/src/jaegertracing/thrift/test/cpp/src/TestClient.cpp b/src/jaegertracing/thrift/test/cpp/src/TestClient.cpp new file mode 100644 index 000000000..c4146cc5c --- /dev/null +++ b/src/jaegertracing/thrift/test/cpp/src/TestClient.cpp @@ -0,0 +1,1231 @@ +/* + * 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. + */ + +#include <limits> +#include <locale> +#include <ios> +#include <iostream> +#include <sstream> +#include <thrift/protocol/TBinaryProtocol.h> +#include <thrift/protocol/TCompactProtocol.h> +#include <thrift/protocol/THeaderProtocol.h> +#include <thrift/protocol/TJSONProtocol.h> +#include <thrift/protocol/TMultiplexedProtocol.h> +#include <thrift/transport/THttpClient.h> +#include <thrift/transport/TTransportUtils.h> +#include <thrift/transport/TSocket.h> +#include <thrift/transport/TSSLSocket.h> +#include <thrift/transport/TZlibTransport.h> +#include <thrift/async/TEvhttpClientChannel.h> +#include <thrift/server/TNonblockingServer.h> // <event.h> + +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif +#ifdef HAVE_INTTYPES_H +#include <inttypes.h> +#endif + +#include <boost/algorithm/string.hpp> +#include <boost/filesystem.hpp> +#include <boost/program_options.hpp> +#include <boost/random/random_device.hpp> +#if _WIN32 +#include <thrift/windows/TWinsockSingleton.h> +#endif + +#include "SecondService.h" +#include "ThriftTest.h" + +using namespace std; +using namespace apache::thrift; +using namespace apache::thrift::async; +using namespace apache::thrift::protocol; +using namespace apache::thrift::transport; +using namespace thrift::test; + +// +// A pedantic protocol that checks to make sure the response sequence ID +// is the same as the sent sequence ID. lib/cpp always sends zero for +// synchronous clients, so this bumps the number to make sure it gets +// returned properly from the remote server. Any server that does not +// respond with the same sequence number is violating the sequence ID +// agreement between client and server. +// + +template<typename Proto> +class TPedanticProtocol : public Proto +{ + public: + TPedanticProtocol(std::shared_ptr<TTransport>& transport) + : Proto(transport), m_last_seqid((std::numeric_limits<int32_t>::max)() - 10) { } + + virtual uint32_t writeMessageBegin_virt(const std::string& name, + const TMessageType messageType, + const int32_t in_seqid) override + { + int32_t seqid = in_seqid; + if (!seqid) { // this is typical for normal cpp generated code + seqid = ++m_last_seqid; + } + + return Proto::writeMessageBegin_virt(name, messageType, seqid); + } + + virtual uint32_t readMessageBegin_virt(std::string& name, + TMessageType& messageType, + int32_t& seqid) override + { + uint32_t result = Proto::readMessageBegin_virt(name, messageType, seqid); + if (seqid != m_last_seqid) { + std::stringstream ss; + ss << "ERROR: send request with seqid " << m_last_seqid << " and got reply with seqid " << seqid; + throw std::logic_error(ss.str()); + } /* else { + std::cout << "verified seqid " << m_last_seqid << " round trip OK" << std::endl; + } */ + return result; + } + + private: + int32_t m_last_seqid; +}; + +// Current time, microseconds since the epoch +uint64_t now() { + int64_t ret; + struct timeval tv; + + THRIFT_GETTIMEOFDAY(&tv, nullptr); + ret = tv.tv_sec; + ret = ret * 1000 * 1000 + tv.tv_usec; + return ret; +} + +static void testString_clientReturn(event_base* base, + int testNr, + ThriftTestCobClient* client) { + try { + string s; + client->recv_testString(s); + std::ostringstream os; + os << "test" << testNr; + const bool ok = (s == os.str()); + cout << "testString: " << s << " " << ((ok) ? "ok" : "failed") << endl; + } catch (TException& exn) { + cout << "Error: " << exn.what() << endl; + } + + if (testNr == 9) + event_base_loopbreak(base); // end test +} + +static void testVoid_clientReturn(event_base* base, ThriftTestCobClient* client) { + try { + client->recv_testVoid(); + cout << "testVoid" << endl; + + for (int testNr = 0; testNr < 10; ++testNr) { + std::ostringstream os; + os << "test" << testNr; + client->testString(std::bind(testString_clientReturn, + base, + testNr, + std::placeholders::_1), + os.str()); + } + } catch (TException& exn) { + cout << "Error: " << exn.what() << endl; + } +} + +// Workaround for absense of C++11 "auto" keyword. +template <typename T> +bool print_eq(T expected, T actual) { + cout << "(" << actual << ")" << endl; + if (expected != actual) { + cout << "*** FAILED ***" << endl << "Expected: " << expected << " but got: " << actual << endl; + return false; + } + return true; +} + +#define BASETYPE_IDENTITY_TEST(func, value) \ + cout << #func "(" << value << ") = "; \ + try { \ + if (!print_eq(value, testClient.func(value))) \ + return_code |= ERR_BASETYPES; \ + } catch (TTransportException&) { \ + throw; \ + } catch (exception & ex) { \ + cout << "*** FAILED ***" << endl << ex.what() << endl; \ + return_code |= ERR_BASETYPES; \ + } + +int binary_test(ThriftTestClient& testClient, string::size_type siz); + +BOOST_CONSTEXPR_OR_CONST int ERR_BASETYPES = 1; +BOOST_CONSTEXPR_OR_CONST int ERR_STRUCTS = 2; +BOOST_CONSTEXPR_OR_CONST int ERR_CONTAINERS = 4; +BOOST_CONSTEXPR_OR_CONST int ERR_EXCEPTIONS = 8; +BOOST_CONSTEXPR_OR_CONST int ERR_UNKNOWN = 64; + +int main(int argc, char** argv) { + cout.precision(19); + + string testDir = boost::filesystem::system_complete(argv[0]).parent_path().parent_path().parent_path().string(); + string caPath = testDir + "/keys/CA.pem"; + string certPath = testDir + "/keys/client.crt"; + string keyPath = testDir + "/keys/client.key"; + +#if _WIN32 + transport::TWinsockSingleton::create(); +#endif + string host = "localhost"; + int port = 9090; + int numTests = 1; + bool ssl = false; + bool zlib = false; + string transport_type = "buffered"; + string protocol_type = "binary"; + string domain_socket = ""; + bool abstract_namespace = false; + bool noinsane = false; + + int return_code = 0; + + boost::program_options::options_description desc("Allowed options"); + desc.add_options() + ("help,h", "produce help message") + ("host", + boost::program_options::value<string>(&host)->default_value(host), + "Host to connect") + ("port", + boost::program_options::value<int>(&port)->default_value(port), + "Port number to connect") + ("domain-socket", + boost::program_options::value<string>(&domain_socket)->default_value(domain_socket), + "Domain Socket (e.g. /tmp/ThriftTest.thrift), instead of host and port") + ("abstract-namespace", + "Look for the domain socket in the Abstract Namespace" + " (no connection with filesystem pathnames)") + ("transport", + boost::program_options::value<string>(&transport_type)->default_value(transport_type), + "Transport: buffered, framed, http, evhttp, zlib") + ("protocol", + boost::program_options::value<string>(&protocol_type)->default_value(protocol_type), + "Protocol: binary, compact, header, json, multi, multic, multih, multij") + ("ssl", + "Encrypted Transport using SSL") + ("zlib", + "Wrap Transport with Zlib") + ("testloops,n", + boost::program_options::value<int>(&numTests)->default_value(numTests), + "Number of Tests") + ("noinsane", + "Do not run insanity test"); + + boost::program_options::variables_map vm; + boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), vm); + boost::program_options::notify(vm); + + if (vm.count("help")) { + cout << desc << endl; + return ERR_UNKNOWN; + } + + try { + if (!protocol_type.empty()) { + if (protocol_type == "binary") { + } else if (protocol_type == "compact") { + } else if (protocol_type == "header") { + } else if (protocol_type == "json") { + } else if (protocol_type == "multi") { + } else if (protocol_type == "multic") { + } else if (protocol_type == "multih") { + } else if (protocol_type == "multij") { + } else { + throw invalid_argument("Unknown protocol type " + protocol_type); + } + } + + if (!transport_type.empty()) { + if (transport_type == "buffered") { + } else if (transport_type == "framed") { + } else if (transport_type == "http") { + } else if (transport_type == "evhttp") { + } else if (transport_type == "zlib") { + // crosstest will pass zlib as a transport and as a flag right now.. + } else { + throw invalid_argument("Unknown transport type " + transport_type); + } + } + + } catch (exception& e) { + cerr << e.what() << endl; + cout << desc << endl; + return ERR_UNKNOWN; + } + + if (vm.count("ssl")) { + ssl = true; + } + + if (vm.count("zlib")) { + zlib = true; + } + + if (vm.count("abstract-namespace")) { + abstract_namespace = true; + } + + if (vm.count("noinsane")) { + noinsane = true; + } + + // THRIFT-4164: The factory MUST outlive any sockets it creates for correct behavior! + std::shared_ptr<TSSLSocketFactory> factory; + std::shared_ptr<TSocket> socket; + std::shared_ptr<TTransport> transport; + std::shared_ptr<TProtocol> protocol; + std::shared_ptr<TProtocol> protocol2; // SecondService for multiplexed + + if (ssl) { + cout << "Client Certificate File: " << certPath << endl; + cout << "Client Key File: " << keyPath << endl; + cout << "CA File: " << caPath << endl; + + factory = std::shared_ptr<TSSLSocketFactory>(new TSSLSocketFactory()); + factory->ciphers("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"); + factory->loadTrustedCertificates(caPath.c_str()); + factory->loadCertificate(certPath.c_str()); + factory->loadPrivateKey(keyPath.c_str()); + factory->authenticate(true); + socket = factory->createSocket(host, port); + } else { + if (domain_socket != "") { + if (abstract_namespace) { + std::string abstract_socket("\0", 1); + abstract_socket += domain_socket; + socket = std::shared_ptr<TSocket>(new TSocket(abstract_socket)); + } else { + socket = std::shared_ptr<TSocket>(new TSocket(domain_socket)); + } + port = 0; + } else { + socket = std::shared_ptr<TSocket>(new TSocket(host, port)); + } + } + + if (transport_type.compare("http") == 0) { + transport = std::make_shared<THttpClient>(socket, host, "/service"); + } else if (transport_type.compare("framed") == 0) { + transport = std::make_shared<TFramedTransport>(socket); + } else { + transport = std::make_shared<TBufferedTransport>(socket); + } + + if (zlib) { + transport = std::make_shared<TZlibTransport>(transport); + } + + if (protocol_type == "json" || protocol_type == "multij") { + typedef TPedanticProtocol<TJSONProtocol> TPedanticJSONProtocol; + protocol = std::make_shared<TPedanticJSONProtocol>(transport); + } else if (protocol_type == "compact" || protocol_type == "multic") { + typedef TPedanticProtocol<TCompactProtocol> TPedanticCompactProtocol; + protocol = std::make_shared<TPedanticCompactProtocol>(transport); + } else if (protocol_type == "header" || protocol_type == "multih") { + typedef TPedanticProtocol<THeaderProtocol> TPedanticHeaderProtocol; + protocol = std::make_shared<TPedanticHeaderProtocol>(transport); + } else { + typedef TPedanticProtocol<TBinaryProtocol> TPedanticBinaryProtocol; + protocol = std::make_shared<TPedanticBinaryProtocol>(transport); + } + + if (boost::starts_with(protocol_type, "multi")) { + protocol2 = std::make_shared<TMultiplexedProtocol>(protocol, "SecondService"); + // we don't need access to the original protocol any more, so... + protocol = std::make_shared<TMultiplexedProtocol>(protocol, "ThriftTest"); + } + + // Connection info + cout << "Connecting (" << transport_type << "/" << protocol_type << ") to: "; + if (abstract_namespace) { + cout << '@'; + } + cout << domain_socket; + if (port != 0) { + cout << host << ":" << port; + } + cout << endl; + + if (transport_type.compare("evhttp") == 0) { + event_base* base = event_base_new(); + cout << "Libevent Version: " << event_get_version() << endl; + cout << "Libevent Method: " << event_base_get_method(base) << endl; +#if LIBEVENT_VERSION_NUMBER >= 0x02000000 + cout << "Libevent Features: 0x" << hex << event_base_get_features(base) << endl; +#endif + + std::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory()); + + std::shared_ptr<TAsyncChannel> channel( + new TEvhttpClientChannel(host.c_str(), "/", host.c_str(), port, base)); + ThriftTestCobClient* client = new ThriftTestCobClient(channel, protocolFactory.get()); + client->testVoid(std::bind(testVoid_clientReturn, + base, + std::placeholders::_1)); + + event_base_loop(base, 0); + return 0; + } + + ThriftTestClient testClient(protocol); + + uint64_t time_min = 0; + uint64_t time_max = 0; + uint64_t time_tot = 0; + + int test = 0; + for (test = 0; test < numTests; ++test) { + + try { + transport->open(); + } catch (TTransportException& ex) { + cout << "Connect failed: " << ex.what() << endl; + return ERR_UNKNOWN; + } + + /** + * CONNECT TEST + */ + printf("Test #%d, connect %s:%d\n", test + 1, host.c_str(), port); + + uint64_t start = now(); + + /** + * VOID TEST + */ + try { + cout << "testVoid()" << flush; + testClient.testVoid(); + cout << " = void" << endl; + } catch (TTransportException&) { + // Stop here if transport got broken + throw; + } catch (exception& ex) { + cout << "*** FAILED ***" << endl << ex.what() << endl; + return_code |= ERR_BASETYPES; + } + + /** + * STRING TEST + */ + cout << "testString(\"Test\")" << flush; + string s; + testClient.testString(s, "Test"); + cout << " = " << s << endl; + if (s != "Test") { + cout << "*** FAILED ***" << endl; + return_code |= ERR_BASETYPES; + } + + // + // Multiplexed protocol - call another service method + // in the middle of the ThriftTest + // + if (boost::starts_with(protocol_type, "multi")) { + SecondServiceClient ssc(protocol2); + // transport is already open... + + try { + cout << "secondService.secondTestString(\"foo\") => " << flush; + std::string result; + ssc.secondtestString(result, "foo"); + cout << "{" << result << "}" << endl; + } catch (std::exception& e) { + cout << " *** FAILED *** " << e.what() << endl; + return_code |= ERR_EXCEPTIONS; + } + } + + try { +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable : 4566 ) +#endif + string str( + "}{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ú, 粵語"); +#ifdef _MSC_VER +#pragma warning( pop ) +#endif + cout << "testString(" << str << ") = " << flush; + testClient.testString(s, str); + cout << s << endl; + if (s != str) { + cout.imbue(locale("en_US.UTF8")); + cout << "*** FAILED ***" << endl << "Expected string: " << str << " but got: " << s << endl << "CLEAR"; + return_code |= ERR_BASETYPES; + } + } catch (TTransportException&) { + throw; + } catch (exception& ex) { + cout << "*** FAILED ***" << endl << ex.what() << endl; + return_code |= ERR_BASETYPES; + return return_code; + } + try { + string str( + "quote: \" backslash:" + " forwardslash-escaped: \\/ " + " 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: ]] \"]] \\\" }}}{ [[[ "); + cout << "testString(" << str << ") = " << flush; + testClient.testString(s, str); + cout << s << endl; + if (s != str) { + cout.imbue(locale("en_US.UTF8")); + cout << "*** FAILED ***" << endl + << "Expected string: " << str << " but got: " << s << endl + << "CLEAR"; + ; + return_code |= ERR_BASETYPES; + } + } catch (TTransportException&) { + throw; + } catch (exception& ex) { + cout << "*** FAILED ***" << endl << ex.what() << endl; + return_code |= ERR_BASETYPES; + return return_code; + } + + /** + * BOOL TEST + */ + cout << boolalpha; + BASETYPE_IDENTITY_TEST(testBool, true); + BASETYPE_IDENTITY_TEST(testBool, false); + + /** + * BYTE TEST + */ + BASETYPE_IDENTITY_TEST(testByte, (int8_t)0); + BASETYPE_IDENTITY_TEST(testByte, (int8_t)-1); + BASETYPE_IDENTITY_TEST(testByte, (int8_t)42); + BASETYPE_IDENTITY_TEST(testByte, (int8_t)-42); + BASETYPE_IDENTITY_TEST(testByte, (int8_t)127); + BASETYPE_IDENTITY_TEST(testByte, (int8_t)-128); + + /** + * I32 TEST + */ + BASETYPE_IDENTITY_TEST(testI32, 0); + BASETYPE_IDENTITY_TEST(testI32, -1); + BASETYPE_IDENTITY_TEST(testI32, 190000013); + BASETYPE_IDENTITY_TEST(testI32, -190000013); + BASETYPE_IDENTITY_TEST(testI32, (numeric_limits<int32_t>::max)()); + BASETYPE_IDENTITY_TEST(testI32, (numeric_limits<int32_t>::min)()); + + /** + * I64 TEST + */ + BASETYPE_IDENTITY_TEST(testI64, (int64_t)0); + BASETYPE_IDENTITY_TEST(testI64, (int64_t)-1); + BASETYPE_IDENTITY_TEST(testI64, (int64_t)7000000000000000123LL); + BASETYPE_IDENTITY_TEST(testI64, (int64_t)-7000000000000000123LL); + BASETYPE_IDENTITY_TEST(testI64, (int64_t)pow(static_cast<double>(2LL), 32)); + BASETYPE_IDENTITY_TEST(testI64, (int64_t)-pow(static_cast<double>(2LL), 32)); + BASETYPE_IDENTITY_TEST(testI64, (int64_t)pow(static_cast<double>(2LL), 32) + 1); + BASETYPE_IDENTITY_TEST(testI64, (int64_t)-pow(static_cast<double>(2LL), 32) - 1); + BASETYPE_IDENTITY_TEST(testI64, (numeric_limits<int64_t>::max)()); + BASETYPE_IDENTITY_TEST(testI64, (numeric_limits<int64_t>::min)()); + + /** + * DOUBLE TEST + */ + // Comparing double values with plain equality because Thrift handles full precision of double + BASETYPE_IDENTITY_TEST(testDouble, 0.0); + BASETYPE_IDENTITY_TEST(testDouble, -1.0); + BASETYPE_IDENTITY_TEST(testDouble, -5.2098523); + BASETYPE_IDENTITY_TEST(testDouble, -0.000341012439638598279); + BASETYPE_IDENTITY_TEST(testDouble, pow(static_cast<double>(2), 32)); + BASETYPE_IDENTITY_TEST(testDouble, pow(static_cast<double>(2), 32) + 1); + BASETYPE_IDENTITY_TEST(testDouble, pow(static_cast<double>(2), 53) - 1); + BASETYPE_IDENTITY_TEST(testDouble, -pow(static_cast<double>(2), 32)); + BASETYPE_IDENTITY_TEST(testDouble, -pow(static_cast<double>(2), 32) - 1); + BASETYPE_IDENTITY_TEST(testDouble, -pow(static_cast<double>(2), 53) + 1); + + try { + double expected = pow(static_cast<double>(10), 307); + cout << "testDouble(" << expected << ") = " << flush; + double actual = testClient.testDouble(expected); + cout << "(" << actual << ")" << endl; + if (expected - actual > pow(static_cast<double>(10), 292)) { + cout << "*** FAILED ***" << endl + << "Expected: " << expected << " but got: " << actual << endl; + } + } catch (TTransportException&) { + throw; + } catch (exception& ex) { + cout << "*** FAILED ***" << endl << ex.what() << endl; + return_code |= ERR_BASETYPES; + } + + try { + double expected = pow(static_cast<double>(10), -292); + cout << "testDouble(" << expected << ") = " << flush; + double actual = testClient.testDouble(expected); + cout << "(" << actual << ")" << endl; + if (expected - actual > pow(static_cast<double>(10), -307)) { + cout << "*** FAILED ***" << endl + << "Expected: " << expected << " but got: " << actual << endl; + } + } catch (TTransportException&) { + throw; + } catch (exception& ex) { + cout << "*** FAILED ***" << endl << ex.what() << endl; + return_code |= ERR_BASETYPES; + } + + /** + * BINARY TEST + */ + for (string::size_type i = 0; i < 131073 && !return_code; ) { + return_code |= binary_test(testClient, i); + if (i > 0) { i *= 2; } else { ++i; } + } + + + /** + * STRUCT TEST + */ + cout << "testStruct({\"Zero\", 1, -3, -5})" << flush; + Xtruct out; + out.string_thing = "Zero"; + out.byte_thing = 1; + out.i32_thing = -3; + out.i64_thing = -5; + Xtruct in; + testClient.testStruct(in, out); + printf(" = {\"%s\", %d, %d, %" PRId64 "}\n", + in.string_thing.c_str(), + (int)in.byte_thing, + in.i32_thing, + in.i64_thing); + if (in != out) { + cout << "*** FAILED ***" << endl; + return_code |= ERR_STRUCTS; + } + + /** + * NESTED STRUCT TEST + */ + cout << "testNest({1, {\"Zero\", 1, -3, -5}), 5}" << flush; + Xtruct2 out2; + out2.byte_thing = 1; + out2.struct_thing = out; + out2.i32_thing = 5; + Xtruct2 in2; + testClient.testNest(in2, out2); + in = in2.struct_thing; + printf(" = {%d, {\"%s\", %d, %d, %" PRId64 "}, %d}\n", + in2.byte_thing, + in.string_thing.c_str(), + (int)in.byte_thing, + in.i32_thing, + in.i64_thing, + in2.i32_thing); + if (in2 != out2) { + cout << "*** FAILED ***" << endl; + return_code |= ERR_STRUCTS; + } + + /** + * MAP TEST + */ + map<int32_t, int32_t> mapout; + for (int32_t i = 0; i < 5; ++i) { + mapout.insert(make_pair(i, i - 10)); + } + cout << "testMap({" << flush; + map<int32_t, int32_t>::const_iterator m_iter; + bool first = true; + for (m_iter = mapout.begin(); m_iter != mapout.end(); ++m_iter) { + if (first) { + first = false; + } else { + cout << ","; + } + cout << m_iter->first << " => " << m_iter->second; + } + cout << "})"; + map<int32_t, int32_t> mapin; + testClient.testMap(mapin, mapout); + cout << " = {"; + first = true; + for (m_iter = mapin.begin(); m_iter != mapin.end(); ++m_iter) { + if (first) { + first = false; + } else { + cout << ","; + } + cout << m_iter->first << " => " << m_iter->second; + } + cout << "}" << endl; + if (mapin != mapout) { + cout << "*** FAILED ***" << endl; + return_code |= ERR_CONTAINERS; + } + + /** + * STRING MAP TEST + */ + cout << "testStringMap({a => 2, b => blah, some => thing}) = {" << flush; + map<string, string> smapin; + map<string, string> smapout; + smapin["a"] = "2"; + smapin["b"] = "blah"; + smapin["some"] = "thing"; + try { + testClient.testStringMap(smapout, smapin); + first = true; + for (map<string, string>::const_iterator it = smapout.begin(); it != smapout.end(); ++it) { + if (first) + cout << ","; + else + first = false; + cout << it->first << " => " << it->second; + } + cout << "}" << endl; + if (smapin != smapout) { + cout << "*** FAILED ***" << endl; + return_code |= ERR_CONTAINERS; + } + } catch (TTransportException&) { + throw; + } catch (exception& ex) { + cout << "*** FAILED ***" << endl << ex.what() << endl; + return_code |= ERR_CONTAINERS; + } + + /** + * SET TEST + */ + set<int32_t> setout; + for (int32_t i = -2; i < 3; ++i) { + setout.insert(i); + } + cout << "testSet({" << flush; + set<int32_t>::const_iterator s_iter; + first = true; + for (s_iter = setout.begin(); s_iter != setout.end(); ++s_iter) { + if (first) { + first = false; + } else { + cout << ","; + } + cout << *s_iter; + } + cout << "})"; + set<int32_t> setin; + testClient.testSet(setin, setout); + cout << " = {"; + first = true; + for (s_iter = setin.begin(); s_iter != setin.end(); ++s_iter) { + if (first) { + first = false; + } else { + cout << ","; + } + cout << *s_iter; + } + cout << "}" << endl; + if (setin != setout) { + cout << "*** FAILED ***" << endl; + return_code |= ERR_CONTAINERS; + } + + /** + * LIST TEST + */ + cout << "testList(empty)" << flush; + try { + vector<int32_t> listout; + testClient.testList(listout, vector<int32_t>()); + if (!listout.empty()) { + cout << "*** FAILED ***" << endl; + cout << "invalid length: " << listout.size() << endl; + return_code |= ERR_CONTAINERS; + } + } catch (TTransportException&) { + throw; + } catch (exception& ex) { + cout << "*** FAILED ***" << endl << ex.what() << endl; + return_code |= ERR_CONTAINERS; + } + try { + vector<int32_t> listout; + for (int32_t i = -2; i < 3; ++i) { + listout.push_back(i); + } + cout << "testList({" << flush; + vector<int32_t>::const_iterator l_iter; + first = true; + for (l_iter = listout.begin(); l_iter != listout.end(); ++l_iter) { + if (first) { + first = false; + } else { + cout << ","; + } + cout << *l_iter; + } + cout << "})"; + vector<int32_t> listin; + testClient.testList(listin, listout); + cout << " = {"; + first = true; + for (l_iter = listin.begin(); l_iter != listin.end(); ++l_iter) { + if (first) { + first = false; + } else { + cout << ","; + } + cout << *l_iter; + } + cout << "}" << endl; + if (listin != listout) { + cout << "*** FAILED ***" << endl; + return_code |= ERR_CONTAINERS; + } + } catch (TTransportException&) { + throw; + } catch (exception& ex) { + cout << "*** FAILED ***" << endl << ex.what() << endl; + return_code |= ERR_CONTAINERS; + } + + /** + * ENUM TEST + */ + cout << "testEnum(ONE)" << flush; + Numberz::type ret = testClient.testEnum(Numberz::ONE); + cout << " = " << ret << endl; + if (ret != Numberz::ONE) { + cout << "*** FAILED ***" << endl; + return_code |= ERR_STRUCTS; + } + + cout << "testEnum(TWO)" << flush; + ret = testClient.testEnum(Numberz::TWO); + cout << " = " << ret << endl; + if (ret != Numberz::TWO) { + cout << "*** FAILED ***" << endl; + return_code |= ERR_STRUCTS; + } + + cout << "testEnum(THREE)" << flush; + ret = testClient.testEnum(Numberz::THREE); + cout << " = " << ret << endl; + if (ret != Numberz::THREE) { + cout << "*** FAILED ***" << endl; + return_code |= ERR_STRUCTS; + } + + cout << "testEnum(FIVE)" << flush; + ret = testClient.testEnum(Numberz::FIVE); + cout << " = " << ret << endl; + if (ret != Numberz::FIVE) { + cout << "*** FAILED ***" << endl; + return_code |= ERR_STRUCTS; + } + + cout << "testEnum(EIGHT)" << flush; + ret = testClient.testEnum(Numberz::EIGHT); + cout << " = " << ret << endl; + if (ret != Numberz::EIGHT) { + cout << "*** FAILED ***" << endl; + return_code |= ERR_STRUCTS; + } + + /** + * TYPEDEF TEST + */ + cout << "testTypedef(309858235082523)" << flush; + UserId uid = testClient.testTypedef(309858235082523LL); + cout << " = " << uid << endl; + if (uid != 309858235082523LL) { + cout << "*** FAILED ***" << endl; + return_code |= ERR_STRUCTS; + } + + /** + * NESTED MAP TEST + */ + cout << "testMapMap(1)" << flush; + map<int32_t, map<int32_t, int32_t> > mm; + testClient.testMapMap(mm, 1); + cout << " = {"; + map<int32_t, map<int32_t, int32_t> >::const_iterator mi; + for (mi = mm.begin(); mi != mm.end(); ++mi) { + printf("%d => {", mi->first); + map<int32_t, int32_t>::const_iterator mi2; + for (mi2 = mi->second.begin(); mi2 != mi->second.end(); ++mi2) { + cout << mi2->first << " => " << mi2->second; + } + cout << "}, "; + } + cout << "}" << endl; + if (mm.size() != 2 || + mm[-4][-4] != -4 || + mm[-4][-3] != -3 || + mm[-4][-2] != -2 || + mm[-4][-1] != -1 || + mm[4][4] != 4 || + mm[4][3] != 3 || + mm[4][2] != 2 || + mm[4][1] != 1) { + cout << "*** FAILED ***" << endl; + return_code |= ERR_CONTAINERS; + } + + /** + * INSANITY TEST + */ + if (!noinsane) { + Insanity insane; + insane.userMap.insert(make_pair(Numberz::FIVE, 5)); + insane.userMap.insert(make_pair(Numberz::EIGHT, 8)); + Xtruct truck; + truck.string_thing = "Goodbye4"; + truck.byte_thing = 4; + truck.i32_thing = 4; + truck.i64_thing = 4; + Xtruct truck2; + truck2.string_thing = "Hello2"; + truck2.byte_thing = 2; + truck2.i32_thing = 2; + truck2.i64_thing = 2; + insane.xtructs.push_back(truck); + insane.xtructs.push_back(truck2); + cout << "testInsanity()" << flush; + map<UserId, map<Numberz::type, Insanity> > whoa; + testClient.testInsanity(whoa, insane); + cout << " = {"; + map<UserId, map<Numberz::type, Insanity> >::const_iterator i_iter; + for (i_iter = whoa.begin(); i_iter != whoa.end(); ++i_iter) { + printf("%" PRId64 " => {", i_iter->first); + map<Numberz::type, Insanity>::const_iterator i2_iter; + for (i2_iter = i_iter->second.begin(); i2_iter != i_iter->second.end(); ++i2_iter) { + printf("%d => {", i2_iter->first); + map<Numberz::type, UserId> userMap = i2_iter->second.userMap; + map<Numberz::type, UserId>::const_iterator um; + cout << "{"; + for (um = userMap.begin(); um != userMap.end(); ++um) { + cout << um->first << " => " << um->second; + } + cout << "}, "; + + vector<Xtruct> xtructs = i2_iter->second.xtructs; + vector<Xtruct>::const_iterator x; + cout << "{"; + for (x = xtructs.begin(); x != xtructs.end(); ++x) { + printf("{\"%s\", %d, %d, %" PRId64 "}, ", + x->string_thing.c_str(), + (int)x->byte_thing, + x->i32_thing, + x->i64_thing); + } + cout << "}"; + + cout << "}, "; + } + cout << "}, "; + } + cout << "}" << endl; + bool failed = false; + map<UserId, map<Numberz::type, Insanity> >::const_iterator it1 = whoa.find(UserId(1)); + if (whoa.size() != 2) { + failed = true; + } + if (it1 == whoa.end()) { + failed = true; + } else { + auto it12 = it1->second.find(Numberz::TWO); + if (it12 == it1->second.end() || it12->second != insane) { + failed = true; + } + auto it13 = it1->second.find(Numberz::THREE); + if (it13 == it1->second.end() || it13->second != insane) { + failed = true; + } + } + map<UserId, map<Numberz::type, Insanity> >::const_iterator it2 = whoa.find(UserId(2)); + if (it2 == whoa.end()) { + failed = true; + } else { + auto it26 = it2->second.find(Numberz::SIX); + if (it26 == it2->second.end() || it26->second != Insanity()) { + failed = true; + } + } + if (failed) { + cout << "*** FAILED ***" << endl; + return_code |= ERR_STRUCTS; + } + } + + /** + * MULTI TEST + */ + cout << "testMulti()" << endl; + try { + map<int16_t, string> mul_map; + Xtruct mul_result; + mul_map[1] = "blah"; + mul_map[2] = "thing"; + testClient.testMulti(mul_result, 42, 4242, 424242, mul_map, Numberz::EIGHT, UserId(24)); + Xtruct xxs; + xxs.string_thing = "Hello2"; + xxs.byte_thing = 42; + xxs.i32_thing = 4242; + xxs.i64_thing = 424242; + if (mul_result != xxs) { + cout << "*** FAILED ***" << endl; + return_code |= ERR_STRUCTS; + } + } catch (TTransportException&) { + throw; + } catch (exception& ex) { + cout << "*** FAILED ***" << endl << ex.what() << endl; + return_code |= ERR_STRUCTS; + } + + /* test exception */ + + try { + cout << "testClient.testException(\"Xception\") =>" << flush; + testClient.testException("Xception"); + cout << " void\n*** FAILED ***" << endl; + return_code |= ERR_EXCEPTIONS; + + } catch (Xception& e) { + printf(" {%u, \"%s\"}\n", e.errorCode, e.message.c_str()); + } + + try { + cout << "testClient.testException(\"TException\") =>" << flush; + testClient.testException("TException"); + cout << " void\n*** FAILED ***" << endl; + return_code |= ERR_EXCEPTIONS; + + } catch (const TException&) { + cout << " Caught TException" << endl; + } + + try { + cout << "testClient.testException(\"success\") =>" << flush; + testClient.testException("success"); + cout << " void" << endl; + } catch (exception & ex) { \ + cout << "*** FAILED ***" << endl << ex.what() << endl; + return_code |= ERR_EXCEPTIONS; + } + + /* test multi exception */ + + try { + cout << "testClient.testMultiException(\"Xception\", \"test 1\") =>" << flush; + Xtruct result; + testClient.testMultiException(result, "Xception", "test 1"); + cout << " result\n*** FAILED ***" << endl; + return_code |= ERR_EXCEPTIONS; + } catch (Xception& e) { + printf(" {%u, \"%s\"}\n", e.errorCode, e.message.c_str()); + } + + try { + cout << "testClient.testMultiException(\"Xception2\", \"test 2\") =>" << flush; + Xtruct result; + testClient.testMultiException(result, "Xception2", "test 2"); + cout << " result\n*** FAILED ***" << endl; + return_code |= ERR_EXCEPTIONS; + + } catch (Xception2& e) { + printf(" {%u, {\"%s\"}}\n", e.errorCode, e.struct_thing.string_thing.c_str()); + } + + try { + cout << "testClient.testMultiException(\"success\", \"test 3\") =>" << flush; + Xtruct result; + testClient.testMultiException(result, "success", "test 3"); + printf(" {{\"%s\"}}\n", result.string_thing.c_str()); + } catch (exception & ex) { \ + cout << "*** FAILED ***" << endl << ex.what() << endl; + return_code |= ERR_EXCEPTIONS; + } + + /* test oneway void */ + { + cout << "testClient.testOneway(1) =>" << flush; + uint64_t startOneway = now(); + testClient.testOneway(1); + uint64_t elapsed = now() - startOneway; + if (elapsed > 200 * 1000) { // 0.2 seconds + printf("*** FAILED *** - took %.2f ms\n", (double)elapsed / 1000.0); + return_code |= ERR_BASETYPES; + } else { + printf(" success - took %.2f ms\n", (double)elapsed / 1000.0); + } + } + + /** + * redo a simple test after the oneway to make sure we aren't "off by one" -- + * if the server treated oneway void like normal void, this next test will + * fail since it will get the void confirmation rather than the correct + * result. In this circumstance, the client will throw the exception: + * + * TApplicationException: Wrong method namea + */ + /** + * I32 TEST + */ + cout << "re-test testI32(-1)" << flush; + int i32 = testClient.testI32(-1); + cout << " = " << i32 << endl; + if (i32 != -1) + return_code |= ERR_BASETYPES; + + cout << endl << "All tests done." << endl << flush; + + uint64_t stop = now(); + uint64_t tot = stop - start; + + cout << "Total time: " << stop - start << " us" << endl; + + time_tot += tot; + if (time_min == 0 || tot < time_min) { + time_min = tot; + } + if (tot > time_max) { + time_max = tot; + } + + cout << flush; + transport->close(); + } + + + uint64_t time_avg = time_tot / numTests; + + cout << "Min time: " << time_min << " us" << endl; + cout << "Max time: " << time_max << " us" << endl; + cout << "Avg time: " << time_avg << " us" << endl; + + return return_code; +} + +void binary_fill(std::string& str, string::size_type siz) +{ + static const signed char bin_data[256] + = {-128, -127, -126, -125, -124, -123, -122, -121, -120, -119, -118, -117, -116, -115, -114, + -113, -112, -111, -110, -109, -108, -107, -106, -105, -104, -103, -102, -101, -100, -99, + -98, -97, -96, -95, -94, -93, -92, -91, -90, -89, -88, -87, -86, -85, -84, + -83, -82, -81, -80, -79, -78, -77, -76, -75, -74, -73, -72, -71, -70, -69, + -68, -67, -66, -65, -64, -63, -62, -61, -60, -59, -58, -57, -56, -55, -54, + -53, -52, -51, -50, -49, -48, -47, -46, -45, -44, -43, -42, -41, -40, -39, + -38, -37, -36, -35, -34, -33, -32, -31, -30, -29, -28, -27, -26, -25, -24, + -23, -22, -21, -20, -19, -18, -17, -16, -15, -14, -13, -12, -11, -10, -9, + -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, + 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, + 127}; + + str.resize(siz); + char *ptr = &str[0]; + string::size_type pos = 0; + for (string::size_type i = 0; i < siz; ++i) + { + if (pos == 255) { pos = 0; } else { ++pos; } + *ptr++ = bin_data[pos]; + } +} + +int binary_test(ThriftTestClient& testClient, string::size_type siz) +{ + string bin_request; + string bin_result; + + cout << "testBinary(siz = " << siz << ")" << endl; + binary_fill(bin_request, siz); + try { + testClient.testBinary(bin_result, bin_request); + + if (bin_request.size() != bin_result.size()) { + cout << "*** FAILED: request size " << bin_request.size() << "; result size " << bin_result.size() << endl; + return ERR_BASETYPES; + } + + for (string::size_type i = 0; i < siz; ++i) { + if (bin_request.at(i) != bin_result.at(i)) { + cout << "*** FAILED: at position " << i << " request[i] is h" << hex << bin_request.at(i) << " result[i] is h" << hex << bin_result.at(i) << endl; + return ERR_BASETYPES; + } + } + } catch (TTransportException&) { + throw; + } catch (exception& ex) { + cout << "*** FAILED ***" << endl << ex.what() << endl; + return ERR_BASETYPES; + } + + return 0; +} diff --git a/src/jaegertracing/thrift/test/cpp/src/TestServer.cpp b/src/jaegertracing/thrift/test/cpp/src/TestServer.cpp new file mode 100644 index 000000000..8d5b4d93e --- /dev/null +++ b/src/jaegertracing/thrift/test/cpp/src/TestServer.cpp @@ -0,0 +1,845 @@ +/* + * 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. + */ + +#include <thrift/async/TAsyncBufferProcessor.h> +#include <thrift/async/TAsyncProtocolProcessor.h> +#include <thrift/async/TEvhttpServer.h> +#include <thrift/concurrency/ThreadFactory.h> +#include <thrift/concurrency/ThreadManager.h> +#include <thrift/processor/TMultiplexedProcessor.h> +#include <thrift/protocol/TBinaryProtocol.h> +#include <thrift/protocol/TCompactProtocol.h> +#include <thrift/protocol/THeaderProtocol.h> +#include <thrift/protocol/TJSONProtocol.h> +#include <thrift/server/TNonblockingServer.h> +#include <thrift/server/TSimpleServer.h> +#include <thrift/server/TThreadPoolServer.h> +#include <thrift/server/TThreadedServer.h> +#include <thrift/transport/THttpServer.h> +#include <thrift/transport/THttpTransport.h> +#include <thrift/transport/TNonblockingSSLServerSocket.h> +#include <thrift/transport/TNonblockingServerSocket.h> +#include <thrift/transport/TSSLServerSocket.h> +#include <thrift/transport/TSSLSocket.h> +#include <thrift/transport/TServerSocket.h> +#include <thrift/transport/TTransportUtils.h> +#include <thrift/transport/TZlibTransport.h> + +#include "SecondService.h" +#include "ThriftTest.h" + +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif +#ifdef HAVE_INTTYPES_H +#include <inttypes.h> +#endif +#ifdef HAVE_SIGNAL_H +#include <signal.h> +#endif + +#include <iostream> +#include <stdexcept> +#include <sstream> + +#include <boost/algorithm/string.hpp> +#include <boost/program_options.hpp> +#include <boost/filesystem.hpp> + +#if _WIN32 +#include <thrift/windows/TWinsockSingleton.h> +#endif + +using namespace std; + +using namespace apache::thrift; +using namespace apache::thrift::async; +using namespace apache::thrift::concurrency; +using namespace apache::thrift::protocol; +using namespace apache::thrift::transport; +using namespace apache::thrift::server; + +using namespace thrift::test; + +// to handle a controlled shutdown, signal handling is mandatory +#ifdef HAVE_SIGNAL_H +apache::thrift::concurrency::Monitor gMonitor; +void signal_handler(int signum) +{ + if (signum == SIGINT) { + gMonitor.notifyAll(); + } +} +#endif + +class TestHandler : public ThriftTestIf { +public: + TestHandler() = default; + + void testVoid() override { printf("testVoid()\n"); } + + void testString(string& out, const string& thing) override { + printf("testString(\"%s\")\n", thing.c_str()); + out = thing; + } + + bool testBool(const bool thing) override { + printf("testBool(%s)\n", thing ? "true" : "false"); + return thing; + } + + int8_t testByte(const int8_t thing) override { + printf("testByte(%d)\n", (int)thing); + return thing; + } + + int32_t testI32(const int32_t thing) override { + printf("testI32(%d)\n", thing); + return thing; + } + + int64_t testI64(const int64_t thing) override { + printf("testI64(%" PRId64 ")\n", thing); + return thing; + } + + double testDouble(const double thing) override { + printf("testDouble(%f)\n", thing); + return thing; + } + + void testBinary(std::string& _return, const std::string& thing) override { + std::ostringstream hexstr; + hexstr << std::hex << thing; + printf("testBinary(%lu: %s)\n", safe_numeric_cast<unsigned long>(thing.size()), hexstr.str().c_str()); + _return = thing; + } + + void testStruct(Xtruct& out, const Xtruct& thing) override { + printf("testStruct({\"%s\", %d, %d, %" PRId64 "})\n", + thing.string_thing.c_str(), + (int)thing.byte_thing, + thing.i32_thing, + thing.i64_thing); + out = thing; + } + + void testNest(Xtruct2& out, const Xtruct2& nest) override { + const Xtruct& thing = nest.struct_thing; + printf("testNest({%d, {\"%s\", %d, %d, %" PRId64 "}, %d})\n", + (int)nest.byte_thing, + thing.string_thing.c_str(), + (int)thing.byte_thing, + thing.i32_thing, + thing.i64_thing, + nest.i32_thing); + out = nest; + } + + void testMap(map<int32_t, int32_t>& out, const map<int32_t, int32_t>& thing) override { + printf("testMap({"); + map<int32_t, int32_t>::const_iterator m_iter; + bool first = true; + for (m_iter = thing.begin(); m_iter != thing.end(); ++m_iter) { + if (first) { + first = false; + } else { + printf(", "); + } + printf("%d => %d", m_iter->first, m_iter->second); + } + printf("})\n"); + out = thing; + } + + void testStringMap(map<std::string, std::string>& out, + const map<std::string, std::string>& thing) override { + printf("testMap({"); + map<std::string, std::string>::const_iterator m_iter; + bool first = true; + for (m_iter = thing.begin(); m_iter != thing.end(); ++m_iter) { + if (first) { + first = false; + } else { + printf(", "); + } + printf("%s => %s", (m_iter->first).c_str(), (m_iter->second).c_str()); + } + printf("})\n"); + out = thing; + } + + void testSet(set<int32_t>& out, const set<int32_t>& thing) override { + printf("testSet({"); + set<int32_t>::const_iterator s_iter; + bool first = true; + for (s_iter = thing.begin(); s_iter != thing.end(); ++s_iter) { + if (first) { + first = false; + } else { + printf(", "); + } + printf("%d", *s_iter); + } + printf("})\n"); + out = thing; + } + + void testList(vector<int32_t>& out, const vector<int32_t>& thing) override { + printf("testList({"); + vector<int32_t>::const_iterator l_iter; + bool first = true; + for (l_iter = thing.begin(); l_iter != thing.end(); ++l_iter) { + if (first) { + first = false; + } else { + printf(", "); + } + printf("%d", *l_iter); + } + printf("})\n"); + out = thing; + } + + Numberz::type testEnum(const Numberz::type thing) override { + printf("testEnum(%d)\n", thing); + return thing; + } + + UserId testTypedef(const UserId thing) override { + printf("testTypedef(%" PRId64 ")\n", thing); + return thing; + } + + void testMapMap(map<int32_t, map<int32_t, int32_t> >& mapmap, const int32_t hello) override { + printf("testMapMap(%d)\n", hello); + + map<int32_t, int32_t> pos; + map<int32_t, int32_t> neg; + for (int i = 1; i < 5; i++) { + pos.insert(make_pair(i, i)); + neg.insert(make_pair(-i, -i)); + } + + mapmap.insert(make_pair(4, pos)); + mapmap.insert(make_pair(-4, neg)); + } + + void testInsanity(map<UserId, map<Numberz::type, Insanity> >& insane, const Insanity& argument) override { + printf("testInsanity()\n"); + + Insanity looney; + map<Numberz::type, Insanity> first_map; + map<Numberz::type, Insanity> second_map; + + first_map.insert(make_pair(Numberz::TWO, argument)); + first_map.insert(make_pair(Numberz::THREE, argument)); + + second_map.insert(make_pair(Numberz::SIX, looney)); + + insane.insert(make_pair(1, first_map)); + insane.insert(make_pair(2, second_map)); + + printf("return"); + printf(" = {"); + map<UserId, map<Numberz::type, Insanity> >::const_iterator i_iter; + for (i_iter = insane.begin(); i_iter != insane.end(); ++i_iter) { + printf("%" PRId64 " => {", i_iter->first); + map<Numberz::type, Insanity>::const_iterator i2_iter; + for (i2_iter = i_iter->second.begin(); i2_iter != i_iter->second.end(); ++i2_iter) { + printf("%d => {", i2_iter->first); + map<Numberz::type, UserId> userMap = i2_iter->second.userMap; + map<Numberz::type, UserId>::const_iterator um; + printf("{"); + for (um = userMap.begin(); um != userMap.end(); ++um) { + printf("%d => %" PRId64 ", ", um->first, um->second); + } + printf("}, "); + + vector<Xtruct> xtructs = i2_iter->second.xtructs; + vector<Xtruct>::const_iterator x; + printf("{"); + for (x = xtructs.begin(); x != xtructs.end(); ++x) { + printf("{\"%s\", %d, %d, %" PRId64 "}, ", + x->string_thing.c_str(), + (int)x->byte_thing, + x->i32_thing, + x->i64_thing); + } + printf("}"); + + printf("}, "); + } + printf("}, "); + } + printf("}\n"); + } + + void testMulti(Xtruct& hello, + const int8_t arg0, + const int32_t arg1, + const int64_t arg2, + const std::map<int16_t, std::string>& arg3, + const Numberz::type arg4, + const UserId arg5) override { + (void)arg3; + (void)arg4; + (void)arg5; + + printf("testMulti()\n"); + + hello.string_thing = "Hello2"; + hello.byte_thing = arg0; + hello.i32_thing = arg1; + hello.i64_thing = (int64_t)arg2; + } + + void testException(const std::string& arg) override { + printf("testException(%s)\n", arg.c_str()); + if (arg.compare("Xception") == 0) { + Xception e; + e.errorCode = 1001; + e.message = arg; + throw e; + } else if (arg.compare("TException") == 0) { + apache::thrift::TException e; + throw e; + } else { + Xtruct result; + result.string_thing = arg; + return; + } + } + + void testMultiException(Xtruct& result, + const std::string& arg0, + const std::string& arg1) override { + + printf("testMultiException(%s, %s)\n", arg0.c_str(), arg1.c_str()); + + if (arg0.compare("Xception") == 0) { + Xception e; + e.errorCode = 1001; + e.message = "This is an Xception"; + throw e; + } else if (arg0.compare("Xception2") == 0) { + Xception2 e; + e.errorCode = 2002; + e.struct_thing.string_thing = "This is an Xception2"; + throw e; + } else { + result.string_thing = arg1; + return; + } + } + + void testOneway(const int32_t aNum) override { + printf("testOneway(%d): call received\n", aNum); + } +}; + +class SecondHandler : public SecondServiceIf +{ + public: + void secondtestString(std::string& result, const std::string& thing) override + { result = "testString(\"" + thing + "\")"; } +}; + +class TestProcessorEventHandler : public TProcessorEventHandler { + void* getContext(const char* fn_name, void* serverContext) override { + (void)serverContext; + return new std::string(fn_name); + } + void freeContext(void* ctx, const char* fn_name) override { + (void)fn_name; + delete static_cast<std::string*>(ctx); + } + void preRead(void* ctx, const char* fn_name) override { communicate("preRead", ctx, fn_name); } + void postRead(void* ctx, const char* fn_name, uint32_t bytes) override { + (void)bytes; + communicate("postRead", ctx, fn_name); + } + void preWrite(void* ctx, const char* fn_name) override { communicate("preWrite", ctx, fn_name); } + void postWrite(void* ctx, const char* fn_name, uint32_t bytes) override { + (void)bytes; + communicate("postWrite", ctx, fn_name); + } + void asyncComplete(void* ctx, const char* fn_name) override { + communicate("asyncComplete", ctx, fn_name); + } + void handlerError(void* ctx, const char* fn_name) override { + communicate("handlerError", ctx, fn_name); + } + + void communicate(const char* event, void* ctx, const char* fn_name) { + std::cout << event << ": " << *static_cast<std::string*>(ctx) << " = " << fn_name << std::endl; + } +}; + +class TestHandlerAsync : public ThriftTestCobSvIf { +public: + TestHandlerAsync(std::shared_ptr<TestHandler>& handler) : _delegate(handler) {} + ~TestHandlerAsync() override = default; + + void testVoid(std::function<void()> cob) override { + _delegate->testVoid(); + cob(); + } + + void testString(std::function<void(std::string const& _return)> cob, + const std::string& thing) override { + std::string res; + _delegate->testString(res, thing); + cob(res); + } + + void testBool(std::function<void(bool const& _return)> cob, const bool thing) override { + bool res = _delegate->testBool(thing); + cob(res); + } + + void testByte(std::function<void(int8_t const& _return)> cob, const int8_t thing) override { + int8_t res = _delegate->testByte(thing); + cob(res); + } + + void testI32(std::function<void(int32_t const& _return)> cob, const int32_t thing) override { + int32_t res = _delegate->testI32(thing); + cob(res); + } + + void testI64(std::function<void(int64_t const& _return)> cob, const int64_t thing) override { + int64_t res = _delegate->testI64(thing); + cob(res); + } + + void testDouble(std::function<void(double const& _return)> cob, const double thing) override { + double res = _delegate->testDouble(thing); + cob(res); + } + + void testBinary(std::function<void(std::string const& _return)> cob, + const std::string& thing) override { + std::string res; + _delegate->testBinary(res, thing); + cob(res); + } + + void testStruct(std::function<void(Xtruct const& _return)> cob, const Xtruct& thing) override { + Xtruct res; + _delegate->testStruct(res, thing); + cob(res); + } + + void testNest(std::function<void(Xtruct2 const& _return)> cob, const Xtruct2& thing) override { + Xtruct2 res; + _delegate->testNest(res, thing); + cob(res); + } + + void testMap(std::function<void(std::map<int32_t, int32_t> const& _return)> cob, + const std::map<int32_t, int32_t>& thing) override { + std::map<int32_t, int32_t> res; + _delegate->testMap(res, thing); + cob(res); + } + + void testStringMap( + std::function<void(std::map<std::string, std::string> const& _return)> cob, + const std::map<std::string, std::string>& thing) override { + std::map<std::string, std::string> res; + _delegate->testStringMap(res, thing); + cob(res); + } + + void testSet(std::function<void(std::set<int32_t> const& _return)> cob, + const std::set<int32_t>& thing) override { + std::set<int32_t> res; + _delegate->testSet(res, thing); + cob(res); + } + + void testList(std::function<void(std::vector<int32_t> const& _return)> cob, + const std::vector<int32_t>& thing) override { + std::vector<int32_t> res; + _delegate->testList(res, thing); + cob(res); + } + + void testEnum(std::function<void(Numberz::type const& _return)> cob, + const Numberz::type thing) override { + Numberz::type res = _delegate->testEnum(thing); + cob(res); + } + + void testTypedef(std::function<void(UserId const& _return)> cob, const UserId thing) override { + UserId res = _delegate->testTypedef(thing); + cob(res); + } + + void testMapMap( + std::function<void(std::map<int32_t, std::map<int32_t, int32_t> > const& _return)> cob, + const int32_t hello) override { + std::map<int32_t, std::map<int32_t, int32_t> > res; + _delegate->testMapMap(res, hello); + cob(res); + } + + void testInsanity( + std::function<void(std::map<UserId, std::map<Numberz::type, Insanity> > const& _return)> cob, + const Insanity& argument) override { + std::map<UserId, std::map<Numberz::type, Insanity> > res; + _delegate->testInsanity(res, argument); + cob(res); + } + + void testMulti(std::function<void(Xtruct const& _return)> cob, + const int8_t arg0, + const int32_t arg1, + const int64_t arg2, + const std::map<int16_t, std::string>& arg3, + const Numberz::type arg4, + const UserId arg5) override { + Xtruct res; + _delegate->testMulti(res, arg0, arg1, arg2, arg3, arg4, arg5); + cob(res); + } + + void testException( + std::function<void()> cob, + std::function<void(::apache::thrift::TDelayedException* _throw)> exn_cob, + const std::string& arg) override { + try { + _delegate->testException(arg); + } catch (const apache::thrift::TException& e) { + exn_cob(apache::thrift::TDelayedException::delayException(e)); + return; + } + cob(); + } + + void testMultiException( + std::function<void(Xtruct const& _return)> cob, + std::function<void(::apache::thrift::TDelayedException* _throw)> exn_cob, + const std::string& arg0, + const std::string& arg1) override { + Xtruct res; + try { + _delegate->testMultiException(res, arg0, arg1); + } catch (const apache::thrift::TException& e) { + exn_cob(apache::thrift::TDelayedException::delayException(e)); + return; + } + cob(res); + } + + void testOneway(std::function<void()> cob, const int32_t secondsToSleep) override { + _delegate->testOneway(secondsToSleep); + cob(); + } + +protected: + std::shared_ptr<TestHandler> _delegate; +}; + +namespace po = boost::program_options; + +int main(int argc, char** argv) { + + string testDir = boost::filesystem::system_complete(argv[0]).parent_path().parent_path().parent_path().string(); + string certPath = testDir + "/keys/server.crt"; + string keyPath = testDir + "/keys/server.key"; + +#if _WIN32 + transport::TWinsockSingleton::create(); +#endif + int port = 9090; + bool ssl = false; + bool zlib = false; + string transport_type = "buffered"; + string protocol_type = "binary"; + string server_type = "simple"; + string domain_socket = ""; + bool abstract_namespace = false; + size_t workers = 4; + int string_limit = 0; + int container_limit = 0; + + po::options_description desc("Allowed options"); + desc.add_options() + ("help,h", "produce help message") + ("port", po::value<int>(&port)->default_value(port), "Port number to listen") + ("domain-socket", po::value<string>(&domain_socket) ->default_value(domain_socket), "Unix Domain Socket (e.g. /tmp/ThriftTest.thrift)") + ("abstract-namespace", "Create the domain socket in the Abstract Namespace (no connection with filesystem pathnames)") + ("server-type", po::value<string>(&server_type)->default_value(server_type), "type of server, \"simple\", \"thread-pool\", \"threaded\", or \"nonblocking\"") + ("transport", po::value<string>(&transport_type)->default_value(transport_type), "transport: buffered, framed, http, zlib") + ("protocol", po::value<string>(&protocol_type)->default_value(protocol_type), "protocol: binary, compact, header, json, multi, multic, multih, multij") + ("ssl", "Encrypted Transport using SSL") + ("zlib", "Wrapped Transport using Zlib") + ("processor-events", "processor-events") + ("workers,n", po::value<size_t>(&workers)->default_value(workers), "Number of thread pools workers. Only valid for thread-pool server type") + ("string-limit", po::value<int>(&string_limit)) + ("container-limit", po::value<int>(&container_limit)); + + po::variables_map vm; + po::store(po::parse_command_line(argc, argv, desc), vm); + po::notify(vm); + + if (vm.count("help")) { + cout << desc << "\n"; + return 1; + } + + try { + if (!server_type.empty()) { + if (server_type == "simple") { + } else if (server_type == "thread-pool") { + } else if (server_type == "threaded") { + } else if (server_type == "nonblocking") { + } else { + throw invalid_argument("Unknown server type " + server_type); + } + } + + if (!protocol_type.empty()) { + if (protocol_type == "binary") { + } else if (protocol_type == "compact") { + } else if (protocol_type == "json") { + } else if (protocol_type == "header") { + } else if (protocol_type == "multi") { // multiplexed binary + } else if (protocol_type == "multic") { // multiplexed compact + } else if (protocol_type == "multih") { // multiplexed header + } else if (protocol_type == "multij") { // multiplexed json + } else { + throw invalid_argument("Unknown protocol type " + protocol_type); + } + } + + if (!transport_type.empty()) { + if (transport_type == "buffered") { + } else if (transport_type == "framed") { + } else if (transport_type == "http") { + } else if (transport_type == "zlib") { + // crosstester will pass zlib as a flag and a transport right now... + } else { + throw invalid_argument("Unknown transport type " + transport_type); + } + } + + } catch (std::exception& e) { + cerr << e.what() << endl; + cout << desc << "\n"; + return 1; + } + + if (vm.count("ssl")) { + ssl = true; + } + + if (vm.count("zlib")) { + zlib = true; + } + +#if defined(HAVE_SIGNAL_H) && defined(SIGPIPE) + if (ssl) { + signal(SIGPIPE, SIG_IGN); // for OpenSSL, otherwise we end abruptly + } +#endif + + if (vm.count("abstract-namespace")) { + abstract_namespace = true; + } + + // Dispatcher + std::shared_ptr<TProtocolFactory> protocolFactory; + if (protocol_type == "json" || protocol_type == "multij") { + std::shared_ptr<TProtocolFactory> jsonProtocolFactory(new TJSONProtocolFactory()); + protocolFactory = jsonProtocolFactory; + } else if (protocol_type == "compact" || protocol_type == "multic") { + auto *compactProtocolFactory = new TCompactProtocolFactoryT<TBufferBase>(); + compactProtocolFactory->setContainerSizeLimit(container_limit); + compactProtocolFactory->setStringSizeLimit(string_limit); + protocolFactory.reset(compactProtocolFactory); + } else if (protocol_type == "header" || protocol_type == "multih") { + std::shared_ptr<TProtocolFactory> headerProtocolFactory(new THeaderProtocolFactory()); + protocolFactory = headerProtocolFactory; + } else { + auto* binaryProtocolFactory = new TBinaryProtocolFactoryT<TBufferBase>(); + binaryProtocolFactory->setContainerSizeLimit(container_limit); + binaryProtocolFactory->setStringSizeLimit(string_limit); + protocolFactory.reset(binaryProtocolFactory); + } + + // Processors + std::shared_ptr<TestHandler> testHandler(new TestHandler()); + std::shared_ptr<TProcessor> testProcessor(new ThriftTestProcessor(testHandler)); + + if (vm.count("processor-events")) { + testProcessor->setEventHandler( + std::shared_ptr<TProcessorEventHandler>(new TestProcessorEventHandler())); + } + + // Transport + std::shared_ptr<TSSLSocketFactory> sslSocketFactory; + std::shared_ptr<TServerSocket> serverSocket; + + if (ssl) { + sslSocketFactory = std::shared_ptr<TSSLSocketFactory>(new TSSLSocketFactory()); + sslSocketFactory->loadCertificate(certPath.c_str()); + sslSocketFactory->loadPrivateKey(keyPath.c_str()); + sslSocketFactory->ciphers("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"); + if (server_type != "nonblocking") { + serverSocket = std::shared_ptr<TServerSocket>(new TSSLServerSocket(port, sslSocketFactory)); + } + } else { + if (domain_socket != "") { + if (abstract_namespace) { + std::string abstract_socket("\0", 1); + abstract_socket += domain_socket; + serverSocket = std::shared_ptr<TServerSocket>(new TServerSocket(abstract_socket)); + } else { + unlink(domain_socket.c_str()); + serverSocket = std::shared_ptr<TServerSocket>(new TServerSocket(domain_socket)); + } + port = 0; + } else { + serverSocket = std::shared_ptr<TServerSocket>(new TServerSocket(port)); + } + } + + // Factory + std::shared_ptr<TTransportFactory> transportFactory; + + if (transport_type == "http" && server_type != "nonblocking") { + transportFactory = std::make_shared<THttpServerTransportFactory>(); + } else if (transport_type == "framed") { + transportFactory = std::make_shared<TFramedTransportFactory>(); + } else { + transportFactory = std::make_shared<TBufferedTransportFactory>(); + } + + if (zlib) { + // hmm.. doesn't seem to be a way to make it wrap the others... + transportFactory = std::make_shared<TZlibTransportFactory>(); + } + + // Server Info + cout << "Starting \"" << server_type << "\" server (" << transport_type << "/" << protocol_type + << ") listen on: "; + if (abstract_namespace) { + cout << '@'; + } + cout << domain_socket; + if (port != 0) { + cout << port; + } + cout << endl; + + // Multiplexed Processor if needed + if (boost::starts_with(protocol_type, "multi")) { + std::shared_ptr<SecondHandler> secondHandler(new SecondHandler()); + std::shared_ptr<SecondServiceProcessor> secondProcessor(new SecondServiceProcessor(secondHandler)); + + std::shared_ptr<TMultiplexedProcessor> multiplexedProcessor(new TMultiplexedProcessor()); + multiplexedProcessor->registerDefault(testProcessor); // non-multi clients go to the default processor (multi:binary, multic:compact, ...) + multiplexedProcessor->registerProcessor("ThriftTest", testProcessor); + multiplexedProcessor->registerProcessor("SecondService", secondProcessor); + testProcessor = std::dynamic_pointer_cast<TProcessor>(multiplexedProcessor); + } + + // Server + std::shared_ptr<apache::thrift::server::TServer> server; + + if (server_type == "simple") { + server.reset(new TSimpleServer(testProcessor, serverSocket, transportFactory, protocolFactory)); + } else if (server_type == "thread-pool") { + + std::shared_ptr<ThreadFactory> threadFactory + = std::shared_ptr<ThreadFactory>(new ThreadFactory()); + + std::shared_ptr<ThreadManager> threadManager = ThreadManager::newSimpleThreadManager(workers); + threadManager->threadFactory(threadFactory); + threadManager->start(); + + server.reset(new TThreadPoolServer(testProcessor, + serverSocket, + transportFactory, + protocolFactory, + threadManager)); + } else if (server_type == "threaded") { + server.reset( + new TThreadedServer(testProcessor, serverSocket, transportFactory, protocolFactory)); + } else if (server_type == "nonblocking") { + if (transport_type == "http") { + std::shared_ptr<TestHandlerAsync> testHandlerAsync(new TestHandlerAsync(testHandler)); + std::shared_ptr<TAsyncProcessor> testProcessorAsync( + new ThriftTestAsyncProcessor(testHandlerAsync)); + std::shared_ptr<TAsyncBufferProcessor> testBufferProcessor( + new TAsyncProtocolProcessor(testProcessorAsync, protocolFactory)); + + // not loading nonblockingServer into "server" because + // TEvhttpServer doesn't inherit from TServer, and doesn't + // provide a stop method. + TEvhttpServer nonblockingServer(testBufferProcessor, port); + nonblockingServer.serve(); + } else if (transport_type == "framed") { + std::shared_ptr<transport::TNonblockingServerTransport> nbSocket; + nbSocket.reset( + ssl ? new transport::TNonblockingSSLServerSocket(port, sslSocketFactory) + : new transport::TNonblockingServerSocket(port)); + server.reset(new TNonblockingServer(testProcessor, protocolFactory, nbSocket)); + } else { + cerr << "server-type nonblocking requires transport of http or framed" << endl; + exit(1); + } + } + + if (server.get() != nullptr) { + if (protocol_type == "header") { + // Tell the server to use the same protocol for input / output + // if using header + server->setOutputProtocolFactory(std::shared_ptr<TProtocolFactory>()); + } + + apache::thrift::concurrency::ThreadFactory factory; + factory.setDetached(false); + std::shared_ptr<apache::thrift::concurrency::Runnable> serverThreadRunner(server); + std::shared_ptr<apache::thrift::concurrency::Thread> thread + = factory.newThread(serverThreadRunner); + +#ifdef HAVE_SIGNAL_H + signal(SIGINT, signal_handler); +#endif + + thread->start(); + gMonitor.waitForever(); // wait for a shutdown signal + +#ifdef HAVE_SIGNAL_H + signal(SIGINT, SIG_DFL); +#endif + + server->stop(); + thread->join(); + server.reset(); + } + + cout << "done." << endl; + return 0; +} + diff --git a/src/jaegertracing/thrift/test/cpp/src/ThriftTest_extras.cpp b/src/jaegertracing/thrift/test/cpp/src/ThriftTest_extras.cpp new file mode 100644 index 000000000..af5606efb --- /dev/null +++ b/src/jaegertracing/thrift/test/cpp/src/ThriftTest_extras.cpp @@ -0,0 +1,33 @@ +/* + * 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. + */ + +// Extra functions required for ThriftTest_types to work + +#include <thrift/protocol/TDebugProtocol.h> +#include "gen-cpp/ThriftTest_types.h" + +namespace thrift { +namespace test { + +bool Insanity::operator<(thrift::test::Insanity const& other) const { + using apache::thrift::ThriftDebugString; + return ThriftDebugString(*this) < ThriftDebugString(other); +} +} +} diff --git a/src/jaegertracing/thrift/test/crossrunner/__init__.py b/src/jaegertracing/thrift/test/crossrunner/__init__.py new file mode 100644 index 000000000..9d0b83acb --- /dev/null +++ b/src/jaegertracing/thrift/test/crossrunner/__init__.py @@ -0,0 +1,23 @@ +# +# 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. +# + +from .test import test_name # noqa +from .collect import collect_cross_tests, collect_feature_tests # noqa +from .run import TestDispatcher # noqa +from .report import generate_known_failures, load_known_failures # noqa diff --git a/src/jaegertracing/thrift/test/crossrunner/collect.py b/src/jaegertracing/thrift/test/crossrunner/collect.py new file mode 100644 index 000000000..e2d897828 --- /dev/null +++ b/src/jaegertracing/thrift/test/crossrunner/collect.py @@ -0,0 +1,164 @@ +# +# 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. +# + +import platform +import re +from itertools import product + +from .util import merge_dict +from .test import TestEntry + +# Those keys are passed to execution as is. +# Note that there are keys other than these, namely: +# delay: After server is started, client start is delayed for the value +# (seconds). +# timeout: Test timeout after client is started (seconds). +# platforms: Supported platforms. Should match platform.system() value. +# protocols: list of supported protocols +# transports: list of supported transports +# sockets: list of supported sockets +# +# protocols and transports entries can be colon separated "spec:impl" pair +# (e.g. binary:accel) where test is run for any matching "spec" while actual +# argument passed to test executable is "impl". +# Otherwise "spec" is equivalent to "spec:spec" pair. +# (e.g. "binary" is equivalent to "binary:binary" in tests.json) +# +VALID_JSON_KEYS = [ + 'name', # name of the library, typically a language name + 'workdir', # work directory where command is executed + 'command', # test command + 'extra_args', # args appended to command after other args are appended + 'remote_args', # args added to the other side of the program + 'join_args', # whether args should be passed as single concatenated string + 'env', # additional environmental variable +] + +DEFAULT_MAX_DELAY = 5 +DEFAULT_SIGNAL = 1 +DEFAULT_TIMEOUT = 5 + + +def _collect_testlibs(config, server_match, client_match=[None]): + """Collects server/client configurations from library configurations""" + def expand_libs(config): + for lib in config: + sv = lib.pop('server', None) + cl = lib.pop('client', None) + yield lib, sv, cl + + def yield_testlibs(base_configs, configs, match): + for base, conf in zip(base_configs, configs): + if conf: + if not match or base['name'] in match: + platforms = conf.get('platforms') or base.get('platforms') + if not platforms or platform.system() in platforms: + yield merge_dict(base, conf) + + libs, svs, cls = zip(*expand_libs(config)) + servers = list(yield_testlibs(libs, svs, server_match)) + clients = list(yield_testlibs(libs, cls, client_match)) + return servers, clients + + +def collect_features(config, match): + res = list(map(re.compile, match)) + return list(filter(lambda c: any(map(lambda r: r.search(c['name']), res)), config)) + + +def _do_collect_tests(servers, clients): + def intersection(key, o1, o2): + """intersection of two collections. + collections are replaced with sets the first time""" + def cached_set(o, key): + v = o[key] + if not isinstance(v, set): + v = set(v) + o[key] = v + return v + return cached_set(o1, key) & cached_set(o2, key) + + def intersect_with_spec(key, o1, o2): + # store as set of (spec, impl) tuple + def cached_set(o): + def to_spec_impl_tuples(values): + for v in values: + spec, _, impl = v.partition(':') + yield spec, impl or spec + v = o[key] + if not isinstance(v, set): + v = set(to_spec_impl_tuples(set(v))) + o[key] = v + return v + for spec1, impl1 in cached_set(o1): + for spec2, impl2 in cached_set(o2): + if spec1 == spec2: + name = impl1 if impl1 == impl2 else '%s-%s' % (impl1, impl2) + yield name, impl1, impl2 + + def maybe_max(key, o1, o2, default): + """maximum of two if present, otherwise default value""" + v1 = o1.get(key) + v2 = o2.get(key) + return max(v1, v2) if v1 and v2 else v1 or v2 or default + + def filter_with_validkeys(o): + ret = {} + for key in VALID_JSON_KEYS: + if key in o: + ret[key] = o[key] + return ret + + def merge_metadata(o, **ret): + for key in VALID_JSON_KEYS: + if key in o: + ret[key] = o[key] + return ret + + for sv, cl in product(servers, clients): + for proto, proto1, proto2 in intersect_with_spec('protocols', sv, cl): + for trans, trans1, trans2 in intersect_with_spec('transports', sv, cl): + for sock in intersection('sockets', sv, cl): + yield { + 'server': merge_metadata(sv, **{'protocol': proto1, 'transport': trans1}), + 'client': merge_metadata(cl, **{'protocol': proto2, 'transport': trans2}), + 'delay': maybe_max('delay', sv, cl, DEFAULT_MAX_DELAY), + 'stop_signal': maybe_max('stop_signal', sv, cl, DEFAULT_SIGNAL), + 'timeout': maybe_max('timeout', sv, cl, DEFAULT_TIMEOUT), + 'protocol': proto, + 'transport': trans, + 'socket': sock + } + + +def _filter_entries(tests, regex): + if regex: + return filter(lambda t: re.search(regex, TestEntry.get_name(**t)), tests) + return tests + + +def collect_cross_tests(tests_dict, server_match, client_match, regex): + sv, cl = _collect_testlibs(tests_dict, server_match, client_match) + return list(_filter_entries(_do_collect_tests(sv, cl), regex)) + + +def collect_feature_tests(tests_dict, features_dict, server_match, feature_match, regex): + sv, _ = _collect_testlibs(tests_dict, server_match) + ft = collect_features(features_dict, feature_match) + return list(_filter_entries(_do_collect_tests(sv, ft), regex)) diff --git a/src/jaegertracing/thrift/test/crossrunner/compat.py b/src/jaegertracing/thrift/test/crossrunner/compat.py new file mode 100644 index 000000000..f1ca91bb3 --- /dev/null +++ b/src/jaegertracing/thrift/test/crossrunner/compat.py @@ -0,0 +1,24 @@ +import os +import sys + +if sys.version_info[0] == 2: + _ENCODE = sys.getfilesystemencoding() + + def path_join(*args): + bin_args = map(lambda a: a.decode(_ENCODE), args) + return os.path.join(*bin_args).encode(_ENCODE) + + def str_join(s, l): + bin_args = map(lambda a: a.decode(_ENCODE), l) + b = s.decode(_ENCODE) + return b.join(bin_args).encode(_ENCODE) + + logfile_open = open + +else: + + path_join = os.path.join + str_join = str.join + + def logfile_open(*args): + return open(*args, errors='replace') diff --git a/src/jaegertracing/thrift/test/crossrunner/report.py b/src/jaegertracing/thrift/test/crossrunner/report.py new file mode 100644 index 000000000..5baf16195 --- /dev/null +++ b/src/jaegertracing/thrift/test/crossrunner/report.py @@ -0,0 +1,441 @@ +# +# 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. +# + +from __future__ import print_function +import datetime +import json +import multiprocessing +import os +import platform +import re +import subprocess +import sys +import time +import traceback + +from .compat import logfile_open, path_join, str_join +from .test import TestEntry + +LOG_DIR = 'log' +RESULT_HTML = 'index.html' +RESULT_JSON = 'results.json' +FAIL_JSON = 'known_failures_%s.json' + + +def generate_known_failures(testdir, overwrite, save, out): + def collect_failures(results): + success_index = 5 + for r in results: + if not r[success_index]: + yield TestEntry.get_name(*r) + try: + with logfile_open(path_join(testdir, RESULT_JSON), 'r') as fp: + results = json.load(fp) + except IOError: + sys.stderr.write('Unable to load last result. Did you run tests ?\n') + return False + fails = collect_failures(results['results']) + if not overwrite: + known = load_known_failures(testdir) + known.extend(fails) + fails = known + fails_json = json.dumps(sorted(set(fails)), indent=2, separators=(',', ': ')) + if save: + with logfile_open(os.path.join(testdir, FAIL_JSON % platform.system()), 'w+') as fp: + fp.write(fails_json) + sys.stdout.write('Successfully updated known failures.\n') + if out: + sys.stdout.write(fails_json) + sys.stdout.write('\n') + return True + + +def load_known_failures(testdir): + try: + with logfile_open(path_join(testdir, FAIL_JSON % platform.system()), 'r') as fp: + return json.load(fp) + except IOError: + return [] + + +class TestReporter(object): + # Unfortunately, standard library doesn't handle timezone well + # DATETIME_FORMAT = '%a %b %d %H:%M:%S %Z %Y' + DATETIME_FORMAT = '%a %b %d %H:%M:%S %Y' + + def __init__(self): + self._log = multiprocessing.get_logger() + self._lock = multiprocessing.Lock() + + @classmethod + def test_logfile(cls, test_name, prog_kind, dir=None): + relpath = path_join('log', '%s_%s.log' % (test_name, prog_kind)) + return relpath if not dir else os.path.realpath(path_join(dir, relpath)) + + def _start(self): + self._start_time = time.time() + + @property + def _elapsed(self): + return time.time() - self._start_time + + @classmethod + def _format_date(cls): + return '%s' % datetime.datetime.now().strftime(cls.DATETIME_FORMAT) + + def _print_date(self): + print(self._format_date(), file=self.out) + + def _print_bar(self, out=None): + print( + '===============================================================================', + file=(out or self.out)) + + def _print_exec_time(self): + print('Test execution took {:.1f} seconds.'.format(self._elapsed), file=self.out) + + +class ExecReporter(TestReporter): + def __init__(self, testdir, test, prog): + super(ExecReporter, self).__init__() + self._test = test + self._prog = prog + self.logpath = self.test_logfile(test.name, prog.kind, testdir) + self.out = None + + def begin(self): + self._start() + self._open() + if self.out and not self.out.closed: + self._print_header() + else: + self._log.debug('Output stream is not available.') + + def end(self, returncode): + self._lock.acquire() + try: + if self.out and not self.out.closed: + self._print_footer(returncode) + self._close() + self.out = None + else: + self._log.debug('Output stream is not available.') + finally: + self._lock.release() + + def killed(self): + print(file=self.out) + print('Server process is successfully killed.', file=self.out) + self.end(None) + + def died(self): + print(file=self.out) + print('*** Server process has died unexpectedly ***', file=self.out) + self.end(None) + + _init_failure_exprs = { + 'server': list(map(re.compile, [ + '[Aa]ddress already in use', + 'Could not bind', + 'EADDRINUSE', + ])), + 'client': list(map(re.compile, [ + '[Cc]onnection refused', + 'Could not connect to', + 'Could not open UNIX ', # domain socket (rb) + 'ECONNREFUSED', + 'econnrefused', # erl + 'CONNECTION-REFUSED-ERROR', # cl + 'connect ENOENT', # nodejs domain socket + 'No such file or directory', # domain socket + 'Sockets.TcpClient.Connect', # csharp + ])), + } + + def maybe_false_positive(self): + """Searches through log file for socket bind error. + Returns True if suspicious expression is found, otherwise False""" + try: + if self.out and not self.out.closed: + self.out.flush() + exprs = self._init_failure_exprs[self._prog.kind] + + def match(line): + for expr in exprs: + if expr.search(line): + self._log.info("maybe false positive: %s" % line) + return True + + with logfile_open(self.logpath, 'r') as fp: + if any(map(match, fp)): + return True + except (KeyboardInterrupt, SystemExit): + raise + except Exception as ex: + self._log.warn('[%s]: Error while detecting false positive: %s' % (self._test.name, str(ex))) + self._log.info(traceback.print_exc()) + return False + + def _open(self): + self.out = logfile_open(self.logpath, 'w+') + + def _close(self): + self.out.close() + + def _print_header(self): + self._print_date() + print('Executing: %s' % str_join(' ', self._prog.command), file=self.out) + print('Directory: %s' % self._prog.workdir, file=self.out) + print('config:delay: %s' % self._test.delay, file=self.out) + print('config:timeout: %s' % self._test.timeout, file=self.out) + self._print_bar() + self.out.flush() + + def _print_footer(self, returncode=None): + self._print_bar() + if returncode is not None: + print('Return code: %d (negative values indicate kill by signal)' % returncode, file=self.out) + else: + print('Process is killed.', file=self.out) + self._print_exec_time() + self._print_date() + + +class SummaryReporter(TestReporter): + def __init__(self, basedir, testdir_relative, concurrent=True): + super(SummaryReporter, self).__init__() + self._basedir = basedir + self._testdir_rel = testdir_relative + self.logdir = path_join(self.testdir, LOG_DIR) + self.out_path = path_join(self.testdir, RESULT_JSON) + self.concurrent = concurrent + self.out = sys.stdout + self._platform = platform.system() + self._revision = self._get_revision() + self._tests = [] + if not os.path.exists(self.logdir): + os.mkdir(self.logdir) + self._known_failures = load_known_failures(self.testdir) + self._unexpected_success = [] + self._flaky_success = [] + self._unexpected_failure = [] + self._expected_failure = [] + self._print_header() + + @property + def testdir(self): + return path_join(self._basedir, self._testdir_rel) + + def _result_string(self, test): + if test.success: + if test.retry_count == 0: + return 'success' + elif test.retry_count == 1: + return 'flaky(1 retry)' + else: + return 'flaky(%d retries)' % test.retry_count + elif test.expired: + return 'failure(timeout)' + else: + return 'failure(%d)' % test.returncode + + def _get_revision(self): + p = subprocess.Popen(['git', 'rev-parse', '--short', 'HEAD'], + cwd=self.testdir, stdout=subprocess.PIPE) + out, _ = p.communicate() + return out.strip() + + def _format_test(self, test, with_result=True): + name = '%s-%s' % (test.server.name, test.client.name) + trans = '%s-%s' % (test.transport, test.socket) + if not with_result: + return '{:24s}{:18s}{:25s}'.format(name[:23], test.protocol[:17], trans[:24]) + else: + return '{:24s}{:18s}{:25s}{:s}\n'.format(name[:23], test.protocol[:17], + trans[:24], self._result_string(test)) + + def _print_test_header(self): + self._print_bar() + print( + '{:24s}{:18s}{:25s}{:s}'.format('server-client:', 'protocol:', 'transport:', 'result:'), + file=self.out) + + def _print_header(self): + self._start() + print('Apache Thrift - Integration Test Suite', file=self.out) + self._print_date() + self._print_test_header() + + def _print_unexpected_failure(self): + if len(self._unexpected_failure) > 0: + self.out.writelines([ + '*** Following %d failures were unexpected ***:\n' % len(self._unexpected_failure), + 'If it is introduced by you, please fix it before submitting the code.\n', + # 'If not, please report at https://issues.apache.org/jira/browse/THRIFT\n', + ]) + self._print_test_header() + for i in self._unexpected_failure: + self.out.write(self._format_test(self._tests[i])) + self._print_bar() + else: + print('No unexpected failures.', file=self.out) + + def _print_flaky_success(self): + if len(self._flaky_success) > 0: + print( + 'Following %d tests were expected to cleanly succeed but needed retry:' % len(self._flaky_success), + file=self.out) + self._print_test_header() + for i in self._flaky_success: + self.out.write(self._format_test(self._tests[i])) + self._print_bar() + + def _print_unexpected_success(self): + if len(self._unexpected_success) > 0: + print( + 'Following %d tests were known to fail but succeeded (maybe flaky):' % len(self._unexpected_success), + file=self.out) + self._print_test_header() + for i in self._unexpected_success: + self.out.write(self._format_test(self._tests[i])) + self._print_bar() + + def _http_server_command(self, port): + if sys.version_info[0] < 3: + return 'python -m SimpleHTTPServer %d' % port + else: + return 'python -m http.server %d' % port + + def _print_footer(self): + fail_count = len(self._expected_failure) + len(self._unexpected_failure) + self._print_bar() + self._print_unexpected_success() + self._print_flaky_success() + self._print_unexpected_failure() + self._write_html_data() + self._assemble_log('unexpected failures', self._unexpected_failure) + self._assemble_log('known failures', self._expected_failure) + self.out.writelines([ + 'You can browse results at:\n', + '\tfile://%s/%s\n' % (self.testdir, RESULT_HTML), + '# If you use Chrome, run:\n', + '# \tcd %s\n#\t%s\n' % (self._basedir, self._http_server_command(8001)), + '# then browse:\n', + '# \thttp://localhost:%d/%s/\n' % (8001, self._testdir_rel), + 'Full log for each test is here:\n', + '\ttest/log/server_client_protocol_transport_client.log\n', + '\ttest/log/server_client_protocol_transport_server.log\n', + '%d failed of %d tests in total.\n' % (fail_count, len(self._tests)), + ]) + self._print_exec_time() + self._print_date() + + def _render_result(self, test): + return [ + test.server.name, + test.client.name, + test.protocol, + test.transport, + test.socket, + test.success, + test.as_expected, + test.returncode, + { + 'server': self.test_logfile(test.name, test.server.kind), + 'client': self.test_logfile(test.name, test.client.kind), + }, + ] + + def _write_html_data(self): + """Writes JSON data to be read by result html""" + results = [self._render_result(r) for r in self._tests] + with logfile_open(self.out_path, 'w+') as fp: + fp.write(json.dumps({ + 'date': self._format_date(), + 'revision': str(self._revision), + 'platform': self._platform, + 'duration': '{:.1f}'.format(self._elapsed), + 'results': results, + }, indent=2)) + + def _assemble_log(self, title, indexes): + if len(indexes) > 0: + def add_prog_log(fp, test, prog_kind): + print('*************************** %s message ***************************' % prog_kind, + file=fp) + path = self.test_logfile(test.name, prog_kind, self.testdir) + if os.path.exists(path): + with logfile_open(path, 'r') as prog_fp: + print(prog_fp.read(), file=fp) + filename = title.replace(' ', '_') + '.log' + with logfile_open(os.path.join(self.logdir, filename), 'w+') as fp: + for test in map(self._tests.__getitem__, indexes): + fp.write('TEST: [%s]\n' % test.name) + add_prog_log(fp, test, test.server.kind) + add_prog_log(fp, test, test.client.kind) + fp.write('**********************************************************************\n\n') + print('%s are logged to %s/%s/%s' % (title.capitalize(), self._testdir_rel, LOG_DIR, filename)) + + def end(self): + self._print_footer() + return len(self._unexpected_failure) == 0 + + def add_test(self, test_dict): + test = TestEntry(self.testdir, **test_dict) + self._lock.acquire() + try: + if not self.concurrent: + self.out.write(self._format_test(test, False)) + self.out.flush() + self._tests.append(test) + return len(self._tests) - 1 + finally: + self._lock.release() + + def add_result(self, index, returncode, expired, retry_count): + self._lock.acquire() + try: + failed = returncode is None or returncode != 0 + flaky = not failed and retry_count != 0 + test = self._tests[index] + known = test.name in self._known_failures + if failed: + if known: + self._log.debug('%s failed as expected' % test.name) + self._expected_failure.append(index) + else: + self._log.info('unexpected failure: %s' % test.name) + self._unexpected_failure.append(index) + elif flaky and not known: + self._log.info('unexpected flaky success: %s' % test.name) + self._flaky_success.append(index) + elif not flaky and known: + self._log.info('unexpected success: %s' % test.name) + self._unexpected_success.append(index) + test.success = not failed + test.returncode = returncode + test.retry_count = retry_count + test.expired = expired + test.as_expected = known == failed + if not self.concurrent: + self.out.write(self._result_string(test) + '\n') + else: + self.out.write(self._format_test(test)) + finally: + self._lock.release() diff --git a/src/jaegertracing/thrift/test/crossrunner/run.py b/src/jaegertracing/thrift/test/crossrunner/run.py new file mode 100644 index 000000000..bb06d25ef --- /dev/null +++ b/src/jaegertracing/thrift/test/crossrunner/run.py @@ -0,0 +1,425 @@ +# +# 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. +# + +import contextlib +import multiprocessing +import multiprocessing.managers +import os +import platform +import random +import socket +import subprocess +import sys +import time + +from .compat import str_join +from .report import ExecReporter, SummaryReporter +from .test import TestEntry +from .util import domain_socket_path + +RESULT_ERROR = 64 +RESULT_TIMEOUT = 128 +SIGNONE = 0 +SIGKILL = 15 + +# globals +ports = None +stop = None + + +class ExecutionContext(object): + def __init__(self, cmd, cwd, env, stop_signal, is_server, report): + self._log = multiprocessing.get_logger() + self.cmd = cmd + self.cwd = cwd + self.env = env + self.stop_signal = stop_signal + self.is_server = is_server + self.report = report + self.expired = False + self.killed = False + self.proc = None + + def _popen_args(self): + args = { + 'cwd': self.cwd, + 'env': self.env, + 'stdout': self.report.out, + 'stderr': subprocess.STDOUT, + } + # make sure child processes doesn't remain after killing + if platform.system() == 'Windows': + DETACHED_PROCESS = 0x00000008 + args.update(creationflags=DETACHED_PROCESS | subprocess.CREATE_NEW_PROCESS_GROUP) + else: + args.update(preexec_fn=os.setsid) + return args + + def start(self): + joined = str_join(' ', self.cmd) + self._log.debug('COMMAND: %s', joined) + self._log.debug('WORKDIR: %s', self.cwd) + self._log.debug('LOGFILE: %s', self.report.logpath) + self.report.begin() + self.proc = subprocess.Popen(self.cmd, **self._popen_args()) + self._log.debug(' PID: %d', self.proc.pid) + self._log.debug(' PGID: %d', os.getpgid(self.proc.pid)) + return self._scoped() + + @contextlib.contextmanager + def _scoped(self): + yield self + if self.is_server: + # the server is supposed to run until we stop it + if self.returncode is not None: + self.report.died() + else: + if self.stop_signal != SIGNONE: + if self.sigwait(self.stop_signal): + self.report.end(self.returncode) + else: + self.report.killed() + else: + self.sigwait(SIGKILL) + else: + # the client is supposed to exit normally + if self.returncode is not None: + self.report.end(self.returncode) + else: + self.sigwait(SIGKILL) + self.report.killed() + self._log.debug('[{0}] exited with return code {1}'.format(self.proc.pid, self.returncode)) + + # Send a signal to the process and then wait for it to end + # If the signal requested is SIGNONE, no signal is sent, and + # instead we just wait for the process to end; further if it + # does not end normally with SIGNONE, we mark it as expired. + # If the process fails to end and the signal is not SIGKILL, + # it re-runs with SIGKILL so that a real process kill occurs + # returns True if the process ended, False if it may not have + def sigwait(self, sig=SIGKILL, timeout=2): + try: + if sig != SIGNONE: + self._log.debug('[{0}] send signal {1}'.format(self.proc.pid, sig)) + if sig == SIGKILL: + self.killed = True + try: + if platform.system() != 'Windows': + os.killpg(os.getpgid(self.proc.pid), sig) + else: + self.proc.send_signal(sig) + except Exception: + self._log.info('[{0}] Failed to kill process'.format(self.proc.pid), exc_info=sys.exc_info()) + self._log.debug('[{0}] wait begin, timeout {1} sec(s)'.format(self.proc.pid, timeout)) + self.proc.communicate(timeout=timeout) + self._log.debug('[{0}] process ended with return code {1}'.format(self.proc.pid, self.returncode)) + self.report.end(self.returncode) + return True + except subprocess.TimeoutExpired: + self._log.info('[{0}] timeout waiting for process to end'.format(self.proc.pid)) + if sig == SIGNONE: + self.expired = True + return False if sig == SIGKILL else self.sigwait(SIGKILL, 1) + + # called on the client process to wait for it to end naturally + def wait(self, timeout): + self.sigwait(SIGNONE, timeout) + + @property + def returncode(self): + return self.proc.returncode if self.proc else None + + +def exec_context(port, logdir, test, prog, is_server): + report = ExecReporter(logdir, test, prog) + prog.build_command(port) + return ExecutionContext(prog.command, prog.workdir, prog.env, prog.stop_signal, is_server, report) + + +def run_test(testdir, logdir, test_dict, max_retry, async_mode=True): + logger = multiprocessing.get_logger() + + def ensure_socket_open(sv, port, test): + slept = 0.1 + time.sleep(slept) + sleep_step = 0.1 + while True: + if slept > test.delay: + logger.warn('[{0}] slept for {1} seconds but server is not open'.format(sv.proc.pid, slept)) + return False + if test.socket == 'domain': + if not os.path.exists(domain_socket_path(port)): + logger.debug('[{0}] domain(unix) socket not available yet. slept for {1} seconds so far'.format(sv.proc.pid, slept)) + time.sleep(sleep_step) + slept += sleep_step + elif test.socket == 'abstract': + return True + else: + # Create sockets every iteration because refused sockets cannot be + # reused on some systems. + sock4 = socket.socket() + sock6 = socket.socket(family=socket.AF_INET6) + try: + if sock4.connect_ex(('127.0.0.1', port)) == 0 \ + or sock6.connect_ex(('::1', port)) == 0: + return True + if sv.proc.poll() is not None: + logger.warn('[{0}] server process is exited'.format(sv.proc.pid)) + return False + logger.debug('[{0}] socket not available yet. slept for {1} seconds so far'.format(sv.proc.pid, slept)) + time.sleep(sleep_step) + slept += sleep_step + finally: + sock4.close() + sock6.close() + logger.debug('[{0}] server ready - waited for {1} seconds'.format(sv.proc.pid, slept)) + return True + + try: + max_bind_retry = 3 + retry_count = 0 + bind_retry_count = 0 + test = TestEntry(testdir, **test_dict) + while True: + if stop.is_set(): + logger.debug('Skipping because shutting down') + return (retry_count, None) + logger.debug('Start') + with PortAllocator.alloc_port_scoped(ports, test.socket) as port: + logger.debug('Start with port %d' % port) + sv = exec_context(port, logdir, test, test.server, True) + cl = exec_context(port, logdir, test, test.client, False) + + logger.debug('Starting server') + with sv.start(): + port_ok = ensure_socket_open(sv, port, test) + if port_ok: + connect_retry_count = 0 + max_connect_retry = 12 + connect_retry_wait = 0.25 + while True: + if sv.proc.poll() is not None: + logger.info('not starting client because server process is absent') + break + logger.debug('Starting client') + cl.start() + logger.debug('Waiting client (up to %d secs)' % test.timeout) + cl.wait(test.timeout) + if not cl.report.maybe_false_positive() or connect_retry_count >= max_connect_retry: + if connect_retry_count > 0 and connect_retry_count < max_connect_retry: + logger.info('[%s]: Connected after %d retry (%.2f sec each)' % (test.server.name, connect_retry_count, connect_retry_wait)) + # Wait for 50ms to see if server does not die at the end. + time.sleep(0.05) + break + logger.debug('Server may not be ready, waiting %.2f second...' % connect_retry_wait) + time.sleep(connect_retry_wait) + connect_retry_count += 1 + + if sv.report.maybe_false_positive() and bind_retry_count < max_bind_retry: + logger.warn('[%s]: Detected socket bind failure, retrying...', test.server.name) + bind_retry_count += 1 + else: + result = RESULT_TIMEOUT if cl.expired else cl.returncode if (cl.proc and cl.proc.poll()) is not None else RESULT_ERROR + + # For servers that handle a controlled shutdown by signal + # if they are killed, or return an error code, that is a + # problem. For servers that are not signal-aware, we simply + # kill them off; if we didn't kill them off, something else + # happened (crashed?) + if test.server.stop_signal != 0: + if sv.killed or sv.returncode > 0: + result |= RESULT_ERROR + else: + if not sv.killed: + result |= RESULT_ERROR + + if result == 0 or retry_count >= max_retry: + return (retry_count, result) + else: + logger.info('[%s-%s]: test failed, retrying...', test.server.name, test.client.name) + retry_count += 1 + except Exception: + if not async_mode: + raise + logger.warn('Error executing [%s]', test.name, exc_info=True) + return (retry_count, RESULT_ERROR) + except Exception: + logger.info('Interrupted execution', exc_info=True) + if not async_mode: + raise + stop.set() + return (retry_count, RESULT_ERROR) + + +class PortAllocator(object): + def __init__(self): + self._log = multiprocessing.get_logger() + self._lock = multiprocessing.Lock() + self._ports = set() + self._dom_ports = set() + self._last_alloc = 0 + + def _get_tcp_port(self): + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + sock.bind(('', 0)) + port = sock.getsockname()[1] + self._lock.acquire() + try: + ok = port not in self._ports + if ok: + self._ports.add(port) + self._last_alloc = time.time() + finally: + self._lock.release() + sock.close() + return port if ok else self._get_tcp_port() + + def _get_domain_port(self): + port = random.randint(1024, 65536) + self._lock.acquire() + try: + ok = port not in self._dom_ports + if ok: + self._dom_ports.add(port) + finally: + self._lock.release() + return port if ok else self._get_domain_port() + + def alloc_port(self, socket_type): + if socket_type in ('domain', 'abstract'): + return self._get_domain_port() + else: + return self._get_tcp_port() + + # static method for inter-process invokation + @staticmethod + @contextlib.contextmanager + def alloc_port_scoped(allocator, socket_type): + port = allocator.alloc_port(socket_type) + yield port + allocator.free_port(socket_type, port) + + def free_port(self, socket_type, port): + self._log.debug('free_port') + self._lock.acquire() + try: + if socket_type == 'domain': + self._dom_ports.remove(port) + path = domain_socket_path(port) + if os.path.exists(path): + os.remove(path) + elif socket_type == 'abstract': + self._dom_ports.remove(port) + else: + self._ports.remove(port) + except IOError: + self._log.info('Error while freeing port', exc_info=sys.exc_info()) + finally: + self._lock.release() + + +class NonAsyncResult(object): + def __init__(self, value): + self._value = value + + def get(self, timeout=None): + return self._value + + def wait(self, timeout=None): + pass + + def ready(self): + return True + + def successful(self): + return self._value == 0 + + +class TestDispatcher(object): + def __init__(self, testdir, basedir, logdir_rel, concurrency): + self._log = multiprocessing.get_logger() + self.testdir = testdir + self._report = SummaryReporter(basedir, logdir_rel, concurrency > 1) + self.logdir = self._report.testdir + # seems needed for python 2.x to handle keyboard interrupt + self._stop = multiprocessing.Event() + self._async = concurrency > 1 + if not self._async: + self._pool = None + global stop + global ports + stop = self._stop + ports = PortAllocator() + else: + self._m = multiprocessing.managers.BaseManager() + self._m.register('ports', PortAllocator) + self._m.start() + self._pool = multiprocessing.Pool(concurrency, self._pool_init, (self._m.address,)) + self._log.debug( + 'TestDispatcher started with %d concurrent jobs' % concurrency) + + def _pool_init(self, address): + global stop + global m + global ports + stop = self._stop + m = multiprocessing.managers.BaseManager(address) + m.connect() + ports = m.ports() + + def _dispatch_sync(self, test, cont, max_retry): + r = run_test(self.testdir, self.logdir, test, max_retry, async_mode=False) + cont(r) + return NonAsyncResult(r) + + def _dispatch_async(self, test, cont, max_retry): + self._log.debug('_dispatch_async') + return self._pool.apply_async(func=run_test, args=(self.testdir, self.logdir, test, max_retry), callback=cont) + + def dispatch(self, test, max_retry): + index = self._report.add_test(test) + + def cont(result): + if not self._stop.is_set(): + if result and len(result) == 2: + retry_count, returncode = result + else: + retry_count = 0 + returncode = RESULT_ERROR + self._log.debug('freeing port') + self._log.debug('adding result') + self._report.add_result(index, returncode, returncode == RESULT_TIMEOUT, retry_count) + self._log.debug('finish continuation') + fn = self._dispatch_async if self._async else self._dispatch_sync + return fn(test, cont, max_retry) + + def wait(self): + if self._async: + self._pool.close() + self._pool.join() + self._m.shutdown() + return self._report.end() + + def terminate(self): + self._stop.set() + if self._async: + self._pool.terminate() + self._pool.join() + self._m.shutdown() diff --git a/src/jaegertracing/thrift/test/crossrunner/setup.cfg b/src/jaegertracing/thrift/test/crossrunner/setup.cfg new file mode 100644 index 000000000..7da1f9608 --- /dev/null +++ b/src/jaegertracing/thrift/test/crossrunner/setup.cfg @@ -0,0 +1,2 @@ +[flake8] +max-line-length = 100 diff --git a/src/jaegertracing/thrift/test/crossrunner/test.py b/src/jaegertracing/thrift/test/crossrunner/test.py new file mode 100644 index 000000000..0e912843a --- /dev/null +++ b/src/jaegertracing/thrift/test/crossrunner/test.py @@ -0,0 +1,149 @@ +# +# 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. +# + +import copy +import multiprocessing +import os +import sys +from .compat import path_join +from .util import merge_dict, domain_socket_path + + +class TestProgram(object): + def __init__(self, kind, name, protocol, transport, socket, workdir, stop_signal, command, env=None, + extra_args=[], extra_args2=[], join_args=False, **kwargs): + + self.kind = kind + self.name = name + self.protocol = protocol + self.transport = transport + self.socket = socket + self.workdir = workdir + self.stop_signal = stop_signal + self.command = None + self._base_command = self._fix_cmd_path(command) + if env: + self.env = copy.copy(os.environ) + self.env.update(env) + else: + self.env = os.environ + self._extra_args = extra_args + self._extra_args2 = extra_args2 + self._join_args = join_args + + def _fix_cmd_path(self, cmd): + # if the arg is a file in the current directory, make it path + def abs_if_exists(arg): + p = path_join(self.workdir, arg) + return p if os.path.exists(p) else arg + + if cmd[0] == 'python': + cmd[0] = sys.executable + else: + cmd[0] = abs_if_exists(cmd[0]) + return cmd + + def _socket_args(self, socket, port): + return { + 'ip-ssl': ['--ssl'], + 'domain': ['--domain-socket=%s' % domain_socket_path(port)], + 'abstract': ['--abstract-namespace', '--domain-socket=%s' % domain_socket_path(port)], + }.get(socket, None) + + def _transport_args(self, transport): + return { + 'zlib': ['--zlib'], + }.get(transport, None) + + def build_command(self, port): + cmd = copy.copy(self._base_command) + args = copy.copy(self._extra_args2) + args.append('--protocol=' + self.protocol) + args.append('--transport=' + self.transport) + transport_args = self._transport_args(self.transport) + if transport_args: + args += transport_args + socket_args = self._socket_args(self.socket, port) + if socket_args: + args += socket_args + args.append('--port=%d' % port) + if self._join_args: + cmd.append('%s' % " ".join(args)) + else: + cmd.extend(args) + if self._extra_args: + cmd.extend(self._extra_args) + self.command = cmd + return self.command + + +class TestEntry(object): + def __init__(self, testdir, server, client, delay, timeout, **kwargs): + self.testdir = testdir + self._log = multiprocessing.get_logger() + self._config = kwargs + self.protocol = kwargs['protocol'] + self.transport = kwargs['transport'] + self.socket = kwargs['socket'] + srv_dict = self._fix_workdir(merge_dict(self._config, server)) + cli_dict = self._fix_workdir(merge_dict(self._config, client)) + cli_dict['extra_args2'] = srv_dict.pop('remote_args', []) + srv_dict['extra_args2'] = cli_dict.pop('remote_args', []) + self.server = TestProgram('server', **srv_dict) + self.client = TestProgram('client', **cli_dict) + self.delay = delay + self.timeout = timeout + self._name = None + # results + self.success = None + self.as_expected = None + self.returncode = None + self.expired = False + self.retry_count = 0 + + def _fix_workdir(self, config): + key = 'workdir' + path = config.get(key, None) + if not path: + path = self.testdir + if os.path.isabs(path): + path = os.path.realpath(path) + else: + path = os.path.realpath(path_join(self.testdir, path)) + config.update({key: path}) + return config + + @classmethod + def get_name(cls, server, client, protocol, transport, socket, *args, **kwargs): + return '%s-%s_%s_%s-%s' % (server, client, protocol, transport, socket) + + @property + def name(self): + if not self._name: + self._name = self.get_name( + self.server.name, self.client.name, self.protocol, self.transport, self.socket) + return self._name + + @property + def transport_name(self): + return '%s-%s' % (self.transport, self.socket) + + +def test_name(server, client, protocol, transport, socket, **kwargs): + return TestEntry.get_name(server['name'], client['name'], protocol, transport, socket) diff --git a/src/jaegertracing/thrift/test/crossrunner/util.py b/src/jaegertracing/thrift/test/crossrunner/util.py new file mode 100644 index 000000000..c214df85a --- /dev/null +++ b/src/jaegertracing/thrift/test/crossrunner/util.py @@ -0,0 +1,35 @@ +# +# 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. +# + +import copy + + +def domain_socket_path(port): + return '/tmp/ThriftTest.thrift.%d' % port + + +def merge_dict(base, update): + """Update dict concatenating list values""" + res = copy.deepcopy(base) + for k, v in list(update.items()): + if k in list(res.keys()) and isinstance(v, list): + res[k].extend(v) + else: + res[k] = v + return res diff --git a/src/jaegertracing/thrift/test/csharp/Makefile.am b/src/jaegertracing/thrift/test/csharp/Makefile.am new file mode 100644 index 000000000..ad166e384 --- /dev/null +++ b/src/jaegertracing/thrift/test/csharp/Makefile.am @@ -0,0 +1,95 @@ +# +# 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. +# + +GENERATED = \ + gen-csharp/Thrift/Test/Bonk.cs \ + gen-csharp/Thrift/Test/Bools.cs \ + gen-csharp/Thrift/Test/BoolTest.cs \ + gen-csharp/Thrift/Test/CrazyNesting.cs \ + gen-csharp/Thrift/Test/EmptyStruct.cs \ + gen-csharp/Thrift/Test/GuessProtocolStruct.cs \ + gen-csharp/Thrift/Test/Insanity.cs \ + gen-csharp/Thrift/Test/LargeDeltas.cs \ + gen-csharp/Thrift/Test/ListBonks.cs \ + gen-csharp/Thrift/Test/ListTypeVersioningV1.cs \ + gen-csharp/Thrift/Test/ListTypeVersioningV2.cs \ + gen-csharp/Thrift/Test/NestedListsBonk.cs \ + gen-csharp/Thrift/Test/NestedListsI32x2.cs \ + gen-csharp/Thrift/Test/NestedListsI32x3.cs \ + gen-csharp/Thrift/Test/NestedMixedx2.cs \ + gen-csharp/Thrift/Test/Numberz.cs \ + gen-csharp/Thrift/Test/OneField.cs \ + gen-csharp/Thrift/Test/SecondService.cs \ + gen-csharp/Thrift/Test/StructA.cs \ + gen-csharp/Thrift/Test/StructB.cs \ + gen-csharp/Thrift/Test/ThriftTest.Constants.cs \ + gen-csharp/Thrift/Test/ThriftTest.cs \ + gen-csharp/Thrift/Test/VersioningTestV1.cs \ + gen-csharp/Thrift/Test/VersioningTestV2.cs \ + gen-csharp/Thrift/Test/Xception.cs \ + gen-csharp/Thrift/Test/Xception2.cs \ + gen-csharp/Thrift/Test/Xtruct.cs \ + gen-csharp/Thrift/Test/Xtruct2.cs \ + gen-csharp/Thrift/Test/Xtruct3.cs + +BUILT_SOURCES = $(GENERATED) + +if MONO_MCS +CSC = mcs +else +CSC = gmcs +endif + +if NET_2_0 +CSC_DEFINES = -d:NET_2_0 +endif + +LIBDIR = $(top_builddir)/lib/csharp + +THRIFT = $(top_builddir)/compiler/cpp/thrift + +$(GENERATED): $(top_srcdir)/test/ThriftTest.thrift $(THRIFT) + $(THRIFT) --gen csharp -o . $< + +precross: TestClientServer.exe + +ThriftImpl.dll: $(GENERATED) $(LIBDIR)/Thrift.dll + $(CSC) $(CSC_DEFINES) -t:library -out:$@ -reference:$(LIBDIR)/Thrift.dll $(GENERATED) + +SRCS = TestClient.cs TestServer.cs Program.cs + +TestClientServer.exe: $(SRCS) ThriftImpl.dll + $(CSC) $(CSC_DEFINES) -out:$@ -reference:$(LIBDIR)/Thrift.dll -reference:ThriftImpl.dll $(SRCS) + +clean-local: + $(RM) -rf gen-csharp *.exe *.dll + +TESTPORT = 9500 +check-local: TestClientServer.exe + MONO_PATH=$(LIBDIR) timeout 10 mono TestClientServer.exe server --port=$(TESTPORT) & + sleep 1 + MONO_PATH=$(LIBDIR) mono TestClientServer.exe client --port=$(TESTPORT) + +EXTRA_DIST = \ + Properties/AssemblyInfo.cs \ + ThriftTest.csproj \ + ThriftTest.sln \ + Program.cs \ + TestServer.cs \ + TestClient.cs diff --git a/src/jaegertracing/thrift/test/csharp/Program.cs b/src/jaegertracing/thrift/test/csharp/Program.cs new file mode 100644 index 000000000..8ec00e300 --- /dev/null +++ b/src/jaegertracing/thrift/test/csharp/Program.cs @@ -0,0 +1,71 @@ +/* + * 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. + */ + +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +using System; +using Thrift.Transport; +using Thrift.Protocol; +using Thrift.Test; //generated code + +namespace Test +{ + class Program + { + static int Main(string[] args) + { + if (args.Length == 0) + { + Console.WriteLine("must provide 'server' or 'client' arg"); + return -1; + } + + try + { + Console.SetBufferSize(Console.BufferWidth, 4096); + } + catch (Exception) + { + Console.WriteLine("Failed to grow scroll-back buffer"); + } + + string[] subArgs = new string[args.Length - 1]; + for(int i = 1; i < args.Length; i++) + { + subArgs[i-1] = args[i]; + } + if (args[0] == "client") + { + return TestClient.Execute(subArgs); + } + else if (args[0] == "server") + { + return TestServer.Execute(subArgs) ? 0 : 1; + } + else + { + Console.WriteLine("first argument must be 'server' or 'client'"); + } + return 0; + } + } +} diff --git a/src/jaegertracing/thrift/test/csharp/Properties/AssemblyInfo.cs b/src/jaegertracing/thrift/test/csharp/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..76c9a80dd --- /dev/null +++ b/src/jaegertracing/thrift/test/csharp/Properties/AssemblyInfo.cs @@ -0,0 +1,55 @@ +/* + * 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. + */ + +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("ThriftTest")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("The Apache Software Foundation")] +[assembly: AssemblyProduct("Thrift")] +[assembly: AssemblyCopyright("The Apache Software Foundation")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("f41b193b-f1ab-48ee-8843-f88e43084e26")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("0.13.0.0")] +[assembly: AssemblyFileVersion("0.13.0.0")] diff --git a/src/jaegertracing/thrift/test/csharp/TestClient.cs b/src/jaegertracing/thrift/test/csharp/TestClient.cs new file mode 100644 index 000000000..949c06e9f --- /dev/null +++ b/src/jaegertracing/thrift/test/csharp/TestClient.cs @@ -0,0 +1,870 @@ +/* + * 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. + */ + +using System; +using System.Linq; +using System.Diagnostics; +using System.Collections.Generic; +using System.Threading; +using System.Security.Cryptography.X509Certificates; +using Thrift.Collections; +using Thrift.Protocol; +using Thrift.Transport; +using Thrift.Test; +using System.Security.Authentication; + +namespace Test +{ + public class TestClient + { + public class TestParams + { + public int numIterations = 1; + public string host = "localhost"; + public int port = 9090; + public string url; + public string pipe; + public bool buffered; + public bool framed; + public string protocol; + public bool encrypted = false; + public bool multiplexed = false; + protected bool _isFirstTransport = true; + + + public TTransport CreateTransport() + { + if (url == null) + { + // endpoint transport + TTransport trans = null; + if (pipe != null) + trans = new TNamedPipeClientTransport(pipe); + else + { + if (encrypted) + { + string certPath = "../keys/client.p12"; + X509Certificate cert = new X509Certificate2(certPath, "thrift"); + trans = new TTLSSocket(host, port, 0, cert, + (o, c, chain, errors) => true, + null, SslProtocols.Tls); + } + else + { + trans = new TSocket(host, port); + } + } + + // layered transport + if (buffered) + trans = new TBufferedTransport(trans); + if (framed) + trans = new TFramedTransport(trans); + + if (_isFirstTransport) + { + //ensure proper open/close of transport + trans.Open(); + trans.Close(); + _isFirstTransport = false; + } + return trans; + } + else + { + return new THttpClient(new Uri(url)); + } + } + + public TProtocol CreateProtocol(TTransport transport) + { + if (protocol == "compact") + return new TCompactProtocol(transport); + else if (protocol == "json") + return new TJSONProtocol(transport); + else + return new TBinaryProtocol(transport); + } + }; + + private const int ErrorBaseTypes = 1; + private const int ErrorStructs = 2; + private const int ErrorContainers = 4; + private const int ErrorExceptions = 8; + private const int ErrorProtocol = 16; + private const int ErrorUnknown = 64; + + private class ClientTest + { + private readonly TestParams param; + private readonly TTransport transport; + private readonly SecondService.Client second; + private readonly ThriftTest.Client client; + private readonly int numIterations; + private bool done; + + public int ReturnCode { get; set; } + + public ClientTest(TestParams paramin) + { + param = paramin; + transport = param.CreateTransport(); + TProtocol protocol = param.CreateProtocol(transport); + if (param.multiplexed) + { + second = new SecondService.Client(new TMultiplexedProtocol(protocol, "SecondService")); + } + client = new ThriftTest.Client(protocol); + numIterations = param.numIterations; + } + public void Execute() + { + if (done) + { + Console.WriteLine("Execute called more than once"); + throw new InvalidOperationException(); + } + + for (int i = 0; i < numIterations; i++) + { + try + { + if (!transport.IsOpen) + transport.Open(); + } + catch (TTransportException ex) + { + Console.WriteLine("*** FAILED ***"); + Console.WriteLine("Connect failed: " + ex.Message); + ReturnCode |= ErrorUnknown; + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + continue; + } + + try + { + ReturnCode |= ExecuteClientTest(client, second, param); + } + catch (Exception ex) + { + Console.WriteLine("*** FAILED ***"); + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + ReturnCode |= ErrorUnknown; + } + } + try + { + transport.Close(); + } + catch(Exception ex) + { + Console.WriteLine("Error while closing transport"); + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + } + done = true; + } + } + + public static int Execute(string[] args) + { + try + { + TestParams param = new TestParams(); + int numThreads = 1; + try + { + for (int i = 0; i < args.Length; i++) + { + if (args[i] == "-u") + { + param.url = args[++i]; + } + else if (args[i] == "-n") + { + param.numIterations = Convert.ToInt32(args[++i]); + } + else if (args[i] == "-pipe") // -pipe <name> + { + param.pipe = args[++i]; + Console.WriteLine("Using named pipes transport"); + } + else if (args[i].Contains("--host=")) + { + param.host = args[i].Substring(args[i].IndexOf("=") + 1); + } + else if (args[i].Contains("--port=")) + { + param.port = int.Parse(args[i].Substring(args[i].IndexOf("=")+1)); + } + else if (args[i] == "-b" || args[i] == "--buffered" || args[i] == "--transport=buffered") + { + param.buffered = true; + Console.WriteLine("Using buffered sockets"); + } + else if (args[i] == "-f" || args[i] == "--framed" || args[i] == "--transport=framed") + { + param.framed = true; + Console.WriteLine("Using framed transport"); + } + else if (args[i] == "-t") + { + numThreads = Convert.ToInt32(args[++i]); + } + else if (args[i] == "--compact" || args[i] == "--protocol=compact" || args[i] == "--protocol=multic") + { + param.protocol = "compact"; + Console.WriteLine("Using compact protocol"); + } + else if (args[i] == "--json" || args[i] == "--protocol=json" || args[i] == "--protocol=multij") + { + param.protocol = "json"; + Console.WriteLine("Using JSON protocol"); + } + else if (args[i] == "--ssl") + { + param.encrypted = true; + Console.WriteLine("Using encrypted transport"); + } + + if (args[i].StartsWith("--protocol=multi")) + { + param.multiplexed = true; + } + } + } + catch (Exception ex) + { + Console.WriteLine("*** FAILED ***"); + Console.WriteLine("Error while parsing arguments"); + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + return ErrorUnknown; + } + + var tests = Enumerable.Range(0, numThreads).Select(_ => new ClientTest(param)).ToArray(); + //issue tests on separate threads simultaneously + var threads = tests.Select(test => new Thread(test.Execute)).ToArray(); + DateTime start = DateTime.Now; + foreach (var t in threads) + t.Start(); + foreach (var t in threads) + t.Join(); + Console.WriteLine("Total time: " + (DateTime.Now - start)); + Console.WriteLine(); + return tests.Select(t => t.ReturnCode).Aggregate((r1, r2) => r1 | r2); + } + catch (Exception outerEx) + { + Console.WriteLine("*** FAILED ***"); + Console.WriteLine("Unexpected error"); + Console.WriteLine(outerEx.Message + " ST: " + outerEx.StackTrace); + return ErrorUnknown; + } + } + + public static string BytesToHex(byte[] data) { + return BitConverter.ToString(data).Replace("-", string.Empty); + } + + public static byte[] PrepareTestData(bool randomDist, bool huge) + { + // huge = true tests for THRIFT-4372 + byte[] retval = new byte[huge ? 0x12345 : 0x100]; + int initLen = retval.Length; + + // linear distribution, unless random is requested + if (!randomDist) { + for (var i = 0; i < initLen; ++i) { + retval[i] = (byte)i; + } + return retval; + } + + // random distribution + for (var i = 0; i < initLen; ++i) { + retval[i] = (byte)0; + } + var rnd = new Random(); + for (var i = 1; i < initLen; ++i) { + while( true) { + int nextPos = rnd.Next() % initLen; + if (retval[nextPos] == 0) { + retval[nextPos] = (byte)i; + break; + } + } + } + return retval; + } + + public static int ExecuteClientTest(ThriftTest.Client client, SecondService.Client second, TestParams param) + { + int returnCode = 0; + + Console.Write("testVoid()"); + client.testVoid(); + Console.WriteLine(" = void"); + + Console.Write("testString(\"Test\")"); + string s = client.testString("Test"); + Console.WriteLine(" = \"" + s + "\""); + if ("Test" != s) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + + if (param.multiplexed) + { + Console.WriteLine("secondTestString(\"Test2\")"); + s = second.secondtestString("Test2"); + Console.WriteLine(" = \"" + s + "\""); + if ("testString(\"Test2\")" != s) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorProtocol; + } + } + + Console.Write("testBool(true)"); + bool t = client.testBool((bool)true); + Console.WriteLine(" = " + t); + if (!t) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + Console.Write("testBool(false)"); + bool f = client.testBool((bool)false); + Console.WriteLine(" = " + f); + if (f) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + + Console.Write("testByte(1)"); + sbyte i8 = client.testByte((sbyte)1); + Console.WriteLine(" = " + i8); + if (1 != i8) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + + Console.Write("testI32(-1)"); + int i32 = client.testI32(-1); + Console.WriteLine(" = " + i32); + if (-1 != i32) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + + Console.Write("testI64(-34359738368)"); + long i64 = client.testI64(-34359738368); + Console.WriteLine(" = " + i64); + if (-34359738368 != i64) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + + // TODO: Validate received message + Console.Write("testDouble(5.325098235)"); + double dub = client.testDouble(5.325098235); + Console.WriteLine(" = " + dub); + if (5.325098235 != dub) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + Console.Write("testDouble(-0.000341012439638598279)"); + dub = client.testDouble(-0.000341012439638598279); + Console.WriteLine(" = " + dub); + if (-0.000341012439638598279 != dub) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + + for (i32 = 0; i32 < 2; ++i32) + { + var huge = (i32 > 0); + byte[] binOut = PrepareTestData(false,huge); + Console.Write("testBinary(" + BytesToHex(binOut) + ")"); + try + { + byte[] binIn = client.testBinary(binOut); + Console.WriteLine(" = " + BytesToHex(binIn)); + if (binIn.Length != binOut.Length) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + for (int ofs = 0; ofs < Math.Min(binIn.Length, binOut.Length); ++ofs) + if (binIn[ofs] != binOut[ofs]) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + } + catch (Thrift.TApplicationException ex) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + } + } + + // binary equals? only with hashcode option enabled ... + Console.WriteLine("Test CrazyNesting"); + if( typeof(CrazyNesting).GetMethod("Equals").DeclaringType == typeof(CrazyNesting)) + { + CrazyNesting one = new CrazyNesting(); + CrazyNesting two = new CrazyNesting(); + one.String_field = "crazy"; + two.String_field = "crazy"; + one.Binary_field = new byte[10] { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0xFF }; + two.Binary_field = new byte[10] { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0xFF }; + if (!one.Equals(two)) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorContainers; + throw new Exception("CrazyNesting.Equals failed"); + } + } + + // TODO: Validate received message + Console.Write("testStruct({\"Zero\", 1, -3, -5})"); + Xtruct o = new Xtruct(); + o.String_thing = "Zero"; + o.Byte_thing = (sbyte)1; + o.I32_thing = -3; + o.I64_thing = -5; + Xtruct i = client.testStruct(o); + Console.WriteLine(" = {\"" + i.String_thing + "\", " + i.Byte_thing + ", " + i.I32_thing + ", " + i.I64_thing + "}"); + + // TODO: Validate received message + Console.Write("testNest({1, {\"Zero\", 1, -3, -5}, 5})"); + Xtruct2 o2 = new Xtruct2(); + o2.Byte_thing = (sbyte)1; + o2.Struct_thing = o; + o2.I32_thing = 5; + Xtruct2 i2 = client.testNest(o2); + i = i2.Struct_thing; + Console.WriteLine(" = {" + i2.Byte_thing + ", {\"" + i.String_thing + "\", " + i.Byte_thing + ", " + i.I32_thing + ", " + i.I64_thing + "}, " + i2.I32_thing + "}"); + + Dictionary<int, int> mapout = new Dictionary<int, int>(); + for (int j = 0; j < 5; j++) + { + mapout[j] = j - 10; + } + Console.Write("testMap({"); + bool first = true; + foreach (int key in mapout.Keys) + { + if (first) + { + first = false; + } + else + { + Console.Write(", "); + } + Console.Write(key + " => " + mapout[key]); + } + Console.Write("})"); + + Dictionary<int, int> mapin = client.testMap(mapout); + + Console.Write(" = {"); + first = true; + foreach (int key in mapin.Keys) + { + if (first) + { + first = false; + } + else + { + Console.Write(", "); + } + Console.Write(key + " => " + mapin[key]); + } + Console.WriteLine("}"); + + // TODO: Validate received message + List<int> listout = new List<int>(); + for (int j = -2; j < 3; j++) + { + listout.Add(j); + } + Console.Write("testList({"); + first = true; + foreach (int j in listout) + { + if (first) + { + first = false; + } + else + { + Console.Write(", "); + } + Console.Write(j); + } + Console.Write("})"); + + List<int> listin = client.testList(listout); + + Console.Write(" = {"); + first = true; + foreach (int j in listin) + { + if (first) + { + first = false; + } + else + { + Console.Write(", "); + } + Console.Write(j); + } + Console.WriteLine("}"); + + //set + // TODO: Validate received message + THashSet<int> setout = new THashSet<int>(); + for (int j = -2; j < 3; j++) + { + setout.Add(j); + } + Console.Write("testSet({"); + first = true; + foreach (int j in setout) + { + if (first) + { + first = false; + } + else + { + Console.Write(", "); + } + Console.Write(j); + } + Console.Write("})"); + + THashSet<int> setin = client.testSet(setout); + + Console.Write(" = {"); + first = true; + foreach (int j in setin) + { + if (first) + { + first = false; + } + else + { + Console.Write(", "); + } + Console.Write(j); + } + Console.WriteLine("}"); + + + Console.Write("testEnum(ONE)"); + Numberz ret = client.testEnum(Numberz.ONE); + Console.WriteLine(" = " + ret); + if (Numberz.ONE != ret) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorStructs; + } + + Console.Write("testEnum(TWO)"); + ret = client.testEnum(Numberz.TWO); + Console.WriteLine(" = " + ret); + if (Numberz.TWO != ret) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorStructs; + } + + Console.Write("testEnum(THREE)"); + ret = client.testEnum(Numberz.THREE); + Console.WriteLine(" = " + ret); + if (Numberz.THREE != ret) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorStructs; + } + + Console.Write("testEnum(FIVE)"); + ret = client.testEnum(Numberz.FIVE); + Console.WriteLine(" = " + ret); + if (Numberz.FIVE != ret) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorStructs; + } + + Console.Write("testEnum(EIGHT)"); + ret = client.testEnum(Numberz.EIGHT); + Console.WriteLine(" = " + ret); + if (Numberz.EIGHT != ret) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorStructs; + } + + Console.Write("testTypedef(309858235082523)"); + long uid = client.testTypedef(309858235082523L); + Console.WriteLine(" = " + uid); + if (309858235082523L != uid) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorStructs; + } + + // TODO: Validate received message + Console.Write("testMapMap(1)"); + Dictionary<int, Dictionary<int, int>> mm = client.testMapMap(1); + Console.Write(" = {"); + foreach (int key in mm.Keys) + { + Console.Write(key + " => {"); + Dictionary<int, int> m2 = mm[key]; + foreach (int k2 in m2.Keys) + { + Console.Write(k2 + " => " + m2[k2] + ", "); + } + Console.Write("}, "); + } + Console.WriteLine("}"); + + // TODO: Validate received message + Insanity insane = new Insanity(); + insane.UserMap = new Dictionary<Numberz, long>(); + insane.UserMap[Numberz.FIVE] = 5000L; + Xtruct truck = new Xtruct(); + truck.String_thing = "Truck"; + truck.Byte_thing = (sbyte)8; + truck.I32_thing = 8; + truck.I64_thing = 8; + insane.Xtructs = new List<Xtruct>(); + insane.Xtructs.Add(truck); + Console.Write("testInsanity()"); + Dictionary<long, Dictionary<Numberz, Insanity>> whoa = client.testInsanity(insane); + Console.Write(" = {"); + foreach (long key in whoa.Keys) + { + Dictionary<Numberz, Insanity> val = whoa[key]; + Console.Write(key + " => {"); + + foreach (Numberz k2 in val.Keys) + { + Insanity v2 = val[k2]; + + Console.Write(k2 + " => {"); + Dictionary<Numberz, long> userMap = v2.UserMap; + + Console.Write("{"); + if (userMap != null) + { + foreach (Numberz k3 in userMap.Keys) + { + Console.Write(k3 + " => " + userMap[k3] + ", "); + } + } + else + { + Console.Write("null"); + } + Console.Write("}, "); + + List<Xtruct> xtructs = v2.Xtructs; + + Console.Write("{"); + if (xtructs != null) + { + foreach (Xtruct x in xtructs) + { + Console.Write("{\"" + x.String_thing + "\", " + x.Byte_thing + ", " + x.I32_thing + ", " + x.I32_thing + "}, "); + } + } + else + { + Console.Write("null"); + } + Console.Write("}"); + + Console.Write("}, "); + } + Console.Write("}, "); + } + Console.WriteLine("}"); + + sbyte arg0 = 1; + int arg1 = 2; + long arg2 = long.MaxValue; + Dictionary<short, string> multiDict = new Dictionary<short, string>(); + multiDict[1] = "one"; + Numberz arg4 = Numberz.FIVE; + long arg5 = 5000000; + Console.Write("Test Multi(" + arg0 + "," + arg1 + "," + arg2 + "," + multiDict + "," + arg4 + "," + arg5 + ")"); + Xtruct multiResponse = client.testMulti(arg0, arg1, arg2, multiDict, arg4, arg5); + Console.Write(" = Xtruct(byte_thing:" + multiResponse.Byte_thing + ",String_thing:" + multiResponse.String_thing + + ",i32_thing:" + multiResponse.I32_thing + ",i64_thing:" + multiResponse.I64_thing + ")\n"); + + try + { + Console.WriteLine("testException(\"Xception\")"); + client.testException("Xception"); + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + } + catch (Xception ex) + { + if (ex.ErrorCode != 1001 || ex.Message != "Xception") + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + } + } + catch (Exception ex) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + } + try + { + Console.WriteLine("testException(\"TException\")"); + client.testException("TException"); + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + } + catch (Thrift.TException) + { + // OK + } + catch (Exception ex) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + } + try + { + Console.WriteLine("testException(\"ok\")"); + client.testException("ok"); + // OK + } + catch (Exception ex) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + } + + try + { + Console.WriteLine("testMultiException(\"Xception\", ...)"); + client.testMultiException("Xception", "ignore"); + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + } + catch (Xception ex) + { + if (ex.ErrorCode != 1001 || ex.Message != "This is an Xception") + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + } + } + catch (Exception ex) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + } + try + { + Console.WriteLine("testMultiException(\"Xception2\", ...)"); + client.testMultiException("Xception2", "ignore"); + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + } + catch (Xception2 ex) + { + if (ex.ErrorCode != 2002 || ex.Struct_thing.String_thing != "This is an Xception2") + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + } + } + catch (Exception ex) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + } + try + { + Console.WriteLine("testMultiException(\"success\", \"OK\")"); + if ("OK" != client.testMultiException("success", "OK").String_thing) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + } + } + catch (Exception ex) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + } + + Stopwatch sw = new Stopwatch(); + sw.Start(); + Console.WriteLine("Test Oneway(1)"); + client.testOneway(1); + sw.Stop(); + if (sw.ElapsedMilliseconds > 1000) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + + Console.Write("Test Calltime()"); + var times = 50; + sw.Reset(); + sw.Start(); + for (int k = 0; k < times; ++k) + client.testVoid(); + sw.Stop(); + Console.WriteLine(" = {0} ms a testVoid() call", sw.ElapsedMilliseconds / times); + return returnCode; + } + } +} diff --git a/src/jaegertracing/thrift/test/csharp/TestServer.cs b/src/jaegertracing/thrift/test/csharp/TestServer.cs new file mode 100644 index 000000000..bf645c26c --- /dev/null +++ b/src/jaegertracing/thrift/test/csharp/TestServer.cs @@ -0,0 +1,535 @@ +/* + * 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. + */ + +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ +using System; +using System.Collections.Generic; +using System.Security.Cryptography.X509Certificates; +using Thrift.Collections; +using Thrift.Test; //generated code +using Thrift.Transport; +using Thrift.Protocol; +using Thrift.Server; +using Thrift; +using System.Threading; +using System.Text; +using System.Security.Authentication; + +namespace Test +{ + public class TestServer + { + public static int _clientID = -1; + public delegate void TestLogDelegate(string msg, params object[] values); + + public class TradeServerEventHandler : TServerEventHandler + { + public int callCount = 0; + public void preServe() + { + callCount++; + } + public Object createContext(Thrift.Protocol.TProtocol input, Thrift.Protocol.TProtocol output) + { + callCount++; + return null; + } + public void deleteContext(Object serverContext, Thrift.Protocol.TProtocol input, Thrift.Protocol.TProtocol output) + { + callCount++; + } + public void processContext(Object serverContext, Thrift.Transport.TTransport transport) + { + callCount++; + } + }; + + + public class TestHandler : ThriftTest.Iface, Thrift.TControllingHandler + { + public TServer server { get; set; } + private int handlerID; + private StringBuilder reusableStringBuilder = new StringBuilder(); + private TestLogDelegate testLogDelegate; + + public TestHandler() + { + handlerID = Interlocked.Increment(ref _clientID); + testLogDelegate += testConsoleLogger; + testLogDelegate.Invoke("New TestHandler instance created"); + } + + public void testConsoleLogger(string msg, params object[] values) + { + reusableStringBuilder.Clear(); + reusableStringBuilder.AppendFormat("handler{0:D3}:",handlerID); + reusableStringBuilder.AppendFormat(msg, values); + reusableStringBuilder.AppendLine(); + Console.Write( reusableStringBuilder.ToString() ); + } + + public void testVoid() + { + testLogDelegate.Invoke("testVoid()"); + } + + public string testString(string thing) + { + testLogDelegate.Invoke("testString({0})", thing); + return thing; + } + + public bool testBool(bool thing) + { + testLogDelegate.Invoke("testBool({0})", thing); + return thing; + } + + public sbyte testByte(sbyte thing) + { + testLogDelegate.Invoke("testByte({0})", thing); + return thing; + } + + public int testI32(int thing) + { + testLogDelegate.Invoke("testI32({0})", thing); + return thing; + } + + public long testI64(long thing) + { + testLogDelegate.Invoke("testI64({0})", thing); + return thing; + } + + public double testDouble(double thing) + { + testLogDelegate.Invoke("testDouble({0})", thing); + return thing; + } + + public byte[] testBinary(byte[] thing) + { + string hex = BitConverter.ToString(thing).Replace("-", string.Empty); + testLogDelegate.Invoke("testBinary({0:X})", hex); + return thing; + } + + public Xtruct testStruct(Xtruct thing) + { + testLogDelegate.Invoke("testStruct({{\"{0}\", {1}, {2}, {3}}})", thing.String_thing, thing.Byte_thing, thing.I32_thing, thing.I64_thing); + return thing; + } + + public Xtruct2 testNest(Xtruct2 nest) + { + Xtruct thing = nest.Struct_thing; + testLogDelegate.Invoke("testNest({{{0}, {{\"{1}\", {2}, {3}, {4}, {5}}}}})", + nest.Byte_thing, + thing.String_thing, + thing.Byte_thing, + thing.I32_thing, + thing.I64_thing, + nest.I32_thing); + return nest; + } + + public Dictionary<int, int> testMap(Dictionary<int, int> thing) + { + reusableStringBuilder.Clear(); + reusableStringBuilder.Append("testMap({{"); + bool first = true; + foreach (int key in thing.Keys) + { + if (first) + { + first = false; + } + else + { + reusableStringBuilder.Append(", "); + } + reusableStringBuilder.AppendFormat("{0} => {1}", key, thing[key]); + } + reusableStringBuilder.Append("}})"); + testLogDelegate.Invoke(reusableStringBuilder.ToString()); + return thing; + } + + public Dictionary<string, string> testStringMap(Dictionary<string, string> thing) + { + reusableStringBuilder.Clear(); + reusableStringBuilder.Append("testStringMap({{"); + bool first = true; + foreach (string key in thing.Keys) + { + if (first) + { + first = false; + } + else + { + reusableStringBuilder.Append(", "); + } + reusableStringBuilder.AppendFormat("{0} => {1}", key, thing[key]); + } + reusableStringBuilder.Append("}})"); + testLogDelegate.Invoke(reusableStringBuilder.ToString()); + return thing; + } + + public THashSet<int> testSet(THashSet<int> thing) + { + reusableStringBuilder.Clear(); + reusableStringBuilder.Append("testSet({{"); + bool first = true; + foreach (int elem in thing) + { + if (first) + { + first = false; + } + else + { + reusableStringBuilder.Append(", "); + } + reusableStringBuilder.AppendFormat("{0}", elem); + } + reusableStringBuilder.Append("}})"); + testLogDelegate.Invoke(reusableStringBuilder.ToString()); + return thing; + } + + public List<int> testList(List<int> thing) + { + reusableStringBuilder.Clear(); + reusableStringBuilder.Append("testList({{"); + bool first = true; + foreach (int elem in thing) + { + if (first) + { + first = false; + } + else + { + reusableStringBuilder.Append(", "); + } + reusableStringBuilder.AppendFormat("{0}", elem); + } + reusableStringBuilder.Append("}})"); + testLogDelegate.Invoke(reusableStringBuilder.ToString()); + return thing; + } + + public Numberz testEnum(Numberz thing) + { + testLogDelegate.Invoke("testEnum({0})", thing); + return thing; + } + + public long testTypedef(long thing) + { + testLogDelegate.Invoke("testTypedef({0})", thing); + return thing; + } + + public Dictionary<int, Dictionary<int, int>> testMapMap(int hello) + { + testLogDelegate.Invoke("testMapMap({0})", hello); + Dictionary<int, Dictionary<int, int>> mapmap = + new Dictionary<int, Dictionary<int, int>>(); + + Dictionary<int, int> pos = new Dictionary<int, int>(); + Dictionary<int, int> neg = new Dictionary<int, int>(); + for (int i = 1; i < 5; i++) + { + pos[i] = i; + neg[-i] = -i; + } + + mapmap[4] = pos; + mapmap[-4] = neg; + + return mapmap; + } + + // Insanity + // returns: + // { 1 => { 2 => argument, + // 3 => argument, + // }, + // 2 => { 6 => <empty Insanity struct>, }, + // } + public Dictionary<long, Dictionary<Numberz, Insanity>> testInsanity(Insanity argument) + { + testLogDelegate.Invoke("testInsanity()"); + + Dictionary<Numberz, Insanity> first_map = new Dictionary<Numberz, Insanity>(); + Dictionary<Numberz, Insanity> second_map = new Dictionary<Numberz, Insanity>(); ; + + first_map[Numberz.TWO] = argument; + first_map[Numberz.THREE] = argument; + + second_map[Numberz.SIX] = new Insanity(); + + Dictionary<long, Dictionary<Numberz, Insanity>> insane = + new Dictionary<long, Dictionary<Numberz, Insanity>>(); + insane[(long)1] = first_map; + insane[(long)2] = second_map; + + return insane; + } + + public Xtruct testMulti(sbyte arg0, int arg1, long arg2, Dictionary<short, string> arg3, Numberz arg4, long arg5) + { + testLogDelegate.Invoke("testMulti()"); + + Xtruct hello = new Xtruct(); ; + hello.String_thing = "Hello2"; + hello.Byte_thing = arg0; + hello.I32_thing = arg1; + hello.I64_thing = arg2; + return hello; + } + + /** + * Print 'testException(%s)' with arg as '%s' + * @param string arg - a string indication what type of exception to throw + * if arg == "Xception" throw Xception with errorCode = 1001 and message = arg + * elsen if arg == "TException" throw TException + * else do not throw anything + */ + public void testException(string arg) + { + testLogDelegate.Invoke("testException({0})", arg); + if (arg == "Xception") + { + Xception x = new Xception(); + x.ErrorCode = 1001; + x.Message = arg; + throw x; + } + if (arg == "TException") + { + throw new Thrift.TException(); + } + return; + } + + public Xtruct testMultiException(string arg0, string arg1) + { + testLogDelegate.Invoke("testMultiException({0}, {1})", arg0,arg1); + if (arg0 == "Xception") + { + Xception x = new Xception(); + x.ErrorCode = 1001; + x.Message = "This is an Xception"; + throw x; + } + else if (arg0 == "Xception2") + { + Xception2 x = new Xception2(); + x.ErrorCode = 2002; + x.Struct_thing = new Xtruct(); + x.Struct_thing.String_thing = "This is an Xception2"; + throw x; + } + + Xtruct result = new Xtruct(); + result.String_thing = arg1; + return result; + } + + public void testStop() + { + if (server != null) + { + server.Stop(); + } + } + + public void testOneway(int arg) + { + testLogDelegate.Invoke("testOneway({0}), sleeping...", arg); + System.Threading.Thread.Sleep(arg * 1000); + testLogDelegate.Invoke("testOneway finished"); + } + + } // class TestHandler + + private enum ServerType + { + TSimpleServer, + TThreadedServer, + TThreadPoolServer, + } + + private enum ProcessorFactoryType + { + TSingletonProcessorFactory, + TPrototypeProcessorFactory, + } + + public static bool Execute(string[] args) + { + try + { + bool useBufferedSockets = false, useFramed = false, useEncryption = false, compact = false, json = false; + ServerType serverType = ServerType.TSimpleServer; + ProcessorFactoryType processorFactoryType = ProcessorFactoryType.TSingletonProcessorFactory; + int port = 9090; + string pipe = null; + for (int i = 0; i < args.Length; i++) + { + if (args[i] == "-pipe") // -pipe name + { + pipe = args[++i]; + } + else if (args[i].Contains("--port=")) + { + port = int.Parse(args[i].Substring(args[i].IndexOf("=") + 1)); + } + else if (args[i] == "-b" || args[i] == "--buffered" || args[i] == "--transport=buffered") + { + useBufferedSockets = true; + } + else if (args[i] == "-f" || args[i] == "--framed" || args[i] == "--transport=framed") + { + useFramed = true; + } + else if (args[i] == "--compact" || args[i] == "--protocol=compact") + { + compact = true; + } + else if (args[i] == "--json" || args[i] == "--protocol=json") + { + json = true; + } + else if (args[i] == "--threaded" || args[i] == "--server-type=threaded") + { + serverType = ServerType.TThreadedServer; + } + else if (args[i] == "--threadpool" || args[i] == "--server-type=threadpool") + { + serverType = ServerType.TThreadPoolServer; + } + else if (args[i] == "--prototype" || args[i] == "--processor=prototype") + { + processorFactoryType = ProcessorFactoryType.TPrototypeProcessorFactory; + } + else if (args[i] == "--ssl") + { + useEncryption = true; + } + } + + // Transport + TServerTransport trans; + if (pipe != null) + { + trans = new TNamedPipeServerTransport(pipe); + } + else + { + if (useEncryption) + { + string certPath = "../keys/server.p12"; + trans = new TTLSServerSocket(port, 0, useBufferedSockets, new X509Certificate2(certPath, "thrift"), + null, + null, SslProtocols.Tls); + } + else + { + trans = new TServerSocket(port, 0, useBufferedSockets); + } + } + + TProtocolFactory proto; + if (compact) + proto = new TCompactProtocol.Factory(); + else if (json) + proto = new TJSONProtocol.Factory(); + else + proto = new TBinaryProtocol.Factory(); + + TProcessorFactory processorFactory; + if (processorFactoryType == ProcessorFactoryType.TPrototypeProcessorFactory) + { + processorFactory = new TPrototypeProcessorFactory<ThriftTest.Processor, TestHandler>(); + } + else + { + // Processor + TestHandler testHandler = new TestHandler(); + ThriftTest.Processor testProcessor = new ThriftTest.Processor(testHandler); + processorFactory = new TSingletonProcessorFactory(testProcessor); + } + + TTransportFactory transFactory; + if (useFramed) + transFactory = new TFramedTransport.Factory(); + else + transFactory = new TTransportFactory(); + + TServer serverEngine; + switch (serverType) + { + case ServerType.TThreadPoolServer: + serverEngine = new TThreadPoolServer(processorFactory, trans, transFactory, proto); + break; + case ServerType.TThreadedServer: + serverEngine = new TThreadedServer(processorFactory, trans, transFactory, proto); + break; + default: + serverEngine = new TSimpleServer(processorFactory, trans, transFactory, proto); + break; + } + + //Server event handler + TradeServerEventHandler serverEvents = new TradeServerEventHandler(); + serverEngine.setEventHandler(serverEvents); + + // Run it + string where = (pipe != null ? "on pipe " + pipe : "on port " + port); + Console.WriteLine("Starting the " + serverType.ToString() + " " + where + + (processorFactoryType == ProcessorFactoryType.TPrototypeProcessorFactory ? " with processor prototype factory " : "") + + (useBufferedSockets ? " with buffered socket" : "") + + (useFramed ? " with framed transport" : "") + + (useEncryption ? " with encryption" : "") + + (compact ? " with compact protocol" : "") + + (json ? " with json protocol" : "") + + "..."); + serverEngine.Serve(); + + } + catch (Exception x) + { + Console.Error.Write(x); + return false; + } + Console.WriteLine("done."); + return true; + } + } +} diff --git a/src/jaegertracing/thrift/test/csharp/ThriftTest.csproj b/src/jaegertracing/thrift/test/csharp/ThriftTest.csproj new file mode 100644 index 000000000..effec1979 --- /dev/null +++ b/src/jaegertracing/thrift/test/csharp/ThriftTest.csproj @@ -0,0 +1,141 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + 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. +--> +<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProductVersion>9.0.21022</ProductVersion> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{48DD757F-CA95-4DD7-BDA4-58DB6F108C2C}</ProjectGuid> + <OutputType>Exe</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>ThriftTest</RootNamespace> + <AssemblyName>ThriftTest</AssemblyName> + <TargetFrameworkVersion>v3.5</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <IsWebBootstrapper>false</IsWebBootstrapper> + <FileUpgradeFlags> + </FileUpgradeFlags> + <OldToolsVersion>3.5</OldToolsVersion> + <UpgradeBackupLocation /> + <PublishUrl>publish\</PublishUrl> + <Install>true</Install> + <InstallFrom>Disk</InstallFrom> + <UpdateEnabled>false</UpdateEnabled> + <UpdateMode>Foreground</UpdateMode> + <UpdateInterval>7</UpdateInterval> + <UpdateIntervalUnits>Days</UpdateIntervalUnits> + <UpdatePeriodically>false</UpdatePeriodically> + <UpdateRequired>false</UpdateRequired> + <MapFileExtensions>true</MapFileExtensions> + <ApplicationRevision>0</ApplicationRevision> + <ApplicationVersion>0.13.0.0</ApplicationVersion> + <UseApplicationTrust>false</UseApplicationTrust> + <BootstrapperEnabled>true</BootstrapperEnabled> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet> + </PropertyGroup> + <ItemGroup> + <Reference Include="System" /> + <Reference Include="ThriftImpl, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>.\ThriftImpl.dll</HintPath> + </Reference> + </ItemGroup> + <ItemGroup> + <Compile Include="Program.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="TestClient.cs" /> + <Compile Include="TestServer.cs" /> + </ItemGroup> + <ItemGroup> + <BootstrapperPackage Include="Microsoft.Net.Client.3.5"> + <Visible>False</Visible> + <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName> + <Install>false</Install> + </BootstrapperPackage> + <BootstrapperPackage Include="Microsoft.Net.Framework.2.0"> + <Visible>False</Visible> + <ProductName>.NET Framework 2.0 %28x86%29</ProductName> + <Install>false</Install> + </BootstrapperPackage> + <BootstrapperPackage Include="Microsoft.Net.Framework.3.0"> + <Visible>False</Visible> + <ProductName>.NET Framework 3.0 %28x86%29</ProductName> + <Install>false</Install> + </BootstrapperPackage> + <BootstrapperPackage Include="Microsoft.Net.Framework.3.5"> + <Visible>False</Visible> + <ProductName>.NET Framework 3.5</ProductName> + <Install>true</Install> + </BootstrapperPackage> + <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1"> + <Visible>False</Visible> + <ProductName>.NET Framework 3.5 SP1</ProductName> + <Install>false</Install> + </BootstrapperPackage> + <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1"> + <Visible>False</Visible> + <ProductName>Windows Installer 3.1</ProductName> + <Install>true</Install> + </BootstrapperPackage> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\..\lib\csharp\Thrift.csproj"> + <Project>{499EB63C-D74C-47E8-AE48-A2FC94538E9D}</Project> + <Name>Thrift</Name> + </ProjectReference> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <!-- To modify your build process, add your task inside one of the targets below and uncomment it. + Other similar extension points exist, see Microsoft.Common.targets. + <Target Name="BeforeBuild"> + </Target> + <Target Name="AfterBuild"> + </Target> + --> + <PropertyGroup> + <PreBuildEvent>rmdir /s /q "$(ProjectDir)gen-csharp" +del /f /q "$(ProjectDir)ThriftImpl.dll" +SET OUTPUT_DIR=$(ProjectDir) +SET THRIFT_FILE=$(ProjectDir)\..\ThriftTest.thrift +for %25%25I in ("%25OUTPUT_DIR%25") do set SHORT_DIR=%25%25~fsI +for %25%25I in ("%25THRIFT_FILE%25") do set THRIFT_SHORT=%25%25~fsI +"$(ProjectDir)\..\..\compiler\cpp\thrift.exe" --gen csharp -o %25SHORT_DIR%25 %25THRIFT_SHORT%25 +$(MSBuildToolsPath)\Csc.exe /t:library /out:"$(ProjectDir)ThriftImpl.dll" /recurse:"$(ProjectDir)gen-csharp"\* /reference:"$(ProjectDir)..\..\lib\csharp\bin\Debug\Thrift.dll"</PreBuildEvent> + </PropertyGroup> +</Project> diff --git a/src/jaegertracing/thrift/test/csharp/ThriftTest.sln b/src/jaegertracing/thrift/test/csharp/ThriftTest.sln new file mode 100644 index 000000000..1765a03ad --- /dev/null +++ b/src/jaegertracing/thrift/test/csharp/ThriftTest.sln @@ -0,0 +1,17 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThriftTest", "ThriftTest.csproj", "{48DD757F-CA95-4DD7-BDA4-58DB6F108C2C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {48DD757F-CA95-4DD7-BDA4-58DB6F108C2C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {48DD757F-CA95-4DD7-BDA4-58DB6F108C2C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {48DD757F-CA95-4DD7-BDA4-58DB6F108C2C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {48DD757F-CA95-4DD7-BDA4-58DB6F108C2C}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/src/jaegertracing/thrift/test/dart/Makefile.am b/src/jaegertracing/thrift/test/dart/Makefile.am new file mode 100644 index 000000000..27fdc099f --- /dev/null +++ b/src/jaegertracing/thrift/test/dart/Makefile.am @@ -0,0 +1,52 @@ +# +# 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. +# + +gen-dart/thrift_test/lib/thrift_test.dart: ../ThriftTest.thrift + $(THRIFT) --gen dart ../ThriftTest.thrift + +pub-get-gen: gen-dart/thrift_test/lib/thrift_test.dart + cd gen-dart/thrift_test; ${DARTPUB} get + +pub-get: pub-get-gen + cd test_client; ${DARTPUB} get + +stubs: gen-dart/thrift_test/lib/thrift_test.dart pub-get + +precross: stubs + +check: stubs + +clean-local: + $(RM) -r gen-dart/ test_client/.pub + find . -type d -name ".dart_tool" | xargs $(RM) -r + find . -type d -name "packages" | xargs $(RM) -r + find . -type f -name ".packages" | xargs $(RM) + find . -type f -name "pubspec.lock" | xargs $(RM) + +dist-hook: + $(RM) -r $(distdir)/gen-dart/ $(distdir)/test_client/.pub + find $(distdir) -type d -name ".dart_tool" | xargs $(RM) -r + find $(distdir) -type d -name "packages" | xargs $(RM) -r + find $(distdir) -type f -name ".packages" | xargs $(RM) + +client: stubs + ${DART} test_client/bin/main.dart + +EXTRA_DIST = \ + test_client diff --git a/src/jaegertracing/thrift/test/dart/test_client/.analysis_options b/src/jaegertracing/thrift/test/dart/test_client/.analysis_options new file mode 100644 index 000000000..a10d4c5a0 --- /dev/null +++ b/src/jaegertracing/thrift/test/dart/test_client/.analysis_options @@ -0,0 +1,2 @@ +analyzer: + strong-mode: true diff --git a/src/jaegertracing/thrift/test/dart/test_client/bin/main.dart b/src/jaegertracing/thrift/test/dart/test_client/bin/main.dart new file mode 100644 index 000000000..feba61299 --- /dev/null +++ b/src/jaegertracing/thrift/test/dart/test_client/bin/main.dart @@ -0,0 +1,337 @@ +/// 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. + +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; + +import 'package:args/args.dart'; +import 'package:collection/collection.dart'; +import 'package:http/http.dart' as http; +import 'package:thrift/thrift.dart'; +import 'package:thrift/thrift_console.dart'; +import 'package:thrift_test/thrift_test.dart'; + +const TEST_BASETYPES = 1; // 0000 0001 +const TEST_STRUCTS = 2; // 0000 0010 +const TEST_CONTAINERS = 4; // 0000 0100 +const TEST_EXCEPTIONS = 8; // 0000 1000 +const TEST_UNKNOWN = 64; // 0100 0000 (Failed to prepare environemt etc.) +const TEST_TIMEOUT = 128; // 1000 0000 +const TEST_NOTUSED = 48; // 0011 0000 (reserved bits) + +typedef Future FutureFunction(); + +class TTest { + final int errorCode; + final String name; + final FutureFunction func; + + TTest(this.errorCode, this.name, this.func); +} + +class TTestError extends Error { + final actual; + final expected; + + TTestError(this.actual, this.expected); + + String toString() => '$actual != $expected'; +} + +List<TTest> _tests; +ThriftTestClient client; +bool verbose; + +/// Adapted from TestClient.php +main(List<String> args) async { + ArgResults results = _parseArgs(args); + + if (results == null) { + exit(TEST_UNKNOWN); + } + + verbose = results['verbose'] == true; + + await _initTestClient( + host: results['host'], + port: int.parse(results['port']), + transportType: results['transport'], + protocolType: results['protocol']).catchError((e) { + stdout.writeln('Error:'); + stdout.writeln('$e'); + if (e is Error) { + stdout.writeln('${e.stackTrace}'); + } + exit(TEST_UNKNOWN); + }); + + // run tests + _tests = _createTests(); + + int result = 0; + + for (TTest test in _tests) { + if (verbose) stdout.write('${test.name}... '); + try { + await test.func(); + if (verbose) stdout.writeln('success!'); + } catch (e) { + if (verbose) stdout.writeln('$e'); + result = result | test.errorCode; + } + } + + exit(result); +} + +ArgResults _parseArgs(List<String> args) { + var parser = new ArgParser(); + parser.addOption('host', defaultsTo: 'localhost', help: 'The server host'); + parser.addOption('port', defaultsTo: '9090', help: 'The port to connect to'); + parser.addOption('transport', + defaultsTo: 'buffered', + allowed: ['buffered', 'framed', 'http'], + help: 'The transport name', + allowedHelp: { + 'buffered': 'TBufferedTransport', + 'framed': 'TFramedTransport' + }); + parser.addOption('protocol', + defaultsTo: 'binary', + allowed: ['binary', 'compact', 'json'], + help: 'The protocol name', + allowedHelp: { + 'binary': 'TBinaryProtocol', + 'compact': 'TCompactProtocol', + 'json': 'TJsonProtocol' + }); + parser.addFlag('verbose', defaultsTo: true); + + ArgResults results; + try { + results = parser.parse(args); + } catch (e) { + stdout.writeln('$e\n'); + } + + if (results == null) stdout.write(parser.usage); + + return results; +} + +TProtocolFactory getProtocolFactory(String protocolType) { + if (protocolType == 'binary') { + return new TBinaryProtocolFactory(); + } else if (protocolType == 'compact') { + return new TCompactProtocolFactory(); + } else if (protocolType == 'json') { + return new TJsonProtocolFactory(); + } + + throw new ArgumentError.value(protocolType); +} + +Future _initTestClient( + {String host, int port, String transportType, String protocolType}) async { + TTransport transport; + var protocolFactory = getProtocolFactory(protocolType); + + if (transportType == 'http') { + var httpClient = new http.IOClient(); + var uri = Uri.parse('http://$host:$port'); + var config = new THttpConfig(uri, {}); + transport = new THttpClientTransport(httpClient, config); + } else { + var socket = await Socket.connect(host, port); + transport = new TClientSocketTransport(new TTcpSocket(socket)); + if (transportType == 'framed') { + transport = new TFramedTransport(transport); + } + } + + var protocol = protocolFactory.getProtocol(transport); + client = new ThriftTestClient(protocol); + + await transport.open(); +} + +List<TTest> _createTests() { + List<TTest> tests = []; + + var xtruct = new Xtruct() + ..string_thing = 'Zero' + ..byte_thing = 1 + ..i32_thing = -3 + ..i64_thing = -5; + + tests.add(new TTest(TEST_BASETYPES, 'testVoid', () async { + await client.testVoid(); + })); + + tests.add(new TTest(TEST_BASETYPES, 'testString', () async { + var input = 'Test'; + var result = await client.testString(input); + if (result != input) throw new TTestError(result, input); + })); + + tests.add(new TTest(TEST_BASETYPES, 'testBool', () async { + var input = true; + var result = await client.testBool(input); + if (result != input) throw new TTestError(result, input); + })); + + tests.add(new TTest(TEST_BASETYPES, 'testByte', () async { + var input = 64; + var result = await client.testByte(input); + if (result != input) throw new TTestError(result, input); + })); + + tests.add(new TTest(TEST_BASETYPES, 'testI32', () async { + var input = 2147483647; + var result = await client.testI32(input); + if (result != input) throw new TTestError(result, input); + })); + + tests.add(new TTest(TEST_BASETYPES, 'testI64', () async { + var input = 9223372036854775807; + var result = await client.testI64(input); + if (result != input) throw new TTestError(result, input); + })); + + tests.add(new TTest(TEST_BASETYPES, 'testDouble', () async { + var input = 3.1415926; + var result = await client.testDouble(input); + if (result != input) throw new TTestError(result, input); + })); + + tests.add(new TTest(TEST_BASETYPES, 'testBinary', () async { + var utf8Codec = const Utf8Codec(); + var input = utf8Codec.encode('foo'); + var result = await client.testBinary(input); + var equality = const ListEquality(); + if (!equality.equals(result, input)) throw new TTestError(result, input); + })); + + tests.add(new TTest(TEST_CONTAINERS, 'testStruct', () async { + var result = await client.testStruct(xtruct); + if ('$result' != '$xtruct') throw new TTestError(result, xtruct); + })); + + tests.add(new TTest(TEST_CONTAINERS, 'testNest', () async { + var input = new Xtruct2() + ..byte_thing = 1 + ..struct_thing = xtruct + ..i32_thing = -3; + + var result = await client.testNest(input); + if ('$result' != '$input') throw new TTestError(result, input); + })); + + tests.add(new TTest(TEST_CONTAINERS, 'testMap', () async { + Map<int, int> input = {1: -10, 2: -9, 3: -8, 4: -7, 5: -6}; + + var result = await client.testMap(input); + var equality = const MapEquality(); + if (!equality.equals(result, input)) throw new TTestError(result, input); + })); + + tests.add(new TTest(TEST_CONTAINERS, 'testSet', () async { + var input = new Set<int>.from([-2, -1, 0, 1, 2]); + var result = await client.testSet(input); + var equality = const SetEquality(); + if (!equality.equals(result, input)) throw new TTestError(result, input); + })); + + tests.add(new TTest(TEST_CONTAINERS, 'testList', () async { + var input = [-2, -1, 0, 1, 2]; + var result = await client.testList(input); + var equality = const ListEquality(); + if (!equality.equals(result, input)) throw new TTestError(result, input); + })); + + tests.add(new TTest(TEST_CONTAINERS, 'testEnum', () async { + await _testEnum(Numberz.ONE); + await _testEnum(Numberz.TWO); + await _testEnum(Numberz.THREE); + await _testEnum(Numberz.FIVE); + await _testEnum(Numberz.EIGHT); + })); + + tests.add(new TTest(TEST_BASETYPES, 'testTypedef', () async { + var input = 309858235082523; + var result = await client.testTypedef(input); + if (result != input) throw new TTestError(result, input); + })); + + tests.add(new TTest(TEST_CONTAINERS, 'testMapMap', () async { + Map<int, Map<int, int>> result = await client.testMapMap(1); + if (result.isEmpty || result[result.keys.first].isEmpty) { + throw new TTestError(result, 'Map<int, Map<int, int>>'); + } + })); + + tests.add(new TTest(TEST_CONTAINERS, 'testInsanity', () async { + var input = new Insanity(); + input.userMap = {Numberz.FIVE: 5000}; + input.xtructs = [xtruct]; + + Map<int, Map<int, Insanity>> result = await client.testInsanity(input); + if (result.isEmpty || result[result.keys.first].isEmpty) { + throw new TTestError(result, 'Map<int, Map<int, Insanity>>'); + } + })); + + tests.add(new TTest(TEST_CONTAINERS, 'testMulti', () async { + var input = new Xtruct() + ..string_thing = 'Hello2' + ..byte_thing = 123 + ..i32_thing = 456 + ..i64_thing = 789; + + var result = await client.testMulti(input.byte_thing, input.i32_thing, + input.i64_thing, {1: 'one'}, Numberz.EIGHT, 5678); + if ('$result' != '$input') throw new TTestError(result, input); + })); + + tests.add(new TTest(TEST_EXCEPTIONS, 'testException', () async { + try { + await client.testException('Xception'); + } on Xception catch (_) { + return; + } + + throw new TTestError(null, 'Xception'); + })); + + tests.add(new TTest(TEST_EXCEPTIONS, 'testMultiException', () async { + try { + await client.testMultiException('Xception2', 'foo'); + } on Xception2 catch (_) { + return; + } + + throw new TTestError(null, 'Xception2'); + })); + + return tests; +} + +Future _testEnum(int input) async { + var result = await client.testEnum(input); + if (result != input) throw new TTestError(result, input); +} diff --git a/src/jaegertracing/thrift/test/dart/test_client/pubspec.yaml b/src/jaegertracing/thrift/test/dart/test_client/pubspec.yaml new file mode 100644 index 000000000..c86225eee --- /dev/null +++ b/src/jaegertracing/thrift/test/dart/test_client/pubspec.yaml @@ -0,0 +1,36 @@ +# 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. + +name: thrift_test_client +version: 0.13.0 +description: A client integration test for the Dart Thrift library +author: Apache Thrift Developers <dev@thrift.apache.org> +homepage: http://thrift.apache.org + +environment: + sdk: ">=1.24.3 <3.0.0" + +dependencies: + args: ">=0.13.0 <2.0.0" + http: ^0.11.0 + thrift: + path: ../../../lib/dart + thrift_test: + path: ../gen-dart/thrift_test + +dev_dependencies: + test: ">=0.12.30 <2.0.0" diff --git a/src/jaegertracing/thrift/test/erl/Makefile.am b/src/jaegertracing/thrift/test/erl/Makefile.am new file mode 100644 index 000000000..81913eefd --- /dev/null +++ b/src/jaegertracing/thrift/test/erl/Makefile.am @@ -0,0 +1,51 @@ +# +# 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. +# + +THRIFT_FILES = $(wildcard ../*.thrift) + +if ERLANG_OTP16 +ERL_FLAG = erl:otp16 +else +ERL_FLAG = erl +endif +# make sure ThriftTest.thrift is generated last to prevent conflicts with other *.thrift files +.generated: $(THRIFT_FILES) + for f in $(THRIFT_FILES) ; do \ + $(THRIFT) --gen $(ERL_FLAG) -o src $$f ; \ + done ; \ + $(THRIFT) --gen $(ERL_FLAG) -o src ../ThriftTest.thrift + touch .generated + +precross: .generated + $(REBAR) compile + +maintainer-clean-local: + $(RM) -r ebin/ + +clean: + $(REBAR) clean + $(RM) .generated + $(RM) -r .rebar/ + $(RM) -r src/gen-erl/ + +dist-hook: + $(RM) $(distdir)/.generated + $(RM) -r $(distdir)/.rebar/ + $(RM) -r $(distdir)/ebin/ + $(RM) -r $(distdir)/src/gen-erl/ diff --git a/src/jaegertracing/thrift/test/erl/rebar.config b/src/jaegertracing/thrift/test/erl/rebar.config new file mode 100644 index 000000000..59a0788de --- /dev/null +++ b/src/jaegertracing/thrift/test/erl/rebar.config @@ -0,0 +1,6 @@ +{sub_dirs, ["../../lib/erl"]}. + +{erl_opts, [ + debug_info, + {i, "../../lib/erl/include"} +]}. diff --git a/src/jaegertracing/thrift/test/erl/src/test_client.erl b/src/jaegertracing/thrift/test/erl/src/test_client.erl new file mode 100644 index 000000000..9bad59229 --- /dev/null +++ b/src/jaegertracing/thrift/test/erl/src/test_client.erl @@ -0,0 +1,174 @@ +%% +%% 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. +%% + +-module(test_client). + +-export([start/0, start/1]). + +-include("gen-erl/thrift_test_types.hrl"). + +-record(options, {port = 9090, + client_opts = []}). + +parse_args(Args) -> parse_args(Args, #options{}). +parse_args([], Opts) -> + Opts; +parse_args([Head | Rest], Opts) -> + NewOpts = + case Head of + "--port=" ++ Port -> + case string:to_integer(Port) of + {IntPort,_} when is_integer(IntPort) -> + Opts#options{port = IntPort}; + _Else -> + erlang:error({bad_arg, Head}) + end; + "--transport=" ++ Trans -> + % TODO: Enable Buffered and HTTP transport + case Trans of + "framed" -> + Opts#options{client_opts = [{framed, true} | Opts#options.client_opts]}; + _Else -> + Opts + end; + "--ssl" -> + ssl:start(), + SslOptions = + {ssloptions, [ + {cacertfile, "../keys/CA.pem"}, + {certfile, "../keys/client.pem"}, + {keyfile, "../keys/client.key"} + ]}, + Opts#options{client_opts = [{ssltransport, true} | [SslOptions | Opts#options.client_opts]]}; + "--protocol=" ++ Proto -> + Opts#options{client_opts = [{protocol, list_to_atom(Proto)}]}; + _Else -> + erlang:error({bad_arg, Head}) + end, + parse_args(Rest, NewOpts). + +start() -> start(init:get_plain_arguments()). +start(Args) -> + #options{port = Port, client_opts = ClientOpts} = parse_args(Args), + {ok, Client0} = thrift_client_util:new( + "127.0.0.1", Port, thrift_test_thrift, ClientOpts), + + DemoXtruct = #'thrift.test.Xtruct'{ + string_thing = <<"Zero">>, + byte_thing = 1, + i32_thing = 9128361, + i64_thing = 9223372036854775807}, + + DemoNest = #'thrift.test.Xtruct2'{ + byte_thing = 7, + struct_thing = DemoXtruct, + % Note that we don't set i32_thing, it will come back as undefined + % from the Python server, but 0 from the C++ server, since it is not + % optional + i32_thing = 2}, + + % Is it safe to match these things? + DemoDict = dict:from_list([ {Key, Key-10} || Key <- lists:seq(0,10) ]), + DemoSet = sets:from_list([ Key || Key <- lists:seq(-3,3) ]), + + DemoInsane = #'thrift.test.Insanity'{ + userMap = dict:from_list([{?THRIFT_TEST_NUMBERZ_FIVE, 5000}]), + xtructs = [#'thrift.test.Xtruct'{ string_thing = <<"Truck">>, byte_thing = 8, i32_thing = 8, i64_thing = 8}]}, + + error_logger:info_msg("testVoid"), + {Client01, {ok, ok}} = thrift_client:call(Client0, testVoid, []), + + error_logger:info_msg("testString"), + {Client02, {ok, <<"Test">>}} = thrift_client:call(Client01, testString, ["Test"]), + error_logger:info_msg("testString"), + {Client03, {ok, <<"Test">>}} = thrift_client:call(Client02, testString, [<<"Test">>]), + error_logger:info_msg("testByte"), + {Client04, {ok, 63}} = thrift_client:call(Client03, testByte, [63]), + error_logger:info_msg("testI32"), + {Client05, {ok, -1}} = thrift_client:call(Client04, testI32, [-1]), + error_logger:info_msg("testI32"), + {Client06, {ok, 0}} = thrift_client:call(Client05, testI32, [0]), + error_logger:info_msg("testI64"), + {Client07, {ok, -34359738368}} = thrift_client:call(Client06, testI64, [-34359738368]), + error_logger:info_msg("testDouble"), + {Client08, {ok, -5.2098523}} = thrift_client:call(Client07, testDouble, [-5.2098523]), + %% TODO: add testBinary() call + error_logger:info_msg("testStruct"), + {Client09, {ok, DemoXtruct}} = thrift_client:call(Client08, testStruct, [DemoXtruct]), + error_logger:info_msg("testNest"), + {Client10, {ok, DemoNest}} = thrift_client:call(Client09, testNest, [DemoNest]), + error_logger:info_msg("testMap"), + {Client11, {ok, DemoDict}} = thrift_client:call(Client10, testMap, [DemoDict]), + error_logger:info_msg("testSet"), + {Client12, {ok, DemoSet}} = thrift_client:call(Client11, testSet, [DemoSet]), + error_logger:info_msg("testList"), + {Client13, {ok, [-1,2,3]}} = thrift_client:call(Client12, testList, [[-1,2,3]]), + error_logger:info_msg("testEnum"), + {Client14, {ok, 1}} = thrift_client:call(Client13, testEnum, [?THRIFT_TEST_NUMBERZ_ONE]), + error_logger:info_msg("testTypedef"), + {Client15, {ok, 309858235082523}} = thrift_client:call(Client14, testTypedef, [309858235082523]), + error_logger:info_msg("testInsanity"), + {Client16, {ok, InsaneResult}} = thrift_client:call(Client15, testInsanity, [DemoInsane]), + io:format("~p~n", [InsaneResult]), + + {Client17, {ok, #'thrift.test.Xtruct'{string_thing = <<"Message">>}}} = + thrift_client:call(Client16, testMultiException, ["Safe", "Message"]), + + Client18 = + try + {ClientS1, Result1} = thrift_client:call(Client17, testMultiException, ["Xception", "Message"]), + io:format("Unexpected return! ~p~n", [Result1]), + ClientS1 + catch + throw:{ClientS2, {exception, ExnS1 = #'thrift.test.Xception'{}}} -> + #'thrift.test.Xception'{errorCode = 1001, message = <<"This is an Xception">>} = ExnS1, + ClientS2; + throw:{ClientS2, {exception, _ExnS1 = #'thrift.test.Xception2'{}}} -> + io:format("Wrong exception type!~n", []), + ClientS2 + end, + + Client19 = + try + {ClientS3, Result2} = thrift_client:call(Client18, testMultiException, ["Xception2", "Message"]), + io:format("Unexpected return! ~p~n", [Result2]), + ClientS3 + catch + throw:{ClientS4, {exception, _ExnS2 = #'thrift.test.Xception'{}}} -> + io:format("Wrong exception type!~n", []), + ClientS4; + throw:{ClientS4, {exception, ExnS2 = #'thrift.test.Xception2'{}}} -> + #'thrift.test.Xception2'{errorCode = 2002, + struct_thing = #'thrift.test.Xtruct'{ + string_thing = <<"This is an Xception2">>}} = ExnS2, + ClientS4 + end, + + %% Started = erlang:monotonic_time(milli_seconds), + {_, StartSec, StartUSec} = erlang:timestamp(), + error_logger:info_msg("testOneway"), + {Client20, {ok, ok}} = thrift_client:call(Client19, testOneway, [1]), + {_, EndSec, EndUSec} = erlang:timestamp(), + Elapsed = (EndSec - StartSec) * 1000 + (EndUSec - StartUSec) / 1000, + if + Elapsed > 1000 -> exit(1); + true -> true + end, + + thrift_client:close(Client20). diff --git a/src/jaegertracing/thrift/test/erl/src/test_thrift_server.erl b/src/jaegertracing/thrift/test/erl/src/test_thrift_server.erl new file mode 100644 index 000000000..dad8dec93 --- /dev/null +++ b/src/jaegertracing/thrift/test/erl/src/test_thrift_server.erl @@ -0,0 +1,233 @@ +%% +%% 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. +%% + +-module(test_thrift_server). + +-export([start/0, start/1, start_link/2, handle_function/2]). + +-include("thrift_constants.hrl"). +-include("gen-erl/thrift_test_types.hrl"). + +-record(options, {port = 9090, + server_opts = []}). + +parse_args(Args) -> parse_args(Args, #options{}). +parse_args([], Opts) -> + Opts; +parse_args([Head | Rest], Opts) -> + NewOpts = + case Head of + "--port=" ++ Port -> + case string:to_integer(Port) of + {IntPort,_} when is_integer(IntPort) -> + Opts#options{port = IntPort}; + _Else -> + erlang:error({bad_arg, Head}) + end; + "--transport=" ++ Trans -> + case Trans of + "framed" -> + Opts#options{server_opts = [{framed, true} | Opts#options.server_opts]}; + _Else -> + Opts + end; + "--ssl" -> + ssl:start(), + SslOptions = + {ssloptions, [ + {certfile, "../keys/server.pem"} + ,{keyfile, "../keys/server.key"} + ]}, + Opts#options{server_opts = [{ssltransport, true} | [SslOptions | Opts#options.server_opts]]}; + "--protocol=" ++ Proto -> + Opts#options{server_opts = [{protocol, list_to_atom(Proto)} | Opts#options.server_opts]}; + _Else -> + erlang:error({bad_arg, Head}) + end, + parse_args(Rest, NewOpts). + +start() -> start(init:get_plain_arguments()). +start(Args) -> + #options{port = Port, server_opts = ServerOpts} = parse_args(Args), + spawn(fun() -> start_link(Port, ServerOpts), receive after infinity -> ok end end). + +start_link(Port, ServerOpts) -> + thrift_socket_server:start([{handler, ?MODULE}, + {service, thrift_test_thrift}, + {port, Port}] ++ + ServerOpts). + + +handle_function(testVoid, {}) -> + io:format("testVoid~n"), + ok; + +handle_function(testString, {S}) when is_binary(S) -> + io:format("testString: ~p~n", [S]), + {reply, S}; + +handle_function(testBool, {B}) when is_boolean(B) -> + io:format("testBool: ~p~n", [B]), + {reply, B}; + +handle_function(testByte, {I8}) when is_integer(I8) -> + io:format("testByte: ~p~n", [I8]), + {reply, I8}; + +handle_function(testI32, {I32}) when is_integer(I32) -> + io:format("testI32: ~p~n", [I32]), + {reply, I32}; + +handle_function(testI64, {I64}) when is_integer(I64) -> + io:format("testI64: ~p~n", [I64]), + {reply, I64}; + +handle_function(testDouble, {Double}) when is_float(Double) -> + io:format("testDouble: ~p~n", [Double]), + {reply, Double}; + +handle_function(testBinary, {S}) when is_binary(S) -> + io:format("testBinary: ~p~n", [S]), + {reply, S}; + +handle_function(testStruct, + {Struct = #'thrift.test.Xtruct'{string_thing = String, + byte_thing = Byte, + i32_thing = I32, + i64_thing = I64}}) +when is_binary(String), + is_integer(Byte), + is_integer(I32), + is_integer(I64) -> + io:format("testStruct: ~p~n", [Struct]), + {reply, Struct}; + +handle_function(testNest, + {Nest}) when is_record(Nest, 'thrift.test.Xtruct2'), + is_record(Nest#'thrift.test.Xtruct2'.struct_thing, 'thrift.test.Xtruct') -> + io:format("testNest: ~p~n", [Nest]), + {reply, Nest}; + +handle_function(testMap, {Map}) -> + io:format("testMap: ~p~n", [dict:to_list(Map)]), + {reply, Map}; + +handle_function(testStringMap, {Map}) -> + io:format("testStringMap: ~p~n", [dict:to_list(Map)]), + {reply, Map}; + +handle_function(testSet, {Set}) -> + true = sets:is_set(Set), + io:format("testSet: ~p~n", [sets:to_list(Set)]), + {reply, Set}; + +handle_function(testList, {List}) when is_list(List) -> + io:format("testList: ~p~n", [List]), + {reply, List}; + +handle_function(testEnum, {Enum}) when is_integer(Enum) -> + io:format("testEnum: ~p~n", [Enum]), + {reply, Enum}; + +handle_function(testTypedef, {UserID}) when is_integer(UserID) -> + io:format("testTypedef: ~p~n", [UserID]), + {reply, UserID}; + +handle_function(testMapMap, {Hello}) -> + io:format("testMapMap: ~p~n", [Hello]), + + PosList = [{I, I} || I <- lists:seq(1, 4)], + NegList = [{-I, -I} || I <- lists:seq(1, 4)], + + MapMap = dict:from_list([{4, dict:from_list(PosList)}, + {-4, dict:from_list(NegList)}]), + {reply, MapMap}; + +handle_function(testInsanity, {Insanity}) when is_record(Insanity, 'thrift.test.Insanity') -> + Hello = #'thrift.test.Xtruct'{string_thing = <<"Hello2">>, + byte_thing = 2, + i32_thing = 2, + i64_thing = 2}, + + Goodbye = #'thrift.test.Xtruct'{string_thing = <<"Goodbye4">>, + byte_thing = 4, + i32_thing = 4, + i64_thing = 4}, + Crazy = #'thrift.test.Insanity'{ + userMap = dict:from_list([{?THRIFT_TEST_NUMBERZ_EIGHT, 8}]), + xtructs = [Goodbye] + }, + + Looney = #'thrift.test.Insanity'{}, + + FirstMap = dict:from_list([{?THRIFT_TEST_NUMBERZ_TWO, Insanity}, + {?THRIFT_TEST_NUMBERZ_THREE, Insanity}]), + + SecondMap = dict:from_list([{?THRIFT_TEST_NUMBERZ_SIX, Looney}]), + + Insane = dict:from_list([{1, FirstMap}, + {2, SecondMap}]), + + io:format("Return = ~p~n", [Insane]), + + {reply, Insane}; + +handle_function(testMulti, Args = {Arg0, Arg1, Arg2, _Arg3, Arg4, Arg5}) + when is_integer(Arg0), + is_integer(Arg1), + is_integer(Arg2), + is_integer(Arg4), + is_integer(Arg5) -> + + io:format("testMulti(~p)~n", [Args]), + {reply, #'thrift.test.Xtruct'{string_thing = <<"Hello2">>, + byte_thing = Arg0, + i32_thing = Arg1, + i64_thing = Arg2}}; + +handle_function(testException, {String}) when is_binary(String) -> + io:format("testException(~p)~n", [String]), + case String of + <<"Xception">> -> + throw(#'thrift.test.Xception'{errorCode = 1001, + message = String}); + <<"TException">> -> + throw({?TApplicationException_Structure}); + _ -> + ok + end; + +handle_function(testMultiException, {Arg0, Arg1}) -> + io:format("testMultiException(~p, ~p)~n", [Arg0, Arg1]), + case Arg0 of + <<"Xception">> -> + throw(#'thrift.test.Xception'{errorCode = 1001, + message = <<"This is an Xception">>}); + <<"Xception2">> -> + throw(#'thrift.test.Xception2'{errorCode = 2002, + struct_thing = + #'thrift.test.Xtruct'{string_thing = <<"This is an Xception2">>}}); + _ -> + {reply, #'thrift.test.Xtruct'{string_thing = Arg1}} + end; + +handle_function(testOneway, {Seconds}) -> + io:format("testOneway: ~p~n", [Seconds]), + timer:sleep(1000 * Seconds), + ok. diff --git a/src/jaegertracing/thrift/test/erl/src/thrift_test.app.src b/src/jaegertracing/thrift/test/erl/src/thrift_test.app.src new file mode 100644 index 000000000..ffbad5883 --- /dev/null +++ b/src/jaegertracing/thrift/test/erl/src/thrift_test.app.src @@ -0,0 +1,54 @@ +%% +%% 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. +%% +%%% -*- mode:erlang -*- +{application, thrift_test, [ + % A quick description of the application. + {description, "Thrift cross language test"}, + + % The version of the applicaton + {vsn, "0.13.0"}, + + % All modules used by the application. + {modules, [ + test_client, + test_thrift_server + ]}, + + % All of the registered names the application uses. This can be ignored. + {registered, []}, + + % Applications that are to be started prior to this one. This can be ignored + % leave it alone unless you understand it well and let the .rel files in + % your release handle this. + {applications, [kernel, stdlib]}, + + % OTP application loader will load, but not start, included apps. Again + % this can be ignored as well. To load but not start an application it + % is easier to include it in the .rel file followed by the atom 'none' + {included_applications, []}, + + % configuration parameters similar to those in the config file specified + % on the command line. can be fetched with gas:get_env + {env, [ + % If an error/crash occurs during processing of a function, + % should the TApplicationException serialized back to the client + % include the erlang backtrace? + {exceptions_include_traces, true} + ]} +]}. diff --git a/src/jaegertracing/thrift/test/features/Makefile.am b/src/jaegertracing/thrift/test/features/Makefile.am new file mode 100644 index 000000000..337d78950 --- /dev/null +++ b/src/jaegertracing/thrift/test/features/Makefile.am @@ -0,0 +1,30 @@ +# 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. +# + +EXTRA_DIST = \ + local_thrift \ + index.html \ + container_limit.py \ + index.html \ + known_failures_Linux.json \ + Makefile.am \ + nosslv3.sh \ + string_limit.py \ + tests.json \ + theader_binary.py \ + setup.cfg \ + tls.sh \ + util.py diff --git a/src/jaegertracing/thrift/test/features/container_limit.py b/src/jaegertracing/thrift/test/features/container_limit.py new file mode 100644 index 000000000..88f8487fa --- /dev/null +++ b/src/jaegertracing/thrift/test/features/container_limit.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python + +import argparse +import sys + +from util import add_common_args, init_protocol +from local_thrift import thrift # noqa +from thrift.Thrift import TMessageType, TType + + +# TODO: generate from ThriftTest.thrift +def test_list(proto, value): + method_name = 'testList' + ttype = TType.LIST + etype = TType.I32 + proto.writeMessageBegin(method_name, TMessageType.CALL, 3) + proto.writeStructBegin(method_name + '_args') + proto.writeFieldBegin('thing', ttype, 1) + proto.writeListBegin(etype, len(value)) + for e in value: + proto.writeI32(e) + proto.writeListEnd() + proto.writeFieldEnd() + proto.writeFieldStop() + proto.writeStructEnd() + proto.writeMessageEnd() + proto.trans.flush() + + _, mtype, _ = proto.readMessageBegin() + assert mtype == TMessageType.REPLY + proto.readStructBegin() + _, ftype, fid = proto.readFieldBegin() + assert fid == 0 + assert ftype == ttype + etype2, len2 = proto.readListBegin() + assert etype == etype2 + assert len2 == len(value) + for i in range(len2): + v = proto.readI32() + assert v == value[i] + proto.readListEnd() + proto.readFieldEnd() + _, ftype, _ = proto.readFieldBegin() + assert ftype == TType.STOP + proto.readStructEnd() + proto.readMessageEnd() + + +def main(argv): + p = argparse.ArgumentParser() + add_common_args(p) + p.add_argument('--limit', type=int) + args = p.parse_args() + proto = init_protocol(args) + # TODO: test set and map + test_list(proto, list(range(args.limit - 1))) + test_list(proto, list(range(args.limit - 1))) + print('[OK]: limit - 1') + test_list(proto, list(range(args.limit))) + test_list(proto, list(range(args.limit))) + print('[OK]: just limit') + try: + test_list(proto, list(range(args.limit + 1))) + except Exception: + print('[OK]: limit + 1') + else: + print('[ERROR]: limit + 1') + assert False + + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:])) diff --git a/src/jaegertracing/thrift/test/features/index.html b/src/jaegertracing/thrift/test/features/index.html new file mode 100644 index 000000000..34a00102f --- /dev/null +++ b/src/jaegertracing/thrift/test/features/index.html @@ -0,0 +1,51 @@ +<!-- + 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. + +--> +<!DOCTYPE HTML> +<html> +<head> +<meta charset="utf-8"> +<title>Apache Thrift - integration test suite</title> +<link rel="stylesheet" type="text/css" href="http://cdn.datatables.net/1.10.4/css/jquery.dataTables.css"> +<script type="text/javascript" charset="utf-8" src="http://code.jquery.com/jquery-2.1.3.min.js"></script> +<script type="text/javascript" charset="utf-8" src="http://cdn.datatables.net/1.10.4/js/jquery.dataTables.js"></script> +<script src="../result.js"> +</script> +</head> +<body> +<h2>Apache Thrift - integration test suite: Results</h2> +<table id="test_results" class="display"> + <thead> + <tr> + <th>Server</th> + <th>Client</th> + <th>Protocol</th> + <th>Transport</th> + <th>Result (log)</th> + <th>Expected</th> + </tr> + </thead> +</table> +<h2>Test Information</h2> +<pre id="test_info"></pre> + +<a href="log">browse raw log files</a> + +</body> +</html> diff --git a/src/jaegertracing/thrift/test/features/known_failures_Linux.json b/src/jaegertracing/thrift/test/features/known_failures_Linux.json new file mode 100644 index 000000000..6547860cb --- /dev/null +++ b/src/jaegertracing/thrift/test/features/known_failures_Linux.json @@ -0,0 +1,52 @@ +[ + "c_glib-limit_container_length_binary_buffered-ip", + "c_glib-limit_string_length_binary_buffered-ip", + "cl-limit_string_length_binary_buffered-ip", + "cl-limit_container_length_binary_buffered-ip", + "cpp-theader_framed_binary_multih-header_buffered-ip", + "cpp-theader_framed_compact_multih-header_buffered-ip", + "cpp-theader_unframed_binary_multih-header_buffered-ip", + "cpp-theader_unframed_compact_multih-header_buffered-ip", + "csharp-limit_container_length_binary_buffered-ip", + "csharp-limit_container_length_compact_buffered-ip", + "csharp-limit_string_length_binary_buffered-ip", + "csharp-limit_string_length_compact_buffered-ip", + "d-limit_container_length_binary_buffered-ip", + "d-limit_container_length_compact_buffered-ip", + "d-limit_string_length_binary_buffered-ip", + "d-limit_string_length_compact_buffered-ip", + "erl-limit_container_length_binary_buffered-ip", + "erl-limit_container_length_compact_buffered-ip", + "erl-limit_string_length_binary_buffered-ip", + "erl-limit_string_length_compact_buffered-ip", + "go-limit_container_length_binary_buffered-ip", + "go-limit_container_length_compact_buffered-ip", + "go-limit_string_length_binary_buffered-ip", + "go-limit_string_length_compact_buffered-ip", + "hs-limit_container_length_binary_buffered-ip", + "hs-limit_container_length_compact_buffered-ip", + "hs-limit_string_length_binary_buffered-ip", + "hs-limit_string_length_compact_buffered-ip", + "nodejs-limit_container_length_binary_buffered-ip", + "nodejs-limit_container_length_compact_buffered-ip", + "nodejs-limit_string_length_binary_buffered-ip", + "nodejs-limit_string_length_compact_buffered-ip", + "perl-limit_container_length_binary_buffered-ip", + "perl-limit_string_length_binary_buffered-ip", + "rb-limit_container_length_accel-binary_buffered-ip", + "rb-limit_container_length_binary_buffered-ip", + "rb-limit_container_length_compact_buffered-ip", + "rb-limit_string_length_accel-binary_buffered-ip", + "rb-limit_string_length_binary_buffered-ip", + "rb-limit_string_length_compact_buffered-ip", + "rs-limit_container_length_binary_buffered-ip", + "rs-limit_container_length_compact_buffered-ip", + "rs-limit_container_length_multic-compact_buffered-ip", + "rs-limit_string_length_binary_buffered-ip", + "rs-limit_string_length_compact_buffered-ip", + "rs-limit_string_length_multic-compact_buffered-ip", + "netcore-limit_string_length_compact_buffered-ip", + "netcore-limit_container_length_compact_buffered-ip", + "nodejs-theader_framed_binary_header_buffered-ip", + "nodejs-theader_framed_compact_header_buffered-ip" +] diff --git a/src/jaegertracing/thrift/test/features/local_thrift/__init__.py b/src/jaegertracing/thrift/test/features/local_thrift/__init__.py new file mode 100644 index 000000000..c85cebe5f --- /dev/null +++ b/src/jaegertracing/thrift/test/features/local_thrift/__init__.py @@ -0,0 +1,32 @@ +# +# 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. +# + +import glob +import os +import sys + +_SCRIPT_DIR = os.path.realpath(os.path.dirname(__file__)) +_ROOT_DIR = os.path.dirname(os.path.dirname(os.path.dirname(_SCRIPT_DIR))) +_LIBDIR = os.path.join(_ROOT_DIR, 'lib', 'py', 'build', 'lib.*') + +for libpath in glob.glob(_LIBDIR): + if libpath.endswith('-%d.%d' % (sys.version_info[0], sys.version_info[1])): + sys.path.insert(0, libpath) + thrift = __import__('thrift') + break diff --git a/src/jaegertracing/thrift/test/features/nosslv3.sh b/src/jaegertracing/thrift/test/features/nosslv3.sh new file mode 100755 index 000000000..38cca0786 --- /dev/null +++ b/src/jaegertracing/thrift/test/features/nosslv3.sh @@ -0,0 +1,59 @@ +#!/bin/bash + +# +# Checks to make sure SSLv3 is not allowed by a server. +# + +THRIFTHOST=localhost +THRIFTPORT=9090 + +while [[ $# -ge 1 ]]; do + arg="$1" + argIN=(${arg//=/ }) + + case ${argIN[0]} in + -h|--host) + THRIFTHOST=${argIN[1]} + shift # past argument + ;; + -p|--port) + THRIFTPORT=${argIN[1]} + shift # past argument + ;; + *) + # unknown option ignored + ;; + esac + + shift # past argument or value +done + +function nosslv3 +{ + local nego + local negodenied + local opensslv + + opensslv=$(openssl version | cut -d' ' -f2) + if [[ $opensslv > "1.0" ]]; then + echo "[pass] OpenSSL 1.1 or later - no need to check ssl3" + return 0 + fi + + # echo "openssl s_client -connect $THRIFTHOST:$THRIFTPORT -CAfile ../keys/CA.pem -ssl3 2>&1 < /dev/null" + nego=$(openssl s_client -connect $THRIFTHOST:$THRIFTPORT -CAfile ../keys/CA.pem -ssl3 2>&1 < /dev/null) + negodenied=$? + + if [[ $negodenied -ne 0 ]]; then + echo "[pass] SSLv3 negotiation disabled" + echo $nego + return 0 + fi + + echo "[fail] SSLv3 negotiation enabled! stdout:" + echo $nego + return 1 +} + +nosslv3 +exit $? diff --git a/src/jaegertracing/thrift/test/features/setup.cfg b/src/jaegertracing/thrift/test/features/setup.cfg new file mode 100644 index 000000000..7da1f9608 --- /dev/null +++ b/src/jaegertracing/thrift/test/features/setup.cfg @@ -0,0 +1,2 @@ +[flake8] +max-line-length = 100 diff --git a/src/jaegertracing/thrift/test/features/string_limit.py b/src/jaegertracing/thrift/test/features/string_limit.py new file mode 100644 index 000000000..b8991d64f --- /dev/null +++ b/src/jaegertracing/thrift/test/features/string_limit.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python + +import argparse +import sys + +from util import add_common_args, init_protocol +from local_thrift import thrift # noqa +from thrift.Thrift import TMessageType, TType + + +# TODO: generate from ThriftTest.thrift +def test_string(proto, value): + method_name = 'testString' + ttype = TType.STRING + proto.writeMessageBegin(method_name, TMessageType.CALL, 3) + proto.writeStructBegin(method_name + '_args') + proto.writeFieldBegin('thing', ttype, 1) + proto.writeString(value) + proto.writeFieldEnd() + proto.writeFieldStop() + proto.writeStructEnd() + proto.writeMessageEnd() + proto.trans.flush() + + _, mtype, _ = proto.readMessageBegin() + assert mtype == TMessageType.REPLY + proto.readStructBegin() + _, ftype, fid = proto.readFieldBegin() + assert fid == 0 + assert ftype == ttype + result = proto.readString() + proto.readFieldEnd() + _, ftype, _ = proto.readFieldBegin() + assert ftype == TType.STOP + proto.readStructEnd() + proto.readMessageEnd() + assert value == result + + +def main(argv): + p = argparse.ArgumentParser() + add_common_args(p) + p.add_argument('--limit', type=int) + args = p.parse_args() + proto = init_protocol(args) + test_string(proto, 'a' * (args.limit - 1)) + test_string(proto, 'a' * (args.limit - 1)) + print('[OK]: limit - 1') + test_string(proto, 'a' * args.limit) + test_string(proto, 'a' * args.limit) + print('[OK]: just limit') + try: + test_string(proto, 'a' * (args.limit + 1)) + except Exception: + print('[OK]: limit + 1') + else: + print('[ERROR]: limit + 1') + assert False + + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/src/jaegertracing/thrift/test/features/tests.json b/src/jaegertracing/thrift/test/features/tests.json new file mode 100644 index 000000000..41e07d7f6 --- /dev/null +++ b/src/jaegertracing/thrift/test/features/tests.json @@ -0,0 +1,114 @@ +[ + { + "description": "THeader detects unframed binary wire format", + "name": "theader_unframed_binary", + "command": [ + "python", + "theader_binary.py", + "--override-protocol=binary", + "--override-transport=buffered" + ], + "protocols": ["header"], + "transports": ["buffered"], + "sockets": ["ip"], + "workdir": "features" + }, + { + "description": "THeader detects framed binary wire format", + "name": "theader_framed_binary", + "command": [ + "python", + "theader_binary.py", + "--override-protocol=binary", + "--override-transport=framed" + ], + "protocols": ["header"], + "transports": ["buffered"], + "sockets": ["ip"], + "workdir": "features" + }, + { + "description": "THeader detects unframed compact wire format", + "name": "theader_unframed_compact", + "command": [ + "python", + "theader_binary.py", + "--override-protocol=compact", + "--override-transport=buffered" + ], + "protocols": ["header"], + "transports": ["buffered"], + "sockets": ["ip"], + "workdir": "features" + }, + { + "description": "THeader detects framed compact wire format", + "name": "theader_framed_compact", + "command": [ + "python", + "theader_binary.py", + "--override-protocol=compact", + "--override-transport=framed" + ], + "protocols": ["header"], + "transports": ["buffered"], + "sockets": ["ip"], + "workdir": "features" + }, + { + "name": "limit_string_length", + "command": [ + "python", + "string_limit.py", + "--limit=50" + ], + "remote_args": [ + "--string-limit=50" + ], + "protocols": [ + "compact" + ], + "transports": ["buffered"], + "sockets": ["ip"], + "workdir": "features" + }, + { + "name": "limit_container_length", + "command": [ + "python", + "container_limit.py", + "--limit=50" + ], + "remote_args": [ + "--container-limit=50" + ], + "protocols": [ + "compact" + ], + "transports": ["buffered"], + "sockets": ["ip"], + "workdir": "features" + }, + { + "name": "nosslv3", + "comment": "check to make sure SSLv3 is not supported", + "command": [ + "nosslv3.sh" + ], + "protocols": ["binary"], + "transports": ["buffered"], + "sockets": ["ip-ssl"], + "workdir": "features" + }, + { + "name": "tls", + "comment": "check to make sure TLSv1.0 or later is supported", + "command": [ + "tls.sh" + ], + "protocols": ["binary"], + "transports": ["buffered"], + "sockets": ["ip-ssl"], + "workdir": "features" + } +] diff --git a/src/jaegertracing/thrift/test/features/theader_binary.py b/src/jaegertracing/thrift/test/features/theader_binary.py new file mode 100644 index 000000000..451399aa7 --- /dev/null +++ b/src/jaegertracing/thrift/test/features/theader_binary.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python + +import argparse +import socket +import sys + +from util import add_common_args +from local_thrift import thrift # noqa +from thrift.Thrift import TMessageType, TType +from thrift.transport.TSocket import TSocket +from thrift.transport.TTransport import TBufferedTransport, TFramedTransport +from thrift.protocol.TBinaryProtocol import TBinaryProtocol +from thrift.protocol.TCompactProtocol import TCompactProtocol + + +def test_void(proto): + proto.writeMessageBegin('testVoid', TMessageType.CALL, 3) + proto.writeStructBegin('testVoid_args') + proto.writeFieldStop() + proto.writeStructEnd() + proto.writeMessageEnd() + proto.trans.flush() + + _, mtype, _ = proto.readMessageBegin() + assert mtype == TMessageType.REPLY + proto.readStructBegin() + _, ftype, _ = proto.readFieldBegin() + assert ftype == TType.STOP + proto.readStructEnd() + proto.readMessageEnd() + + +# THeader stack should accept binary protocol with optionally framed transport +def main(argv): + p = argparse.ArgumentParser() + add_common_args(p) + # Since THeaderTransport acts as framed transport when detected frame, we + # cannot use --transport=framed as it would result in 2 layered frames. + p.add_argument('--override-transport') + p.add_argument('--override-protocol') + args = p.parse_args() + assert args.protocol == 'header' + assert args.transport == 'buffered' + assert not args.ssl + + sock = TSocket(args.host, args.port, socket_family=socket.AF_INET) + if not args.override_transport or args.override_transport == 'buffered': + trans = TBufferedTransport(sock) + elif args.override_transport == 'framed': + print('TFRAMED') + trans = TFramedTransport(sock) + else: + raise ValueError('invalid transport') + trans.open() + + if not args.override_protocol or args.override_protocol == 'binary': + proto = TBinaryProtocol(trans) + elif args.override_protocol == 'compact': + proto = TCompactProtocol(trans) + else: + raise ValueError('invalid transport') + + test_void(proto) + test_void(proto) + + trans.close() + + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:])) diff --git a/src/jaegertracing/thrift/test/features/tls.sh b/src/jaegertracing/thrift/test/features/tls.sh new file mode 100755 index 000000000..6fd90a5fc --- /dev/null +++ b/src/jaegertracing/thrift/test/features/tls.sh @@ -0,0 +1,72 @@ +#!/bin/bash + +# +# Checks to make sure TLSv1.0 or later is allowed by a server. +# + +THRIFTHOST=localhost +THRIFTPORT=9090 + +while [[ $# -ge 1 ]]; do + arg="$1" + argIN=(${arg//=/ }) + + case ${argIN[0]} in + -h|--host) + THRIFTHOST=${argIN[1]} + shift # past argument + ;; + -p|--port) + THRIFTPORT=${argIN[1]} + shift # past argument + ;; + *) + # unknown option ignored + ;; + esac + + shift # past argument or value +done + +declare -A EXPECT_NEGOTIATE +EXPECT_NEGOTIATE[tls1]=1 +EXPECT_NEGOTIATE[tls1_1]=1 +EXPECT_NEGOTIATE[tls1_2]=1 +EXPECT_NEGOTIATE[tls1_3]=1 + +failures=0 + +function tls +{ + for PROTO in "${!EXPECT_NEGOTIATE[@]}"; do + + local nego + local negodenied + local res + + echo "openssl s_client -connect $THRIFTHOST:$THRIFTPORT -CAfile ../keys/CA.pem -$PROTO 2>&1 < /dev/null" + nego=$(openssl s_client -connect $THRIFTHOST:$THRIFTPORT -CAfile ../keys/CA.pem -$PROTO 2>&1 < /dev/null) + negodenied=$? + echo "result of command: $negodenied" + + res="enabled"; if [[ ${EXPECT_NEGOTIATE[$PROTO]} -eq 0 ]]; then res="disabled"; fi + + if [[ $negodenied -ne ${EXPECT_NEGOTIATE[$PROTO]} ]]; then + echo "$PROTO negotiation allowed" + else + echo "[warn] $PROTO negotiation did not work" + echo $nego + ((failures++)) + fi + done +} + +tls + +if [[ $failures -eq 4 ]]; then + echo "[fail] At least one of TLSv1.0, TLSv1.1, TLSv1.2, or TLSv1.3 needs to work, but does not" + exit $failures +fi + +echo "[pass] At least one of TLSv1.0, TLSv1.1, TLSv1.2, or TLSv1.3 worked" +exit 0 diff --git a/src/jaegertracing/thrift/test/features/util.py b/src/jaegertracing/thrift/test/features/util.py new file mode 100644 index 000000000..3abbbbd9a --- /dev/null +++ b/src/jaegertracing/thrift/test/features/util.py @@ -0,0 +1,40 @@ +import argparse +import socket + +from local_thrift import thrift # noqa +from thrift.transport.TSocket import TSocket +from thrift.transport.TTransport import TBufferedTransport, TFramedTransport +from thrift.transport.THttpClient import THttpClient +from thrift.protocol.TBinaryProtocol import TBinaryProtocol +from thrift.protocol.TCompactProtocol import TCompactProtocol +from thrift.protocol.TJSONProtocol import TJSONProtocol + + +def add_common_args(p): + p.add_argument('--host', default='localhost') + p.add_argument('--port', type=int, default=9090) + p.add_argument('--protocol', default='binary') + p.add_argument('--transport', default='buffered') + p.add_argument('--ssl', action='store_true') + + +def parse_common_args(argv): + p = argparse.ArgumentParser() + add_common_args(p) + return p.parse_args(argv) + + +def init_protocol(args): + sock = TSocket(args.host, args.port, socket_family=socket.AF_INET) + sock.setTimeout(500) + trans = { + 'buffered': TBufferedTransport, + 'framed': TFramedTransport, + 'http': THttpClient, + }[args.transport](sock) + trans.open() + return { + 'binary': TBinaryProtocol, + 'compact': TCompactProtocol, + 'json': TJSONProtocol, + }[args.protocol](trans) diff --git a/src/jaegertracing/thrift/test/go/Makefile.am b/src/jaegertracing/thrift/test/go/Makefile.am new file mode 100644 index 000000000..3cf6a70ee --- /dev/null +++ b/src/jaegertracing/thrift/test/go/Makefile.am @@ -0,0 +1,65 @@ +# +# 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. +# + +BUILT_SOURCES = gopath + +THRIFTCMD = $(THRIFT) -out src/gen --gen go:thrift_import=thrift$(COMPILER_EXTRAFLAG) +THRIFTTEST = $(top_srcdir)/test/ThriftTest.thrift + +precross: bin/testclient bin/testserver + +ThriftTest.thrift: $(THRIFTTEST) + grep -v list.*map.*list.*map $(THRIFTTEST) > ThriftTest.thrift + +.PHONY: gopath + +# Thrift for GO has problems with complex map keys: THRIFT-2063 +gopath: $(THRIFT) ThriftTest.thrift + mkdir -p src/gen + $(THRIFTCMD) ThriftTest.thrift + $(THRIFTCMD) ../StressTest.thrift + GOPATH=`pwd` $(GO) get github.com/golang/mock/gomock || true + sed -i 's/\"context\"/\"golang.org\/x\/net\/context\"/g' src/github.com/golang/mock/gomock/controller.go || true + GOPATH=`pwd` $(GO) get github.com/golang/mock/gomock + ln -nfs ../../../lib/go/thrift src/thrift + touch gopath + +bin/testclient: gopath + GOPATH=`pwd` $(GO) install bin/testclient + +bin/testserver: gopath + GOPATH=`pwd` $(GO) install bin/testserver + +bin/stress: gopath + GOPATH=`pwd` $(GO) install bin/stress + +clean-local: + $(RM) -r src/gen src/github.com/golang src/thrift bin pkg gopath ThriftTest.thrift + +check_PROGRAMS: bin/testclient bin/testserver bin/stress + +check: gopath genmock + GOPATH=`pwd` $(GO) test -v common/... + +genmock: gopath + sh genmock.sh + +EXTRA_DIST = \ + src/bin \ + src/common diff --git a/src/jaegertracing/thrift/test/go/genmock.sh b/src/jaegertracing/thrift/test/go/genmock.sh new file mode 100644 index 000000000..3ba41b9ed --- /dev/null +++ b/src/jaegertracing/thrift/test/go/genmock.sh @@ -0,0 +1,15 @@ +#!/bin/sh +set -e + +export GOPATH=`pwd` +export GOBIN=`pwd`/bin +export GO111MODULE=off + +mkdir -p src/github.com/golang/mock +cd src/github.com/golang +curl -fsSL https://github.com/golang/mock/archive/v1.2.0.tar.gz -o mock.tar.gz +tar -xzvf mock.tar.gz -C mock --strip-components=1 +cd mock/mockgen +go install . +cd ../../../../../ +bin/mockgen -destination=src/common/mock_handler.go -package=common gen/thrifttest ThriftTest diff --git a/src/jaegertracing/thrift/test/go/src/bin/stress/main.go b/src/jaegertracing/thrift/test/go/src/bin/stress/main.go new file mode 100644 index 000000000..f2e0f2073 --- /dev/null +++ b/src/jaegertracing/thrift/test/go/src/bin/stress/main.go @@ -0,0 +1,254 @@ +/* + * 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 main + +import ( + "context" + "flag" + "fmt" + "gen/stress" + "log" + _ "net/http/pprof" + "os" + "runtime" + "runtime/pprof" + "sync" + "sync/atomic" + "thrift" + "time" +) + +var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to this file") +var memprofile = flag.String("memprofile", "", "write memory profile to this file") + +var ( + host = flag.String("host", "localhost", "Host to connect") + port = flag.Int64("port", 9091, "Port number to connect") + loop = flag.Int("loops", 50000, "The number of remote thrift calls each client makes") + runserver = flag.Int("server", 1, "Run the Thrift server in this process") + clients = flag.Int("clients", 20, "Number of client threads to create - 0 implies no clients, i.e. server only") + callName = flag.String("call", "echoVoid", "Service method to call, one of echoVoid, echoByte, echoI32, echoI64, echoString, echiList, echoSet, echoMap") + compact = flag.Bool("compact", false, "Use compact protocol instead of binary.") + framed = flag.Bool("framed", false, "Use framed transport instead of buffered.") +) +var hostPort string + +type callT int64 + +const ( + echoVoid callT = iota + echoByte + echoI32 + echoI64 + echoString + echiList + echoSet + echoMap +) + +var callTMap = map[string]callT{ + "echoVoid": echoVoid, + "echoByte": echoByte, + "echoI32": echoI32, + "echoI64": echoI64, + "echoString": echoString, + "echiList": echiList, + "echoSet": echoSet, + "echoMap": echoMap, +} +var callType callT + +var ready, done sync.WaitGroup + +var clicounter int64 = 0 +var counter int64 = 0 + +func main() { + flag.Parse() + if *memprofile != "" { + runtime.MemProfileRate = 100 + } + var ok bool + if callType, ok = callTMap[*callName]; !ok { + log.Fatal("Unknown service call", *callName) + } + if *cpuprofile != "" { + f, err := os.Create(*cpuprofile) + if err != nil { + log.Fatal(err) + } + pprof.StartCPUProfile(f) + defer pprof.StopCPUProfile() + } + hostPort = fmt.Sprintf("%s:%d", *host, *port) + var protocolFactory thrift.TProtocolFactory + var transportFactory thrift.TTransportFactory + + if *compact { + protocolFactory = thrift.NewTCompactProtocolFactory() + } else { + protocolFactory = thrift.NewTBinaryProtocolFactoryDefault() + } + + if *framed { + transportFactory = thrift.NewTTransportFactory() + transportFactory = thrift.NewTFramedTransportFactory(transportFactory) + } else { + transportFactory = thrift.NewTBufferedTransportFactory(8192) + } + + if *runserver > 0 { + serverTransport, err := thrift.NewTServerSocket(hostPort) + if err != nil { + log.Fatalf("Unable to create server socket: %s", err) + } + + processor := stress.NewServiceProcessor(&handler{}) + server := thrift.NewTSimpleServer4(processor, serverTransport, transportFactory, protocolFactory) + if *clients == 0 { + server.Serve() + } else { + go server.Serve() + } + } + //start clients + if *clients != 0 { + ready.Add(*clients + 1) + done.Add(*clients) + for i := 0; i < *clients; i++ { + go client(protocolFactory) + } + ready.Done() + ready.Wait() + //run! + startTime := time.Now() + //wait for completion + done.Wait() + endTime := time.Now() + duration := endTime.Sub(startTime) + log.Printf("%d calls in %v (%f calls per second)\n", clicounter, duration, float64(clicounter)/duration.Seconds()) + } + if *memprofile != "" { + f, err := os.Create(*memprofile) + if err != nil { + log.Fatal(err) + } + pprof.WriteHeapProfile(f) + f.Close() + return + } +} + +func client(protocolFactory thrift.TProtocolFactory) { + trans, err := thrift.NewTSocket(hostPort) + if err != nil { + log.Fatalf("Unable to create server socket: %s", err) + } + btrans := thrift.NewTBufferedTransport(trans, 2048) + client := stress.NewServiceClientFactory(btrans, protocolFactory) + err = trans.Open() + if err != nil { + log.Fatalf("Unable to open connection: %s", err) + } + ready.Done() + ready.Wait() + switch callType { + case echoVoid: + for i := 0; i < *loop; i++ { + client.EchoVoid() + atomic.AddInt64(&clicounter, 1) + } + case echoByte: + for i := 0; i < *loop; i++ { + client.EchoByte(42) + atomic.AddInt64(&clicounter, 1) + } + case echoI32: + for i := 0; i < *loop; i++ { + client.EchoI32(4242) + atomic.AddInt64(&clicounter, 1) + } + case echoI64: + for i := 0; i < *loop; i++ { + client.EchoI64(424242) + atomic.AddInt64(&clicounter, 1) + } + case echoString: + for i := 0; i < *loop; i++ { + client.EchoString("TestString") + atomic.AddInt64(&clicounter, 1) + } + case echiList: + l := []int8{-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8} + for i := 0; i < *loop; i++ { + client.EchoList(l) + atomic.AddInt64(&clicounter, 1) + } + case echoSet: + s := map[int8]struct{}{-10: {}, -9: {}, -8: {}, -7: {}, -6: {}, -5: {}, -4: {}, -3: {}, -2: {}, -1: {}, 0: {}, 1: {}, 2: {}, 3: {}, 4: {}, 5: {}, 6: {}, 7: {}, 8: {}} + for i := 0; i < *loop; i++ { + client.EchoSet(s) + atomic.AddInt64(&clicounter, 1) + } + case echoMap: + m := map[int8]int8{-10: 10, -9: 9, -8: 8, -7: 7, -6: 6, -5: 5, -4: 4, -3: 3, -2: 2, -1: 1, 0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8} + for i := 0; i < *loop; i++ { + client.EchoMap(m) + atomic.AddInt64(&clicounter, 1) + } + } + + done.Done() +} + +type handler struct{} + +func (h *handler) EchoVoid(ctx context.Context) (err error) { + atomic.AddInt64(&counter, 1) + return nil +} +func (h *handler) EchoByte(ctx context.Context, arg int8) (r int8, err error) { + atomic.AddInt64(&counter, 1) + return arg, nil +} +func (h *handler) EchoI32(ctx context.Context, arg int32) (r int32, err error) { + atomic.AddInt64(&counter, 1) + return arg, nil +} +func (h *handler) EchoI64(ctx context.Context, arg int64) (r int64, err error) { + atomic.AddInt64(&counter, 1) + return arg, nil +} +func (h *handler) EchoString(ctx context.Context, arg string) (r string, err error) { + atomic.AddInt64(&counter, 1) + return arg, nil +} +func (h *handler) EchoList(ctx context.Context, arg []int8) (r []int8, err error) { + atomic.AddInt64(&counter, 1) + return arg, nil +} +func (h *handler) EchoSet(ctx context.Context, arg map[int8]struct{}) (r map[int8]struct{}, err error) { + atomic.AddInt64(&counter, 1) + return arg, nil +} +func (h *handler) EchoMap(ctx context.Context, arg map[int8]int8) (r map[int8]int8, err error) { + atomic.AddInt64(&counter, 1) + return arg, nil +} diff --git a/src/jaegertracing/thrift/test/go/src/bin/testclient/main.go b/src/jaegertracing/thrift/test/go/src/bin/testclient/main.go new file mode 100644 index 000000000..4357ee83f --- /dev/null +++ b/src/jaegertracing/thrift/test/go/src/bin/testclient/main.go @@ -0,0 +1,316 @@ +/* + * 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 main + +import ( + "common" + "context" + "flag" + "gen/thrifttest" + t "log" + "reflect" + "thrift" +) + +var host = flag.String("host", "localhost", "Host to connect") +var port = flag.Int64("port", 9090, "Port number to connect") +var domain_socket = flag.String("domain-socket", "", "Domain Socket (e.g. /tmp/thrifttest.thrift), instead of host and port") +var transport = flag.String("transport", "buffered", "Transport: buffered, framed, http, zlib") +var protocol = flag.String("protocol", "binary", "Protocol: binary, compact, json") +var ssl = flag.Bool("ssl", false, "Encrypted Transport using SSL") +var zlib = flag.Bool("zlib", false, "Wrapped Transport using Zlib") +var testloops = flag.Int("testloops", 1, "Number of Tests") + +func main() { + flag.Parse() + client, _, err := common.StartClient(*host, *port, *domain_socket, *transport, *protocol, *ssl) + if err != nil { + t.Fatalf("Unable to start client: ", err) + } + for i := 0; i < *testloops; i++ { + callEverything(client) + } +} + +var rmapmap = map[int32]map[int32]int32{ + -4: map[int32]int32{-4: -4, -3: -3, -2: -2, -1: -1}, + 4: map[int32]int32{4: 4, 3: 3, 2: 2, 1: 1}, +} + +var xxs = &thrifttest.Xtruct{ + StringThing: "Hello2", + ByteThing: 42, + I32Thing: 4242, + I64Thing: 424242, +} + +var xcept = &thrifttest.Xception{ErrorCode: 1001, Message: "Xception"} +var defaultCtx = context.Background() + +func callEverything(client *thrifttest.ThriftTestClient) { + var err error + if err = client.TestVoid(defaultCtx); err != nil { + t.Fatalf("Unexpected error in TestVoid() call: ", err) + } + + thing, err := client.TestString(defaultCtx, "thing") + if err != nil { + t.Fatalf("Unexpected error in TestString() call: ", err) + } + if thing != "thing" { + t.Fatalf("Unexpected TestString() result, expected 'thing' got '%s' ", thing) + } + + bl, err := client.TestBool(defaultCtx, true) + if err != nil { + t.Fatalf("Unexpected error in TestBool() call: ", err) + } + if !bl { + t.Fatalf("Unexpected TestBool() result expected true, got %f ", bl) + } + bl, err = client.TestBool(defaultCtx, false) + if err != nil { + t.Fatalf("Unexpected error in TestBool() call: ", err) + } + if bl { + t.Fatalf("Unexpected TestBool() result expected false, got %f ", bl) + } + + b, err := client.TestByte(defaultCtx, 42) + if err != nil { + t.Fatalf("Unexpected error in TestByte() call: ", err) + } + if b != 42 { + t.Fatalf("Unexpected TestByte() result expected 42, got %d ", b) + } + + i32, err := client.TestI32(defaultCtx, 4242) + if err != nil { + t.Fatalf("Unexpected error in TestI32() call: ", err) + } + if i32 != 4242 { + t.Fatalf("Unexpected TestI32() result expected 4242, got %d ", i32) + } + + i64, err := client.TestI64(defaultCtx, 424242) + if err != nil { + t.Fatalf("Unexpected error in TestI64() call: ", err) + } + if i64 != 424242 { + t.Fatalf("Unexpected TestI64() result expected 424242, got %d ", i64) + } + + d, err := client.TestDouble(defaultCtx, 42.42) + if err != nil { + t.Fatalf("Unexpected error in TestDouble() call: ", err) + } + if d != 42.42 { + t.Fatalf("Unexpected TestDouble() result expected 42.42, got %f ", d) + } + + binout := make([]byte, 256) + for i := 0; i < 256; i++ { + binout[i] = byte(i) + } + bin, err := client.TestBinary(defaultCtx, binout) + for i := 0; i < 256; i++ { + if binout[i] != bin[i] { + t.Fatalf("Unexpected TestBinary() result expected %d, got %d ", binout[i], bin[i]) + } + } + + xs := thrifttest.NewXtruct() + xs.StringThing = "thing" + xs.ByteThing = 42 + xs.I32Thing = 4242 + xs.I64Thing = 424242 + xsret, err := client.TestStruct(defaultCtx, xs) + if err != nil { + t.Fatalf("Unexpected error in TestStruct() call: ", err) + } + if *xs != *xsret { + t.Fatalf("Unexpected TestStruct() result expected %#v, got %#v ", xs, xsret) + } + + x2 := thrifttest.NewXtruct2() + x2.StructThing = xs + x2ret, err := client.TestNest(defaultCtx, x2) + if err != nil { + t.Fatalf("Unexpected error in TestNest() call: ", err) + } + if !reflect.DeepEqual(x2, x2ret) { + t.Fatalf("Unexpected TestNest() result expected %#v, got %#v ", x2, x2ret) + } + + m := map[int32]int32{1: 2, 3: 4, 5: 42} + mret, err := client.TestMap(defaultCtx, m) + if err != nil { + t.Fatalf("Unexpected error in TestMap() call: ", err) + } + if !reflect.DeepEqual(m, mret) { + t.Fatalf("Unexpected TestMap() result expected %#v, got %#v ", m, mret) + } + + sm := map[string]string{"a": "2", "b": "blah", "some": "thing"} + smret, err := client.TestStringMap(defaultCtx, sm) + if err != nil { + t.Fatalf("Unexpected error in TestStringMap() call: ", err) + } + if !reflect.DeepEqual(sm, smret) { + t.Fatalf("Unexpected TestStringMap() result expected %#v, got %#v ", sm, smret) + } + + s := []int32{1, 2, 42} + sret, err := client.TestSet(defaultCtx, s) + if err != nil { + t.Fatalf("Unexpected error in TestSet() call: ", err) + } + // Sets can be in any order, but Go slices are ordered, so reflect.DeepEqual won't work. + stemp := map[int32]struct{}{} + for _, val := range s { + stemp[val] = struct{}{} + } + for _, val := range sret { + if _, ok := stemp[val]; !ok { + t.Fatalf("Unexpected TestSet() result expected %#v, got %#v ", s, sret) + } + } + + l := []int32{1, 2, 42} + lret, err := client.TestList(defaultCtx, l) + if err != nil { + t.Fatalf("Unexpected error in TestList() call: ", err) + } + if !reflect.DeepEqual(l, lret) { + t.Fatalf("Unexpected TestList() result expected %#v, got %#v ", l, lret) + } + + eret, err := client.TestEnum(defaultCtx, thrifttest.Numberz_TWO) + if err != nil { + t.Fatalf("Unexpected error in TestEnum() call: ", err) + } + if eret != thrifttest.Numberz_TWO { + t.Fatalf("Unexpected TestEnum() result expected %#v, got %#v ", thrifttest.Numberz_TWO, eret) + } + + tret, err := client.TestTypedef(defaultCtx, thrifttest.UserId(42)) + if err != nil { + t.Fatalf("Unexpected error in TestTypedef() call: ", err) + } + if tret != thrifttest.UserId(42) { + t.Fatalf("Unexpected TestTypedef() result expected %#v, got %#v ", thrifttest.UserId(42), tret) + } + + mapmap, err := client.TestMapMap(defaultCtx, 42) + if err != nil { + t.Fatalf("Unexpected error in TestMapMap() call: ", err) + } + if !reflect.DeepEqual(mapmap, rmapmap) { + t.Fatalf("Unexpected TestMapMap() result expected %#v, got %#v ", rmapmap, mapmap) + } + + crazy := thrifttest.NewInsanity() + crazy.UserMap = map[thrifttest.Numberz]thrifttest.UserId{ + thrifttest.Numberz_FIVE: 5, + thrifttest.Numberz_EIGHT: 8, + } + truck1 := thrifttest.NewXtruct() + truck1.StringThing = "Goodbye4" + truck1.ByteThing = 4 + truck1.I32Thing = 4 + truck1.I64Thing = 4 + truck2 := thrifttest.NewXtruct() + truck2.StringThing = "Hello2" + truck2.ByteThing = 2 + truck2.I32Thing = 2 + truck2.I64Thing = 2 + crazy.Xtructs = []*thrifttest.Xtruct{ + truck1, + truck2, + } + insanity, err := client.TestInsanity(defaultCtx, crazy) + if err != nil { + t.Fatalf("Unexpected error in TestInsanity() call: ", err) + } + if !reflect.DeepEqual(crazy, insanity[1][2]) { + t.Fatalf("Unexpected TestInsanity() first result expected %#v, got %#v ", + crazy, + insanity[1][2]) + } + if !reflect.DeepEqual(crazy, insanity[1][3]) { + t.Fatalf("Unexpected TestInsanity() second result expected %#v, got %#v ", + crazy, + insanity[1][3]) + } + if len(insanity[2][6].UserMap) > 0 || len(insanity[2][6].Xtructs) > 0 { + t.Fatalf("Unexpected TestInsanity() non-empty result got %#v ", + insanity[2][6]) + } + + xxsret, err := client.TestMulti(defaultCtx, 42, 4242, 424242, map[int16]string{1: "blah", 2: "thing"}, thrifttest.Numberz_EIGHT, thrifttest.UserId(24)) + if err != nil { + t.Fatalf("Unexpected error in TestMulti() call: ", err) + } + if !reflect.DeepEqual(xxs, xxsret) { + t.Fatalf("Unexpected TestMulti() result expected %#v, got %#v ", xxs, xxsret) + } + + err = client.TestException(defaultCtx, "Xception") + if err == nil { + t.Fatalf("Expecting exception in TestException() call") + } + if !reflect.DeepEqual(err, xcept) { + t.Fatalf("Unexpected TestException() result expected %#v, got %#v ", xcept, err) + } + + err = client.TestException(defaultCtx, "TException") + _, ok := err.(thrift.TApplicationException) + if err == nil || !ok { + t.Fatalf("Unexpected TestException() result expected ApplicationError, got %#v ", err) + } + + ign, err := client.TestMultiException(defaultCtx, "Xception", "ignoreme") + if ign != nil || err == nil { + t.Fatalf("Expecting exception in TestMultiException() call") + } + if !reflect.DeepEqual(err, &thrifttest.Xception{ErrorCode: 1001, Message: "This is an Xception"}) { + t.Fatalf("Unexpected TestMultiException() %#v ", err) + } + + ign, err = client.TestMultiException(defaultCtx, "Xception2", "ignoreme") + if ign != nil || err == nil { + t.Fatalf("Expecting exception in TestMultiException() call") + } + expecting := &thrifttest.Xception2{ErrorCode: 2002, StructThing: &thrifttest.Xtruct{StringThing: "This is an Xception2"}} + + if !reflect.DeepEqual(err, expecting) { + t.Fatalf("Unexpected TestMultiException() %#v ", err) + } + + err = client.TestOneway(defaultCtx, 2) + if err != nil { + t.Fatalf("Unexpected error in TestOneway() call: ", err) + } + + //Make sure the connection still alive + if err = client.TestVoid(defaultCtx); err != nil { + t.Fatalf("Unexpected error in TestVoid() call: ", err) + } +} diff --git a/src/jaegertracing/thrift/test/go/src/bin/testserver/main.go b/src/jaegertracing/thrift/test/go/src/bin/testserver/main.go new file mode 100644 index 000000000..6fc1185a2 --- /dev/null +++ b/src/jaegertracing/thrift/test/go/src/bin/testserver/main.go @@ -0,0 +1,71 @@ +/* + * 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 main + +import ( + "common" + "flag" + "fmt" + "log" + "net/http" + "thrift" +) + +var host = flag.String("host", "localhost", "Host to connect") +var port = flag.Int64("port", 9090, "Port number to connect") +var domain_socket = flag.String("domain-socket", "", "Domain Socket (e.g. /tmp/ThriftTest.thrift), instead of host and port") +var transport = flag.String("transport", "buffered", "Transport: buffered, framed, http, zlib") +var protocol = flag.String("protocol", "binary", "Protocol: binary, compact, json, header") +var ssl = flag.Bool("ssl", false, "Encrypted Transport using SSL") +var zlib = flag.Bool("zlib", false, "Wrapped Transport using Zlib") +var certPath = flag.String("certPath", "keys", "Directory that contains SSL certificates") + +func main() { + flag.Parse() + + processor, serverTransport, transportFactory, protocolFactory, err := common.GetServerParams(*host, *port, *domain_socket, *transport, *protocol, *ssl, *certPath, common.PrintingHandler) + + if err != nil { + log.Fatalf("Unable to process server params: %v", err) + } + + if *transport == "http" { + http.HandleFunc("/", thrift.NewThriftHandlerFunc(processor, protocolFactory, protocolFactory)) + + if *ssl { + err := http.ListenAndServeTLS(fmt.Sprintf(":%d", *port), + *certPath+"/server.pem", *certPath+"/server.key", nil) + + if err != nil { + fmt.Println(err) + return + } + } else { + http.ListenAndServe(fmt.Sprintf(":%d", *port), nil) + } + } else { + server := thrift.NewTSimpleServer4(processor, serverTransport, transportFactory, protocolFactory) + if err = server.Listen(); err != nil { + return + } + go server.AcceptLoop() + server.Serve() + } +} diff --git a/src/jaegertracing/thrift/test/go/src/common/client.go b/src/jaegertracing/thrift/test/go/src/common/client.go new file mode 100644 index 000000000..ed820aeaf --- /dev/null +++ b/src/jaegertracing/thrift/test/go/src/common/client.go @@ -0,0 +1,111 @@ +/* + * 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 common + +import ( + "compress/zlib" + "crypto/tls" + "flag" + "fmt" + "gen/thrifttest" + "net/http" + "thrift" +) + +var debugClientProtocol bool + +func init() { + flag.BoolVar(&debugClientProtocol, "debug_client_protocol", false, "turn client protocol trace on") +} + +func StartClient( + host string, + port int64, + domain_socket string, + transport string, + protocol string, + ssl bool) (client *thrifttest.ThriftTestClient, trans thrift.TTransport, err error) { + + hostPort := fmt.Sprintf("%s:%d", host, port) + + var protocolFactory thrift.TProtocolFactory + switch protocol { + case "compact": + protocolFactory = thrift.NewTCompactProtocolFactory() + case "simplejson": + protocolFactory = thrift.NewTSimpleJSONProtocolFactory() + case "json": + protocolFactory = thrift.NewTJSONProtocolFactory() + case "binary": + protocolFactory = thrift.NewTBinaryProtocolFactoryDefault() + case "header": + protocolFactory = thrift.NewTHeaderProtocolFactory() + default: + return nil, nil, fmt.Errorf("Invalid protocol specified %s", protocol) + } + if debugClientProtocol { + protocolFactory = thrift.NewTDebugProtocolFactory(protocolFactory, "client:") + } + if ssl { + trans, err = thrift.NewTSSLSocket(hostPort, &tls.Config{InsecureSkipVerify: true}) + } else { + if domain_socket != "" { + trans, err = thrift.NewTSocket(domain_socket) + } else { + trans, err = thrift.NewTSocket(hostPort) + } + } + if err != nil { + return nil, nil, err + } + switch transport { + case "http": + if ssl { + tr := &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + } + client := &http.Client{Transport: tr} + trans, err = thrift.NewTHttpPostClientWithOptions(fmt.Sprintf("https://%s/", hostPort), thrift.THttpClientOptions{Client: client}) + fmt.Println(hostPort) + } else { + trans, err = thrift.NewTHttpPostClient(fmt.Sprintf("http://%s/", hostPort)) + } + case "framed": + trans = thrift.NewTFramedTransport(trans) + case "buffered": + trans = thrift.NewTBufferedTransport(trans, 8192) + case "zlib": + trans, err = thrift.NewTZlibTransport(trans, zlib.BestCompression) + case "": + trans = trans + default: + return nil, nil, fmt.Errorf("Invalid transport specified %s", transport) + } + if err != nil { + return nil, nil, err + } + if err = trans.Open(); err != nil { + return nil, nil, err + } + iprot := protocolFactory.GetProtocol(trans) + oprot := protocolFactory.GetProtocol(trans) + client = thrifttest.NewThriftTestClient(thrift.NewTStandardClient(iprot, oprot)) + return +} diff --git a/src/jaegertracing/thrift/test/go/src/common/clientserver_test.go b/src/jaegertracing/thrift/test/go/src/common/clientserver_test.go new file mode 100644 index 000000000..9f93c4c6c --- /dev/null +++ b/src/jaegertracing/thrift/test/go/src/common/clientserver_test.go @@ -0,0 +1,335 @@ +/* + * 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 common + +import ( + "context" + "errors" + "gen/thrifttest" + "reflect" + "sync" + "testing" + "thrift" + + "github.com/golang/mock/gomock" +) + +type test_unit struct { + host string + port int64 + domain_socket string + transport string + protocol string + ssl bool +} + +var units = []test_unit{ + {"127.0.0.1", 9095, "", "", "binary", false}, + {"127.0.0.1", 9091, "", "", "compact", false}, + {"127.0.0.1", 9092, "", "", "binary", true}, + {"127.0.0.1", 9093, "", "", "compact", true}, +} + +func TestAllConnection(t *testing.T) { + certPath = "../../../keys" + wg := &sync.WaitGroup{} + wg.Add(len(units)) + for _, unit := range units { + go func(u test_unit) { + defer wg.Done() + doUnit(t, &u) + }(unit) + } + wg.Wait() +} + +func doUnit(t *testing.T, unit *test_unit) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + handler := NewMockThriftTest(ctrl) + + processor, serverTransport, transportFactory, protocolFactory, err := GetServerParams(unit.host, unit.port, unit.domain_socket, unit.transport, unit.protocol, unit.ssl, "../../../keys", handler) + + server := thrift.NewTSimpleServer4(processor, serverTransport, transportFactory, protocolFactory) + if err = server.Listen(); err != nil { + t.Errorf("Unable to start server: %v", err) + return + } + go server.AcceptLoop() + defer server.Stop() + client, trans, err := StartClient(unit.host, unit.port, unit.domain_socket, unit.transport, unit.protocol, unit.ssl) + if err != nil { + t.Errorf("Unable to start client: %v", err) + return + } + defer trans.Close() + callEverythingWithMock(t, client, handler) +} + +var rmapmap = map[int32]map[int32]int32{ + -4: map[int32]int32{-4: -4, -3: -3, -2: -2, -1: -1}, + 4: map[int32]int32{4: 4, 3: 3, 2: 2, 1: 1}, +} + +var xxs = &thrifttest.Xtruct{ + StringThing: "Hello2", + ByteThing: 42, + I32Thing: 4242, + I64Thing: 424242, +} + +var xcept = &thrifttest.Xception{ErrorCode: 1001, Message: "some"} +var defaultCtx = context.Background() + +func callEverythingWithMock(t *testing.T, client *thrifttest.ThriftTestClient, handler *MockThriftTest) { + gomock.InOrder( + handler.EXPECT().TestVoid(gomock.Any()), + handler.EXPECT().TestString(gomock.Any(), "thing").Return("thing", nil), + handler.EXPECT().TestBool(gomock.Any(), true).Return(true, nil), + handler.EXPECT().TestBool(gomock.Any(), false).Return(false, nil), + handler.EXPECT().TestByte(gomock.Any(), int8(42)).Return(int8(42), nil), + handler.EXPECT().TestI32(gomock.Any(), int32(4242)).Return(int32(4242), nil), + handler.EXPECT().TestI64(gomock.Any(), int64(424242)).Return(int64(424242), nil), + // TODO: add TestBinary() + handler.EXPECT().TestDouble(gomock.Any(), float64(42.42)).Return(float64(42.42), nil), + handler.EXPECT().TestStruct(gomock.Any(), &thrifttest.Xtruct{StringThing: "thing", ByteThing: 42, I32Thing: 4242, I64Thing: 424242}).Return(&thrifttest.Xtruct{StringThing: "thing", ByteThing: 42, I32Thing: 4242, I64Thing: 424242}, nil), + handler.EXPECT().TestNest(gomock.Any(), &thrifttest.Xtruct2{StructThing: &thrifttest.Xtruct{StringThing: "thing", ByteThing: 42, I32Thing: 4242, I64Thing: 424242}}).Return(&thrifttest.Xtruct2{StructThing: &thrifttest.Xtruct{StringThing: "thing", ByteThing: 42, I32Thing: 4242, I64Thing: 424242}}, nil), + handler.EXPECT().TestMap(gomock.Any(), map[int32]int32{1: 2, 3: 4, 5: 42}).Return(map[int32]int32{1: 2, 3: 4, 5: 42}, nil), + handler.EXPECT().TestStringMap(gomock.Any(), map[string]string{"a": "2", "b": "blah", "some": "thing"}).Return(map[string]string{"a": "2", "b": "blah", "some": "thing"}, nil), + handler.EXPECT().TestSet(gomock.Any(), []int32{1, 2, 42}).Return([]int32{1, 2, 42}, nil), + handler.EXPECT().TestList(gomock.Any(), []int32{1, 2, 42}).Return([]int32{1, 2, 42}, nil), + handler.EXPECT().TestEnum(gomock.Any(), thrifttest.Numberz_TWO).Return(thrifttest.Numberz_TWO, nil), + handler.EXPECT().TestTypedef(gomock.Any(), thrifttest.UserId(42)).Return(thrifttest.UserId(42), nil), + handler.EXPECT().TestMapMap(gomock.Any(), int32(42)).Return(rmapmap, nil), + // TODO: not testing insanity + handler.EXPECT().TestMulti(gomock.Any(), int8(42), int32(4242), int64(424242), map[int16]string{1: "blah", 2: "thing"}, thrifttest.Numberz_EIGHT, thrifttest.UserId(24)).Return(xxs, nil), + handler.EXPECT().TestException(gomock.Any(), "some").Return(xcept), + handler.EXPECT().TestException(gomock.Any(), "TException").Return(errors.New("Just random exception")), + handler.EXPECT().TestMultiException(gomock.Any(), "Xception", "ignoreme").Return(nil, &thrifttest.Xception{ErrorCode: 1001, Message: "This is an Xception"}), + handler.EXPECT().TestMultiException(gomock.Any(), "Xception2", "ignoreme").Return(nil, &thrifttest.Xception2{ErrorCode: 2002, StructThing: &thrifttest.Xtruct{StringThing: "This is an Xception2"}}), + handler.EXPECT().TestOneway(gomock.Any(), int32(2)).Return(nil), + handler.EXPECT().TestVoid(gomock.Any()), + ) + var err error + if err = client.TestVoid(defaultCtx); err != nil { + t.Errorf("Unexpected error in TestVoid() call: %s", err) + } + + thing, err := client.TestString(defaultCtx, "thing") + if err != nil { + t.Errorf("Unexpected error in TestString() call: %s", err) + } + if thing != "thing" { + t.Errorf("Unexpected TestString() result, expected 'thing' got '%s' ", thing) + } + + bl, err := client.TestBool(defaultCtx, true) + if err != nil { + t.Errorf("Unexpected error in TestBool() call: %s", err) + } + if !bl { + t.Errorf("Unexpected TestBool() result expected true, got %v ", bl) + } + bl, err = client.TestBool(defaultCtx, false) + if err != nil { + t.Errorf("Unexpected error in TestBool() call: %s", err) + } + if bl { + t.Errorf("Unexpected TestBool() result expected false, got %v ", bl) + } + + b, err := client.TestByte(defaultCtx, 42) + if err != nil { + t.Errorf("Unexpected error in TestByte() call: %s", err) + } + if b != 42 { + t.Errorf("Unexpected TestByte() result expected 42, got %d ", b) + } + + i32, err := client.TestI32(defaultCtx, 4242) + if err != nil { + t.Errorf("Unexpected error in TestI32() call: %s", err) + } + if i32 != 4242 { + t.Errorf("Unexpected TestI32() result expected 4242, got %d ", i32) + } + + i64, err := client.TestI64(defaultCtx, 424242) + if err != nil { + t.Errorf("Unexpected error in TestI64() call: %s", err) + } + if i64 != 424242 { + t.Errorf("Unexpected TestI64() result expected 424242, got %d ", i64) + } + + d, err := client.TestDouble(defaultCtx, 42.42) + if err != nil { + t.Errorf("Unexpected error in TestDouble() call: %s", err) + } + if d != 42.42 { + t.Errorf("Unexpected TestDouble() result expected 42.42, got %f ", d) + } + + // TODO: add TestBinary() call + + xs := thrifttest.NewXtruct() + xs.StringThing = "thing" + xs.ByteThing = 42 + xs.I32Thing = 4242 + xs.I64Thing = 424242 + xsret, err := client.TestStruct(defaultCtx, xs) + if err != nil { + t.Errorf("Unexpected error in TestStruct() call: %s", err) + } + if *xs != *xsret { + t.Errorf("Unexpected TestStruct() result expected %#v, got %#v ", xs, xsret) + } + + x2 := thrifttest.NewXtruct2() + x2.StructThing = xs + x2ret, err := client.TestNest(defaultCtx, x2) + if err != nil { + t.Errorf("Unexpected error in TestNest() call: %s", err) + } + if !reflect.DeepEqual(x2, x2ret) { + t.Errorf("Unexpected TestNest() result expected %#v, got %#v ", x2, x2ret) + } + + m := map[int32]int32{1: 2, 3: 4, 5: 42} + mret, err := client.TestMap(defaultCtx, m) + if err != nil { + t.Errorf("Unexpected error in TestMap() call: %s", err) + } + if !reflect.DeepEqual(m, mret) { + t.Errorf("Unexpected TestMap() result expected %#v, got %#v ", m, mret) + } + + sm := map[string]string{"a": "2", "b": "blah", "some": "thing"} + smret, err := client.TestStringMap(defaultCtx, sm) + if err != nil { + t.Errorf("Unexpected error in TestStringMap() call: %s", err) + } + if !reflect.DeepEqual(sm, smret) { + t.Errorf("Unexpected TestStringMap() result expected %#v, got %#v ", sm, smret) + } + + s := []int32{1, 2, 42} + sret, err := client.TestSet(defaultCtx, s) + if err != nil { + t.Errorf("Unexpected error in TestSet() call: %s", err) + } + // Sets can be in any order, but Go slices are ordered, so reflect.DeepEqual won't work. + stemp := map[int32]struct{}{} + for _, val := range s { + stemp[val] = struct{}{} + } + for _, val := range sret { + if _, ok := stemp[val]; !ok { + t.Fatalf("Unexpected TestSet() result expected %#v, got %#v ", s, sret) + } + } + + l := []int32{1, 2, 42} + lret, err := client.TestList(defaultCtx, l) + if err != nil { + t.Errorf("Unexpected error in TestList() call: %s", err) + } + if !reflect.DeepEqual(l, lret) { + t.Errorf("Unexpected TestList() result expected %#v, got %#v ", l, lret) + } + + eret, err := client.TestEnum(defaultCtx, thrifttest.Numberz_TWO) + if err != nil { + t.Errorf("Unexpected error in TestEnum() call: %s", err) + } + if eret != thrifttest.Numberz_TWO { + t.Errorf("Unexpected TestEnum() result expected %#v, got %#v ", thrifttest.Numberz_TWO, eret) + } + + tret, err := client.TestTypedef(defaultCtx, thrifttest.UserId(42)) + if err != nil { + t.Errorf("Unexpected error in TestTypedef() call: %s", err) + } + if tret != thrifttest.UserId(42) { + t.Errorf("Unexpected TestTypedef() result expected %#v, got %#v ", thrifttest.UserId(42), tret) + } + + mapmap, err := client.TestMapMap(defaultCtx, 42) + if err != nil { + t.Errorf("Unexpected error in TestMapmap() call: %s", err) + } + if !reflect.DeepEqual(mapmap, rmapmap) { + t.Errorf("Unexpected TestMapmap() result expected %#v, got %#v ", rmapmap, mapmap) + } + + xxsret, err := client.TestMulti(defaultCtx, 42, 4242, 424242, map[int16]string{1: "blah", 2: "thing"}, thrifttest.Numberz_EIGHT, thrifttest.UserId(24)) + if err != nil { + t.Errorf("Unexpected error in TestMulti() call: %s", err) + } + if !reflect.DeepEqual(xxs, xxsret) { + t.Errorf("Unexpected TestMulti() result expected %#v, got %#v ", xxs, xxsret) + } + + err = client.TestException(defaultCtx, "some") + if err == nil { + t.Errorf("Expecting exception in TestException() call") + } + if !reflect.DeepEqual(err, xcept) { + t.Errorf("Unexpected TestException() result expected %#v, got %#v ", xcept, err) + } + + // TODO: connection is being closed on this + err = client.TestException(defaultCtx, "TException") + if err == nil { + t.Error("expected exception got nil") + } else if tex, ok := err.(thrift.TApplicationException); !ok { + t.Errorf("Unexpected TestException() result expected ApplicationError, got %T ", err) + } else if tex.TypeId() != thrift.INTERNAL_ERROR { + t.Errorf("expected internal_error got %v", tex.TypeId()) + } + + ign, err := client.TestMultiException(defaultCtx, "Xception", "ignoreme") + if ign != nil || err == nil { + t.Errorf("Expecting exception in TestMultiException() call") + } + if !reflect.DeepEqual(err, &thrifttest.Xception{ErrorCode: 1001, Message: "This is an Xception"}) { + t.Errorf("Unexpected TestMultiException() %#v ", err) + } + + ign, err = client.TestMultiException(defaultCtx, "Xception2", "ignoreme") + if ign != nil || err == nil { + t.Errorf("Expecting exception in TestMultiException() call") + } + expecting := &thrifttest.Xception2{ErrorCode: 2002, StructThing: &thrifttest.Xtruct{StringThing: "This is an Xception2"}} + + if !reflect.DeepEqual(err, expecting) { + t.Errorf("Unexpected TestMultiException() %#v ", err) + } + + err = client.TestOneway(defaultCtx, 2) + if err != nil { + t.Errorf("Unexpected error in TestOneway() call: %s", err) + } + + //Make sure the connection still alive + if err = client.TestVoid(defaultCtx); err != nil { + t.Errorf("Unexpected error in TestVoid() call: %s", err) + } +} diff --git a/src/jaegertracing/thrift/test/go/src/common/context_test.go b/src/jaegertracing/thrift/test/go/src/common/context_test.go new file mode 100644 index 000000000..e64dbb9ad --- /dev/null +++ b/src/jaegertracing/thrift/test/go/src/common/context_test.go @@ -0,0 +1,98 @@ +/* + * 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 common + +import ( + "context" + "fmt" + "net" + "net/http" + "net/url" + "os" + "syscall" + "testing" + "thrift" + "time" +) + +type slowHttpHandler struct{} + +func (slowHttpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + time.Sleep(1 * time.Second) +} + +func TestHttpContextTimeout(t *testing.T) { + certPath = "../../../keys" + + unit := test_unit{"127.0.0.1", 9096, "", "http", "binary", false} + + server := &http.Server{Addr: unit.host + fmt.Sprintf(":%d", unit.port), Handler: slowHttpHandler{}} + go server.ListenAndServe() + + client, trans, err := StartClient(unit.host, unit.port, unit.domain_socket, unit.transport, unit.protocol, unit.ssl) + if err != nil { + t.Errorf("Unable to start client: %v", err) + return + } + defer trans.Close() + + unwrapErr := func(err error) error { + for { + switch err.(type) { + case thrift.TTransportException: + err = err.(thrift.TTransportException).Err() + case *url.Error: + err = err.(*url.Error).Err + case *net.OpError: + err = err.(*net.OpError).Err + case *os.SyscallError: + err = err.(*os.SyscallError).Err + default: + return err + } + } + } + + serverStartupDeadline := time.Now().Add(5 * time.Second) + for { + ctx, _ := context.WithTimeout(context.Background(), 50*time.Millisecond) + err = client.TestVoid(ctx) + err = unwrapErr(err) + if err != syscall.ECONNREFUSED || time.Now().After(serverStartupDeadline) { + break + } + time.Sleep(time.Millisecond) + } + + if err == nil { + t.Errorf("Request completed (should have timed out)") + return + } + + // We've got to switch on `err.Error()` here since go1.7 doesn't properly return + // `context.DeadlineExceeded` error and `http.errRequestCanceled` is not exported. + // See https://github.com/golang/go/issues/17711 + switch err.Error() { + case context.DeadlineExceeded.Error(), "net/http: request canceled": + // Expected error + default: + t.Errorf("Unexpected error: %s", err) + } +} diff --git a/src/jaegertracing/thrift/test/go/src/common/printing_handler.go b/src/jaegertracing/thrift/test/go/src/common/printing_handler.go new file mode 100644 index 000000000..2b22d0c97 --- /dev/null +++ b/src/jaegertracing/thrift/test/go/src/common/printing_handler.go @@ -0,0 +1,384 @@ +/* + * 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 common + +import ( + "context" + "encoding/hex" + "errors" + "fmt" + . "gen/thrifttest" + "time" +) + +var PrintingHandler = &printingHandler{} + +type printingHandler struct{} + +// Prints "testVoid()" and returns nothing. +func (p *printingHandler) TestVoid(ctx context.Context) (err error) { + fmt.Println("testVoid()") + return nil +} + +// Prints 'testString("%s")' with thing as '%s' +// @param string thing - the string to print +// @return string - returns the string 'thing' +// +// Parameters: +// - Thing +func (p *printingHandler) TestString(ctx context.Context, thing string) (r string, err error) { + fmt.Printf("testString(\"%s\")\n", thing) + return thing, nil +} + +// Prints 'testBool("%t")' with thing as 'true' or 'false' +// @param bool thing - the bool to print +// @return bool - returns the bool 'thing' +// +// Parameters: +// - Thing +func (p *printingHandler) TestBool(ctx context.Context, thing bool) (r bool, err error) { + fmt.Printf("testBool(%t)\n", thing) + return thing, nil +} + +// Prints 'testByte("%d")' with thing as '%d' +// @param byte thing - the byte to print +// @return byte - returns the byte 'thing' +// +// Parameters: +// - Thing +func (p *printingHandler) TestByte(ctx context.Context, thing int8) (r int8, err error) { + fmt.Printf("testByte(%d)\n", thing) + return thing, nil +} + +// Prints 'testI32("%d")' with thing as '%d' +// @param i32 thing - the i32 to print +// @return i32 - returns the i32 'thing' +// +// Parameters: +// - Thing +func (p *printingHandler) TestI32(ctx context.Context, thing int32) (r int32, err error) { + fmt.Printf("testI32(%d)\n", thing) + return thing, nil +} + +// Prints 'testI64("%d")' with thing as '%d' +// @param i64 thing - the i64 to print +// @return i64 - returns the i64 'thing' +// +// Parameters: +// - Thing +func (p *printingHandler) TestI64(ctx context.Context, thing int64) (r int64, err error) { + fmt.Printf("testI64(%d)\n", thing) + return thing, nil +} + +// Prints 'testDouble("%f")' with thing as '%f' +// @param double thing - the double to print +// @return double - returns the double 'thing' +// +// Parameters: +// - Thing +func (p *printingHandler) TestDouble(ctx context.Context, thing float64) (r float64, err error) { + fmt.Printf("testDouble(%f)\n", thing) + return thing, nil +} + +// Prints 'testBinary("%s")' where '%s' is a hex-formatted string of thing's data +// @param []byte thing - the binary to print +// @return []byte - returns the binary 'thing' +// +// Parameters: +// - Thing +func (p *printingHandler) TestBinary(ctx context.Context, thing []byte) (r []byte, err error) { + fmt.Printf("testBinary(%s)\n", hex.EncodeToString(thing)) + return thing, nil +} + +// Prints 'testStruct("{%s}")' where thing has been formatted into a string of comma separated values +// @param Xtruct thing - the Xtruct to print +// @return Xtruct - returns the Xtruct 'thing' +// +// Parameters: +// - Thing +func (p *printingHandler) TestStruct(ctx context.Context, thing *Xtruct) (r *Xtruct, err error) { + fmt.Printf("testStruct({\"%s\", %d, %d, %d})\n", thing.StringThing, thing.ByteThing, thing.I32Thing, thing.I64Thing) + return thing, err +} + +// Prints 'testNest("{%s}")' where thing has been formatted into a string of the nested struct +// @param Xtruct2 thing - the Xtruct2 to print +// @return Xtruct2 - returns the Xtruct2 'thing' +// +// Parameters: +// - Thing +func (p *printingHandler) TestNest(ctx context.Context, nest *Xtruct2) (r *Xtruct2, err error) { + thing := nest.StructThing + fmt.Printf("testNest({%d, {\"%s\", %d, %d, %d}, %d})\n", nest.ByteThing, thing.StringThing, thing.ByteThing, thing.I32Thing, thing.I64Thing, nest.I32Thing) + return nest, nil +} + +// Prints 'testMap("{%s")' where thing has been formatted into a string of 'key => value' pairs +// separated by commas and new lines +// @param map<i32,i32> thing - the map<i32,i32> to print +// @return map<i32,i32> - returns the map<i32,i32> 'thing' +// +// Parameters: +// - Thing +func (p *printingHandler) TestMap(ctx context.Context, thing map[int32]int32) (r map[int32]int32, err error) { + fmt.Printf("testMap({") + first := true + for k, v := range thing { + if first { + first = false + } else { + fmt.Printf(", ") + } + fmt.Printf("%d => %d", k, v) + } + fmt.Printf("})\n") + return thing, nil +} + +// Prints 'testStringMap("{%s}")' where thing has been formatted into a string of 'key => value' pairs +// separated by commas and new lines +// @param map<string,string> thing - the map<string,string> to print +// @return map<string,string> - returns the map<string,string> 'thing' +// +// Parameters: +// - Thing +func (p *printingHandler) TestStringMap(ctx context.Context, thing map[string]string) (r map[string]string, err error) { + fmt.Printf("testStringMap({") + first := true + for k, v := range thing { + if first { + first = false + } else { + fmt.Printf(", ") + } + fmt.Printf("%s => %s", k, v) + } + fmt.Printf("})\n") + return thing, nil +} + +// Prints 'testSet("{%s}")' where thing has been formatted into a string of values +// separated by commas and new lines +// @param set<i32> thing - the set<i32> to print +// @return set<i32> - returns the set<i32> 'thing' +// +// Parameters: +// - Thing +func (p *printingHandler) TestSet(ctx context.Context, thing []int32) (r []int32, err error) { + fmt.Printf("testSet({") + first := true + for k, _ := range thing { + if first { + first = false + } else { + fmt.Printf(", ") + } + fmt.Printf("%d", k) + } + fmt.Printf("})\n") + return thing, nil +} + +// Prints 'testList("{%s}")' where thing has been formatted into a string of values +// separated by commas and new lines +// @param list<i32> thing - the list<i32> to print +// @return list<i32> - returns the list<i32> 'thing' +// +// Parameters: +// - Thing +func (p *printingHandler) TestList(ctx context.Context, thing []int32) (r []int32, err error) { + fmt.Printf("testList({") + for i, v := range thing { + if i != 0 { + fmt.Printf(", ") + } + fmt.Printf("%d", v) + } + fmt.Printf("})\n") + return thing, nil +} + +// Prints 'testEnum("%d")' where thing has been formatted into it's numeric value +// @param Numberz thing - the Numberz to print +// @return Numberz - returns the Numberz 'thing' +// +// Parameters: +// - Thing +func (p *printingHandler) TestEnum(ctx context.Context, thing Numberz) (r Numberz, err error) { + fmt.Printf("testEnum(%d)\n", thing) + return thing, nil +} + +// Prints 'testTypedef("%d")' with thing as '%d' +// @param UserId thing - the UserId to print +// @return UserId - returns the UserId 'thing' +// +// Parameters: +// - Thing +func (p *printingHandler) TestTypedef(ctx context.Context, thing UserId) (r UserId, err error) { + fmt.Printf("testTypedef(%d)\n", thing) + return thing, nil +} + +// Prints 'testMapMap("%d")' with hello as '%d' +// @param i32 hello - the i32 to print +// @return map<i32,map<i32,i32>> - returns a dictionary with these values: +// {-4 => {-4 => -4, -3 => -3, -2 => -2, -1 => -1, }, 4 => {1 => 1, 2 => 2, 3 => 3, 4 => 4, }, } +// +// Parameters: +// - Hello +func (p *printingHandler) TestMapMap(ctx context.Context, hello int32) (r map[int32]map[int32]int32, err error) { + fmt.Printf("testMapMap(%d)\n", hello) + + r = map[int32]map[int32]int32{ + -4: map[int32]int32{-4: -4, -3: -3, -2: -2, -1: -1}, + 4: map[int32]int32{4: 4, 3: 3, 2: 2, 1: 1}, + } + return +} + +// So you think you've got this all worked, out eh? +// +// Creates a the returned map with these values and prints it out: +// { 1 => { 2 => argument, +// 3 => argument, +// }, +// 2 => { 6 => <empty Insanity struct>, }, +// } +// @return map<UserId, map<Numberz,Insanity>> - a map with the above values +// +// Parameters: +// - Argument +func (p *printingHandler) TestInsanity(ctx context.Context, argument *Insanity) (r map[UserId]map[Numberz]*Insanity, err error) { + fmt.Printf("testInsanity()\n") + r = make(map[UserId]map[Numberz]*Insanity) + r[1] = map[Numberz]*Insanity{ + 2: argument, + 3: argument, + } + r[2] = map[Numberz]*Insanity{ + 6: NewInsanity(), + } + return +} + +// Prints 'testMulti()' +// @param byte arg0 - +// @param i32 arg1 - +// @param i64 arg2 - +// @param map<i16, string> arg3 - +// @param Numberz arg4 - +// @param UserId arg5 - +// @return Xtruct - returns an Xtruct with StringThing = "Hello2, ByteThing = arg0, I32Thing = arg1 +// and I64Thing = arg2 +// +// Parameters: +// - Arg0 +// - Arg1 +// - Arg2 +// - Arg3 +// - Arg4 +// - Arg5 +func (p *printingHandler) TestMulti(ctx context.Context, arg0 int8, arg1 int32, arg2 int64, arg3 map[int16]string, arg4 Numberz, arg5 UserId) (r *Xtruct, err error) { + fmt.Printf("testMulti()\n") + r = NewXtruct() + + r.StringThing = "Hello2" + r.ByteThing = arg0 + r.I32Thing = arg1 + r.I64Thing = arg2 + return +} + +// Print 'testException(%s)' with arg as '%s' +// @param string arg - a string indication what type of exception to throw +// if arg == "Xception" throw Xception with errorCode = 1001 and message = arg +// elsen if arg == "TException" throw TException +// else do not throw anything +// +// Parameters: +// - Arg +func (p *printingHandler) TestException(ctx context.Context, arg string) (err error) { + fmt.Printf("testException(%s)\n", arg) + switch arg { + case "Xception": + e := NewXception() + e.ErrorCode = 1001 + e.Message = arg + return e + case "TException": + return errors.New("Just TException") + } + return +} + +// Print 'testMultiException(%s, %s)' with arg0 as '%s' and arg1 as '%s' +// @param string arg - a string indication what type of exception to throw +// if arg0 == "Xception" throw Xception with errorCode = 1001 and message = "This is an Xception" +// elsen if arg0 == "Xception2" throw Xception2 with errorCode = 2002 and message = "This is an Xception2" +// else do not throw anything +// @return Xtruct - an Xtruct with StringThing = arg1 +// +// Parameters: +// - Arg0 +// - Arg1 +func (p *printingHandler) TestMultiException(ctx context.Context, arg0 string, arg1 string) (r *Xtruct, err error) { + fmt.Printf("testMultiException(%s, %s)\n", arg0, arg1) + switch arg0 { + + case "Xception": + e := NewXception() + e.ErrorCode = 1001 + e.Message = "This is an Xception" + return nil, e + case "Xception2": + e := NewXception2() + e.ErrorCode = 2002 + e.StructThing = NewXtruct() + e.StructThing.StringThing = "This is an Xception2" + return nil, e + default: + r = NewXtruct() + r.StringThing = arg1 + return + } +} + +// Print 'testOneway(%d): Sleeping...' with secondsToSleep as '%d' +// sleep 'secondsToSleep' +// Print 'testOneway(%d): done sleeping!' with secondsToSleep as '%d' +// @param i32 secondsToSleep - the number of seconds to sleep +// +// Parameters: +// - SecondsToSleep +func (p *printingHandler) TestOneway(ctx context.Context, secondsToSleep int32) (err error) { + fmt.Printf("testOneway(%d): Sleeping...\n", secondsToSleep) + time.Sleep(time.Second * time.Duration(secondsToSleep)) + fmt.Printf("testOneway(%d): done sleeping!\n", secondsToSleep) + return +} diff --git a/src/jaegertracing/thrift/test/go/src/common/server.go b/src/jaegertracing/thrift/test/go/src/common/server.go new file mode 100644 index 000000000..c6674ae75 --- /dev/null +++ b/src/jaegertracing/thrift/test/go/src/common/server.go @@ -0,0 +1,113 @@ +/* + * 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 common + +import ( + "compress/zlib" + "crypto/tls" + "flag" + "fmt" + "gen/thrifttest" + "thrift" +) + +var ( + debugServerProtocol bool + certPath string +) + +func init() { + flag.BoolVar(&debugServerProtocol, "debug_server_protocol", false, "turn server protocol trace on") +} + +func GetServerParams( + host string, + port int64, + domain_socket string, + transport string, + protocol string, + ssl bool, + certPath string, + handler thrifttest.ThriftTest) (thrift.TProcessor, thrift.TServerTransport, thrift.TTransportFactory, thrift.TProtocolFactory, error) { + + var err error + hostPort := fmt.Sprintf("%s:%d", host, port) + + var protocolFactory thrift.TProtocolFactory + switch protocol { + case "compact": + protocolFactory = thrift.NewTCompactProtocolFactory() + case "simplejson": + protocolFactory = thrift.NewTSimpleJSONProtocolFactory() + case "json": + protocolFactory = thrift.NewTJSONProtocolFactory() + case "binary": + protocolFactory = thrift.NewTBinaryProtocolFactoryDefault() + case "header": + protocolFactory = thrift.NewTHeaderProtocolFactory() + default: + return nil, nil, nil, nil, fmt.Errorf("Invalid protocol specified %s", protocol) + } + if debugServerProtocol { + protocolFactory = thrift.NewTDebugProtocolFactory(protocolFactory, "server:") + } + + var serverTransport thrift.TServerTransport + if ssl { + cfg := new(tls.Config) + if cert, err := tls.LoadX509KeyPair(certPath+"/server.crt", certPath+"/server.key"); err != nil { + return nil, nil, nil, nil, err + } else { + cfg.Certificates = append(cfg.Certificates, cert) + } + serverTransport, err = thrift.NewTSSLServerSocket(hostPort, cfg) + } else { + if domain_socket != "" { + serverTransport, err = thrift.NewTServerSocket(domain_socket) + } else { + serverTransport, err = thrift.NewTServerSocket(hostPort) + } + } + if err != nil { + return nil, nil, nil, nil, err + } + + var transportFactory thrift.TTransportFactory + + switch transport { + case "http": + // there is no such factory, and we don't need any + transportFactory = nil + case "framed": + transportFactory = thrift.NewTTransportFactory() + transportFactory = thrift.NewTFramedTransportFactory(transportFactory) + case "buffered": + transportFactory = thrift.NewTBufferedTransportFactory(8192) + case "zlib": + transportFactory = thrift.NewTZlibTransportFactory(zlib.BestCompression) + case "": + transportFactory = thrift.NewTTransportFactory() + default: + return nil, nil, nil, nil, fmt.Errorf("Invalid transport specified %s", transport) + } + processor := thrifttest.NewThriftTestProcessor(handler) + + return processor, serverTransport, transportFactory, protocolFactory, nil +} diff --git a/src/jaegertracing/thrift/test/go/src/common/simple_handler.go b/src/jaegertracing/thrift/test/go/src/common/simple_handler.go new file mode 100644 index 000000000..0c9463da0 --- /dev/null +++ b/src/jaegertracing/thrift/test/go/src/common/simple_handler.go @@ -0,0 +1,155 @@ +/* + * 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 common + +import ( + "errors" + . "gen/thrifttest" + "time" +) + +var SimpleHandler = &simpleHandler{} + +type simpleHandler struct{} + +func (p *simpleHandler) TestVoid() (err error) { + return nil +} + +func (p *simpleHandler) TestString(thing string) (r string, err error) { + return thing, nil +} + +func (p *simpleHandler) TestBool(thing []byte) (r []byte, err error) { + return thing, nil +} + +func (p *simpleHandler) TestByte(thing int8) (r int8, err error) { + return thing, nil +} + +func (p *simpleHandler) TestI32(thing int32) (r int32, err error) { + return thing, nil +} + +func (p *simpleHandler) TestI64(thing int64) (r int64, err error) { + return thing, nil +} + +func (p *simpleHandler) TestDouble(thing float64) (r float64, err error) { + return thing, nil +} + +func (p *simpleHandler) TestBinary(thing []byte) (r []byte, err error) { + return thing, nil +} + +func (p *simpleHandler) TestStruct(thing *Xtruct) (r *Xtruct, err error) { + return r, err +} + +func (p *simpleHandler) TestNest(nest *Xtruct2) (r *Xtruct2, err error) { + return nest, nil +} + +func (p *simpleHandler) TestMap(thing map[int32]int32) (r map[int32]int32, err error) { + return thing, nil +} + +func (p *simpleHandler) TestStringMap(thing map[string]string) (r map[string]string, err error) { + return thing, nil +} + +func (p *simpleHandler) TestSet(thing []int32) (r []int32, err error) { + return thing, nil +} + +func (p *simpleHandler) TestList(thing []int32) (r []int32, err error) { + return thing, nil +} + +func (p *simpleHandler) TestEnum(thing Numberz) (r Numberz, err error) { + return thing, nil +} + +func (p *simpleHandler) TestTypedef(thing UserId) (r UserId, err error) { + return thing, nil +} + +func (p *simpleHandler) TestMapMap(hello int32) (r map[int32]map[int32]int32, err error) { + + r = map[int32]map[int32]int32{ + -4: map[int32]int32{-4: -4, -3: -3, -2: -2, -1: -1}, + 4: map[int32]int32{4: 4, 3: 3, 2: 2, 1: 1}, + } + return +} + +func (p *simpleHandler) TestInsanity(argument *Insanity) (r map[UserId]map[Numberz]*Insanity, err error) { + return nil, errors.New("No Insanity") +} + +func (p *simpleHandler) TestMulti(arg0 int8, arg1 int32, arg2 int64, arg3 map[int16]string, arg4 Numberz, arg5 UserId) (r *Xtruct, err error) { + r = NewXtruct() + + r.StringThing = "Hello2" + r.ByteThing = arg0 + r.I32Thing = arg1 + r.I64Thing = arg2 + return +} + +func (p *simpleHandler) TestException(arg string) (err error) { + switch arg { + case "Xception": + e := NewXception() + e.ErrorCode = 1001 + e.Message = arg + return e + case "TException": + return errors.New("Just TException") + } + return +} + +func (p *simpleHandler) TestMultiException(arg0 string, arg1 string) (r *Xtruct, err error) { + switch arg0 { + + case "Xception": + e := NewXception() + e.ErrorCode = 1001 + e.Message = "This is an Xception" + return nil, e + case "Xception2": + e := NewXception2() + e.ErrorCode = 2002 + e.StructThing.StringThing = "This is an Xception2" + return nil, e + default: + r = NewXtruct() + r.StringThing = arg1 + return + } +} + +func (p *simpleHandler) TestOneway(secondsToSleep int32) (err error) { + time.Sleep(time.Second * time.Duration(secondsToSleep)) + return +} diff --git a/src/jaegertracing/thrift/test/haxe/Makefile.am b/src/jaegertracing/thrift/test/haxe/Makefile.am new file mode 100644 index 000000000..6c0483e9e --- /dev/null +++ b/src/jaegertracing/thrift/test/haxe/Makefile.am @@ -0,0 +1,104 @@ +# +# 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. +# + +THRIFTCMD = $(THRIFT) --gen haxe -r +THRIFTTEST = $(top_srcdir)/test/ThriftTest.thrift + +BIN_CPP = bin/Main-debug +BIN_PHP = bin/php/Main-debug.php +BIN_PHP_WEB = bin/php-web-server/Main-debug.php + +gen-haxe/thrift/test/ThriftTest.hx: $(THRIFTTEST) + $(THRIFTCMD) $(THRIFTTEST) + +all-local: $(BIN_CPP) $(BIN_PHP) $(BIN_PHP_WEB) + +$(BIN_CPP): \ + src/*.hx \ + ../../lib/haxe/src/org/apache/thrift/**/*.hx \ + gen-haxe/thrift/test/ThriftTest.hx + $(HAXE) --cwd . cpp.hxml + +$(BIN_PHP): \ + src/*.hx \ + ../../lib/haxe/src/org/apache/thrift/**/*.hx \ + gen-haxe/thrift/test/ThriftTest.hx + $(HAXE) --cwd . php.hxml + +$(BIN_PHP_WEB): \ + src/*.hx \ + ../../lib/haxe/src/org/apache/thrift/**/*.hx \ + gen-haxe/thrift/test/ThriftTest.hx + $(HAXE) --cwd . php-web-server.hxml + + + +#TODO: other haxe targets +# $(HAXE) --cwd . csharp +# $(HAXE) --cwd . flash +# $(HAXE) --cwd . java +# $(HAXE) --cwd . javascript +# $(HAXE) --cwd . neko +# $(HAXE) --cwd . python # needs Haxe 3.2.0 + + +clean-local: + $(RM) -r gen-haxe bin + +.NOTPARALLEL: + +check: check_cpp \ + check_php \ + check_php_web + +check_cpp: $(BIN_CPP) + timeout 20 $(BIN_CPP) server & + sleep 1 + $(BIN_CPP) client + sleep 10 + +check_php: $(BIN_PHP) + timeout 20 php -f $(BIN_PHP) server & + sleep 1 + php -f $(BIN_PHP) client + sleep 10 + +check_php_web: $(BIN_PHP_WEB) $(BIN_CPP) + timeout 20 php -S 127.0.0.1:9090 router.php & + sleep 1 + $(BIN_CPP) client --transport http + sleep 10 + + +EXTRA_DIST = \ + src \ + cpp.hxml \ + csharp.hxml \ + flash.hxml \ + java.hxml \ + javascript.hxml \ + neko.hxml \ + php.hxml \ + python.hxml \ + router.php \ + project.hide \ + php-web-server.hxml \ + TestClientServer.hxproj \ + make_all.bat \ + make_all.sh diff --git a/src/jaegertracing/thrift/test/haxe/TestClientServer.hxproj b/src/jaegertracing/thrift/test/haxe/TestClientServer.hxproj new file mode 100644 index 000000000..6696d80c2 --- /dev/null +++ b/src/jaegertracing/thrift/test/haxe/TestClientServer.hxproj @@ -0,0 +1,67 @@ +<?xml version="1.0" encoding="utf-8"?> +<project version="2"> + <!-- Output SWF options --> + <output> + <movie outputType="Application" /> + <movie input="" /> + <movie path="bin/TestClientServer" /> + <movie fps="30" /> + <movie width="800" /> + <movie height="600" /> + <movie version="1" /> + <movie minorVersion="0" /> + <movie platform="C++" /> + <movie background="#FFFFFF" /> + </output> + <!-- Other classes to be compiled into your SWF --> + <classpaths> + <class path="src" /> + <class path="gen-haxe" /> + <class path="../../lib/haxe/src" /> + </classpaths> + <!-- Build options --> + <build> + <option directives="" /> + <option flashStrict="False" /> + <option noInlineOnDebug="False" /> + <option mainClass="Main" /> + <option enabledebug="False" /> + <option additional="" /> + </build> + <!-- haxelib libraries --> + <haxelib> + <!-- example: <library name="..." /> --> + </haxelib> + <!-- Class files to compile (other referenced classes will automatically be included) --> + <compileTargets> + <!-- example: <compile path="..." /> --> + </compileTargets> + <!-- Paths to exclude from the Project Explorer tree --> + <hiddenPaths> + <hidden path="obj" /> + <hidden path="cpp.hxml" /> + <hidden path="csharp.hxml" /> + <hidden path="flash.hxml" /> + <hidden path="java.hxml" /> + <hidden path="javascript.hxml" /> + <hidden path="make_all.bat" /> + <hidden path="make_all.sh" /> + <hidden path="Makefile.am" /> + <hidden path="neko.hxml" /> + <hidden path="php.hxml" /> + <hidden path="project.hide" /> + <hidden path="python.hxml" /> + </hiddenPaths> + <!-- Executed before build --> + <preBuildCommand>thrift -r -gen haxe ../ThriftTest.thrift</preBuildCommand> + <!-- Executed after build --> + <postBuildCommand alwaysRun="False" /> + <!-- Other project options --> + <options> + <option showHiddenPaths="False" /> + <option testMovie="Unknown" /> + <option testMovieCommand="" /> + </options> + <!-- Plugin storage --> + <storage /> +</project>
\ No newline at end of file diff --git a/src/jaegertracing/thrift/test/haxe/cpp.hxml b/src/jaegertracing/thrift/test/haxe/cpp.hxml new file mode 100644 index 000000000..6adb52d7e --- /dev/null +++ b/src/jaegertracing/thrift/test/haxe/cpp.hxml @@ -0,0 +1,41 @@ +# +# 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. +# + +#integrate files to classpath +-cp src +-cp gen-haxe +-cp ../../lib/haxe/src + +#this class wil be used as entry point for your app. +-main Main + +#CPP target +-cpp bin + +#To produce 64 bit binaries the file should define the HXCPP_M64 compile variable: +#-D HXCPP_M64 + +#Add debug information +-debug + +#dead code elimination : remove unused code +#"-dce no" : do not remove unused code +#"-dce std" : remove unused code in the std lib (default) +#"-dce full" : remove all unused code +-dce full
\ No newline at end of file diff --git a/src/jaegertracing/thrift/test/haxe/csharp.hxml b/src/jaegertracing/thrift/test/haxe/csharp.hxml new file mode 100644 index 000000000..295c017e7 --- /dev/null +++ b/src/jaegertracing/thrift/test/haxe/csharp.hxml @@ -0,0 +1,38 @@ +# +# 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. +# + +#integrate files to classpath +-cp src +-cp gen-haxe +-cp ../../lib/haxe/src + +#this class wil be used as entry point for your app. +-main Main + +#CSHARP target +-cs bin/Tutorial.exe + +#Add debug information +-debug + +#dead code elimination : remove unused code +#"-dce no" : do not remove unused code +#"-dce std" : remove unused code in the std lib (default) +#"-dce full" : remove all unused code +-dce full
\ No newline at end of file diff --git a/src/jaegertracing/thrift/test/haxe/flash.hxml b/src/jaegertracing/thrift/test/haxe/flash.hxml new file mode 100644 index 000000000..a1f0568ad --- /dev/null +++ b/src/jaegertracing/thrift/test/haxe/flash.hxml @@ -0,0 +1,41 @@ +# +# 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. +# + +#integrate files to classpath +-cp src +-cp gen-haxe +-cp ../../lib/haxe/src + +#this class wil be used as entry point for your app. +-main Main + +#Flash target +-swf bin/Tutorial.swf + +#Add debug information +-debug + +# we need some goodies from sys.net +# --macro allowPackage("sys") + +#dead code elimination : remove unused code +#"-dce no" : do not remove unused code +#"-dce std" : remove unused code in the std lib (default) +#"-dce full" : remove all unused code +-dce full
\ No newline at end of file diff --git a/src/jaegertracing/thrift/test/haxe/java.hxml b/src/jaegertracing/thrift/test/haxe/java.hxml new file mode 100644 index 000000000..c615565a9 --- /dev/null +++ b/src/jaegertracing/thrift/test/haxe/java.hxml @@ -0,0 +1,38 @@ +# +# 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. +# + +#integrate files to classpath +-cp src +-cp gen-haxe +-cp ../../lib/haxe/src + +#this class wil be used as entry point for your app. +-main Main + +#Java target +-java bin/Tutorial.jar + +#Add debug information +-debug + +#dead code elimination : remove unused code +#"-dce no" : do not remove unused code +#"-dce std" : remove unused code in the std lib (default) +#"-dce full" : remove all unused code +-dce full
\ No newline at end of file diff --git a/src/jaegertracing/thrift/test/haxe/javascript.hxml b/src/jaegertracing/thrift/test/haxe/javascript.hxml new file mode 100644 index 000000000..b2b3876cf --- /dev/null +++ b/src/jaegertracing/thrift/test/haxe/javascript.hxml @@ -0,0 +1,44 @@ +# +# 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. +# + +#integrate files to classpath +-cp src +-cp gen-haxe +-cp ../../lib/haxe/src + +#this class wil be used as entry point for your app. +-main Main + +#JavaScript target +-js bin/Tutorial.js + +#You can use -D source-map-content (requires Haxe 3.1+) to have the .hx +#files directly embedded into the map file, this way you only have to +#upload it, and it will be always in sync with the compiled .js even if +#you modify your .hx files. +-D source-map-content + +#Generate source map and add debug information +-debug + +#dead code elimination : remove unused code +#"-dce no" : do not remove unused code +#"-dce std" : remove unused code in the std lib (default) +#"-dce full" : remove all unused code +-dce full
\ No newline at end of file diff --git a/src/jaegertracing/thrift/test/haxe/make_all.bat b/src/jaegertracing/thrift/test/haxe/make_all.bat new file mode 100644 index 000000000..eaeba890d --- /dev/null +++ b/src/jaegertracing/thrift/test/haxe/make_all.bat @@ -0,0 +1,68 @@ +@echo off +rem /* +rem * Licensed to the Apache Software Foundation (ASF) under one +rem * or more contributor license agreements. See the NOTICE file +rem * distributed with this work for additional information +rem * regarding copyright ownership. The ASF licenses this file +rem * to you under the Apache License, Version 2.0 (the +rem * "License"); you may not use this file except in compliance +rem * with the License. You may obtain a copy of the License at +rem * +rem * http://www.apache.org/licenses/LICENSE-2.0 +rem * +rem * Unless required by applicable law or agreed to in writing, +rem * software distributed under the License is distributed on an +rem * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +rem * KIND, either express or implied. See the License for the +rem * specific language governing permissions and limitations +rem * under the License. +rem */ + +setlocal +if "%HOMEDRIVE%"=="" goto MISSINGVARS +if "%HOMEPATH%"=="" goto MISSINGVARS +if "%HAXEPATH%"=="" goto NOTINSTALLED + +set path=%HAXEPATH%;%HAXEPATH%\..\neko;%path% + +rem # invoke Thrift comnpiler +thrift -r -gen haxe ..\ThriftTest.thrift +if errorlevel 1 goto STOP + +rem # invoke Haxe compiler for all targets +for %%a in (*.hxml) do ( + rem * filter Python, as it is not supported by Haxe 3.1.3 (but will be in 3.1.4) + if not "%%a"=="python.hxml" ( + echo -------------------------- + echo Building %%a ... + echo -------------------------- + haxe --cwd . %%a + ) +) + + +echo. +echo done. +pause +goto eof + +:NOTINSTALLED +echo FATAL: Either Haxe is not installed, or the HAXEPATH variable is not set. +pause +goto eof + +:MISSINGVARS +echo FATAL: Unable to locate home folder. +echo. +echo Both HOMEDRIVE and HOMEPATH need to be set to point to your Home folder. +echo The current values are: +echo HOMEDRIVE=%HOMEDRIVE% +echo HOMEPATH=%HOMEPATH% +pause +goto eof + +:STOP +pause +goto eof + +:eof diff --git a/src/jaegertracing/thrift/test/haxe/make_all.sh b/src/jaegertracing/thrift/test/haxe/make_all.sh new file mode 100755 index 000000000..eb2c9c2c7 --- /dev/null +++ b/src/jaegertracing/thrift/test/haxe/make_all.sh @@ -0,0 +1,41 @@ +#!/bin/sh +# +# 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. +# + +# invoke Thrift comnpiler +../../compiler/cpp/thrift -r -gen haxe ../ThriftTest.thrift + +# output folder +if [ ! -d bin ]; then + mkdir bin +fi + +# invoke Haxe compiler +for target in *.hxml; do + echo -------------------------- + echo Building ${target} ... + echo -------------------------- + if [ ! -d bin/${target} ]; then + mkdir bin/${target} + fi + haxe --cwd . ${target} +done + + +#eof diff --git a/src/jaegertracing/thrift/test/haxe/neko.hxml b/src/jaegertracing/thrift/test/haxe/neko.hxml new file mode 100644 index 000000000..6161f6977 --- /dev/null +++ b/src/jaegertracing/thrift/test/haxe/neko.hxml @@ -0,0 +1,38 @@ +# +# 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. +# + +#integrate files to classpath +-cp src +-cp gen-haxe +-cp ../../lib/haxe/src + +#this class wil be used as entry point for your app. +-main Main + +#neko target +-neko bin/Tutorial.n + +#Add debug information +-debug + +#dead code elimination : remove unused code +#"-dce no" : do not remove unused code +#"-dce std" : remove unused code in the std lib (default) +#"-dce full" : remove all unused code +-dce full
\ No newline at end of file diff --git a/src/jaegertracing/thrift/test/haxe/php-web-server.hxml b/src/jaegertracing/thrift/test/haxe/php-web-server.hxml new file mode 100644 index 000000000..395a8521e --- /dev/null +++ b/src/jaegertracing/thrift/test/haxe/php-web-server.hxml @@ -0,0 +1,43 @@ +# +# 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. +# + +#integrate files to classpath +-cp src +-cp gen-haxe +-cp ../../lib/haxe/src + +#this class wil be used as entry point for your app. +-main Main + +#PHP target +-php bin/php-web-server/ +--php-front Main-debug.php + +#defines +-D phpwebserver + + +#Add debug information +-debug + +#dead code elimination : remove unused code +#"-dce no" : do not remove unused code +#"-dce std" : remove unused code in the std lib (default) +#"-dce full" : remove all unused code +-dce full diff --git a/src/jaegertracing/thrift/test/haxe/php.hxml b/src/jaegertracing/thrift/test/haxe/php.hxml new file mode 100644 index 000000000..965189843 --- /dev/null +++ b/src/jaegertracing/thrift/test/haxe/php.hxml @@ -0,0 +1,40 @@ +# +# 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. +# + +#integrate files to classpath +-cp src +-cp gen-haxe +-cp ../../lib/haxe/src + +#this class wil be used as entry point for your app. +-main Main + +#PHP target +-php bin/php/ +--php-front Main-debug.php + + +#Add debug information +-debug + +#dead code elimination : remove unused code +#"-dce no" : do not remove unused code +#"-dce std" : remove unused code in the std lib (default) +#"-dce full" : remove all unused code +-dce full diff --git a/src/jaegertracing/thrift/test/haxe/project.hide b/src/jaegertracing/thrift/test/haxe/project.hide new file mode 100644 index 000000000..a1c09bac3 --- /dev/null +++ b/src/jaegertracing/thrift/test/haxe/project.hide @@ -0,0 +1,76 @@ +{ + "type" : 0 + ,"target" : 4 + ,"name" : "Apache Thrift cross-platform test client/server" + ,"main" : null + ,"projectPackage" : "" + ,"company" : "Apache Software Foundation (ASF)" + ,"license" : "Apache License, Version 2.0" + ,"url" : "http://www.apache.org/licenses/LICENSE-2.0" + ,"targetData" : [ + { + "pathToHxml" : "flash.hxml" + ,"runActionType" : 1 + ,"runActionText" : "bin/Tutorial.swf" + } + ,{ + "pathToHxml" : "javascript.hxml" + ,"runActionType" : 1 + ,"runActionText" : "bin\\index.html" + } + ,{ + "pathToHxml" : "neko.hxml" + ,"runActionType" : 2 + ,"runActionText" : "neko bin/Tutorial.n" + } + ,{ + "pathToHxml" : "php.hxml" + } + ,{ + "pathToHxml" : "cpp.hxml" + ,"runActionType" : 2 + ,"runActionText" : "bin/Main-debug.exe client --protocol json" + } + ,{ + "pathToHxml" : "java.hxml" + } + ,{ + "pathToHxml" : "csharp.hxml" + } + ,{ + "pathToHxml" : "python.hxml" + ,"runActionType" : 2 + ,"runActionText" : "python bin/Tutorial.py" + } + ] + ,"files" : [ + { + "path" : "src\\TestClient.hx" + ,"useTabs" : true + ,"indentSize" : 4 + ,"foldedRegions" : [ + + ] + ,"activeLine" : 188 + } + ,{ + "path" : "src\\TestServer.hx" + ,"useTabs" : true + ,"indentSize" : 4 + ,"foldedRegions" : [ + + ] + ,"activeLine" : 88 + } + ] + ,"activeFile" : "src\\TestClient.hx" + ,"openFLTarget" : null + ,"openFLBuildMode" : "Debug" + ,"runActionType" : null + ,"runActionText" : null + ,"buildActionCommand" : null + ,"hiddenItems" : [ + + ] + ,"showHiddenItems" : false +}
\ No newline at end of file diff --git a/src/jaegertracing/thrift/test/haxe/python.hxml b/src/jaegertracing/thrift/test/haxe/python.hxml new file mode 100644 index 000000000..f2c19fa93 --- /dev/null +++ b/src/jaegertracing/thrift/test/haxe/python.hxml @@ -0,0 +1,38 @@ +# +# 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. +# + +#integrate files to classpath +-cp src +-cp gen-haxe +-cp ../../lib/haxe/src + +#this class wil be used as entry point for your app. +-main Main + +#Python target +-python bin/Tutorial.py + +#Add debug information +-debug + +#dead code elimination : remove unused code +#"-dce no" : do not remove unused code +#"-dce std" : remove unused code in the std lib (default) +#"-dce full" : remove all unused code +-dce full
\ No newline at end of file diff --git a/src/jaegertracing/thrift/test/haxe/router.php b/src/jaegertracing/thrift/test/haxe/router.php new file mode 100644 index 000000000..e34135cc9 --- /dev/null +++ b/src/jaegertracing/thrift/test/haxe/router.php @@ -0,0 +1,31 @@ +<?php +/* + * 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 thrift + */ + + + +//router file to run testing web server + +//set_time_limit(1); + +require_once dirname(__FILE__) . '/bin/php-web-server/Main-debug.php'; + + diff --git a/src/jaegertracing/thrift/test/haxe/src/Arguments.hx b/src/jaegertracing/thrift/test/haxe/src/Arguments.hx new file mode 100644 index 000000000..cc1074987 --- /dev/null +++ b/src/jaegertracing/thrift/test/haxe/src/Arguments.hx @@ -0,0 +1,335 @@ +/* + * 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; + +import org.apache.thrift.*; +import org.apache.thrift.protocol.*; +import org.apache.thrift.transport.*; +import org.apache.thrift.server.*; +import org.apache.thrift.meta_data.*; +import haxe.io.Path; + +using StringTools; + + +enum ProtocolType { + binary; + json; + compact; +} + +enum EndpointTransport { + socket; + http; +} + +enum ServerType { + simple; + /* + threadpool; + threaded; + nonblocking; + */ +} + + +class Arguments +{ + public var printHelpOnly(default,null) : Bool = false; + + public var server(default,null) : Bool = false; + public var servertype(default,null) : ServerType = simple; + + public var host(default,null) : String = "localhost"; + public var port(default,null) : Int = 9090; + + public var protocol(default,null) : ProtocolType = binary; + public var transport(default,null) : EndpointTransport = socket; + public var framed(default,null) : Bool = false; + public var buffered(default,null) : Bool = false; + + public var numIterations(default,null) : Int = 1; + public var numThreads(default,null) : Int = 1; + public var skipSpeedTest(default,null) : Bool = false; + + + public function new() { + #if sys + #if !phpwebserver + try { + ParseArgs(); + } catch (e : String) { + trace(GetHelp()); + throw e; + } + #else + //forcing server + server = true; + transport = http; + #end + #else + trace("WN: Platform does not support program arguments, using defaults."); + #end + } + + #if sys + + private static function GetHelp() : String { + var sProg = Path.withoutDirectory( Sys.executablePath()); + return "\n" + +sProg+" [client|server] [options]\n" + +"\n" + +"Modus: Either client or server, the default is client.\n" + +"\n" + +"Common options:\n" + +" -h [ --help ] produce help message\n" + +" --port arg (=9090) Port number to listen / connect to\n" + /* not supported yet + +" --domain-socket arg Unix Domain Socket (e.g. /tmp/ThriftTest.thrift)\n" + +" --named-pipe arg Windows Named Pipe (e.g. MyThriftPipe)\n" + */ + +" --protocol arg (=binary) protocol: binary, compact, json\n" + /* not supported yet + +" --ssl Encrypted Transport using SSL\n" + */ + +"\n" + +"Server only options:\n" + +" --transport arg (=sockets) Transport: buffered, framed, http, anonpipe\n" + /* not supported yet + +" --processor-events processor-events\n" + +" --server-type arg (=simple) type of server, \"simple\", \"thread-pool\", \n" + +" \"threaded\", or \"nonblocking\"\n" + +" -n [ --workers ] arg (=4) Number of thread pools workers. Only valid for \n" + +" thread-pool server type\n" + */ + +"\n" + +"Client only options:\n" + +" --host arg (=localhost) Host to connect\n" + +" --transport arg (=sockets) Transport: buffered, framed, http, evhttp\n" + /* not supported yet + +" --anon-pipes hRead hWrite Windows Anonymous Pipes pair (handles)\n" + */ + +" -n [ --testloops ] arg (=1) Number of Tests\n" + +" -t [ --threads ] arg (=1) Number of Test threads\n" + +" --skip-speed-test Skip the speed test\n" + +"\n" + +"All arguments are optional.\n" + ; + } + + + private function ParseArgs() : Void { + + var args = Sys.args().copy(); + if( (args == null) || (args.length <= 0)) { + server = false; + numThreads = 1; + return; + } + + var arg = args.shift(); + if ( arg == "client") { + server = false; + numThreads = 1; + } + else if ( arg == "server") { + server = true; + numThreads = 4; + } + else if ( (arg == "-h") || (arg == "--help")) { + // -h [ --help ] produce help message + Sys.println( GetHelp()); + printHelpOnly = true; + return; + } + else { + throw "First argument must be 'server' or 'client'"; + } + + + while( args.length > 0) { + arg = args.shift(); + + if ( (arg == "-h") || (arg == "--help")) { + // -h [ --help ] produce help message + Sys.println( GetHelp()); + printHelpOnly = true; + return; + } + else if (arg == "--port") { + // --port arg (=9090) Port number to listen + arg = args.shift(); + var tmp = Std.parseInt(arg); + if( tmp != null) { + port = tmp; + } else { + throw "Invalid port number "+arg; + } + } + else if (arg == "--domain-socket") { + // --domain-socket arg Unix Domain Socket (e.g. /tmp/ThriftTest.thrift) + throw "domain sockets not supported yet"; + } + else if (arg == "--named-pipe") { + // --named-pipe arg Windows Named Pipe (e.g. MyThriftPipe) + throw "named pipes not supported yet"; + } + else if (arg == "--protocol") { + // --protocol arg (=binary) protocol: binary, compact, json + arg = args.shift(); + if( arg == "binary") { + protocol = binary; + } else if( arg == "compact") { + protocol = compact; + } else if( arg == "json") { + protocol = json; + } else { + InvalidArg(arg); + } + } + else if (arg == "--ssl") { + // --ssl Encrypted Transport using SSL + throw "SSL not supported yet"; + } + else { + //Server only options: + if( server) { + ParseServerArgument( arg, args); + } else { + ParseClientArgument( arg, args); + } + } + } + } + + + private function ParseServerArgument( arg : String, args : Array<String>) : Void { + if (arg == "--transport") { + // --transport arg (=sockets) Transport: buffered, framed, http, anonpipe + arg = args.shift(); + if( arg == "buffered") { + buffered = true; + } else if( arg == "framed") { + framed = true; + } else if( arg == "http") { + transport = http; + } else if( arg == "anonpipe") { + throw "Anon pipes transport not supported yet"; + } else { + InvalidArg(arg); + } + } + else if (arg == "--processor-events") { + throw "Processor events not supported yet"; + } + else if (arg == "--server-type") { + // --server-type arg (=simple) type of server, + // one of "simple", "thread-pool", "threaded", "nonblocking" + arg = args.shift(); + if( arg == "simple") { + servertype = simple; + } else if( arg == "thread-pool") { + throw arg+" server not supported yet"; + } else if( arg == "threaded") { + throw arg+" server not supported yet"; + } else if( arg == "nonblocking") { + throw arg+" server not supported yet"; + } else { + InvalidArg(arg); + } + } + else if ((arg == "-n") || (arg == "--workers")) { + // -n [ --workers ] arg (=4) Number of thread pools workers. Only valid for + // thread-pool server type + arg = args.shift(); + var tmp = Std.parseInt(arg); + if( tmp != null) { + numThreads = tmp; + } else{ + throw "Invalid number "+arg; + } + } + else { + InvalidArg(arg); + } + } + + + private function ParseClientArgument( arg : String, args : Array<String>) : Void { + if (arg == "--host") { + // --host arg (=localhost) Host to connect + host = args.shift(); + } + else if (arg == "--transport") { + // --transport arg (=sockets) Transport: buffered, framed, http, evhttp + arg = args.shift(); + if( arg == "buffered") { + buffered = true; + } else if( arg == "framed") { + framed = true; + } else if( arg == "http") { + transport = http; + } else if( arg == "evhttp") { + throw "evhttp transport not supported yet"; + } else { + InvalidArg(arg); + } + } + else if (arg == "--anon-pipes") { + // --anon-pipes hRead hWrite Windows Anonymous Pipes pair (handles) + throw "Anon pipes transport not supported yet"; + } + else if ((arg == "-n") || (arg == "--testloops")) { + // -n [ --testloops ] arg (=1) Number of Tests + arg = args.shift(); + var tmp = Std.parseInt(arg); + if( tmp != null) { + numIterations = tmp; + } else { + throw "Invalid number "+arg; + } + } + else if ((arg == "-t") || (arg == "--threads")) { + // -t [ --threads ] arg (=1) Number of Test threads + arg = args.shift(); + var tmp = Std.parseInt(arg); + if( tmp != null) { + numThreads = tmp; + } else { + throw "Invalid number "+arg; + } + } + else if (arg == "--skip-speed-test") { + // --skip-speed-test Skip the speed test + skipSpeedTest = true; + } + else { + InvalidArg(arg); + } + } + + + #end + + + private function InvalidArg( arg : String) : Void { + throw 'Invalid argument $arg'; + } +} diff --git a/src/jaegertracing/thrift/test/haxe/src/Main.hx b/src/jaegertracing/thrift/test/haxe/src/Main.hx new file mode 100644 index 000000000..9eb828f1f --- /dev/null +++ b/src/jaegertracing/thrift/test/haxe/src/Main.hx @@ -0,0 +1,83 @@ +/* + * 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; + +import org.apache.thrift.*; +import org.apache.thrift.protocol.*; +import org.apache.thrift.transport.*; +import org.apache.thrift.server.*; +import org.apache.thrift.meta_data.*; + +import thrift.test.*; // generated code + +class Main +{ + static function main() { + #if phpwebserver + initPhpWebServer(); + //check method + if(php.Web.getMethod() != 'POST') { + Sys.println('http endpoint for thrift test server'); + return; + } + #end + + try { + var args = new Arguments(); + + if( args.printHelpOnly) + return; + + if (args.server) + TestServer.Execute(args); + else + TestClient.Execute(args); + + trace("Completed."); + } catch (e : String) { + trace(e); + } + } + + #if phpwebserver + private static function initPhpWebServer() + { + //remap trace to error log + haxe.Log.trace = function(v:Dynamic, ?infos:haxe.PosInfos) + { + // handle trace + var newValue : Dynamic; + if (infos != null && infos.customParams!=null) { + var extra:String = ""; + for( v in infos.customParams ) + extra += "," + v; + newValue = v + extra; + } + else { + newValue = v; + } + var msg = infos != null ? infos.fileName + ':' + infos.lineNumber + ': ' : ''; + Sys.stderr().writeString('${msg}${newValue}\n'); + } + } + #end + +} diff --git a/src/jaegertracing/thrift/test/haxe/src/TestClient.hx b/src/jaegertracing/thrift/test/haxe/src/TestClient.hx new file mode 100644 index 000000000..853319e23 --- /dev/null +++ b/src/jaegertracing/thrift/test/haxe/src/TestClient.hx @@ -0,0 +1,937 @@ +/* + * 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; + +import haxe.Int32; +import haxe.Int64; +import haxe.io.Bytes; +import haxe.Timer; +import haxe.ds.IntMap; +import haxe.ds.StringMap; +import haxe.ds.ObjectMap; + +import org.apache.thrift.*; +import org.apache.thrift.helper.*; +import org.apache.thrift.protocol.*; +import org.apache.thrift.transport.*; +import org.apache.thrift.server.*; +import org.apache.thrift.meta_data.*; + +#if cpp +import cpp.vm.Thread; +#else +// no thread support (yet) +#end + +import thrift.test.*; // generated code + + +using StringTools; + +class TestResults { + private var successCnt : Int = 0; + private var errorCnt : Int = 0; + private var failedTests : String = ""; + private var print_direct : Bool = false; + + public static var EXITCODE_SUCCESS = 0x00; // no errors bits set + // + public static var EXITCODE_FAILBIT_BASETYPES = 0x01; + public static var EXITCODE_FAILBIT_STRUCTS = 0x02; + public static var EXITCODE_FAILBIT_CONTAINERS = 0x04; + public static var EXITCODE_FAILBIT_EXCEPTIONS = 0x08; + // + public static var EXITCODE_ALL_FAILBITS = 0x0F; + // + private var testsExecuted : Int = 0; + private var testsFailed : Int = 0; + private var currentTest : Int = 0; + + + public function new(direct : Bool) { + print_direct = direct; + } + + public function StartTestGroup( groupBit : Int) : Void { + currentTest = groupBit; + testsExecuted |= groupBit; + } + + public function Expect( expr : Bool, msg : String) : Void { + if ( expr) { + ++successCnt; + } else { + ++errorCnt; + testsFailed |= currentTest; + failedTests += "\n " + msg; + if( print_direct) { + trace('FAIL: $msg'); + } + } + } + + public function CalculateExitCode() : Int { + var notExecuted : Int = EXITCODE_ALL_FAILBITS & (~testsExecuted); + return testsFailed | notExecuted; + } + + public function PrintSummary() : Void { + var total = successCnt + errorCnt; + var sp = Math.round((1000 * successCnt) / total) / 10; + var ep = Math.round((1000 * errorCnt) / total) / 10; + + trace('==========================='); + trace('Tests executed $total'); + trace('Tests succeeded $successCnt ($sp%)'); + trace('Tests failed $errorCnt ($ep%)'); + if ( errorCnt > 0) + { + trace('==========================='); + trace('FAILED TESTS: $failedTests'); + } + trace('==========================='); + } +} + + +class TestClient { + + public static function Execute(args : Arguments) : Void + { + var exitCode = 0xFF; + try + { + var difft = Timer.stamp(); + + if ( args.numThreads > 1) { + #if cpp + exitCode = MultiThreadClient(args); + #else + trace('Threads not supported/implemented for this platform.'); + exitCode = SingleThreadClient(args); + #end + } else { + exitCode = SingleThreadClient(args); + } + + difft = Math.round( 1000 * (Timer.stamp() - difft)) / 1000; + trace('total test time: $difft seconds'); + } + catch (e : TException) + { + trace('TException: $e'); + exitCode = 0xFF; + } + catch (e : Dynamic) + { + trace('Exception: $e'); + exitCode = 0xFF; + } + + #if sys + Sys.exit( exitCode); + #end + } + + + public static function SingleThreadClient(args : Arguments) : Int + { + var rslt = new TestResults(true); + RunClient(args,rslt); + rslt.PrintSummary(); + return rslt.CalculateExitCode(); + } + + + #if cpp + public static function MultiThreadClient(args : Arguments) : Int + { + var threads = new List<Thread>(); + for( test in 0 ... args.numThreads) { + threads.add( StartThread( args)); + } + var exitCode : Int = 0; + for( thread in threads) { + exitCode |= Thread.readMessage(true); + } + return exitCode; + } + #end + + #if cpp + private static function StartThread(args : Arguments) : Thread { + var thread = Thread.create( + function() : Void { + var rslt = new TestResults(false); + var main : Thread = Thread.readMessage(true); + try + { + RunClient(args,rslt); + } + catch (e : TException) + { + rslt.Expect( false, '$e'); + trace('$e'); + } + catch (e : Dynamic) + { + rslt.Expect( false, '$e'); + trace('$e'); + } + main.sendMessage( rslt.CalculateExitCode()); + }); + + thread.sendMessage(Thread.current()); + return thread; + } + #end + + + public static function RunClient(args : Arguments, rslt : TestResults) + { + var transport : TTransport = null; + switch (args.transport) + { + case socket: + transport = new TSocket(args.host, args.port); + case http: + var uri = 'http://${args.host}:${args.port}'; + trace('- http client : ${uri}'); + transport = new THttpClient(uri); + default: + throw "Unhandled transport"; + } + + // optional: layered transport + if ( args.framed) { + trace("- framed transport"); + transport = new TFramedTransport(transport); + } + if ( args.buffered) { + trace("- buffered transport"); + transport = new TBufferedTransport(transport); + } + + // protocol + var protocol : TProtocol = null; + switch( args.protocol) + { + case binary: + trace("- binary protocol"); + protocol = new TBinaryProtocol(transport); + case json: + trace("- json protocol"); + protocol = new TJSONProtocol(transport); + case compact: + trace("- compact protocol"); + protocol = new TCompactProtocol(transport); + } + + // some quick and basic unit tests + HaxeBasicsTest( args, rslt); + ModuleUnitTests( args, rslt); + + // now run the test code + trace('- ${args.numIterations} iterations'); + for( i in 0 ... args.numIterations) { + ClientTest( transport, protocol, args, rslt); + } + } + + + public static function HaxeBasicsTest( args : Arguments, rslt : TestResults) : Void + { + // We need to test a few basic things used in the ClientTest + // Anything else beyond this scope should go into /lib/haxe/ instead + rslt.StartTestGroup( TestResults.EXITCODE_FAILBIT_BASETYPES); + + var map32 = new IntMap<Int32>(); + var map64 = new Int64Map<Int32>(); + + rslt.Expect( map32.keys().hasNext() == map64.keys().hasNext(), "Int64Map<Int32> Test #1"); + rslt.Expect( map32.exists( 4711) == map64.exists( Int64.make(47,11)), "Int64Map<Int32> Test #2"); + rslt.Expect( map32.remove( 4711) == map64.remove( Int64.make(47,11)), "Int64Map<Int32> Test #3"); + rslt.Expect( map32.get( 4711) == map64.get( Int64.make(47,11)), "Int64Map<Int32> Test #4"); + + map32.set( 42, 815); + map64.set( Int64.make(0,42), 815); + map32.set( -517, 23); + map64.set( Int64.neg(Int64.make(0,517)), 23); + map32.set( 0, -123); + map64.set( Int64.make(0,0), -123); + + //trace('map32 = $map32'); + //trace('map64 = $map64'); + + rslt.Expect( map32.keys().hasNext() == map64.keys().hasNext(), "Int64Map<Int32> Test #10"); + rslt.Expect( map32.exists( 4711) == map64.exists( Int64.make(47,11)), "Int64Map<Int32> Test #11"); + rslt.Expect( map32.exists( -517) == map64.exists( Int64.neg(Int64.make(0,517))), "Int64Map<Int32> Test #12"); + rslt.Expect( map32.exists( 42) == map64.exists( Int64.make(0,42)), "Int64Map<Int32> Test #13"); + rslt.Expect( map32.exists( 0) == map64.exists( Int64.make(0,0)), "Int64Map<Int32> Test #14"); + rslt.Expect( map32.get( 4711) == map64.get( Int64.make(47,11)), "Int64Map<Int32> Test #15"); + rslt.Expect( map32.get( -517) == map64.get( Int64.neg(Int64.make(0,517))), "Int64Map<Int32> Test #16"); + rslt.Expect( map32.get( 42) == map64.get( Int64.make(0,42)), "Int64Map<Int32> Test #Int64.make(-5,17)"); + rslt.Expect( map32.get( 0) == map64.get( Int64.make(0,0)), "Int64Map<Int32> Test #18"); + rslt.Expect( map32.remove( 4711) == map64.remove( Int64.make(47,11)), "Int64Map<Int32> Test #19"); + rslt.Expect( map32.remove( -517) == map64.remove( Int64.neg(Int64.make(0,517))), "Int64Map<Int32> Test #20"); + rslt.Expect( map32.exists( 4711) == map64.exists( Int64.make(47,11)), "Int64Map<Int32> Test #21"); + rslt.Expect( map32.exists( -517) == map64.exists( Int64.neg(Int64.make(0,517))), "Int64Map<Int32> Test #22"); + rslt.Expect( map32.exists( 42) == map64.exists( Int64.make(0,42)), "Int64Map<Int32> Test #23"); + rslt.Expect( map32.exists( 0) == map64.exists( Int64.make(0,0)), "Int64Map<Int32> Test #24"); + rslt.Expect( map32.get( 4711) == map64.get( Int64.make(47,11)), "Int64Map<Int32> Test #25"); + rslt.Expect( map32.get( -517) == map64.get( Int64.neg(Int64.make(0,517))), "Int64Map<Int32> Test #26"); + rslt.Expect( map32.get( 42) == map64.get( Int64.make(0,42)), "Int64Map<Int32> Test #27"); + rslt.Expect( map32.get( 0) == map64.get( Int64.make(0,0)), "Int64Map<Int32> Test #28"); + + map32.set( 42, 1); + map64.set( Int64.make(0,42), 1); + map32.set( -517, -2); + map64.set( Int64.neg(Int64.make(0,517)), -2); + map32.set( 0, 3); + map64.set( Int64.make(0,0), 3); + + var c32 = 0; + var ksum32 = 0; + for (key in map32.keys()) { + ++c32; + ksum32 += key; + } + var c64 = 0; + var ksum64 = Int64.make(0,0); + for (key in map64.keys()) { + ++c64; + ksum64 = Int64.add( ksum64, key); + } + rslt.Expect( c32 == c64, "Int64Map<Int32> Test #30"); + rslt.Expect( '$ksum64' == '$ksum32', '$ksum64 == $ksum32 Test #31'); + + //compare without spaces because differ in php and cpp + var s32 = map32.toString().replace(' ', ''); + var s64 = map64.toString().replace(' ', ''); + rslt.Expect( s32 == s64, "Int64Map<Int32>.toString(): " + ' ("$s32" == "$s64") Test #32'); + + map32.remove( 42); + map64.remove( Int64.make(0,42)); + map32.remove( -517); + map64.remove( Int64.neg(Int64.make(0,517))); + map32.remove( 0); + map64.remove( Int64.make(0,0)); + + rslt.Expect( map32.keys().hasNext() == map64.keys().hasNext(), "Int64Map<Int32> Test #90"); + rslt.Expect( map32.exists( 4711) == map64.exists( Int64.make(47,11)), "Int64Map<Int32> Test #91"); + rslt.Expect( map32.exists( -517) == map64.exists( Int64.neg(Int64.make(0,517))), "Int64Map<Int32> Test #92"); + rslt.Expect( map32.exists( 42) == map64.exists( Int64.make(0,42)), "Int64Map<Int32> Test #93"); + rslt.Expect( map32.exists( 0) == map64.exists( Int64.make(0,0)), "Int64Map<Int32> Test #94"); + rslt.Expect( map32.get( 4711) == map64.get( Int64.make(47,11)), "Int64Map<Int32> Test #95"); + rslt.Expect( map32.get( -517) == map64.get( Int64.make(-5,17)), "Int64Map<Int32> Test #96"); + rslt.Expect( map32.get( 42) == map64.get( Int64.make(0,42)), "Int64Map<Int32> Test #97"); + rslt.Expect( map32.get( 0) == map64.get( Int64.make(0, 0)), "Int64Map<Int32> Test #98"); + } + + + // core module unit tests + public static function ModuleUnitTests( args : Arguments, rslt : TestResults) : Void { + #if debug + + try { + BitConverter.UnitTest(); + rslt.Expect( true, 'BitConverter.UnitTest Test #100'); + } + catch( e : Dynamic) { + rslt.Expect( false, 'BitConverter.UnitTest: $e Test #100'); + } + + try { + ZigZag.UnitTest(); + rslt.Expect( true, 'ZigZag.UnitTest Test #101'); + } + catch( e : Dynamic) { + rslt.Expect( false, 'ZigZag.UnitTest: $e Test #101'); + } + + #end + } + + + public static function BytesToHex(data : Bytes) : String { + var hex = ""; + for ( i in 0 ... data.length) { + hex += StringTools.hex( data.get(i), 2); + } + return hex; + } + + public static function PrepareTestData(randomDist : Bool) : Bytes { + var retval = Bytes.alloc(0x100); + var initLen : Int = (retval.length > 0x100 ? 0x100 : retval.length); + + // linear distribution, unless random is requested + if (!randomDist) { + for (i in 0 ... initLen) { + retval.set(i, i % 0x100); + } + return retval; + } + + // random distribution + for (i in 0 ... initLen) { + retval.set(i, 0); + } + for (i in 1 ... initLen) { + while( true) { + var nextPos = Std.random(initLen); + if (retval.get(nextPos) == 0) { + retval.set( nextPos, i % 0x100); + break; + } + } + } + return retval; + } + + + public static function ClientTest( transport : TTransport, protocol : TProtocol, + args : Arguments, rslt : TestResults) : Void + { + var client = new ThriftTestImpl(protocol,protocol); + try + { + if (!transport.isOpen()) + { + transport.open(); + } + } + catch (e : TException) + { + rslt.Expect( false, 'unable to open transport: $e'); + return; + } + catch (e : Dynamic) + { + rslt.Expect( false, 'unable to open transport: $e'); + return; + } + + var start = Date.now(); + + rslt.StartTestGroup( TestResults.EXITCODE_FAILBIT_EXCEPTIONS); + + // if arg == "Xception" throw Xception with errorCode = 1001 and message = arg + trace('testException("Xception")'); + try { + client.testException("Xception"); + rslt.Expect( false, 'testException("Xception") should throw'); + } + catch (e : Xception) + { + rslt.Expect( e.message == "Xception", 'testException("Xception") - e.message == "Xception"'); + rslt.Expect( e.errorCode == 1001, 'testException("Xception") - e.errorCode == 1001'); + } + catch (e : TException) + { + rslt.Expect( false, 'testException("Xception") - ${e} : ${e.errorMsg}'); + } + catch (e : Dynamic) + { + rslt.Expect( false, 'testException("Xception") - $e'); + } + + // if arg == "TException" throw TException + trace('testException("TException")'); + try { + client.testException("TException"); + rslt.Expect( false, 'testException("TException") should throw'); + } + catch (e : TException) + { + rslt.Expect( true, 'testException("TException") - $e : ${e.errorMsg}'); + } + catch (e : Dynamic) + { + rslt.Expect( false, 'testException("TException") - $e'); + } + + // reopen the transport, just in case the server closed his end + if (transport.isOpen()) + transport.close(); + transport.open(); + + // else do not throw anything + trace('testException("bla")'); + try { + client.testException("bla"); + rslt.Expect( true, 'testException("bla") should not throw'); + } + catch (e : TException) + { + rslt.Expect( false, 'testException("bla") - ${e} : ${e.errorMsg}'); + } + catch (e : Dynamic) + { + rslt.Expect( false, 'testException("bla") - $e'); + } + + rslt.StartTestGroup( TestResults.EXITCODE_FAILBIT_BASETYPES); + + trace('testVoid()'); + client.testVoid(); + trace(' = void'); + rslt.Expect(true,"testVoid()"); // bump counter + + trace('testBool(${true})'); + var b = client.testBool(true); + trace(' = $b'); + rslt.Expect(b, '$b == "${true}"'); + trace('testBool(${false})'); + b = client.testBool(false); + trace(' = $b'); + rslt.Expect( ! b, '$b == "${false}"'); + + trace('testString("Test")'); + var s = client.testString("Test"); + trace(' = "$s"'); + rslt.Expect(s == "Test", '$s == "Test"'); + + trace('testByte(1)'); + var i8 = client.testByte(1); + trace(' = $i8'); + rslt.Expect(i8 == 1, '$i8 == 1'); + + trace('testI32(-1)'); + var i32 = client.testI32(-1); + trace(' = $i32'); + rslt.Expect(i32 == -1, '$i32 == -1'); + + trace('testI64(-34359738368)'); + var i64 = client.testI64( Int64.make( 0xFFFFFFF8, 0x00000000)); // -34359738368 + trace(' = $i64'); + rslt.Expect( Int64.compare( i64, Int64.make( 0xFFFFFFF8, 0x00000000)) == 0, + Int64.toStr(i64) +" == "+Int64.toStr(Int64.make( 0xFFFFFFF8, 0x00000000))); + + // edge case: the largest negative Int64 has no positive Int64 equivalent + trace('testI64(-9223372036854775808)'); + i64 = client.testI64( Int64.make( 0x80000000, 0x00000000)); // -9223372036854775808 + trace(' = $i64'); + rslt.Expect( Int64.compare( i64, Int64.make( 0x80000000, 0x00000000)) == 0, + Int64.toStr(i64) +" == "+Int64.toStr(Int64.make( 0x80000000, 0x00000000))); + + trace('testDouble(5.325098235)'); + var dub = client.testDouble(5.325098235); + trace(' = $dub'); + rslt.Expect(dub == 5.325098235, '$dub == 5.325098235'); + + var binOut = PrepareTestData(true); + trace('testBinary('+BytesToHex(binOut)+')'); + try { + var binIn = client.testBinary(binOut); + trace('testBinary() = '+BytesToHex(binIn)); + rslt.Expect( binIn.length == binOut.length, '${binIn.length} == ${binOut.length}'); + var len = ((binIn.length < binOut.length) ? binIn.length : binOut.length); + for (ofs in 0 ... len) { + if (binIn.get(ofs) != binOut.get(ofs)) { + rslt.Expect( false, 'testBinary('+BytesToHex(binOut)+'): content mismatch at offset $ofs'); + } + } + } + catch (e : TApplicationException) { + trace('testBinary('+BytesToHex(binOut)+'): '+e.errorMsg); // may not be supported by the server + } + + + rslt.StartTestGroup( TestResults.EXITCODE_FAILBIT_STRUCTS); + + trace('testStruct({"Zero", 1, -3, -5})'); + var o = new Xtruct(); + o.string_thing = "Zero"; + o.byte_thing = 1; + o.i32_thing = -3; + o.i64_thing = Int64.make(0,-5); + var i = client.testStruct(o); + trace(' = {"' + i.string_thing + '", ' + i.byte_thing +', ' + + i.i32_thing +', '+ Int64.toStr(i.i64_thing) + '}'); + rslt.Expect( i.string_thing == o.string_thing, "i.string_thing == o.string_thing"); + rslt.Expect( i.byte_thing == o.byte_thing, "i.byte_thing == o.byte_thing"); + rslt.Expect( i.i32_thing == o.i32_thing, "i.i64_thing == o.i64_thing"); + rslt.Expect( i.i32_thing == o.i32_thing, "i.i64_thing == o.i64_thing"); + + trace('testNest({1, {\"Zero\", 1, -3, -5}, 5})'); + var o2 = new Xtruct2(); + o2.byte_thing = 1; + o2.struct_thing = o; + o2.i32_thing = 5; + var i2 = client.testNest(o2); + i = i2.struct_thing; + trace(" = {" + i2.byte_thing + ", {\"" + i.string_thing + "\", " + + i.byte_thing + ", " + i.i32_thing + ", " + Int64.toStr(i.i64_thing) + "}, " + + i2.i32_thing + "}"); + rslt.Expect( i2.byte_thing == o2.byte_thing, "i2.byte_thing == o2.byte_thing"); + rslt.Expect( i2.i32_thing == o2.i32_thing, "i2.i32_thing == o2.i32_thing"); + rslt.Expect( i.string_thing == o.string_thing, "i.string_thing == o.string_thing"); + rslt.Expect( i.byte_thing == o.byte_thing, "i.byte_thing == o.byte_thing"); + rslt.Expect( i.i32_thing == o.i32_thing, "i.i32_thing == o.i32_thing"); + rslt.Expect( Int64.compare( i.i64_thing, o.i64_thing) == 0, "i.i64_thing == o.i64_thing"); + + + rslt.StartTestGroup( TestResults.EXITCODE_FAILBIT_CONTAINERS); + + var mapout = new IntMap< haxe.Int32>(); + for ( j in 0 ... 5) + { + mapout.set(j, j - 10); + } + trace("testMap({"); + var first : Bool = true; + for( key in mapout.keys()) + { + if (first) + { + first = false; + } + else + { + trace(", "); + } + trace(key + " => " + mapout.get(key)); + } + trace("})"); + + var mapin = client.testMap(mapout); + + trace(" = {"); + first = true; + for( key in mapin.keys()) + { + if (first) + { + first = false; + } + else + { + trace(", "); + } + trace(key + " => " + mapin.get(key)); + rslt.Expect( mapin.get(key) == mapout.get(key), ' mapin.get($key) == mapout.get($key)'); + } + trace("}"); + for( key in mapout.keys()) + { + rslt.Expect(mapin.exists(key), 'mapin.exists($key)'); + } + + var listout = new List<Int>(); + for (j in -2 ... 3) + { + listout.add(j); + } + trace("testList({"); + first = true; + for( j in listout) + { + if (first) + { + first = false; + } + else + { + trace(", "); + } + trace(j); + } + trace("})"); + + var listin = client.testList(listout); + + trace(" = {"); + first = true; + for( j in listin) + { + if (first) + { + first = false; + } + else + { + trace(", "); + } + trace(j); + } + trace("}"); + + rslt.Expect(listin.length == listout.length, "listin.length == listout.length"); + var literout = listout.iterator(); + var literin = listin.iterator(); + while( literin.hasNext()) { + rslt.Expect(literin.next() == literout.next(), "literin[i] == literout[i]"); + } + + //set + var setout = new IntSet(); + for (j in -2 ... 3) + { + setout.add(j); + } + trace("testSet({"); + first = true; + for( j in setout) + { + if (first) + { + first = false; + } + else + { + trace(", "); + } + trace(j); + } + trace("})"); + + var setin = client.testSet(setout); + + trace(" = {"); + first = true; + for( j in setin) + { + if (first) + { + first = false; + } + else + { + trace(", "); + } + trace(j); + rslt.Expect(setout.contains(j), 'setout.contains($j)'); + } + trace("}"); + rslt.Expect(setin.size == setout.size, "setin.length == setout.length"); + + + rslt.StartTestGroup( TestResults.EXITCODE_FAILBIT_BASETYPES); + + trace("testEnum(ONE)"); + var ret = client.testEnum(Numberz.ONE); + trace(" = " + ret); + rslt.Expect(ret == Numberz.ONE, '$ret == Numberz.ONE'); + + trace("testEnum(TWO)"); + ret = client.testEnum(Numberz.TWO); + trace(" = " + ret); + rslt.Expect(ret == Numberz.TWO, '$ret == Numberz.TWO'); + + trace("testEnum(THREE)"); + ret = client.testEnum(Numberz.THREE); + trace(" = " + ret); + rslt.Expect(ret == Numberz.THREE, '$ret == Numberz.THREE'); + + trace("testEnum(FIVE)"); + ret = client.testEnum(Numberz.FIVE); + trace(" = " + ret); + rslt.Expect(ret == Numberz.FIVE, '$ret == Numberz.FIVE'); + + trace("testEnum(EIGHT)"); + ret = client.testEnum(Numberz.EIGHT); + trace(" = " + ret); + rslt.Expect(ret == Numberz.EIGHT, '$ret == Numberz.EIGHT'); + + trace("testTypedef(309858235082523)"); + var uid = client.testTypedef( Int64.make( 0x119D0, 0x7E08671B)); // 309858235082523 + trace(" = " + uid); + rslt.Expect( Int64.compare( uid, Int64.make( 0x119D0, 0x7E08671B)) == 0, + Int64.toStr(uid)+" == "+Int64.toStr(Int64.make( 0x119D0, 0x7E08671B))); + + + rslt.StartTestGroup( TestResults.EXITCODE_FAILBIT_CONTAINERS); + + trace("testMapMap(1)"); + var mm = client.testMapMap(1); + trace(" = {"); + for( key in mm.keys()) + { + trace(key + " => {"); + var m2 = mm.get(key); + for( k2 in m2.keys()) + { + trace(k2 + " => " + m2.get(k2) + ", "); + } + trace("}, "); + } + trace("}"); + + var pos = mm.get(4); + var neg = mm.get(-4); + rslt.Expect( (pos != null) && (neg != null), "(pos != null) && (neg != null)"); + for (i in 1 ... 5) { + rslt.Expect( pos.get(i) == i, 'pos.get($i) == $i'); + rslt.Expect( neg.get(-i) == -i, 'neg.get(-$i) == -$i'); + } + rslt.Expect( ! pos.exists(0), '!pos.exists(0)'); + rslt.Expect( ! neg.exists(-0), '!neg.exists(-0)'); + rslt.Expect( ! pos.exists(42), '!pos.exists(42)'); + rslt.Expect( ! neg.exists(-42), '!neg.exists(-42)'); + + + rslt.StartTestGroup( TestResults.EXITCODE_FAILBIT_STRUCTS); + + var insane = new Insanity(); + insane.userMap = new IntMap< Int64>(); + insane.userMap.set( Numberz.FIVE, Int64.make(0,5000)); + var truck = new Xtruct(); + truck.string_thing = "Truck"; + truck.byte_thing = 8; + truck.i32_thing = 8; + truck.i64_thing = Int64.make(0,8); + insane.xtructs = new List<Xtruct>(); + insane.xtructs.add(truck); + trace("testInsanity()"); + var whoa = client.testInsanity(insane); + trace(" = {"); + for( key in whoa.keys()) + { + var val = whoa.get(key); + trace(key + " => {"); + + for( k2 in val.keys()) + { + var v2 = val.get(k2); + + trace(k2 + " => {"); + var userMap = v2.userMap; + + trace("{"); + if (userMap != null) + { + for( k3 in userMap.keys()) + { + trace(k3 + " => " + userMap.get(k3) + ", "); + } + } + else + { + trace("null"); + } + trace("}, "); + + var xtructs = v2.xtructs; + + trace("{"); + if (xtructs != null) + { + for( x in xtructs) + { + trace("{\"" + x.string_thing + "\", " + + x.byte_thing + ", " + x.i32_thing + ", " + + x.i32_thing + "}, "); + } + } + else + { + trace("null"); + } + trace("}"); + + trace("}, "); + } + trace("}, "); + } + trace("}"); + + + /** + * So you think you've got this all worked, out eh? + * + * Creates a the returned map with these values and prints it out: + * { 1 => { 2 => argument, + * 3 => argument, + * }, + * 2 => { 6 => <empty Insanity struct>, }, + * } + * @return map<UserId, map<Numberz,Insanity>> - a map with the above values + */ + + var first_map = whoa.get(Int64.make(0,1)); + var second_map = whoa.get(Int64.make(0,2)); + rslt.Expect( (first_map != null) && (second_map != null), "(first_map != null) && (second_map != null)"); + if ((first_map != null) && (second_map != null)) + { + var crazy2 = first_map.get(Numberz.TWO); + var crazy3 = first_map.get(Numberz.THREE); + var looney = second_map.get(Numberz.SIX); + rslt.Expect( (crazy2 != null) && (crazy3 != null) && (looney != null), + "(crazy2 != null) && (crazy3 != null) && (looney != null)"); + + var crz2iter = crazy2.xtructs.iterator(); + var crz3iter = crazy3.xtructs.iterator(); + rslt.Expect( crz2iter.hasNext() && crz3iter.hasNext(), "crz2iter.hasNext() && crz3iter.hasNext()"); + var goodbye2 = crz2iter.next(); + var goodbye3 = crz3iter.next(); + rslt.Expect( ! (crz2iter.hasNext() || crz3iter.hasNext()), "! (crz2iter.hasNext() || crz3iter.hasNext())"); + + rslt.Expect( Int64.compare( crazy2.userMap.get(Numberz.FIVE), insane.userMap.get(Numberz.FIVE)) == 0, "crazy2.userMap[5] == insane.userMap[5]"); + rslt.Expect( truck.string_thing == goodbye2.string_thing, "truck.string_thing == goodbye2.string_thing"); + rslt.Expect( truck.byte_thing == goodbye2.byte_thing, "truck.byte_thing == goodbye2.byte_thing"); + rslt.Expect( truck.i32_thing == goodbye2.i32_thing, "truck.i32_thing == goodbye2.i32_thing"); + rslt.Expect( Int64.compare( truck.i64_thing, goodbye2.i64_thing) == 0, "truck.i64_thing == goodbye2.i64_thing"); + + rslt.Expect( Int64.compare( crazy3.userMap.get(Numberz.FIVE), insane.userMap.get(Numberz.FIVE)) == 0, "crazy3.userMap[5] == insane.userMap[5]"); + rslt.Expect( truck.string_thing == goodbye3.string_thing, "truck.string_thing == goodbye3.string_thing"); + rslt.Expect( truck.byte_thing == goodbye3.byte_thing, "truck.byte_thing == goodbye3.byte_thing"); + rslt.Expect( truck.i32_thing == goodbye3.i32_thing, "truck.i32_thing == goodbye3.i32_thing"); + rslt.Expect( Int64.compare( truck.i64_thing, goodbye3.i64_thing) == 0, "truck.i64_thing == goodbye3.i64_thing"); + + rslt.Expect( ! looney.isSet(1), "! looney.isSet(1)"); + rslt.Expect( ! looney.isSet(2), "! looney.isSet(2)"); + } + + var arg0 = 1; + var arg1 = 2; + var arg2 = Int64.make( 0x7FFFFFFF,0xFFFFFFFF); + var multiDict = new IntMap< String>(); + multiDict.set(1, "one"); + var arg4 = Numberz.FIVE; + var arg5 = Int64.make(0,5000000); + trace("Test Multi(" + arg0 + "," + arg1 + "," + arg2 + "," + multiDict + "," + arg4 + "," + arg5 + ")"); + var multiResponse = client.testMulti(arg0, arg1, arg2, multiDict, arg4, arg5); + trace(" = Xtruct(byte_thing:" + multiResponse.byte_thing + ",string_thing:" + multiResponse.string_thing + + ",i32_thing:" + multiResponse.i32_thing + + ",i64_thing:" + Int64.toStr(multiResponse.i64_thing) + ")"); + + rslt.Expect( multiResponse.string_thing == "Hello2", 'multiResponse.String_thing == "Hello2"'); + rslt.Expect( multiResponse.byte_thing == arg0, 'multiResponse.Byte_thing == arg0'); + rslt.Expect( multiResponse.i32_thing == arg1, 'multiResponse.I32_thing == arg1'); + rslt.Expect( Int64.compare( multiResponse.i64_thing, arg2) == 0, 'multiResponse.I64_thing == arg2'); + + + rslt.StartTestGroup( 0); + + trace("Test Oneway(1)"); + client.testOneway(1); + + if( ! args.skipSpeedTest) { + trace("Test Calltime()"); + var difft = Timer.stamp(); + for ( k in 0 ... 1000) { + client.testVoid(); + } + difft = Math.round( 1000 * (Timer.stamp() - difft)) / 1000; + trace('$difft ms per testVoid() call'); + } + } +} diff --git a/src/jaegertracing/thrift/test/haxe/src/TestMacro.hx b/src/jaegertracing/thrift/test/haxe/src/TestMacro.hx new file mode 100644 index 000000000..a6207606a --- /dev/null +++ b/src/jaegertracing/thrift/test/haxe/src/TestMacro.hx @@ -0,0 +1,40 @@ +/* + * 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 ; + +import haxe.macro.Context; +import haxe.macro.Expr; + +/**** + * If you call the Thrift compiler this way (e.g. by changing the prebuild command) + * + * thrift -r -gen haxe:buildmacro=TestMacro.handle() ../ThriftTest.thrift + * + * the TestMacro.handle() function implemented below is called for each generated class + * and interface. Use "thrift --help" to get more info about other available options. + */ +class TestMacro +{ + public static function handle( ) : Array< Field> { + trace('TestMacro called for ' + Context.getLocalType()); + return Context.getBuildFields(); + } + +} diff --git a/src/jaegertracing/thrift/test/haxe/src/TestServer.hx b/src/jaegertracing/thrift/test/haxe/src/TestServer.hx new file mode 100644 index 000000000..450c8f28c --- /dev/null +++ b/src/jaegertracing/thrift/test/haxe/src/TestServer.hx @@ -0,0 +1,131 @@ +/* + * 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; + +import org.apache.thrift.*; +import org.apache.thrift.protocol.*; +import org.apache.thrift.transport.*; +import org.apache.thrift.server.*; +import org.apache.thrift.meta_data.*; + +import thrift.test.*; // generated code + + +class TestServer +{ + public static function Execute(args : Arguments) : Void + { + try + { + // Transport + var transport : TServerTransport = null; + switch( args.transport) { + case socket: + trace("- socket port "+args.port); + transport = new TServerSocket( args.port); + case http: + trace("- http"); + #if !phpwebserver + throw "HTTP server not implemented yet"; + //transport = new THttpServer( targetHost); + #else + transport = new TWrappingServerTransport( + new TStreamTransport( + new TFileStream("php://input", Read), + new TFileStream("php://output", Append) + ) + ); + + #end + default: + throw "Unhandled transport"; + } + + // optional: layered transport + var transfactory : TTransportFactory = null; + if ( args.framed) { + trace("- framed transport"); + transfactory = new TFramedTransportFactory(); + } + if ( args.buffered) { + trace("- buffered transport"); + transfactory = new TBufferedTransportFactory(); + } + + // protocol + var protfactory : TProtocolFactory = null; + switch( args.protocol) + { + case binary: + trace("- binary protocol"); + protfactory = new TBinaryProtocolFactory(); + case json: + trace("- json protocol"); + protfactory = new TJSONProtocolFactory(); + case compact: + trace("- compact protocol"); + protfactory = new TCompactProtocolFactory(); + } + + + // Processor + var handler = new TestServerHandler(); + var processor = new ThriftTestProcessor(handler); + + // Simple Server + var server : TServer = null; + switch( args.servertype) + { + case simple: + var simpleServer = new TSimpleServer( processor, transport, transfactory, protfactory); + #if phpwebserver + simpleServer.runOnce = true; + #end + server = simpleServer; + + default: + throw "Unhandled server type"; + } + + + /* + // Server event handler + if( args.serverEvents) { + var events = new TestServerEventHandler(); + server.setEventHandler(serverEvents); + handler.server = serverEngine; + } + */ + + // Run it + server.Serve(); + trace("done."); + + } + catch (x : TException) + { + trace('$x ${x.errorID} ${x.errorMsg}'); + } + catch (x : Dynamic) + { + trace('$x'); + } + } +} diff --git a/src/jaegertracing/thrift/test/haxe/src/TestServerEventHandler.hx b/src/jaegertracing/thrift/test/haxe/src/TestServerEventHandler.hx new file mode 100644 index 000000000..d17567c2f --- /dev/null +++ b/src/jaegertracing/thrift/test/haxe/src/TestServerEventHandler.hx @@ -0,0 +1,53 @@ +/* + * 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; + +import org.apache.thrift.*; +import org.apache.thrift.protocol.*; +import org.apache.thrift.transport.*; +import org.apache.thrift.server.*; +import org.apache.thrift.meta_data.*; + +import thrift.test.*; // generated code + + +class TestServerEventHandler : TServerEventHandler +{ + public int callCount = 0; + public void preServe() + { + callCount++; + } + public Object createContext(Thrift.Protocol.TProtocol input, Thrift.Protocol.TProtocol output) + { + callCount++; + return null; + } + public void deleteContext(Object serverContext, Thrift.Protocol.TProtocol input, Thrift.Protocol.TProtocol output) + { + callCount++; + } + public void processContext(Object serverContext, Thrift.Transport.TTransport transport) + { + callCount++; + } +} + +
\ No newline at end of file diff --git a/src/jaegertracing/thrift/test/haxe/src/TestServerHandler.hx b/src/jaegertracing/thrift/test/haxe/src/TestServerHandler.hx new file mode 100644 index 000000000..b8a2590d5 --- /dev/null +++ b/src/jaegertracing/thrift/test/haxe/src/TestServerHandler.hx @@ -0,0 +1,479 @@ +/* + * 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; + +import org.apache.thrift.*; +import org.apache.thrift.protocol.*; +import org.apache.thrift.transport.*; +import org.apache.thrift.server.*; +import org.apache.thrift.meta_data.*; +import org.apache.thrift.helper.*; + +import haxe.Int32; +import haxe.Int64; +import haxe.io.Bytes; +import haxe.ds.IntMap; +import haxe.ds.StringMap; +import haxe.ds.ObjectMap; + +import thrift.test.*; // generated code + + +class TestServerHandler implements ThriftTest { + + public var server:TServer; + + public function new() { + } + + /** + * Prints "testVoid()" and returns nothing. + */ + public function testVoid():Void + { + trace("testVoid()"); + } + + /** + * Prints 'testBool("%s")' where '%s' with thing as 'true' or 'false' + * @param bool thing - the bool data to print + * @return bool - returns the bool 'thing' + * + * @param thing + */ + public function testBool(thing : Bool) : Bool + { + trace('testBool($thing)'); + return thing; + } + + /** + * Prints 'testString("%s")' with thing as '%s' + * @param string thing - the string to print + * @return string - returns the string 'thing' + * + * @param thing + */ + public function testString(thing:String):String + { + trace("teststring(\"" + thing + "\")"); + return thing; + } + + /** + * Prints 'testByte("%d")' with thing as '%d' + * @param byte thing - the byte to print + * @return byte - returns the byte 'thing' + * + * @param thing + */ + public function testByte(thing:haxe.Int32):haxe.Int32 + { + trace("testByte(" + thing + ")"); + return thing; + } + + /** + * Prints 'testI32("%d")' with thing as '%d' + * @param i32 thing - the i32 to print + * @return i32 - returns the i32 'thing' + * + * @param thing + */ + public function testI32(thing:haxe.Int32):haxe.Int32 + { + trace("testI32(" + thing + ")"); + return thing; + } + + /** + * Prints 'testI64("%d")' with thing as '%d' + * @param i64 thing - the i64 to print + * @return i64 - returns the i64 'thing' + * + * @param thing + */ + public function testI64(thing:haxe.Int64):haxe.Int64 + { + trace("testI64(" + thing + ")"); + return thing; + } + + /** + * Prints 'testDouble("%f")' with thing as '%f' + * @param double thing - the double to print + * @return double - returns the double 'thing' + * + * @param thing + */ + public function testDouble(thing:Float):Float + { + trace("testDouble(" + thing + ")"); + return thing; + } + + /** + * Prints 'testBinary("%s")' where '%s' is a hex-formatted string of thing's data + * @param binary thing - the binary data to print + * @return binary - returns the binary 'thing' + * + * @param thing + */ + public function testBinary(thing : haxe.io.Bytes) : haxe.io.Bytes + { + var hex = ""; + for ( i in 0 ... thing.length) { + hex += StringTools.hex( thing.get(i), 2); + } + trace('testBinary($hex)'); + return thing; + } + + /** + * Prints 'testStruct("{%s}")' where thing has been formatted + * into a string of comma separated values + * @param Xtruct thing - the Xtruct to print + * @return Xtruct - returns the Xtruct 'thing' + * + * @param thing + */ + public function testStruct(thing:Xtruct):Xtruct + { + trace("testStruct({" + + "\"" + thing.string_thing + "\", " + + thing.byte_thing + ", " + + thing.i32_thing + ", " + + Int64.toStr(thing.i64_thing) + "})"); + return thing; + } + + /** + * Prints 'testNest("{%s}")' where thing has been formatted + * into a string of the nested struct + * @param Xtruct2 thing - the Xtruct2 to print + * @return Xtruct2 - returns the Xtruct2 'thing' + * + * @param thing + */ + public function testNest(nest:Xtruct2):Xtruct2 + { + var thing:Xtruct = nest.struct_thing; + trace("testNest({" + + nest.byte_thing + ", {" + + "\"" + thing.string_thing + "\", " + + thing.byte_thing + ", " + + thing.i32_thing + ", " + + Int64.toStr(thing.i64_thing) + "}, " + + nest.i32_thing + "})"); + return nest; + } + + /** + * Prints 'testMap("{%s")' where thing has been formatted + * into a string of 'key => value' pairs + * separated by commas and new lines + * @param map<i32,i32> thing - the map<i32,i32> to print + * @return map<i32,i32> - returns the map<i32,i32> 'thing' + * + * @param thing + */ + public function testMap(thing:IntMap<haxe.Int32>):IntMap<haxe.Int32> + { + trace("testMap({"); + var first:Bool = true; + for (key in thing.keys()) { + if (first) { + first = false; + } else { + trace(", "); + }; + trace(key + " => " + thing.get(key)); + }; + trace("})"); + return thing; + } + + /** + * Prints 'testStringMap("{%s}")' where thing has been formatted + * into a string of 'key => value' pairs + * separated by commas and new lines + * @param map<string,string> thing - the map<string,string> to print + * @return map<string,string> - returns the map<string,string> 'thing' + * + * @param thing + */ + public function testStringMap(thing:StringMap<String>):StringMap<String> + { + trace("testStringMap({"); + var first:Bool = true; + for (key in thing.keys()) { + if (first) { + first = false; + } else { + trace(", "); + }; + trace(key + " => " + thing.get(key)); + }; + trace("})"); + return thing; + } + + /** + * Prints 'testSet("{%s}")' where thing has been formatted + * into a string of values + * separated by commas and new lines + * @param set<i32> thing - the set<i32> to print + * @return set<i32> - returns the set<i32> 'thing' + * + * @param thing + */ + public function testSet(thing:IntSet):IntSet + { + trace("testSet({"); + var first:Bool = true; + for (elem in thing) { + if (first) { + first = false; + } else { + trace(", "); + }; + trace(elem); + }; + trace("})"); + return thing; + } + + /** + * Prints 'testList("{%s}")' where thing has been formatted + * into a string of values + * separated by commas and new lines + * @param list<i32> thing - the list<i32> to print + * @return list<i32> - returns the list<i32> 'thing' + * + * @param thing + */ + public function testList(thing:List<haxe.Int32>):List<haxe.Int32> + { + trace("testList({"); + var first:Bool = true; + for (elem in thing) { + if (first) { + first = false; + } else { + trace(", "); + }; + trace(elem); + }; + trace("})"); + return thing; + } + + /** + * Prints 'testEnum("%d")' where thing has been formatted into it's numeric value + * @param Numberz thing - the Numberz to print + * @return Numberz - returns the Numberz 'thing' + * + * @param thing + */ + public function testEnum(thing:Int):Int + { + trace("testEnum(" + thing + ")"); + return thing; + } + + /** + * Prints 'testTypedef("%d")' with thing as '%d' + * @param UserId thing - the UserId to print + * @return UserId - returns the UserId 'thing' + * + * @param thing + */ + public function testTypedef(thing:haxe.Int64):haxe.Int64 + { + trace("testTypedef(" + thing + ")"); + return thing; + } + + /** + * Prints 'testMapMap("%d")' with hello as '%d' + * @param i32 hello - the i32 to print + * @return map<i32,map<i32,i32>> - returns a dictionary with these values: + * {-4 => {-4 => -4, -3 => -3, -2 => -2, -1 => -1, }, + * 4 => {1 => 1, 2 => 2, 3 => 3, 4 => 4, }, } + * + * @param hello + */ + public function testMapMap(hello:haxe.Int32):IntMap<IntMap<haxe.Int32>> + { + trace("testMapMap(" + hello + ")"); + var mapmap = new IntMap<IntMap<Int>>(); + var pos = new IntMap<Int>(); + var neg = new IntMap<Int>(); + for (i in 1 ... 5) { + pos.set(i, i); + neg.set(-i, -i); + }; + mapmap.set(4, pos); + mapmap.set(-4, neg); + return mapmap; + } + + /** + * So you think you've got this all worked, out eh? + * + * Creates a the returned map with these values and prints it out: + * { 1 => { 2 => argument, + * 3 => argument, + * }, + * 2 => { 6 => <empty Insanity struct>, }, + * } + * @return map<UserId, map<Numberz,Insanity>> - a map with the above values + * + * @param argument + */ + public function testInsanity(argument : Insanity) : Int64Map< IntMap< Insanity>> + { + trace("testInsanity()"); + + var first_map = new IntMap< Insanity>(); + first_map.set(Numberz.TWO, argument); + first_map.set(Numberz.THREE, argument); + + var second_map = new IntMap< Insanity>(); + var looney = new Insanity(); + second_map.set(Numberz.SIX, looney); + + var insane = new Int64Map< IntMap< Insanity>>(); + insane.set( Int64.make(0,1), first_map); + insane.set( Int64.make(0,2), second_map); + + return insane; + } + + /** + * Prints 'testMulti()' + * @param byte arg0 - + * @param i32 arg1 - + * @param i64 arg2 - + * @param map<i16, string> arg3 - + * @param Numberz arg4 - + * @param UserId arg5 - + * @return Xtruct - returns an Xtruct + * with string_thing = "Hello2, byte_thing = arg0, i32_thing = arg1 + * and i64_thing = arg2 + * + * @param arg0 + * @param arg1 + * @param arg2 + * @param arg3 + * @param arg4 + * @param arg5 + */ + public function testMulti(arg0:haxe.Int32, arg1:haxe.Int32, arg2:haxe.Int64, + arg3:IntMap<String>, arg4:Int, arg5:haxe.Int64):Xtruct + { + trace("testMulti()"); + var hello = new Xtruct(); + hello.string_thing = "Hello2"; + hello.byte_thing = arg0; + hello.i32_thing = arg1; + hello.i64_thing = arg2; + return hello; + } + + /** + * Print 'testException(%s)' with arg as '%s' + * @param string arg - a string indication what type of exception to throw + * if arg == "Xception" throw Xception with errorCode = 1001 and message = arg + * elsen if arg == "TException" throw TException + * else do not throw anything + * + * @param arg + */ + public function testException(arg:String):Void + { + trace("testException(" + arg + ")"); + if (arg == "Xception") { + var x = new Xception(); + x.errorCode = 1001; + x.message = arg; + throw x; + }; + if (arg == "TException") { + throw new TException(); + }; + return; + } + + /** + * Print 'testMultiException(%s, %s)' with arg0 as '%s' and arg1 as '%s' + * @param string arg - a string indication what type of exception to throw + * if arg0 == "Xception" + * throw Xception with errorCode = 1001 and message = "This is an Xception" + * else if arg0 == "Xception2" + * throw Xception2 with errorCode = 2002 and message = "This is an Xception2" + * else do not throw anything + * @return Xtruct - an Xtruct with string_thing = arg1 + * + * @param arg0 + * @param arg1 + */ + public function testMultiException(arg0:String, arg1:String):Xtruct + { + trace("testMultiException(" + arg0 + ", " + arg1 + ")"); + if (arg0 == "Xception") { + var x = new Xception(); + x.errorCode = 1001; + x.message = "This is an Xception"; + throw x; + } else if (arg0 == "Xception2") { + var x = new Xception2(); + x.errorCode = 2002; + x.struct_thing = new Xtruct(); + x.struct_thing.string_thing = "This is an Xception2"; + throw x; + }; + var result = new Xtruct(); + result.string_thing = arg1; + return result; + } + + /** + * Print 'testOneway(%d): Sleeping...' with secondsToSleep as '%d' + * sleep 'secondsToSleep' + * Print 'testOneway(%d): done sleeping!' with secondsToSleep as '%d' + * @param i32 secondsToSleep - the number of seconds to sleep + * + * @param secondsToSleep + */ + public function testOneway(secondsToSleep:haxe.Int32):Void + { + trace("testOneway(" + secondsToSleep + "), sleeping..."); + Sys.sleep(secondsToSleep); + trace("testOneway finished"); + } + + public function testStop():Void + { + if (server != null) { + server.Stop(); + }; + } +} diff --git a/src/jaegertracing/thrift/test/hs/CMakeLists.txt b/src/jaegertracing/thrift/test/hs/CMakeLists.txt new file mode 100644 index 000000000..eaca3fa04 --- /dev/null +++ b/src/jaegertracing/thrift/test/hs/CMakeLists.txt @@ -0,0 +1,114 @@ +# +# 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. +# + +set(hs_test_gen + ${CMAKE_CURRENT_BINARY_DIR}/gen-hs/ConstantsDemo_Consts.hs + ${CMAKE_CURRENT_BINARY_DIR}/gen-hs/ConstantsDemo_Types.hs + ${CMAKE_CURRENT_BINARY_DIR}/gen-hs/DebugProtoTest_Consts.hs + ${CMAKE_CURRENT_BINARY_DIR}/gen-hs/DebugProtoTest_Types.hs + ${CMAKE_CURRENT_BINARY_DIR}/gen-hs/EmptyService_Client.hs + ${CMAKE_CURRENT_BINARY_DIR}/gen-hs/EmptyService.hs + ${CMAKE_CURRENT_BINARY_DIR}/gen-hs/EmptyService_Iface.hs + ${CMAKE_CURRENT_BINARY_DIR}/gen-hs/Include_Consts.hs + ${CMAKE_CURRENT_BINARY_DIR}/gen-hs/Include_Types.hs + ${CMAKE_CURRENT_BINARY_DIR}/gen-hs/Inherited_Client.hs + ${CMAKE_CURRENT_BINARY_DIR}/gen-hs/Inherited.hs + ${CMAKE_CURRENT_BINARY_DIR}/gen-hs/Inherited_Iface.hs + ${CMAKE_CURRENT_BINARY_DIR}/gen-hs/ReverseOrderService_Client.hs + ${CMAKE_CURRENT_BINARY_DIR}/gen-hs/ReverseOrderService.hs + ${CMAKE_CURRENT_BINARY_DIR}/gen-hs/ReverseOrderService_Iface.hs + ${CMAKE_CURRENT_BINARY_DIR}/gen-hs/SecondService_Client.hs + ${CMAKE_CURRENT_BINARY_DIR}/gen-hs/SecondService.hs + ${CMAKE_CURRENT_BINARY_DIR}/gen-hs/SecondService_Iface.hs + ${CMAKE_CURRENT_BINARY_DIR}/gen-hs/ServiceForExceptionWithAMap_Client.hs + ${CMAKE_CURRENT_BINARY_DIR}/gen-hs/ServiceForExceptionWithAMap.hs + ${CMAKE_CURRENT_BINARY_DIR}/gen-hs/ServiceForExceptionWithAMap_Iface.hs + ${CMAKE_CURRENT_BINARY_DIR}/gen-hs/Srv_Client.hs + ${CMAKE_CURRENT_BINARY_DIR}/gen-hs/Srv.hs + ${CMAKE_CURRENT_BINARY_DIR}/gen-hs/Srv_Iface.hs + ${CMAKE_CURRENT_BINARY_DIR}/gen-hs/ThriftTest_Client.hs + ${CMAKE_CURRENT_BINARY_DIR}/gen-hs/ThriftTest_Consts.hs + ${CMAKE_CURRENT_BINARY_DIR}/gen-hs/ThriftTest.hs + ${CMAKE_CURRENT_BINARY_DIR}/gen-hs/ThriftTest_Iface.hs + ${CMAKE_CURRENT_BINARY_DIR}/gen-hs/ThriftTest_Types.hs + ${CMAKE_CURRENT_BINARY_DIR}/gen-hs/Yowza_Client.hs + ${CMAKE_CURRENT_BINARY_DIR}/gen-hs/Yowza.hs + ${CMAKE_CURRENT_BINARY_DIR}/gen-hs/Yowza_Iface.hs +) + +set(hs_crosstest_apps + ${CMAKE_CURRENT_BINARY_DIR}/TestServer + ${CMAKE_CURRENT_BINARY_DIR}/TestClient +) +set(hs_crosstest_args + -igen-hs + -odir=${CMAKE_CURRENT_BINARY_DIR} + -hidir=${CMAKE_CURRENT_BINARY_DIR} +) + +if (CMAKE_BUILD_TYPE STREQUAL "Debug") + set(hs_optimize -O0) +else() + set(hs_optimize -O1) +endif() + +add_custom_command( + OUTPUT ${hs_crosstest_apps} + COMMAND ${GHC} ${hs_optimize} ${hs_crosstest_args} ${CMAKE_CURRENT_SOURCE_DIR}/TestServer.hs -o TestServer + COMMAND ${GHC} ${hs_optimize} ${hs_crosstest_args} ${CMAKE_CURRENT_SOURCE_DIR}/TestClient.hs -o TestClient + DEPENDS ${hs_test_gen} haskell_library TestServer.hs TestClient.hs +) +add_custom_target(haskell_crosstest ALL + COMMENT "Building Haskell cross test executables" + DEPENDS ${hs_crosstest_apps} +) + +set(hs_test_sources + ConstantsDemo_Main.hs + DebugProtoTest_Main.hs + Include_Main.hs + ThriftTest_Main.hs +) +set(hs_test_args + -Wall + -XScopedTypeVariables + -i${PROJECT_SOURCE_DIR}/lib/hs/src + -i${CMAKE_CURRENT_BINARY_DIR}/gen-hs +) +add_custom_target(haskell_tests ALL DEPENDS ${hs_test_gen}) +foreach(SRC ${hs_test_sources}) + get_filename_component(BASE ${SRC} NAME_WE) + add_test(NAME HaskellTests-${BASE} + COMMAND ${RUN_HASKELL} ${hs_test_args} ${SRC} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) +endforeach() + +set(hs_test_gen_sources + ${PROJECT_SOURCE_DIR}/test/ConstantsDemo.thrift + ${PROJECT_SOURCE_DIR}/test/DebugProtoTest.thrift + ${PROJECT_SOURCE_DIR}/test/ThriftTest.thrift + ${PROJECT_SOURCE_DIR}/test/Include.thrift +) +add_custom_command(OUTPUT ${hs_test_gen} + COMMAND ${THRIFT_COMPILER} --gen hs ${PROJECT_SOURCE_DIR}/test/ConstantsDemo.thrift + COMMAND ${THRIFT_COMPILER} --gen hs ${PROJECT_SOURCE_DIR}/test/DebugProtoTest.thrift + COMMAND ${THRIFT_COMPILER} --gen hs ${PROJECT_SOURCE_DIR}/test/ThriftTest.thrift + COMMAND ${THRIFT_COMPILER} --gen hs ${PROJECT_SOURCE_DIR}/test/Include.thrift + DEPENDS ${hs_test_gen_sources} +) diff --git a/src/jaegertracing/thrift/test/hs/ConstantsDemo_Main.hs b/src/jaegertracing/thrift/test/hs/ConstantsDemo_Main.hs new file mode 100644 index 000000000..28de4f7ea --- /dev/null +++ b/src/jaegertracing/thrift/test/hs/ConstantsDemo_Main.hs @@ -0,0 +1,68 @@ +-- +-- 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. +-- + +module Main where + + +import qualified Control.Exception +import qualified Network + +import Thrift.Protocol.Binary +import Thrift.Server +import Thrift.Transport.Handle + +import qualified ThriftTestUtils + +import qualified Yowza +import qualified Yowza_Client as Client +import qualified Yowza_Iface as Iface + + +data YowzaHandler = YowzaHandler +instance Iface.Yowza_Iface YowzaHandler where + blingity _ = do + ThriftTestUtils.serverLog "SERVER: Got blingity" + return () + + blangity _ = do + ThriftTestUtils.serverLog "SERVER: Got blangity" + return $ 31 + + +client :: (String, Network.PortID) -> IO () +client addr = do + to <- hOpen addr + let ps = (BinaryProtocol to, BinaryProtocol to) + + Client.blingity ps + + rv <- Client.blangity ps + ThriftTestUtils.clientLog $ show rv + + tClose to + +server :: Network.PortNumber -> IO () +server port = do + ThriftTestUtils.serverLog "Ready..." + (runBasicServer YowzaHandler Yowza.process port) + `Control.Exception.catch` + (\(TransportExn s _) -> error $ "FAILURE: " ++ show s) + +main :: IO () +main = ThriftTestUtils.runTest server client diff --git a/src/jaegertracing/thrift/test/hs/DebugProtoTest_Main.hs b/src/jaegertracing/thrift/test/hs/DebugProtoTest_Main.hs new file mode 100644 index 000000000..97d4347c2 --- /dev/null +++ b/src/jaegertracing/thrift/test/hs/DebugProtoTest_Main.hs @@ -0,0 +1,172 @@ +-- +-- 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. +-- + +{-# LANGUAGE OverloadedStrings #-} + +module Main where + + +import qualified Control.Exception +import qualified Data.ByteString.Lazy as DBL +import qualified Data.HashMap.Strict as Map +import qualified Data.HashSet as Set +import qualified Data.Vector as Vector +import qualified Network + +import Thrift.Protocol.Binary +import Thrift.Server +import Thrift.Transport.Handle + +import qualified ThriftTestUtils + +import qualified DebugProtoTest_Types as Types +import qualified Inherited +import qualified Inherited_Client as IClient +import qualified Inherited_Iface as IIface +import qualified Srv_Client as SClient +import qualified Srv_Iface as SIface + +-- we don't actually need this import, but force it to check the code generator exports proper Haskell syntax +import qualified Srv() + + +data InheritedHandler = InheritedHandler +instance SIface.Srv_Iface InheritedHandler where + janky _ arg = do + ThriftTestUtils.serverLog $ "Got janky method call: " ++ show arg + return $ 31 + + voidMethod _ = do + ThriftTestUtils.serverLog "Got voidMethod method call" + return () + + primitiveMethod _ = do + ThriftTestUtils.serverLog "Got primitiveMethod call" + return $ 42 + + structMethod _ = do + ThriftTestUtils.serverLog "Got structMethod call" + return $ Types.CompactProtoTestStruct { + Types.compactProtoTestStruct_a_byte = 0x01, + Types.compactProtoTestStruct_a_i16 = 0x02, + Types.compactProtoTestStruct_a_i32 = 0x03, + Types.compactProtoTestStruct_a_i64 = 0x04, + Types.compactProtoTestStruct_a_double = 0.1, + Types.compactProtoTestStruct_a_string = "abcdef", + Types.compactProtoTestStruct_a_binary = DBL.empty, + Types.compactProtoTestStruct_true_field = True, + Types.compactProtoTestStruct_false_field = False, + Types.compactProtoTestStruct_empty_struct_field = Types.Empty, + + Types.compactProtoTestStruct_byte_list = Vector.empty, + Types.compactProtoTestStruct_i16_list = Vector.empty, + Types.compactProtoTestStruct_i32_list = Vector.empty, + Types.compactProtoTestStruct_i64_list = Vector.empty, + Types.compactProtoTestStruct_double_list = Vector.empty, + Types.compactProtoTestStruct_string_list = Vector.empty, + Types.compactProtoTestStruct_binary_list = Vector.empty, + Types.compactProtoTestStruct_boolean_list = Vector.empty, + Types.compactProtoTestStruct_struct_list = Vector.empty, + + Types.compactProtoTestStruct_byte_set = Set.empty, + Types.compactProtoTestStruct_i16_set = Set.empty, + Types.compactProtoTestStruct_i32_set = Set.empty, + Types.compactProtoTestStruct_i64_set = Set.empty, + Types.compactProtoTestStruct_double_set = Set.empty, + Types.compactProtoTestStruct_string_set = Set.empty, + Types.compactProtoTestStruct_binary_set = Set.empty, + Types.compactProtoTestStruct_boolean_set = Set.empty, + Types.compactProtoTestStruct_struct_set = Set.empty, + + Types.compactProtoTestStruct_byte_byte_map = Map.empty, + Types.compactProtoTestStruct_i16_byte_map = Map.empty, + Types.compactProtoTestStruct_i32_byte_map = Map.empty, + Types.compactProtoTestStruct_i64_byte_map = Map.empty, + Types.compactProtoTestStruct_double_byte_map = Map.empty, + Types.compactProtoTestStruct_string_byte_map = Map.empty, + Types.compactProtoTestStruct_binary_byte_map = Map.empty, + Types.compactProtoTestStruct_boolean_byte_map = Map.empty, + + Types.compactProtoTestStruct_byte_i16_map = Map.empty, + Types.compactProtoTestStruct_byte_i32_map = Map.empty, + Types.compactProtoTestStruct_byte_i64_map = Map.empty, + Types.compactProtoTestStruct_byte_double_map = Map.empty, + Types.compactProtoTestStruct_byte_string_map = Map.empty, + Types.compactProtoTestStruct_byte_binary_map = Map.empty, + Types.compactProtoTestStruct_byte_boolean_map = Map.empty, + + Types.compactProtoTestStruct_list_byte_map = Map.empty, + Types.compactProtoTestStruct_set_byte_map = Map.empty, + Types.compactProtoTestStruct_map_byte_map = Map.empty, + + Types.compactProtoTestStruct_byte_map_map = Map.empty, + Types.compactProtoTestStruct_byte_set_map = Map.empty, + Types.compactProtoTestStruct_byte_list_map = Map.empty, + + Types.compactProtoTestStruct_field500 = 500, + Types.compactProtoTestStruct_field5000 = 5000, + Types.compactProtoTestStruct_field20000 = 20000 } + + methodWithDefaultArgs _ arg = do + ThriftTestUtils.serverLog $ "Got methodWithDefaultArgs: " ++ show arg + return () + + onewayMethod _ = do + ThriftTestUtils.serverLog "Got onewayMethod" + +instance IIface.Inherited_Iface InheritedHandler where + identity _ arg = do + ThriftTestUtils.serverLog $ "Got identity method: " ++ show arg + return arg + +client :: (String, Network.PortID) -> IO () +client addr = do + to <- hOpen addr + let p = BinaryProtocol to + let ps = (p,p) + + v1 <- SClient.janky ps 42 + ThriftTestUtils.clientLog $ show v1 + + SClient.voidMethod ps + + v2 <- SClient.primitiveMethod ps + ThriftTestUtils.clientLog $ show v2 + + v3 <- SClient.structMethod ps + ThriftTestUtils.clientLog $ show v3 + + SClient.methodWithDefaultArgs ps 42 + + SClient.onewayMethod ps + + v4 <- IClient.identity ps 42 + ThriftTestUtils.clientLog $ show v4 + + return () + +server :: Network.PortNumber -> IO () +server port = do + ThriftTestUtils.serverLog "Ready..." + (runBasicServer InheritedHandler Inherited.process port) + `Control.Exception.catch` + (\(TransportExn s _) -> error $ "FAILURE: " ++ show s) + +main :: IO () +main = ThriftTestUtils.runTest server client diff --git a/src/jaegertracing/thrift/test/hs/Include_Main.hs b/src/jaegertracing/thrift/test/hs/Include_Main.hs new file mode 100644 index 000000000..d3977a157 --- /dev/null +++ b/src/jaegertracing/thrift/test/hs/Include_Main.hs @@ -0,0 +1,7 @@ +module Main where + +import Include_Types +import ThriftTest_Types + +main :: IO () +main = putStrLn ("Includes work: " ++ (show (IncludeTest $ Bools True False))) diff --git a/src/jaegertracing/thrift/test/hs/Makefile.am b/src/jaegertracing/thrift/test/hs/Makefile.am new file mode 100644 index 000000000..817070d8f --- /dev/null +++ b/src/jaegertracing/thrift/test/hs/Makefile.am @@ -0,0 +1,50 @@ +# +# 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. +# + +stubs: $(THRIFT) ../ConstantsDemo.thrift ../DebugProtoTest.thrift ../ThriftTest.thrift ../Include.thrift + $(THRIFT) --gen hs ../ConstantsDemo.thrift + $(THRIFT) --gen hs ../DebugProtoTest.thrift + $(THRIFT) --gen hs ../ThriftTest.thrift + $(THRIFT) --gen hs ../Include.thrift + +check: stubs + sh run-test.sh ConstantsDemo + sh run-test.sh DebugProtoTest + sh run-test.sh ThriftTest + sh run-test.sh Include + +clean-local: + $(RM) -r gen-hs/ + $(RM) *.hi + $(RM) *.o + $(RM) TestClient + $(RM) TestServer + +dist-hook: + $(RM) -r $(distdir)/gen-hs/ + $(RM) $(distdir)/*.hi + $(RM) $(distdir)/*.o + $(RM) $(destdir)/TestClient + $(RM) $(destdir)/TestServer + +all-local: stubs + ghc -igen-hs TestServer.hs + ghc -igen-hs TestClient.hs + +precross: all-local diff --git a/src/jaegertracing/thrift/test/hs/TestClient.hs b/src/jaegertracing/thrift/test/hs/TestClient.hs new file mode 100644 index 000000000..93fb591b3 --- /dev/null +++ b/src/jaegertracing/thrift/test/hs/TestClient.hs @@ -0,0 +1,306 @@ +-- +-- 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. +-- + +{-# LANGUAGE OverloadedStrings, RecordWildCards, ScopedTypeVariables #-} +module Main where + +import Control.Exception +import Control.Monad +import Data.Functor +import Data.List.Split +import Data.String +import Network +import Network.URI +import System.Environment +import System.Exit +import qualified Data.ByteString.Lazy as LBS +import qualified Data.HashMap.Strict as Map +import qualified Data.HashSet as Set +import qualified Data.Vector as Vector +import qualified System.IO as IO + +import ThriftTest_Iface +import ThriftTest_Types +import qualified ThriftTest_Client as Client + +import Thrift.Transport +import Thrift.Transport.Framed +import Thrift.Transport.Handle +import Thrift.Transport.HttpClient +import Thrift.Protocol +import Thrift.Protocol.Binary +import Thrift.Protocol.Compact +import Thrift.Protocol.Header +import Thrift.Protocol.JSON + +data Options = Options + { host :: String + , port :: Int + , domainSocket :: String + , transport :: String + , protocol :: ProtocolType + -- TODO: Haskell lib does not have SSL support + , ssl :: Bool + , testLoops :: Int + } + deriving (Show, Eq) + +data TransportType = Buffered IO.Handle + | Framed (FramedTransport IO.Handle) + | Http HttpClient + | NoTransport String + +getTransport :: String -> String -> Int -> (IO TransportType) +getTransport "buffered" host port = do + h <- hOpen (host, PortNumber $ fromIntegral port) + IO.hSetBuffering h $ IO.BlockBuffering Nothing + return $ Buffered h +getTransport "framed" host port = do + h <- hOpen (host, PortNumber $ fromIntegral port) + t <- openFramedTransport h + return $ Framed t +getTransport "http" host port = let uriStr = "http://" ++ host ++ ":" ++ show port in + case parseURI uriStr of + Nothing -> do return (NoTransport $ "Failed to parse URI: " ++ uriStr) + Just(uri) -> do + t <- openHttpClient uri + return $ Http t +getTransport t host port = do return (NoTransport $ "Unsupported transport: " ++ t) + +data ProtocolType = Binary + | Compact + | JSON + | Header + deriving (Show, Eq) + +getProtocol :: String -> ProtocolType +getProtocol "binary" = Binary +getProtocol "compact" = Compact +getProtocol "json" = JSON +getProtocol "header" = Header +getProtocol p = error $ "Unsupported Protocol: " ++ p + +defaultOptions :: Options +defaultOptions = Options + { port = 9090 + , domainSocket = "" + , host = "localhost" + , transport = "buffered" + , protocol = Binary + , ssl = False + , testLoops = 1 + } + +runClient :: Protocol p => p -> IO () +runClient p = do + let prot = (p,p) + putStrLn "Starting Tests" + + -- VOID Test + putStrLn "testVoid" + Client.testVoid prot + + -- String Test + putStrLn "testString" + s <- Client.testString prot "Test" + when (s /= "Test") exitFailure + + -- Bool Test + putStrLn "testBool" + bool <- Client.testBool prot True + when (not bool) exitFailure + putStrLn "testBool" + bool <- Client.testBool prot False + when (bool) exitFailure + + -- Byte Test + putStrLn "testByte" + byte <- Client.testByte prot 1 + when (byte /= 1) exitFailure + + -- I32 Test + putStrLn "testI32" + i32 <- Client.testI32 prot (-1) + when (i32 /= -1) exitFailure + + -- I64 Test + putStrLn "testI64" + i64 <- Client.testI64 prot (-34359738368) + when (i64 /= -34359738368) exitFailure + + -- Double Test + putStrLn "testDouble" + dub <- Client.testDouble prot (-5.2098523) + when (abs (dub + 5.2098523) > 0.001) exitFailure + + -- Binary Test + putStrLn "testBinary" + bin <- Client.testBinary prot (LBS.pack . reverse $ [-128..127]) + when ((reverse [-128..127]) /= LBS.unpack bin) exitFailure + + -- Struct Test + let structIn = Xtruct{ xtruct_string_thing = "Zero" + , xtruct_byte_thing = 1 + , xtruct_i32_thing = -3 + , xtruct_i64_thing = -5 + } + putStrLn "testStruct" + structOut <- Client.testStruct prot structIn + when (structIn /= structOut) exitFailure + + -- Nested Struct Test + let nestIn = Xtruct2{ xtruct2_byte_thing = 1 + , xtruct2_struct_thing = structIn + , xtruct2_i32_thing = 5 + } + putStrLn "testNest" + nestOut <- Client.testNest prot nestIn + when (nestIn /= nestOut) exitFailure + + -- Map Test + let mapIn = Map.fromList $ map (\i -> (i, i-10)) [1..5] + putStrLn "testMap" + mapOut <- Client.testMap prot mapIn + when (mapIn /= mapOut) exitFailure + + -- Set Test + let setIn = Set.fromList [-2..3] + putStrLn "testSet" + setOut <- Client.testSet prot setIn + when (setIn /= setOut) exitFailure + + -- List Test + let listIn = Vector.fromList [-2..3] + putStrLn "testList" + listOut <- Client.testList prot listIn + when (listIn /= listOut) exitFailure + + -- Enum Test + putStrLn "testEnum" + numz1 <- Client.testEnum prot ONE + when (numz1 /= ONE) exitFailure + + putStrLn "testEnum" + numz2 <- Client.testEnum prot TWO + when (numz2 /= TWO) exitFailure + + putStrLn "testEnum" + numz5 <- Client.testEnum prot FIVE + when (numz5 /= FIVE) exitFailure + + -- Typedef Test + putStrLn "testTypedef" + uid <- Client.testTypedef prot 309858235082523 + when (uid /= 309858235082523) exitFailure + + -- Nested Map Test + putStrLn "testMapMap" + _ <- Client.testMapMap prot 1 + + -- Exception Test + putStrLn "testException" + exn1 <- try $ Client.testException prot "Xception" + case exn1 of + Left (Xception _ _) -> return () + _ -> putStrLn (show exn1) >> exitFailure + + putStrLn "testException" + exn2 <- try $ Client.testException prot "TException" + case exn2 of + Left (_ :: SomeException) -> return () + Right _ -> exitFailure + + putStrLn "testException" + exn3 <- try $ Client.testException prot "success" + case exn3 of + Left (_ :: SomeException) -> exitFailure + Right _ -> return () + + -- Multi Exception Test + putStrLn "testMultiException" + multi1 <- try $ Client.testMultiException prot "Xception" "test 1" + case multi1 of + Left (Xception _ _) -> return () + _ -> exitFailure + + putStrLn "testMultiException" + multi2 <- try $ Client.testMultiException prot "Xception2" "test 2" + case multi2 of + Left (Xception2 _ _) -> return () + _ -> exitFailure + + putStrLn "testMultiException" + multi3 <- try $ Client.testMultiException prot "success" "test 3" + case multi3 of + Left (_ :: SomeException) -> exitFailure + Right _ -> return () + + +main :: IO () +main = do + options <- flip parseFlags defaultOptions <$> getArgs + case options of + Nothing -> showHelp + Just Options{..} -> do + trans <- Main.getTransport transport host port + case trans of + Buffered t -> runTest testLoops protocol t + Framed t -> runTest testLoops protocol t + Http t -> runTest testLoops protocol t + NoTransport err -> putStrLn err + where + makeClient p t = case p of + Binary -> runClient $ BinaryProtocol t + Compact -> runClient $ CompactProtocol t + JSON -> runClient $ JSONProtocol t + Header -> createHeaderProtocol t t >>= runClient + runTest loops p t = do + let client = makeClient p t + replicateM_ loops client + putStrLn "COMPLETED SUCCESSFULLY" + +parseFlags :: [String] -> Options -> Maybe Options +parseFlags (flag : flags) opts = do + let pieces = splitOn "=" flag + case pieces of + "--port" : arg : _ -> parseFlags flags opts{ port = read arg } + "--domain-socket" : arg : _ -> parseFlags flags opts{ domainSocket = read arg } + "--host" : arg : _ -> parseFlags flags opts{ host = arg } + "--transport" : arg : _ -> parseFlags flags opts{ transport = arg } + "--protocol" : arg : _ -> parseFlags flags opts{ protocol = getProtocol arg } + "-n" : arg : _ -> parseFlags flags opts{ testLoops = read arg } + "--h" : _ -> Nothing + "--help" : _ -> Nothing + "--ssl" : _ -> parseFlags flags opts{ ssl = True } + "--processor-events" : _ -> parseFlags flags opts + _ -> Nothing +parseFlags [] opts = Just opts + +showHelp :: IO () +showHelp = putStrLn + "Allowed options:\n\ + \ -h [ --help ] produce help message\n\ + \ --host arg (=localhost) Host to connect\n\ + \ --port arg (=9090) Port number to connect\n\ + \ --domain-socket arg Domain Socket (e.g. /tmp/ThriftTest.thrift),\n\ + \ instead of host and port\n\ + \ --transport arg (=buffered) Transport: buffered, framed, http\n\ + \ --protocol arg (=binary) Protocol: binary, compact, json\n\ + \ --ssl Encrypted Transport using SSL\n\ + \ -n [ --testloops ] arg (=1) Number of Tests" diff --git a/src/jaegertracing/thrift/test/hs/TestServer.hs b/src/jaegertracing/thrift/test/hs/TestServer.hs new file mode 100644 index 000000000..b7731ab1c --- /dev/null +++ b/src/jaegertracing/thrift/test/hs/TestServer.hs @@ -0,0 +1,312 @@ +-- +-- 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. +-- + +{-# LANGUAGE OverloadedStrings,RecordWildCards #-} +module Main where + +import Control.Exception +import Control.Monad +import Data.Functor +import Data.HashMap.Strict (HashMap) +import Data.List +import Data.List.Split +import Data.String +import Network +import System.Environment +import System.Exit +import System.IO +import Control.Concurrent (threadDelay) +import qualified System.IO as IO +import qualified Data.HashMap.Strict as Map +import qualified Data.HashSet as Set +import qualified Data.Text.Lazy as Text +import qualified Data.Vector as Vector + +import ThriftTest +import ThriftTest_Iface +import ThriftTest_Types + +import Thrift +import Thrift.Server +import Thrift.Transport.Framed +import Thrift.Transport.Handle +import Thrift.Protocol.Binary +import Thrift.Protocol.Compact +import Thrift.Protocol.Header +import Thrift.Protocol.JSON + +data Options = Options + { port :: Int + , domainSocket :: String + , serverType :: ServerType + , transport :: String + , protocol :: ProtocolType + , ssl :: Bool + , workers :: Int + } + +data ServerType = Simple + | ThreadPool + | Threaded + | NonBlocking + deriving (Show, Eq) + +instance IsString ServerType where + fromString "simple" = Simple + fromString "thread-pool" = ThreadPool + fromString "threaded" = Threaded + fromString "nonblocking" = NonBlocking + fromString _ = error "not a valid server type" + +data TransportType = Buffered (Socket -> (IO IO.Handle)) + | Framed (Socket -> (IO (FramedTransport IO.Handle))) + | NoTransport String + +getTransport :: String -> TransportType +getTransport "buffered" = Buffered $ \s -> do + (h, _, _) <- (accept s) + IO.hSetBuffering h $ IO.BlockBuffering Nothing + return h +getTransport "framed" = Framed $ \s -> do + (h, _, _) <- (accept s) + openFramedTransport h +getTransport t = NoTransport $ "Unsupported transport: " ++ t + +data ProtocolType = Binary + | Compact + | JSON + | Header + +getProtocol :: String -> ProtocolType +getProtocol "binary" = Binary +getProtocol "compact" = Compact +getProtocol "json" = JSON +getProtocol "header" = Header +getProtocol p = error $"Unsupported Protocol: " ++ p + +defaultOptions :: Options +defaultOptions = Options + { port = 9090 + , domainSocket = "" + , serverType = Threaded + , transport = "buffered" + , protocol = Binary + -- TODO: Haskell lib does not have SSL support + , ssl = False + , workers = 4 + } + +stringifyMap :: (Show a, Show b) => Map.HashMap a b -> String +stringifyMap = Data.List.intercalate ", " . Data.List.map joinKV . Map.toList + where joinKV (k, v) = show k ++ " => " ++ show v + +stringifySet :: Show a => Set.HashSet a -> String +stringifySet = Data.List.intercalate ", " . Data.List.map show . Set.toList + +stringifyList :: Show a => Vector.Vector a -> String +stringifyList = Data.List.intercalate ", " . Data.List.map show . Vector.toList + +data TestHandler = TestHandler +instance ThriftTest_Iface TestHandler where + testVoid _ = System.IO.putStrLn "testVoid()" + + testString _ s = do + System.IO.putStrLn $ "testString(" ++ show s ++ ")" + return s + + testBool _ x = do + System.IO.putStrLn $ "testBool(" ++ show x ++ ")" + return x + + testByte _ x = do + System.IO.putStrLn $ "testByte(" ++ show x ++ ")" + return x + + testI32 _ x = do + System.IO.putStrLn $ "testI32(" ++ show x ++ ")" + return x + + testI64 _ x = do + System.IO.putStrLn $ "testI64(" ++ show x ++ ")" + return x + + testDouble _ x = do + System.IO.putStrLn $ "testDouble(" ++ show x ++ ")" + return x + + testBinary _ x = do + System.IO.putStrLn $ "testBinary(" ++ show x ++ ")" + return x + + testStruct _ struct@Xtruct{..} = do + System.IO.putStrLn $ "testStruct({" ++ show xtruct_string_thing + ++ ", " ++ show xtruct_byte_thing + ++ ", " ++ show xtruct_i32_thing + ++ ", " ++ show xtruct_i64_thing + ++ "})" + return struct + + testNest _ nest@Xtruct2{..} = do + let Xtruct{..} = xtruct2_struct_thing + System.IO.putStrLn $ "testNest({" ++ show xtruct2_byte_thing + ++ "{, " ++ show xtruct_string_thing + ++ ", " ++ show xtruct_byte_thing + ++ ", " ++ show xtruct_i32_thing + ++ ", " ++ show xtruct_i64_thing + ++ "}, " ++ show xtruct2_i32_thing + return nest + + testMap _ m = do + System.IO.putStrLn $ "testMap({" ++ stringifyMap m ++ "})" + return m + + testStringMap _ m = do + System.IO.putStrLn $ "testStringMap(" ++ stringifyMap m ++ "})" + return m + + testSet _ x = do + System.IO.putStrLn $ "testSet({" ++ stringifySet x ++ "})" + return x + + testList _ x = do + System.IO.putStrLn $ "testList(" ++ stringifyList x ++ "})" + return x + + testEnum _ x = do + System.IO.putStrLn $ "testEnum(" ++ show x ++ ")" + return x + + testTypedef _ x = do + System.IO.putStrLn $ "testTypedef(" ++ show x ++ ")" + return x + + testMapMap _ x = do + System.IO.putStrLn $ "testMapMap(" ++ show x ++ ")" + return $ Map.fromList [ (-4, Map.fromList [ (-4, -4) + , (-3, -3) + , (-2, -2) + , (-1, -1) + ]) + , (4, Map.fromList [ (1, 1) + , (2, 2) + , (3, 3) + , (4, 4) + ]) + ] + + testInsanity _ x = do + System.IO.putStrLn "testInsanity()" + return $ Map.fromList [ (1, Map.fromList [ (TWO , x) + , (THREE, x) + ]) + , (2, Map.fromList [ (SIX, default_Insanity) + ]) + ] + + testMulti _ byte i32 i64 _ _ _ = do + System.IO.putStrLn "testMulti()" + return Xtruct{ xtruct_string_thing = Text.pack "Hello2" + , xtruct_byte_thing = byte + , xtruct_i32_thing = i32 + , xtruct_i64_thing = i64 + } + + testException _ s = do + System.IO.putStrLn $ "testException(" ++ show s ++ ")" + case s of + "Xception" -> throw $ Xception 1001 s + "TException" -> throw ThriftException + _ -> return () + + testMultiException _ s1 s2 = do + System.IO.putStrLn $ "testMultiException(" ++ show s1 ++ ", " ++ show s2 ++ ")" + case s1 of + "Xception" -> throw $ Xception 1001 "This is an Xception" + "Xception2" -> throw $ Xception2 2002 $ Xtruct "This is an Xception2" 0 0 0 + "TException" -> throw ThriftException + _ -> return default_Xtruct{ xtruct_string_thing = s2 } + + testOneway _ i = do + System.IO.putStrLn $ "testOneway(" ++ show i ++ "): Sleeping..." + threadDelay $ (fromIntegral i) * 1000000 + System.IO.putStrLn $ "testOneway(" ++ show i ++ "): done sleeping!" + +main :: IO () +main = do + options <- flip parseFlags defaultOptions <$> getArgs + case options of + Nothing -> showHelp + Just Options{..} -> do + case Main.getTransport transport of + Buffered f -> runServer protocol f port + Framed f -> runServer protocol f port + NoTransport err -> putStrLn err + System.IO.putStrLn $ "Starting \"" ++ show serverType ++ "\" server (" ++ + show transport ++ ") listen on: " ++ domainSocket ++ show port + where + acceptor p f socket = do + t <- f socket + return (p t, p t) + + headerAcceptor f socket = do + t <- f socket + p <- createHeaderProtocol1 t + return (p, p) + + doRunServer p f = do + runThreadedServer (acceptor p f) TestHandler ThriftTest.process . PortNumber . fromIntegral + + runServer p f port = case p of + Binary -> doRunServer BinaryProtocol f port + Compact -> doRunServer CompactProtocol f port + JSON -> doRunServer JSONProtocol f port + Header -> runThreadedServer (headerAcceptor f) TestHandler ThriftTest.process (PortNumber $ fromIntegral port) + +parseFlags :: [String] -> Options -> Maybe Options +parseFlags (flag : flags) opts = do + let pieces = splitOn "=" flag + case pieces of + "--port" : arg : _ -> parseFlags flags opts{ port = read arg } + "--domain-socket" : arg : _ -> parseFlags flags opts{ domainSocket = read arg } + "--server-type" : arg : _ -> parseFlags flags opts{ serverType = fromString arg } + "--transport" : arg : _ -> parseFlags flags opts{ transport = arg } + "--protocol" : arg : _ -> parseFlags flags opts{ protocol = getProtocol arg } + "--workers" : arg : _ -> parseFlags flags opts{ workers = read arg } + "-n" : arg : _ -> parseFlags flags opts{ workers = read arg } + "--h" : _ -> Nothing + "--help" : _ -> Nothing + "--ssl" : _ -> parseFlags flags opts{ ssl = True } + "--processor-events" : _ -> parseFlags flags opts + _ -> Nothing +parseFlags [] opts = Just opts + +showHelp :: IO () +showHelp = System.IO.putStrLn + "Allowed options:\n\ + \ -h [ --help ] produce help message\n\ + \ --port arg (=9090) Port number to listen\n\ + \ --domain-socket arg Unix Domain Socket (e.g. /tmp/ThriftTest.thrift)\n\ + \ --server-type arg (=simple) type of server, \"simple\", \"thread-pool\",\n\ + \ \"threaded\", or \"nonblocking\"\n\ + \ --transport arg (=buffered) transport: buffered, framed\n\ + \ --protocol arg (=binary) protocol: binary, compact, json\n\ + \ --ssl Encrypted Transport using SSL\n\ + \ --processor-events processor-events\n\ + \ -n [ --workers ] arg (=4) Number of thread pools workers. Only valid for\n\ + \ thread-pool server type" diff --git a/src/jaegertracing/thrift/test/hs/ThriftTestUtils.hs b/src/jaegertracing/thrift/test/hs/ThriftTestUtils.hs new file mode 100644 index 000000000..9c19b56a9 --- /dev/null +++ b/src/jaegertracing/thrift/test/hs/ThriftTestUtils.hs @@ -0,0 +1,65 @@ +-- +-- 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. +-- + +module ThriftTestUtils (ClientFunc, ServerFunc, clientLog, serverLog, testLog, runTest) where + + +import qualified Control.Concurrent +import qualified Network +import qualified System.IO + + +serverPort :: Network.PortNumber +serverPort = 9090 + +serverAddress :: (String, Network.PortID) +serverAddress = ("localhost", Network.PortNumber serverPort) + + +testLog :: String -> IO () +testLog str = do + System.IO.hPutStr System.IO.stdout $ str ++ "\n" + System.IO.hFlush System.IO.stdout + + +clientLog :: String -> IO () +clientLog str = testLog $ "CLIENT: " ++ str + +serverLog :: String -> IO () +serverLog str = testLog $ "SERVER: " ++ str + + +type ServerFunc = Network.PortNumber -> IO () +type ClientFunc = (String, Network.PortID) -> IO () + +runTest :: ServerFunc -> ClientFunc -> IO () +runTest server client = do + _ <- Control.Concurrent.forkIO (server serverPort) + + -- Fairly horrible; this does not 100% guarantees that the other thread + -- has actually opened the socket we need... but not much else we can do + -- without this, the client races the server to the socket, and wins every + -- time + Control.Concurrent.yield + Control.Concurrent.threadDelay $ 500 * 1000 -- unit is in _micro_seconds + Control.Concurrent.yield + + client serverAddress + + testLog "SUCCESS" diff --git a/src/jaegertracing/thrift/test/hs/ThriftTest_Main.hs b/src/jaegertracing/thrift/test/hs/ThriftTest_Main.hs new file mode 100644 index 000000000..670023e29 --- /dev/null +++ b/src/jaegertracing/thrift/test/hs/ThriftTest_Main.hs @@ -0,0 +1,214 @@ +{-# LANGUAGE ScopedTypeVariables #-} +-- +-- 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. +-- + +{-# LANGUAGE OverloadedStrings #-} + +module Main where + + +import qualified Control.Exception +import qualified Data.HashMap.Strict as Map +import qualified Data.HashSet as Set +import qualified Data.Vector as Vector + +import qualified Network + +import Thrift +import Thrift.Protocol.Binary +import Thrift.Server +import Thrift.Transport.Handle + +import qualified ThriftTestUtils + +import qualified ThriftTest +import qualified ThriftTest_Client as Client +import qualified ThriftTest_Iface as Iface +import qualified ThriftTest_Types as Types + + +data TestHandler = TestHandler +instance Iface.ThriftTest_Iface TestHandler where + testVoid _ = return () + + testString _ s = do + ThriftTestUtils.serverLog $ show s + return s + + testByte _ x = do + ThriftTestUtils.serverLog $ show x + return x + + testI32 _ x = do + ThriftTestUtils.serverLog $ show x + return x + + testI64 _ x = do + ThriftTestUtils.serverLog $ show x + return x + + testDouble _ x = do + ThriftTestUtils.serverLog $ show x + return x + + testBinary _ x = do + ThriftTestUtils.serverLog $ show x + return x + + testStruct _ x = do + ThriftTestUtils.serverLog $ show x + return x + + testNest _ x = do + ThriftTestUtils.serverLog $ show x + return x + + testMap _ x = do + ThriftTestUtils.serverLog $ show x + return x + + testStringMap _ x = do + ThriftTestUtils.serverLog $ show x + return x + + testSet _ x = do + ThriftTestUtils.serverLog $ show x + return x + + testList _ x = do + ThriftTestUtils.serverLog $ show x + return x + + testEnum _ x = do + ThriftTestUtils.serverLog $ show x + return x + + testTypedef _ x = do + ThriftTestUtils.serverLog $ show x + return x + + testMapMap _ _ = do + return (Map.fromList [(1, Map.fromList [(2, 2)])]) + + testInsanity _ x = do + return (Map.fromList [(1, Map.fromList [(Types.ONE, x)])]) + + testMulti _ _ _ _ _ _ _ = do + return (Types.Xtruct "" 0 0 0) + + testException _ _ = do + Control.Exception.throw (Types.Xception 1 "bya") + + testMultiException _ _ _ = do + Control.Exception.throw (Types.Xception 1 "xyz") + + testOneway _ i = do + ThriftTestUtils.serverLog $ show i + + +client :: (String, Network.PortID) -> IO () +client addr = do + to <- hOpen addr + let ps = (BinaryProtocol to, BinaryProtocol to) + + v1 <- Client.testString ps "bya" + ThriftTestUtils.clientLog $ show v1 + + v2 <- Client.testByte ps 8 + ThriftTestUtils.clientLog $ show v2 + + v3 <- Client.testByte ps (-8) + ThriftTestUtils.clientLog $ show v3 + + v4 <- Client.testI32 ps 32 + ThriftTestUtils.clientLog $ show v4 + + v5 <- Client.testI32 ps (-32) + ThriftTestUtils.clientLog $ show v5 + + v6 <- Client.testI64 ps 64 + ThriftTestUtils.clientLog $ show v6 + + v7 <- Client.testI64 ps (-64) + ThriftTestUtils.clientLog $ show v7 + + v8 <- Client.testDouble ps 3.14 + ThriftTestUtils.clientLog $ show v8 + + v9 <- Client.testDouble ps (-3.14) + ThriftTestUtils.clientLog $ show v9 + + -- TODO: Client.testBinary ... + + v10 <- Client.testMap ps (Map.fromList [(1,1),(2,2),(3,3)]) + ThriftTestUtils.clientLog $ show v10 + + v11 <- Client.testStringMap ps (Map.fromList [("a","123"),("a b","with spaces "),("same","same"),("0","numeric key")]) + ThriftTestUtils.clientLog $ show v11 + + v12 <- Client.testList ps (Vector.fromList [1,2,3,4,5]) + ThriftTestUtils.clientLog $ show v12 + + v13 <- Client.testSet ps (Set.fromList [1,2,3,4,5]) + ThriftTestUtils.clientLog $ show v13 + + v14 <- Client.testStruct ps (Types.Xtruct "hi" 4 5 0) + ThriftTestUtils.clientLog $ show v14 + + (testException ps "bad") `Control.Exception.catch` testExceptionHandler + + (testMultiException ps "ok") `Control.Exception.catch` testMultiExceptionHandler1 + (testMultiException ps "bad") `Control.Exception.catch` testMultiExceptionHandler2 `Control.Exception.catch` testMultiExceptionHandler3 + + -- ( (Client.testMultiException ps "e" "e2">> ThriftTestUtils.clientLog "bad") `Control.Exception.catch` + + tClose to + where testException ps msg = do + _ <- Client.testException ps "e" + ThriftTestUtils.clientLog msg + return () + + testExceptionHandler (e :: Types.Xception) = do + ThriftTestUtils.clientLog $ show e + + testMultiException ps msg = do + _ <- Client.testMultiException ps "e" "e2" + ThriftTestUtils.clientLog msg + return () + + testMultiExceptionHandler1 (e :: Types.Xception) = do + ThriftTestUtils.clientLog $ show e + + testMultiExceptionHandler2 (e :: Types.Xception2) = do + ThriftTestUtils.clientLog $ show e + + testMultiExceptionHandler3 (_ :: Control.Exception.SomeException) = do + ThriftTestUtils.clientLog "ok" + + +server :: Network.PortNumber -> IO () +server port = do + ThriftTestUtils.serverLog "Ready..." + (runBasicServer TestHandler ThriftTest.process port) + `Control.Exception.catch` + (\(TransportExn s _) -> error $ "FAILURE: " ++ s) + + +main :: IO () +main = ThriftTestUtils.runTest server client diff --git a/src/jaegertracing/thrift/test/hs/run-test.sh b/src/jaegertracing/thrift/test/hs/run-test.sh new file mode 100755 index 000000000..ecafc18b0 --- /dev/null +++ b/src/jaegertracing/thrift/test/hs/run-test.sh @@ -0,0 +1,43 @@ +#!/bin/sh + +# +# 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. +# + +if [ "x" = "x$1" ]; then + printf "run-test.sh needs an argument, the name of the test to run. Try 'ThriftTest' or 'ProtoDebugTest'\n" + exit 2 +fi + +# Check some basics +if [ -z $BASE ]; then + BASE=../.. +fi + +# Figure out what file to run has a server +if [ -z $TEST_SOURCE_FILE ]; then + TEST_SOURCE_FILE=$BASE/test/hs/$1_Main.hs +fi + +if [ ! -e $TEST_SOURCE_FILE ]; then + printf "Missing server code file $TEST_SOURCE_FILE \n" + exit 3 +fi + +printf "Running test... \n" +runhaskell -Wall -XScopedTypeVariables -i$BASE/lib/hs/src -igen-hs $TEST_SOURCE_FILE diff --git a/src/jaegertracing/thrift/test/index.html b/src/jaegertracing/thrift/test/index.html new file mode 100644 index 000000000..3611a9249 --- /dev/null +++ b/src/jaegertracing/thrift/test/index.html @@ -0,0 +1,51 @@ +<!-- + 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. + +--> +<!DOCTYPE HTML> +<html> +<head> +<meta charset="utf-8"> +<title>Apache Thrift - integration test suite</title> +<link rel="stylesheet" type="text/css" href="http://cdn.datatables.net/1.10.4/css/jquery.dataTables.css"> +<script type="text/javascript" charset="utf-8" src="http://code.jquery.com/jquery-2.1.3.min.js"></script> +<script type="text/javascript" charset="utf-8" src="http://cdn.datatables.net/1.10.4/js/jquery.dataTables.js"></script> +<script src="result.js"> +</script> +</head> +<body> +<h2>Apache Thrift - integration test suite: Results</h2> +<table id="test_results" class="display"> + <thead> + <tr> + <th>Server</th> + <th>Client</th> + <th>Protocol</th> + <th>Transport</th> + <th>Result (log)</th> + <th>Expected</th> + </tr> + </thead> +</table> +<h2>Test Information</h2> +<pre id="test_info"></pre> + +<a href="log">browse raw log</a> + +</body> +</html> diff --git a/src/jaegertracing/thrift/test/keys/CA.pem b/src/jaegertracing/thrift/test/keys/CA.pem new file mode 100644 index 000000000..a747b9aca --- /dev/null +++ b/src/jaegertracing/thrift/test/keys/CA.pem @@ -0,0 +1,82 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 16582080088954381212 (0xe61f61fc3b34239c) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, ST=Maryland, L=Forest Hill, O=The Apache Software Foundation, OU=Apache Thrift, CN=localhost/emailAddress=dev@thrift.apache.org + Validity + Not Before: Apr 7 18:58:00 2014 GMT + Not After : Jun 24 18:58:00 2022 GMT + Subject: C=US, ST=Maryland, L=Forest Hill, O=The Apache Software Foundation, OU=Apache Thrift, CN=localhost/emailAddress=dev@thrift.apache.org + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:aa:13:d4:c4:f7:01:17:a7:92:d1:b4:b4:15:0d: + 21:90:19:5e:fc:fb:b6:6d:3f:f2:3f:65:a2:7a:43: + a6:46:95:fc:43:16:f6:63:14:5e:f7:b1:e3:61:02: + f9:4a:95:89:bf:8d:f9:48:1d:82:e7:34:e0:b2:48: + df:08:d9:7c:3a:2f:d3:1b:0b:e8:ef:c2:41:0a:7d: + 0a:38:78:3a:31:66:73:99:8c:d1:79:27:5f:e5:66: + d0:5e:3a:8c:0c:92:18:73:04:c1:f5:45:db:37:e7: + 5f:c7:8c:a3:60:e9:92:a0:d8:29:5d:77:48:fb:1d: + b0:ed:12:2c:4e:2e:02:db:3d:1a:41:71:a6:2b:2e: + b3:4c:6a:c7:f7:1d:a9:7e:c7:cf:db:f2:e7:b6:f3: + 1f:77:1d:24:01:1a:66:66:30:85:30:02:29:c4:bb: + f7:cd:3f:89:4b:1a:5f:f4:91:96:fb:e9:39:f2:46: + 96:12:3d:8a:23:b5:2e:82:9e:41:fe:40:b6:27:b1: + 14:44:5c:96:30:0f:55:e4:bb:ad:8b:8a:99:17:c0: + 29:11:4e:76:79:9d:4b:03:31:7e:85:3c:a8:23:40: + 54:02:58:35:c6:fc:dd:3d:eb:e3:d1:51:00:02:86: + 1a:d7:b0:9f:a0:17:73:6a:5a:d0:e6:b6:b8:55:40: + 5e:27 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 28:F2:FD:30:CD:03:F1:DC:41:1E:C4:93:C6:97:13:CA:D4:FA:60:2A + X509v3 Authority Key Identifier: + keyid:28:F2:FD:30:CD:03:F1:DC:41:1E:C4:93:C6:97:13:CA:D4:FA:60:2A + + X509v3 Basic Constraints: + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 46:15:18:89:b2:57:17:d1:a2:64:c1:9a:73:4f:04:94:76:07: + 1f:29:ba:6f:34:46:c2:36:d5:68:85:f4:15:4c:8e:1a:fe:83: + 79:53:ec:aa:0d:92:60:de:f3:9a:3a:e8:80:66:ac:87:70:89: + 59:f2:ac:9e:b0:28:11:37:7d:78:4e:5e:3f:25:0f:be:09:6f: + 26:2a:3d:66:79:38:28:e5:81:71:71:96:26:4f:db:ec:23:70: + be:37:39:fc:e0:32:0d:80:8f:66:c7:ac:a4:b4:8b:77:40:e2: + 99:44:3a:73:c8:f9:14:cf:1b:32:27:c2:78:db:b0:da:8a:60: + eb:8d:34:7e:7d:3c:03:d4:38:74:f7:17:9e:32:74:9a:e7:37: + 95:d4:71:03:c8:94:ea:09:7b:ad:2d:eb:70:43:f2:32:7e:63: + 01:84:8c:7e:9e:f0:79:7f:ae:e9:cf:f9:be:0e:fe:95:d2:bd: + c8:a7:81:c2:71:d9:c3:50:31:89:6d:fa:ad:a2:ab:00:01:34: + 10:58:ef:96:5a:eb:30:07:a9:8e:84:36:ef:3d:3c:61:46:96: + 6a:e8:09:20:5a:ab:f8:4b:eb:b7:33:61:8e:af:9a:7d:16:b0: + 60:6a:f0:30:e5:b2:8e:e7:80:b4:a1:02:a9:37:fe:5f:b5:ae: + 65:e9:6b:34 +-----BEGIN CERTIFICATE----- +MIIENzCCAx+gAwIBAgIJAOYfYfw7NCOcMA0GCSqGSIb3DQEBBQUAMIGxMQswCQYD +VQQGEwJVUzERMA8GA1UECAwITWFyeWxhbmQxFDASBgNVBAcMC0ZvcmVzdCBIaWxs +MScwJQYDVQQKDB5UaGUgQXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24xFjAUBgNV +BAsMDUFwYWNoZSBUaHJpZnQxEjAQBgNVBAMMCWxvY2FsaG9zdDEkMCIGCSqGSIb3 +DQEJARYVZGV2QHRocmlmdC5hcGFjaGUub3JnMB4XDTE0MDQwNzE4NTgwMFoXDTIy +MDYyNDE4NTgwMFowgbExCzAJBgNVBAYTAlVTMREwDwYDVQQIDAhNYXJ5bGFuZDEU +MBIGA1UEBwwLRm9yZXN0IEhpbGwxJzAlBgNVBAoMHlRoZSBBcGFjaGUgU29mdHdh +cmUgRm91bmRhdGlvbjEWMBQGA1UECwwNQXBhY2hlIFRocmlmdDESMBAGA1UEAwwJ +bG9jYWxob3N0MSQwIgYJKoZIhvcNAQkBFhVkZXZAdGhyaWZ0LmFwYWNoZS5vcmcw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCqE9TE9wEXp5LRtLQVDSGQ +GV78+7ZtP/I/ZaJ6Q6ZGlfxDFvZjFF73seNhAvlKlYm/jflIHYLnNOCySN8I2Xw6 +L9MbC+jvwkEKfQo4eDoxZnOZjNF5J1/lZtBeOowMkhhzBMH1Rds351/HjKNg6ZKg +2Cldd0j7HbDtEixOLgLbPRpBcaYrLrNMasf3Hal+x8/b8ue28x93HSQBGmZmMIUw +AinEu/fNP4lLGl/0kZb76TnyRpYSPYojtS6CnkH+QLYnsRREXJYwD1Xku62LipkX +wCkRTnZ5nUsDMX6FPKgjQFQCWDXG/N096+PRUQAChhrXsJ+gF3NqWtDmtrhVQF4n +AgMBAAGjUDBOMB0GA1UdDgQWBBQo8v0wzQPx3EEexJPGlxPK1PpgKjAfBgNVHSME +GDAWgBQo8v0wzQPx3EEexJPGlxPK1PpgKjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3 +DQEBBQUAA4IBAQBGFRiJslcX0aJkwZpzTwSUdgcfKbpvNEbCNtVohfQVTI4a/oN5 +U+yqDZJg3vOaOuiAZqyHcIlZ8qyesCgRN314Tl4/JQ++CW8mKj1meTgo5YFxcZYm +T9vsI3C+Nzn84DINgI9mx6yktIt3QOKZRDpzyPkUzxsyJ8J427DaimDrjTR+fTwD +1Dh09xeeMnSa5zeV1HEDyJTqCXutLetwQ/IyfmMBhIx+nvB5f67pz/m+Dv6V0r3I +p4HCcdnDUDGJbfqtoqsAATQQWO+WWuswB6mOhDbvPTxhRpZq6AkgWqv4S+u3M2GO +r5p9FrBgavAw5bKO54C0oQKpN/5fta5l6Ws0 +-----END CERTIFICATE----- diff --git a/src/jaegertracing/thrift/test/keys/README.md b/src/jaegertracing/thrift/test/keys/README.md new file mode 100755 index 000000000..010835d35 --- /dev/null +++ b/src/jaegertracing/thrift/test/keys/README.md @@ -0,0 +1,102 @@ +# Test Keys and Certificates +This folder is dedicated to test keys and certificates provided in multiple formats. +Primary use are unit test suites and cross language tests. + + test/keys + +**The files in this directory must never be used on production systems.** + +## SSL Keys and Certificates + + +## create certificates + +we use the following parameters for test key and certificate creation + + C=US, + ST=Maryland, + L=Forest Hill, + O=The Apache Software Foundation, + OU=Apache Thrift, + CN=localhost/emailAddress=dev@thrift.apache.org + +### create self-signed server key and certificate + + openssl req -new -x509 -nodes -days 3000 -out server.crt -keyout server.key + openssl x509 -in server.crt -text > CA.pem + cat server.crt server.key > server.pem + +Export password is "thrift" without the quotes + + openssl pkcs12 -export -clcerts -in server.crt -inkey server.key -out server.p12 + +### create client key and certificate + + openssl genrsa -out client.key + +create a signing request: + + openssl req -new -key client.key -out client.csr + +sign the client certificate with the server.key + + openssl x509 -req -days 3000 -in client.csr -CA CA.pem -CAkey server.key -set_serial 01 -out client.crt + +export certificate in PKCS12 format (Export password is "thrift" without the quotes) + + openssl pkcs12 -export -clcerts -in client.crt -inkey client.key -out client.p12 + +export certificate in PEM format for OpenSSL usage + + openssl pkcs12 -in client.p12 -out client.pem -clcerts + +### create client key and certificate with altnames + +copy openssl.cnf from your system e.g. /etc/ssl/openssl.cnf and append following to the end of [ v3_req ] + + subjectAltName=@alternate_names + + [ alternate_names ] + IP.1=127.0.0.1 + IP.2=::1 + IP.3=::ffff:127.0.0.1 + +create a signing request: + + openssl req -new -key client_v3.key -out client_v3.csr -config openssl.cnf \ + -subj "/C=US/ST=Maryland/L=Forest Hill/O=The Apache Software Foundation/OU=Apache Thrift/CN=localhost" -extensions v3_req + +sign the client certificate with the server.key + + openssl x509 -req -days 3000 -in client_v3.csr -CA CA.pem -CAkey server.key -set_serial 01 -out client_v3.crt -extensions v3_req -extfile openssl.cnf + +## Java key and certificate import +Java Test Environment uses key and trust store password "thrift" without the quotes + +list keystore entries + + keytool -list -storepass thrift -keystore ../../lib/java/test/.keystore + +list truststore entries + + keytool -list -storepass thrift -keystore ../../lib/java/test/.truststore + + +delete an entry + + keytool -delete -storepass thrift -keystore ../../lib/java/test/.truststore -alias ssltest + + +import certificate into truststore + + keytool -importcert -storepass thrift -keystore ../../lib/java/test/.truststore -alias localhost --file server.crt + +import key into keystore + + keytool -importkeystore -storepass thrift -keystore ../../lib/java/test/.keystore -srcstoretype pkcs12 -srckeystore server.p12 + +# Test SSL server and clients + + openssl s_client -connect localhost:9090 + openssl s_server -accept 9090 -www + diff --git a/src/jaegertracing/thrift/test/keys/client.crt b/src/jaegertracing/thrift/test/keys/client.crt new file mode 100644 index 000000000..80a9ad0e2 --- /dev/null +++ b/src/jaegertracing/thrift/test/keys/client.crt @@ -0,0 +1,23 @@ +-----BEGIN CERTIFICATE----- +MIID2DCCAsACAQEwDQYJKoZIhvcNAQELBQAwgbExCzAJBgNVBAYTAlVTMREwDwYD +VQQIDAhNYXJ5bGFuZDEUMBIGA1UEBwwLRm9yZXN0IEhpbGwxJzAlBgNVBAoMHlRo +ZSBBcGFjaGUgU29mdHdhcmUgRm91bmRhdGlvbjEWMBQGA1UECwwNQXBhY2hlIFRo +cmlmdDESMBAGA1UEAwwJbG9jYWxob3N0MSQwIgYJKoZIhvcNAQkBFhVkZXZAdGhy +aWZ0LmFwYWNoZS5vcmcwHhcNMTUxMjIzMDcwNzUwWhcNMjQwMzEwMDcwNzUwWjCB +sTELMAkGA1UEBhMCVVMxETAPBgNVBAgMCE1hcnlsYW5kMRQwEgYDVQQHDAtGb3Jl +c3QgSGlsbDEnMCUGA1UECgweVGhlIEFwYWNoZSBTb2Z0d2FyZSBGb3VuZGF0aW9u +MRYwFAYDVQQLDA1BcGFjaGUgVGhyaWZ0MRIwEAYDVQQDDAlsb2NhbGhvc3QxJDAi +BgkqhkiG9w0BCQEWFWRldkB0aHJpZnQuYXBhY2hlLm9yZzCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBALl/bJhg17Pu1t785JIuwlh7e2E51eoWFvuxMWfH +dsUAVqDaOz99O5sv8pgWKXrkPBttE98T+Mx/Pwz5JHs4Qcre3A5adm6cdab0AKug +eVG1PvHrWzV4aheg4KUfVSiMz8BG2K3Q1VGvZkgMRa/Q409FKjU6Z4D9vBG4Pas3 +PN5FxnAL6P70yWCEr2Vu/tWJlCN+qrRDfSaE2hqmT1irxaoPa61GvuRVsGQ3TeoE +mGfENtvFqC6qQWuSCbG5aI47Rv66pqoWWxqkrcolNc7+vhx6rW+wdFO3IlqIT8IG +sdQVp+Y4ir/dGp2ejzqGZCremPJ1uEKjLMpIukdg25ymHC0CAwEAATANBgkqhkiG +9w0BAQsFAAOCAQEABcRdwc9mdY9zOvTixtThHrciVvqwp6RaiQqMEVomozYilZDR +J90M3H6KnlADJbCv0FXujsaApB53awq5I7sObAYWFhDJZ9LKlw0lDF7KchLXiAlk +XVyvL2nJjuJcxPCFPWktwrw5bTguRCBzG12Hzikn+xs6uPur7VQYM33jbXEda5PS +UEqvAVWaONJCX8MDYOscVoJF0ESyI+fN92ipFaXR7fGajod/rc0AfeN2GVMZETve +21pkUyDwwCGA44uvNUCd1e32NxE3ah9UApCRn5sGJ64R6urpFTXT3IALF3kaOO7U +VsMhFrUiZ7+Bw5nIeiK0QOF6Eipj+bJvrLZpSg== +-----END CERTIFICATE----- diff --git a/src/jaegertracing/thrift/test/keys/client.key b/src/jaegertracing/thrift/test/keys/client.key new file mode 100644 index 000000000..25dcfd713 --- /dev/null +++ b/src/jaegertracing/thrift/test/keys/client.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAuX9smGDXs+7W3vzkki7CWHt7YTnV6hYW+7ExZ8d2xQBWoNo7 +P307my/ymBYpeuQ8G20T3xP4zH8/DPkkezhByt7cDlp2bpx1pvQAq6B5UbU+8etb +NXhqF6DgpR9VKIzPwEbYrdDVUa9mSAxFr9DjT0UqNTpngP28Ebg9qzc83kXGcAvo +/vTJYISvZW7+1YmUI36qtEN9JoTaGqZPWKvFqg9rrUa+5FWwZDdN6gSYZ8Q228Wo +LqpBa5IJsblojjtG/rqmqhZbGqStyiU1zv6+HHqtb7B0U7ciWohPwgax1BWn5jiK +v90anZ6POoZkKt6Y8nW4QqMsyki6R2DbnKYcLQIDAQABAoIBAFotbCmXysUaczLs +VmIKgUhqn0xgxXGLU5kARzhga4jR5UtFTFBNHVEQOitdesTXd7ENkf98whMIOSqh +Y+7TJojtVqVTrQeQ4FFNhZXp6ZCjP/pzpF+WLl1WRF+Bn/Cao9ShnGzDfTC8yEh2 +Ttpt/lNnGGHQBslakLc8jh5SODEFfbugX8SdTCwZYsesKNrXm1pS/5IEunPqaRi0 +II0EcnqHEsgqSo+CljpW7uNxSryA2vSAVdlPej6+9FZjdIHLP5AEKYvk7e9D2CMV +1+grNe/QkQppShizPirbb93tHm86v5bkDFCM9yWrhcMcjvILMXETxIppMGPmacRu +jqtYcAECgYEA8VDzylTz4kS3+D3n3hTgb41XVYa7feUsh99GWRO1wXIFpHjCIRjA +9r/BXW9+Rx3puVPhS8hwLQ4BLdA7lFpV1C8ag0e3+vn6zVirnz1jtI+uHMvStzhO +d6i0nf+w4HYXo7mN6o9ZdHEfC8SFNbymhCoVKh2DILDwb4EX9RXNpy0CgYEAxMj4 ++vrklJ/ilH+Ry1zst4zQYIwmm3QWjarDrypGucHgd4jg5v9A/CJIKUi8x0MjrcuN +wVb7R8XJyYzFQRXIUXR6GnLeeSnfpxzt4YlifCvXxnOi8w4fv7KeGBV5np1Egpo8 +nWNyZFxdvQDuCopr3SUoS9JI8JPwVgA7T+7DaQECgYAGoavhbo45NJw9pS3fC4HT +bvXscsRqREcCAN/FCOagx0piZ7MmB7Ed1s0wjSTSPX8zyZtSYtK6Wj0sDiHlBMqB +Bz5aRzlGG2KKDBrDSIOZ7aziO7Oxt0lovmkgQmuQ743cwPemb4QM0CMDRsZGYMXO +sf1c5+y3lEU3Ozv2T0AUjQKBgBlnzOUyMQKTJcCAO8ViiNkln91nGrDlKug9TKg3 +sAvZYO5tyINqHuyuTFywHFcpbtjIN9PnM+fPPD7+IpVFh6gkfoMdo2VHJ62+iWOd +xg475s6jLT1t7GFmYQzA8QOuUCMAYKT9Ks6UMjHthc3skwJpAqvPSUVuBBBGVWH7 +dFUBAoGBAL67ARLujiAEVNHt5rajixB6ncl7/R+Z2uawI1JfmdnCZonAKVZYHuXU +/4j2+o4QhJIPLtWIoaxAkMigQtAkesqirn3Kk/c7kZRIoN549HTJuwZqYqNp7CB/ +kVi5R335+M9z49i6qA0RZsJGSoSBk7PufG4RmLimcRbGwrY93sPD +-----END RSA PRIVATE KEY----- diff --git a/src/jaegertracing/thrift/test/keys/client.p12 b/src/jaegertracing/thrift/test/keys/client.p12 Binary files differnew file mode 100644 index 000000000..5d2669c12 --- /dev/null +++ b/src/jaegertracing/thrift/test/keys/client.p12 diff --git a/src/jaegertracing/thrift/test/keys/client.pem b/src/jaegertracing/thrift/test/keys/client.pem new file mode 100644 index 000000000..66ef626d9 --- /dev/null +++ b/src/jaegertracing/thrift/test/keys/client.pem @@ -0,0 +1,60 @@ +Bag Attributes + localKeyID: 39 EC 3D 5B 28 17 DA DD 09 7A 62 68 D5 44 1F C7 E2 F8 E0 CD +subject=/C=US/ST=Maryland/L=Forest Hill/O=The Apache Software Foundation/OU=Apache Thrift/CN=localhost/emailAddress=dev@thrift.apache.org +issuer=/C=US/ST=Maryland/L=Forest Hill/O=The Apache Software Foundation/OU=Apache Thrift/CN=localhost/emailAddress=dev@thrift.apache.org +-----BEGIN CERTIFICATE----- +MIID2DCCAsACAQEwDQYJKoZIhvcNAQELBQAwgbExCzAJBgNVBAYTAlVTMREwDwYD +VQQIDAhNYXJ5bGFuZDEUMBIGA1UEBwwLRm9yZXN0IEhpbGwxJzAlBgNVBAoMHlRo +ZSBBcGFjaGUgU29mdHdhcmUgRm91bmRhdGlvbjEWMBQGA1UECwwNQXBhY2hlIFRo +cmlmdDESMBAGA1UEAwwJbG9jYWxob3N0MSQwIgYJKoZIhvcNAQkBFhVkZXZAdGhy +aWZ0LmFwYWNoZS5vcmcwHhcNMTUxMjIzMDcwNzUwWhcNMjQwMzEwMDcwNzUwWjCB +sTELMAkGA1UEBhMCVVMxETAPBgNVBAgMCE1hcnlsYW5kMRQwEgYDVQQHDAtGb3Jl +c3QgSGlsbDEnMCUGA1UECgweVGhlIEFwYWNoZSBTb2Z0d2FyZSBGb3VuZGF0aW9u +MRYwFAYDVQQLDA1BcGFjaGUgVGhyaWZ0MRIwEAYDVQQDDAlsb2NhbGhvc3QxJDAi +BgkqhkiG9w0BCQEWFWRldkB0aHJpZnQuYXBhY2hlLm9yZzCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBALl/bJhg17Pu1t785JIuwlh7e2E51eoWFvuxMWfH +dsUAVqDaOz99O5sv8pgWKXrkPBttE98T+Mx/Pwz5JHs4Qcre3A5adm6cdab0AKug +eVG1PvHrWzV4aheg4KUfVSiMz8BG2K3Q1VGvZkgMRa/Q409FKjU6Z4D9vBG4Pas3 +PN5FxnAL6P70yWCEr2Vu/tWJlCN+qrRDfSaE2hqmT1irxaoPa61GvuRVsGQ3TeoE +mGfENtvFqC6qQWuSCbG5aI47Rv66pqoWWxqkrcolNc7+vhx6rW+wdFO3IlqIT8IG +sdQVp+Y4ir/dGp2ejzqGZCremPJ1uEKjLMpIukdg25ymHC0CAwEAATANBgkqhkiG +9w0BAQsFAAOCAQEABcRdwc9mdY9zOvTixtThHrciVvqwp6RaiQqMEVomozYilZDR +J90M3H6KnlADJbCv0FXujsaApB53awq5I7sObAYWFhDJZ9LKlw0lDF7KchLXiAlk +XVyvL2nJjuJcxPCFPWktwrw5bTguRCBzG12Hzikn+xs6uPur7VQYM33jbXEda5PS +UEqvAVWaONJCX8MDYOscVoJF0ESyI+fN92ipFaXR7fGajod/rc0AfeN2GVMZETve +21pkUyDwwCGA44uvNUCd1e32NxE3ah9UApCRn5sGJ64R6urpFTXT3IALF3kaOO7U +VsMhFrUiZ7+Bw5nIeiK0QOF6Eipj+bJvrLZpSg== +-----END CERTIFICATE----- +Bag Attributes + localKeyID: 39 EC 3D 5B 28 17 DA DD 09 7A 62 68 D5 44 1F C7 E2 F8 E0 CD +Key Attributes: <No Attributes> +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIRKol42bAS3ACAggA +MBQGCCqGSIb3DQMHBAjOulcyHMaWsQSCBMgbeXQ8pIYTENKm08UPeqxkCR2nLxSO +gtRmBxDYjqYv35y4K8KhybBvSBlIPgE5jEWxUCcc1Qvy5ydUQ/X9pmkU8dnmAmDC +o0zwd3lt2eNPy+4WliqFDVmHrLfYQFOoIrHjuzC0lI4C2iPOjxhfa1zFumedgwGS +Gx10X5uEVH5N64fW6B3BvzQM0rn2qr0ONuSRmteRtI8NsznfkgeJ9a4CIAF7E5Z2 +JTGI12edNzzUJ1JhX47ZW4miQwCU5Lcy01UZqTFuUpmK7FUQegtLy3e5eDKq+bIg +ZYq6Hx7lu8hjT5kWZGKy71aYmHKEjI0f727cAbqDTG5uZBHBjwK/3p/znQVQXxBb +1+E9CiKeFdXj2ElptsnDyoTvrSwJ/Jqu1wkXBcH5Embg7aJMod1IOs6OQB1rPDvd +FFa84zbqRNWHSxxxYZxcB8YZinL6/dQJnisKu9LMQd3BBGsGWqH8Zz5tEvXjS5Kv +3g9JRa7QDkSF005x6U+q/678G2MG+W+NWqje3NZx9Psh/Ptm+h+q9n2GSvnibiK5 +mEj9FIwGquGpbZUTK5aXHcKN657dKiICsEJeNar1iZznRmzrMbZJ+DxqJnTw+GAv +7Yb63/CNAtqSxiyNHGZ6NM2ZA9vAKY1HXn0RVC0y1+9FmNpSRwv3u/+ydSCnJonR +GEKjzOqM9Dn7qxd+h4UnnA7hXWxITageB6G6KmfiXRxhiWyqtOICdCneCwpq8UZ4 +e0fm05NRW6M2mqGQHsMNSvTWddwz5b8wgw4eVsb+xQytxVdj9lpBuB9KyjQjxUgU +3oZx4KyWLoEWjkztPAiK3uv5GfotNIMdznRfON1+xm1M5swtn3y3Ru1f6STZC7Sp +qvbG7jPmpB5gLEUri+chw+aKUYbJ0b820Od4FLQYnwLWr46VelYmV44xuR06wgqP +1HchMSsHtS+ZlIiQQU9jhdyTrl86EQHH33dh+Sua8AhfewPRy2VFp3Zk34AUsWcX +EfIYGemhqUD3drG0SMVbFFNOaFGp9e0tQouYOC6/qFBv/SNgQz3mAEkciJYbUuUZ +V4YQPvtdvSrISV0e7bjFgdSEjG7P7F6CFrWTrjUlHZuWj6/rJ3+/1PHeJViyhsrJ +ZYFe14W/48PDxBRl4IEAmxcN1Eb2Ez9eCqv0HW77HviG6zIgnkPrhWHjFGUpxKk4 +jLfuB2Tfq9F7ozv4L2QAn+F/yKt1Rm2Hh5J61eUJtAT60pajg+gJtjmpu5Pr4HDn +b6p3xmYwaL5Let1zCAbbMfdlDK14YjdOdM/BEKpXb9y4EIubX5AMY4ljXeG9gx+T +B1TuQVdJ0P5wIK/D10TQzAWDKam0kv3RXidlzRxpZ3snRnN/L3EVd58Rntj1Oc0y +FiIiSKRszDbPzKDxQE2sNgQcdO24JNLSa/sZYtq2gRgspl/YqIDo4ZYqi9x8F5OS +rdPU5D/H8LWR4vpJLL8DYrHh5qFG3BX2OJIhPRS+48pDYtrRjp7S/1ZU64OJAytk +99hDqSrn1j2a6yFE8L2Ptz+4UCF2OQXEc9Rqqeb8QEUuMSkNH4oQ+A2F6uzLpZi0 +XH64R2niNC56LxV2i+3T5KREFLahyk8epLZlv8YdxYR4Sb7J/5yiooK3g9hmYVKO +zLc= +-----END ENCRYPTED PRIVATE KEY----- diff --git a/src/jaegertracing/thrift/test/keys/client_v3.crt b/src/jaegertracing/thrift/test/keys/client_v3.crt new file mode 100644 index 000000000..a47f156a8 --- /dev/null +++ b/src/jaegertracing/thrift/test/keys/client_v3.crt @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIIECDCCAvCgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBsTELMAkGA1UEBhMCVVMx +ETAPBgNVBAgMCE1hcnlsYW5kMRQwEgYDVQQHDAtGb3Jlc3QgSGlsbDEnMCUGA1UE +CgweVGhlIEFwYWNoZSBTb2Z0d2FyZSBGb3VuZGF0aW9uMRYwFAYDVQQLDA1BcGFj +aGUgVGhyaWZ0MRIwEAYDVQQDDAlsb2NhbGhvc3QxJDAiBgkqhkiG9w0BCQEWFWRl +dkB0aHJpZnQuYXBhY2hlLm9yZzAeFw0xNjAyMjIxMTU4NDFaFw0yNDA1MTAxMTU4 +NDFaMIGLMQswCQYDVQQGEwJVUzERMA8GA1UECAwITWFyeWxhbmQxFDASBgNVBAcM +C0ZvcmVzdCBIaWxsMScwJQYDVQQKDB5UaGUgQXBhY2hlIFNvZnR3YXJlIEZvdW5k +YXRpb24xFjAUBgNVBAsMDUFwYWNoZSBUaHJpZnQxEjAQBgNVBAMMCWxvY2FsaG9z +dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALZ0wiQnXg5QMZZWugd/ +O3woatyHuczJuFSmYiRGWLr3PugB+xtvjy0rTcE2MNx/bdsVxrapCKA+tMFORbEl +sF6jk0H+B7BzGoIwHr6N8GP1VOoA2esrhsNEz22aJI00VaFTFE8G/qgFcihyaVWH +ZsLa3MakOzFUmOBaV2tLBjCjaznqXw3eo3XwUI0BkgS9b9vqXjScmfWXDw5+1is4 +bCgumG2zj9EpLypc9qCGNKFBO2YIg0XsIIJ8RprlianjL6P4MfC6GPOyW4NbZaLd +ESv/bumpVyuV/C/xqkPahvOwBuPE1loxZZPx6Qv368qn7SVNVZOLyX722spooA5G +6csCAwEAAaNPME0wCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAwMwYDVR0RBCwwKocE +fwAAAYcQAAAAAAAAAAAAAAAAAAAAAYcQAAAAAAAAAAAAAP//fwAAATANBgkqhkiG +9w0BAQsFAAOCAQEABUEmeQkG/PS935jMHDrg/5zm4X2xrnFtmTwb0jdxfau6z/7h +AbxD5ioyY7FUTNCzI6SyMo9vJJtYCTCuEGr84JjT2R7232z60k4c1z/av01W3Orv +ExHfAZ8llhkfu0209T5TaIYCB7hDFj5KDbta8c6fEcwtmlHQWj3M31lSNsr4ZtWW +wObhK3sqTsOluHbhKNwlNEat48lbOQUC19I1Wi3dAS6n8lr0lEhfGKvqxu0ViASS +N1nLfdkREGp39bYpKg0n6EFw5bYyV4qE3cnIedFJp7NIOM/6xndJMh/c5l6N2uyZ +upArRQpw/3j+HkL1x9bs+900QK0GI6AxgjbopA== +-----END CERTIFICATE----- diff --git a/src/jaegertracing/thrift/test/keys/client_v3.key b/src/jaegertracing/thrift/test/keys/client_v3.key new file mode 100644 index 000000000..b989f738e --- /dev/null +++ b/src/jaegertracing/thrift/test/keys/client_v3.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAtnTCJCdeDlAxlla6B387fChq3Ie5zMm4VKZiJEZYuvc+6AH7 +G2+PLStNwTYw3H9t2xXGtqkIoD60wU5FsSWwXqOTQf4HsHMagjAevo3wY/VU6gDZ +6yuGw0TPbZokjTRVoVMUTwb+qAVyKHJpVYdmwtrcxqQ7MVSY4FpXa0sGMKNrOepf +Dd6jdfBQjQGSBL1v2+peNJyZ9ZcPDn7WKzhsKC6YbbOP0SkvKlz2oIY0oUE7ZgiD +RewggnxGmuWJqeMvo/gx8LoY87Jbg1tlot0RK/9u6alXK5X8L/GqQ9qG87AG48TW +WjFlk/HpC/fryqftJU1Vk4vJfvbaymigDkbpywIDAQABAoIBAQCJpyUhaaIIYnBG +4D+RkGgsj8Gvh6ah3j53ft/kRj6DMC4BlB0C4fO/PEB5WI0cjfcvpwo4nOapHyX4 +ATmLIMgjXn2m+CSM9wo01mEbmrKWd20M7n96cWhGwg9MvVJ+RdGk2K0lwj02PoWW +Blt576GTuNN/+j++Q/jiqsXxaLTO0/Wj+4b2gQh3n8I0u6bkolDLoERKIdrLGHH+ +FU3sk8bpUhHmeiUTfwwci+juhtOY9e30AEst6xakCHbq1lRRyEYPtWL7oLds6yv0 +UAKP7wS9Yl6dcekXSF1RZpB+fovTW+qPYn8aEuksaMz0wK96FCOjVNGYxMp+Xnvl +sKx63UZBAoGBAOCbCbJtO0HsgIauvCvGZ50aZ1vDvQReCwri4ioutEg4JCAXHEsX ++axz2J5j3UEQhGKr0EX9BG6YbxGW0Mmjf3QxeRB+0WLpMMY2SFt93oC2R1AX9l0I +h50O6tYv5SXm96pKxwRz01d84mCJgwn/G+cZ/EJj4rfZsNbQst6JQFvzAoGBAM/1 +gLVQt5l+IK+6s68EnADI66i7cKe6sj3rFRTahZJxL2vY28J9EB2mF/XEgARSNJQV +X/H9zDrwKm9MX87/eCH2nEbc+5qSGpDPQm482C9DqsMitxCKD8bble1BlpjFb8hr +R0Q3v5q8u5uomLBds5eUBeRKMtu9tOMA9KRSDGjJAoGAF44K2Ux9T2+XFwjSMSEQ +krhHKKeBdijKrayXnWbif0Rr/XWPAQ0VoRFRIWNFu+IYkCSGpiBfy51u4IBZixv7 +bNsXYDR8jwv3koH02qt7nzH+jpbEvoL7fewnkqjZNj1fsds/vebLvjwZnZguRukb +KwRdoTTKfQ92bUDb0VzBhCMCgYB7H+3ObDXoCQctRCsyilYbGNp+EkxG4oC5rD/V +EvRWmfDrt3+VjRpHk5lIB8mLxWgf7O/bhNqwYpWdQ+jN0++6nBo20oudHrff2PaJ +8jhE85lc42bjwfpJUKVZzaVuWicu0GVnfGJTKT8ikBWnBjNYoWlDmrK164H3jQ9L +YtC6EQKBgQCabFXXHx5cIJ2XOm4K/nTOG7ClvD80xapqyGroQd9E/cJUHHPp/wQ4 +c1dMO5EViM7JRsKfxkl9vM5o9IM7swlYh4EMFSLJNjzgOY9XVkvQh0uGbiJOBO4f +inUuWn1YWUj/HFtrT+0No+cYvZVcMKrFAy3K/AwpTbfKCk6roullNA== +-----END RSA PRIVATE KEY----- diff --git a/src/jaegertracing/thrift/test/keys/server.crt b/src/jaegertracing/thrift/test/keys/server.crt new file mode 100644 index 000000000..8a5ef3c3a --- /dev/null +++ b/src/jaegertracing/thrift/test/keys/server.crt @@ -0,0 +1,25 @@ +-----BEGIN CERTIFICATE----- +MIIENzCCAx+gAwIBAgIJAOYfYfw7NCOcMA0GCSqGSIb3DQEBBQUAMIGxMQswCQYD +VQQGEwJVUzERMA8GA1UECAwITWFyeWxhbmQxFDASBgNVBAcMC0ZvcmVzdCBIaWxs +MScwJQYDVQQKDB5UaGUgQXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24xFjAUBgNV +BAsMDUFwYWNoZSBUaHJpZnQxEjAQBgNVBAMMCWxvY2FsaG9zdDEkMCIGCSqGSIb3 +DQEJARYVZGV2QHRocmlmdC5hcGFjaGUub3JnMB4XDTE0MDQwNzE4NTgwMFoXDTIy +MDYyNDE4NTgwMFowgbExCzAJBgNVBAYTAlVTMREwDwYDVQQIDAhNYXJ5bGFuZDEU +MBIGA1UEBwwLRm9yZXN0IEhpbGwxJzAlBgNVBAoMHlRoZSBBcGFjaGUgU29mdHdh +cmUgRm91bmRhdGlvbjEWMBQGA1UECwwNQXBhY2hlIFRocmlmdDESMBAGA1UEAwwJ +bG9jYWxob3N0MSQwIgYJKoZIhvcNAQkBFhVkZXZAdGhyaWZ0LmFwYWNoZS5vcmcw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCqE9TE9wEXp5LRtLQVDSGQ +GV78+7ZtP/I/ZaJ6Q6ZGlfxDFvZjFF73seNhAvlKlYm/jflIHYLnNOCySN8I2Xw6 +L9MbC+jvwkEKfQo4eDoxZnOZjNF5J1/lZtBeOowMkhhzBMH1Rds351/HjKNg6ZKg +2Cldd0j7HbDtEixOLgLbPRpBcaYrLrNMasf3Hal+x8/b8ue28x93HSQBGmZmMIUw +AinEu/fNP4lLGl/0kZb76TnyRpYSPYojtS6CnkH+QLYnsRREXJYwD1Xku62LipkX +wCkRTnZ5nUsDMX6FPKgjQFQCWDXG/N096+PRUQAChhrXsJ+gF3NqWtDmtrhVQF4n +AgMBAAGjUDBOMB0GA1UdDgQWBBQo8v0wzQPx3EEexJPGlxPK1PpgKjAfBgNVHSME +GDAWgBQo8v0wzQPx3EEexJPGlxPK1PpgKjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3 +DQEBBQUAA4IBAQBGFRiJslcX0aJkwZpzTwSUdgcfKbpvNEbCNtVohfQVTI4a/oN5 +U+yqDZJg3vOaOuiAZqyHcIlZ8qyesCgRN314Tl4/JQ++CW8mKj1meTgo5YFxcZYm +T9vsI3C+Nzn84DINgI9mx6yktIt3QOKZRDpzyPkUzxsyJ8J427DaimDrjTR+fTwD +1Dh09xeeMnSa5zeV1HEDyJTqCXutLetwQ/IyfmMBhIx+nvB5f67pz/m+Dv6V0r3I +p4HCcdnDUDGJbfqtoqsAATQQWO+WWuswB6mOhDbvPTxhRpZq6AkgWqv4S+u3M2GO +r5p9FrBgavAw5bKO54C0oQKpN/5fta5l6Ws0 +-----END CERTIFICATE----- diff --git a/src/jaegertracing/thrift/test/keys/server.key b/src/jaegertracing/thrift/test/keys/server.key new file mode 100644 index 000000000..263cfce59 --- /dev/null +++ b/src/jaegertracing/thrift/test/keys/server.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCqE9TE9wEXp5LR +tLQVDSGQGV78+7ZtP/I/ZaJ6Q6ZGlfxDFvZjFF73seNhAvlKlYm/jflIHYLnNOCy +SN8I2Xw6L9MbC+jvwkEKfQo4eDoxZnOZjNF5J1/lZtBeOowMkhhzBMH1Rds351/H +jKNg6ZKg2Cldd0j7HbDtEixOLgLbPRpBcaYrLrNMasf3Hal+x8/b8ue28x93HSQB +GmZmMIUwAinEu/fNP4lLGl/0kZb76TnyRpYSPYojtS6CnkH+QLYnsRREXJYwD1Xk +u62LipkXwCkRTnZ5nUsDMX6FPKgjQFQCWDXG/N096+PRUQAChhrXsJ+gF3NqWtDm +trhVQF4nAgMBAAECggEAW/y52YYW6ypROGbZ94DQpFV0kLO7qT8q0Ksxw5sPNaIt +fEPRIymDa8ikyHWJS5Oxmw84wo5jnJV26jaLmwe2Lupq7Xf1lqej8f5LJtuv7cQR +xfzp1vM65KJFFJHp6WqjGqJ6HSSZOpVDsnQYcXQjQCdpyAmaSWd3p+FqYSZ1mQmD +bFNI7jqpczWSZhTdotQ7p7Hn9TVCehflP3yGIB3bQ+wCcCB85dOBz201L+YgaIck +Sz43A4NvWaQIRLRDw7s9GW4jY5T0Jv282WIeAlVpVxLIwu48r4R4yGTIx9Ydowvq +57+Y5iPPjAXxu0V9t00oS3bYxDaKh2DUfc/5zowq8QKBgQDYNVPXmaG0aIH4vjQ9 +7fRdw/UDkYcQbn6CnglQOu77/S8ogQzpKCVJgJgkZNqOVtQMEPzekGEcLTbje1gU +8Bky2k+PL9UwbFy0emnOVh4rqrNXHsRvJcehNT/PRb5hjF3MUMFV/0iD4b+naFaE +jrSWiZ2ZXj2qfwAK52GFbtOuBQKBgQDJYQuGiY0r22E4waJmCSKczoBT3cwlVzWj +V2ljgA9RHLNTVkvNNYQLGu2qngFrtwpeaSnsMDerVG4wKAQWyCnYzxVrlnC4uDrJ +HXuFEltBWi9Ffbgfsnd3749AT0oBP1NT2tMleguyf5DFgjCR3VRJLdrVaaZ8row/ +LqKcFMqnOwKBgB+OIO99l7E584Y3VG6ZdSneOLtNmRXX2pT7tcZE465ZdHGH7Dd3 +SYHhx9K/+Xn+yDH+pLli/xlarAEldmSP6k2WuTfftlC78AfTOfAId5zN7CDR9791 +Fx67I9X/itq33tS8EIuZl57P6uXm/4GXRloWOa8xpvRkVsBApuYPl8t1AoGATQDS +y2sllDObBXzlgGbV2WgNIgSZ311toTv3jJiXQsjauW8yJRHln+l4H9mzaWDgkiFc +ang1kUoDqF5k0eFQPxtQcYdhKwEnWWfwp33RbzfxA32DPnubuzzbZhfrkHaKgnIW +cyor9uFYlm2l7ODZLfJez2RKyTplXnOSsmQw6akCgYAz3dj9Hskyj+HVJ+ht1OcE +c7ai/ESkSA7Vajp0tjJp0EKjW/zq8DvUSXOtcdnJgkKycFluLwbmnaN4txBds1C1 +Qr8Rt2sUCCBNZe1L6DHe3XBdbkJe9sgZVNTjtUSQrzy8UhvsCqG4YWeCu07Szcbc +rdPUV9/uQkdx8VrShxlD8A== +-----END PRIVATE KEY----- diff --git a/src/jaegertracing/thrift/test/keys/server.p12 b/src/jaegertracing/thrift/test/keys/server.p12 Binary files differnew file mode 100644 index 000000000..f3908a438 --- /dev/null +++ b/src/jaegertracing/thrift/test/keys/server.p12 diff --git a/src/jaegertracing/thrift/test/keys/server.pem b/src/jaegertracing/thrift/test/keys/server.pem new file mode 100644 index 000000000..c45a9f8ac --- /dev/null +++ b/src/jaegertracing/thrift/test/keys/server.pem @@ -0,0 +1,53 @@ +-----BEGIN CERTIFICATE----- +MIIENzCCAx+gAwIBAgIJAOYfYfw7NCOcMA0GCSqGSIb3DQEBBQUAMIGxMQswCQYD +VQQGEwJVUzERMA8GA1UECAwITWFyeWxhbmQxFDASBgNVBAcMC0ZvcmVzdCBIaWxs +MScwJQYDVQQKDB5UaGUgQXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24xFjAUBgNV +BAsMDUFwYWNoZSBUaHJpZnQxEjAQBgNVBAMMCWxvY2FsaG9zdDEkMCIGCSqGSIb3 +DQEJARYVZGV2QHRocmlmdC5hcGFjaGUub3JnMB4XDTE0MDQwNzE4NTgwMFoXDTIy +MDYyNDE4NTgwMFowgbExCzAJBgNVBAYTAlVTMREwDwYDVQQIDAhNYXJ5bGFuZDEU +MBIGA1UEBwwLRm9yZXN0IEhpbGwxJzAlBgNVBAoMHlRoZSBBcGFjaGUgU29mdHdh +cmUgRm91bmRhdGlvbjEWMBQGA1UECwwNQXBhY2hlIFRocmlmdDESMBAGA1UEAwwJ +bG9jYWxob3N0MSQwIgYJKoZIhvcNAQkBFhVkZXZAdGhyaWZ0LmFwYWNoZS5vcmcw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCqE9TE9wEXp5LRtLQVDSGQ +GV78+7ZtP/I/ZaJ6Q6ZGlfxDFvZjFF73seNhAvlKlYm/jflIHYLnNOCySN8I2Xw6 +L9MbC+jvwkEKfQo4eDoxZnOZjNF5J1/lZtBeOowMkhhzBMH1Rds351/HjKNg6ZKg +2Cldd0j7HbDtEixOLgLbPRpBcaYrLrNMasf3Hal+x8/b8ue28x93HSQBGmZmMIUw +AinEu/fNP4lLGl/0kZb76TnyRpYSPYojtS6CnkH+QLYnsRREXJYwD1Xku62LipkX +wCkRTnZ5nUsDMX6FPKgjQFQCWDXG/N096+PRUQAChhrXsJ+gF3NqWtDmtrhVQF4n +AgMBAAGjUDBOMB0GA1UdDgQWBBQo8v0wzQPx3EEexJPGlxPK1PpgKjAfBgNVHSME +GDAWgBQo8v0wzQPx3EEexJPGlxPK1PpgKjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3 +DQEBBQUAA4IBAQBGFRiJslcX0aJkwZpzTwSUdgcfKbpvNEbCNtVohfQVTI4a/oN5 +U+yqDZJg3vOaOuiAZqyHcIlZ8qyesCgRN314Tl4/JQ++CW8mKj1meTgo5YFxcZYm +T9vsI3C+Nzn84DINgI9mx6yktIt3QOKZRDpzyPkUzxsyJ8J427DaimDrjTR+fTwD +1Dh09xeeMnSa5zeV1HEDyJTqCXutLetwQ/IyfmMBhIx+nvB5f67pz/m+Dv6V0r3I +p4HCcdnDUDGJbfqtoqsAATQQWO+WWuswB6mOhDbvPTxhRpZq6AkgWqv4S+u3M2GO +r5p9FrBgavAw5bKO54C0oQKpN/5fta5l6Ws0 +-----END CERTIFICATE----- +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCqE9TE9wEXp5LR +tLQVDSGQGV78+7ZtP/I/ZaJ6Q6ZGlfxDFvZjFF73seNhAvlKlYm/jflIHYLnNOCy +SN8I2Xw6L9MbC+jvwkEKfQo4eDoxZnOZjNF5J1/lZtBeOowMkhhzBMH1Rds351/H +jKNg6ZKg2Cldd0j7HbDtEixOLgLbPRpBcaYrLrNMasf3Hal+x8/b8ue28x93HSQB +GmZmMIUwAinEu/fNP4lLGl/0kZb76TnyRpYSPYojtS6CnkH+QLYnsRREXJYwD1Xk +u62LipkXwCkRTnZ5nUsDMX6FPKgjQFQCWDXG/N096+PRUQAChhrXsJ+gF3NqWtDm +trhVQF4nAgMBAAECggEAW/y52YYW6ypROGbZ94DQpFV0kLO7qT8q0Ksxw5sPNaIt +fEPRIymDa8ikyHWJS5Oxmw84wo5jnJV26jaLmwe2Lupq7Xf1lqej8f5LJtuv7cQR +xfzp1vM65KJFFJHp6WqjGqJ6HSSZOpVDsnQYcXQjQCdpyAmaSWd3p+FqYSZ1mQmD +bFNI7jqpczWSZhTdotQ7p7Hn9TVCehflP3yGIB3bQ+wCcCB85dOBz201L+YgaIck +Sz43A4NvWaQIRLRDw7s9GW4jY5T0Jv282WIeAlVpVxLIwu48r4R4yGTIx9Ydowvq +57+Y5iPPjAXxu0V9t00oS3bYxDaKh2DUfc/5zowq8QKBgQDYNVPXmaG0aIH4vjQ9 +7fRdw/UDkYcQbn6CnglQOu77/S8ogQzpKCVJgJgkZNqOVtQMEPzekGEcLTbje1gU +8Bky2k+PL9UwbFy0emnOVh4rqrNXHsRvJcehNT/PRb5hjF3MUMFV/0iD4b+naFaE +jrSWiZ2ZXj2qfwAK52GFbtOuBQKBgQDJYQuGiY0r22E4waJmCSKczoBT3cwlVzWj +V2ljgA9RHLNTVkvNNYQLGu2qngFrtwpeaSnsMDerVG4wKAQWyCnYzxVrlnC4uDrJ +HXuFEltBWi9Ffbgfsnd3749AT0oBP1NT2tMleguyf5DFgjCR3VRJLdrVaaZ8row/ +LqKcFMqnOwKBgB+OIO99l7E584Y3VG6ZdSneOLtNmRXX2pT7tcZE465ZdHGH7Dd3 +SYHhx9K/+Xn+yDH+pLli/xlarAEldmSP6k2WuTfftlC78AfTOfAId5zN7CDR9791 +Fx67I9X/itq33tS8EIuZl57P6uXm/4GXRloWOa8xpvRkVsBApuYPl8t1AoGATQDS +y2sllDObBXzlgGbV2WgNIgSZ311toTv3jJiXQsjauW8yJRHln+l4H9mzaWDgkiFc +ang1kUoDqF5k0eFQPxtQcYdhKwEnWWfwp33RbzfxA32DPnubuzzbZhfrkHaKgnIW +cyor9uFYlm2l7ODZLfJez2RKyTplXnOSsmQw6akCgYAz3dj9Hskyj+HVJ+ht1OcE +c7ai/ESkSA7Vajp0tjJp0EKjW/zq8DvUSXOtcdnJgkKycFluLwbmnaN4txBds1C1 +Qr8Rt2sUCCBNZe1L6DHe3XBdbkJe9sgZVNTjtUSQrzy8UhvsCqG4YWeCu07Szcbc +rdPUV9/uQkdx8VrShxlD8A== +-----END PRIVATE KEY----- diff --git a/src/jaegertracing/thrift/test/known_failures_Linux.json b/src/jaegertracing/thrift/test/known_failures_Linux.json new file mode 100644 index 000000000..dd6195a37 --- /dev/null +++ b/src/jaegertracing/thrift/test/known_failures_Linux.json @@ -0,0 +1,618 @@ +[ + "c_glib-rs_multi_buffered-ip", + "c_glib-rs_multi_framed-ip", + "c_glib-rs_multic_buffered-ip", + "c_glib-rs_multic_framed-ip", + "cl-c_glib_binary_buffered-ip", + "cl-c_glib_binary_framed-ip", + "cl-c_glib_multi-binary_buffered-ip", + "cl-c_glib_multi-binary_framed-ip", + "cl-c_glib_multi_buffered-ip", + "cl-c_glib_multi_framed-ip", + "cl-go_binary_buffered-ip", + "cl-go_binary_framed-ip", + "cl-rb_binary-accel_buffered-ip", + "cl-rb_binary-accel_framed-ip", + "cl-rb_binary_buffered-ip", + "cl-rb_binary_framed-ip", + "cl-rs_binary_buffered-ip", + "cl-rs_binary_framed-ip", + "cl-rs_multi-binary_buffered-ip", + "cl-rs_multi-binary_framed-ip", + "cl-rs_multi_buffered-ip", + "cl-rs_multi_framed-ip", + "cpp-dart_binary_http-ip", + "cpp-dart_compact_http-ip", + "cpp-dart_json_http-ip", + "cpp-dart_multi-binary_http-ip", + "cpp-dart_multic-compact_http-ip", + "cpp-dart_multij-json_http-ip", + "cpp-go_binary_http-ip", + "cpp-go_binary_http-ip-ssl", + "cpp-go_compact_http-ip", + "cpp-go_compact_http-ip-ssl", + "cpp-go_header_http-ip", + "cpp-go_header_http-ip-ssl", + "cpp-go_json_http-ip", + "cpp-go_json_http-ip-ssl", + "cpp-go_multi-binary_http-ip", + "cpp-go_multi-binary_http-ip-ssl", + "cpp-go_multic-compact_http-ip", + "cpp-go_multic-compact_http-ip-ssl", + "cpp-go_multih-header_http-ip", + "cpp-go_multih-header_http-ip-ssl", + "cpp-go_multij-json_http-ip", + "cpp-go_multij-json_http-ip-ssl", + "cpp-java_binary_http-ip", + "cpp-java_binary_http-ip-ssl", + "cpp-java_compact_http-ip", + "cpp-java_compact_http-ip-ssl", + "cpp-java_json_http-ip", + "cpp-java_json_http-ip-ssl", + "cpp-java_multi-binary_http-ip", + "cpp-java_multi-binary_http-ip-ssl", + "cpp-java_multi_http-ip", + "cpp-java_multi_http-ip-ssl", + "cpp-java_multic-compact_http-ip", + "cpp-java_multic-compact_http-ip-ssl", + "cpp-java_multic_http-ip", + "cpp-java_multic_http-ip-ssl", + "cpp-java_multij-json_http-ip", + "cpp-java_multij-json_http-ip-ssl", + "cpp-java_multij_http-ip", + "cpp-java_multij_http-ip-ssl", + "cpp-nodejs_binary_http-domain", + "cpp-nodejs_binary_http-ip", + "cpp-nodejs_binary_http-ip-ssl", + "cpp-nodejs_compact_http-domain", + "cpp-nodejs_compact_http-ip", + "cpp-nodejs_compact_http-ip-ssl", + "cpp-nodejs_header_http-domain", + "cpp-nodejs_header_http-ip", + "cpp-nodejs_header_http-ip-ssl", + "cpp-nodejs_json_http-domain", + "cpp-nodejs_json_http-ip", + "cpp-nodejs_json_http-ip-ssl", + "cpp-nodejs_multi-binary_http-domain", + "cpp-nodejs_multi-binary_http-ip", + "cpp-nodejs_multi-binary_http-ip-ssl", + "cpp-nodejs_multic-compact_http-domain", + "cpp-nodejs_multic-compact_http-ip", + "cpp-nodejs_multic-compact_http-ip-ssl", + "cpp-nodejs_multih-header_http-domain", + "cpp-nodejs_multih-header_http-ip", + "cpp-nodejs_multih-header_http-ip-ssl", + "cpp-nodejs_multij-json_http-domain", + "cpp-nodejs_multij-json_http-ip", + "cpp-nodejs_multij-json_http-ip-ssl", + "cpp-py3_binary-accel_http-ip", + "cpp-py3_binary-accel_http-ip-ssl", + "cpp-py3_binary_http-ip", + "cpp-py3_binary_http-ip-ssl", + "cpp-py3_compact-accelc_http-ip", + "cpp-py3_compact-accelc_http-ip-ssl", + "cpp-py3_compact_http-ip", + "cpp-py3_compact_http-ip-ssl", + "cpp-py3_header_http-ip", + "cpp-py3_header_http-ip-ssl", + "cpp-py3_json_http-ip", + "cpp-py3_json_http-ip-ssl", + "cpp-py3_multi-accel_http-ip", + "cpp-py3_multi-accel_http-ip-ssl", + "cpp-py3_multi-binary_http-ip", + "cpp-py3_multi-binary_http-ip-ssl", + "cpp-py3_multi-multia_http-ip", + "cpp-py3_multi-multia_http-ip-ssl", + "cpp-py3_multi_http-ip", + "cpp-py3_multi_http-ip-ssl", + "cpp-py3_multic-accelc_http-ip", + "cpp-py3_multic-accelc_http-ip-ssl", + "cpp-py3_multic-compact_http-ip", + "cpp-py3_multic-compact_http-ip-ssl", + "cpp-py3_multic-multiac_http-ip", + "cpp-py3_multic-multiac_http-ip-ssl", + "cpp-py3_multic_http-ip", + "cpp-py3_multic_http-ip-ssl", + "cpp-py3_multih-header_http-ip", + "cpp-py3_multih-header_http-ip-ssl", + "cpp-py3_multij-json_http-ip", + "cpp-py3_multij-json_http-ip-ssl", + "cpp-py3_multij_http-ip", + "cpp-py3_multij_http-ip-ssl", + "cpp-py_binary-accel_http-ip", + "cpp-py_binary-accel_http-ip-ssl", + "cpp-py_binary_http-ip", + "cpp-py_binary_http-ip-ssl", + "cpp-py_compact-accelc_http-ip", + "cpp-py_compact-accelc_http-ip-ssl", + "cpp-py_compact_http-ip", + "cpp-py_compact_http-ip-ssl", + "cpp-py_header_http-ip", + "cpp-py_header_http-ip-ssl", + "cpp-py_json_http-ip", + "cpp-py_json_http-ip-ssl", + "cpp-py_multi-accel_http-ip", + "cpp-py_multi-accel_http-ip-ssl", + "cpp-py_multi-binary_http-ip", + "cpp-py_multi-binary_http-ip-ssl", + "cpp-py_multi-multia_http-ip", + "cpp-py_multi-multia_http-ip-ssl", + "cpp-py_multi_http-ip", + "cpp-py_multi_http-ip-ssl", + "cpp-py_multic-accelc_http-ip", + "cpp-py_multic-accelc_http-ip-ssl", + "cpp-py_multic-compact_http-ip", + "cpp-py_multic-compact_http-ip-ssl", + "cpp-py_multic-multiac_http-ip", + "cpp-py_multic-multiac_http-ip-ssl", + "cpp-py_multic_http-ip", + "cpp-py_multic_http-ip-ssl", + "cpp-py_multih-header_http-ip", + "cpp-py_multih-header_http-ip-ssl", + "cpp-py_multih_http-ip", + "cpp-py_multih_http-ip-ssl", + "cpp-py_multij-json_http-ip", + "cpp-py_multij-json_http-ip-ssl", + "cpp-py_multij_http-ip", + "cpp-py_multij_http-ip-ssl", + "cpp-rs_multi_buffered-ip", + "cpp-rs_multi_framed-ip", + "cpp-rs_multic_buffered-ip", + "cpp-rs_multic_framed-ip", + "csharp-erl_binary_buffered-ip-ssl", + "csharp-erl_binary_framed-ip-ssl", + "csharp-erl_compact_buffered-ip-ssl", + "csharp-erl_compact_framed-ip-ssl", + "csharp-rb_binary-accel_buffered-ip-ssl", + "csharp-rb_binary-accel_framed-ip-ssl", + "csharp-rb_binary_buffered-ip-ssl", + "csharp-rb_binary_framed-ip-ssl", + "csharp-rb_compact_buffered-ip-ssl", + "csharp-rb_compact_framed-ip-ssl", + "csharp-rb_json_buffered-ip-ssl", + "csharp-rb_json_framed-ip-ssl", + "d-cl_binary_buffered-ip", + "d-cl_binary_framed-ip", + "d-cpp_binary_buffered-ip", + "d-cpp_binary_buffered-ip-ssl", + "d-cpp_binary_framed-ip", + "d-cpp_binary_framed-ip-ssl", + "d-cpp_binary_http-ip", + "d-cpp_binary_http-ip-ssl", + "d-cpp_compact_buffered-ip", + "d-cpp_compact_buffered-ip-ssl", + "d-cpp_compact_framed-ip", + "d-cpp_compact_framed-ip-ssl", + "d-cpp_compact_http-ip", + "d-cpp_compact_http-ip-ssl", + "d-cpp_json_buffered-ip", + "d-cpp_json_buffered-ip-ssl", + "d-cpp_json_framed-ip", + "d-cpp_json_framed-ip-ssl", + "d-cpp_json_http-ip", + "d-cpp_json_http-ip-ssl", + "d-d_binary_http-ip", + "d-d_compact_http-ip", + "d-d_json_http-ip", + "d-dart_binary_http-ip", + "d-dart_compact_http-ip", + "d-dart_json_http-ip", + "d-go_binary_http-ip", + "d-go_binary_http-ip-ssl", + "d-go_compact_http-ip", + "d-go_compact_http-ip-ssl", + "d-go_json_http-ip", + "d-go_json_http-ip-ssl", + "d-java_binary_http-ip", + "d-java_binary_http-ip-ssl", + "d-java_compact_http-ip", + "d-java_compact_http-ip-ssl", + "d-java_json_http-ip", + "d-java_json_http-ip-ssl", + "d-js_json_http-ip", + "d-nodejs_binary_buffered-ip", + "d-nodejs_binary_buffered-ip-ssl", + "d-nodejs_binary_framed-ip", + "d-nodejs_binary_framed-ip-ssl", + "d-nodejs_binary_http-ip", + "d-nodejs_binary_http-ip-ssl", + "d-nodejs_compact_buffered-ip", + "d-nodejs_compact_buffered-ip-ssl", + "d-nodejs_compact_framed-ip", + "d-nodejs_compact_framed-ip-ssl", + "d-nodejs_compact_http-ip", + "d-nodejs_compact_http-ip-ssl", + "d-nodejs_json_buffered-ip", + "d-nodejs_json_buffered-ip-ssl", + "d-nodejs_json_framed-ip", + "d-nodejs_json_framed-ip-ssl", + "d-nodejs_json_http-ip", + "d-nodejs_json_http-ip-ssl", + "d-nodets_binary_buffered-ip", + "d-py3_binary-accel_buffered-ip", + "d-py3_binary-accel_buffered-ip-ssl", + "d-py3_binary-accel_framed-ip", + "d-py3_binary-accel_framed-ip-ssl", + "d-py3_binary-accel_http-ip", + "d-py3_binary-accel_http-ip-ssl", + "d-py3_binary_buffered-ip", + "d-py3_binary_buffered-ip-ssl", + "d-py3_binary_framed-ip", + "d-py3_binary_framed-ip-ssl", + "d-py3_binary_http-ip", + "d-py3_binary_http-ip-ssl", + "d-py3_compact-accelc_buffered-ip", + "d-py3_compact-accelc_buffered-ip-ssl", + "d-py3_compact-accelc_framed-ip", + "d-py3_compact-accelc_framed-ip-ssl", + "d-py3_compact-accelc_http-ip", + "d-py3_compact-accelc_http-ip-ssl", + "d-py3_compact_buffered-ip", + "d-py3_compact_buffered-ip-ssl", + "d-py3_compact_framed-ip", + "d-py3_compact_framed-ip-ssl", + "d-py3_compact_http-ip", + "d-py3_compact_http-ip-ssl", + "d-py3_json_buffered-ip", + "d-py3_json_buffered-ip-ssl", + "d-py3_json_framed-ip", + "d-py3_json_framed-ip-ssl", + "d-py3_json_http-ip", + "d-py3_json_http-ip-ssl", + "d-py_binary-accel_buffered-ip", + "d-py_binary-accel_buffered-ip-ssl", + "d-py_binary-accel_framed-ip", + "d-py_binary-accel_framed-ip-ssl", + "d-py_binary-accel_http-ip", + "d-py_binary-accel_http-ip-ssl", + "d-py_binary_buffered-ip", + "d-py_binary_buffered-ip-ssl", + "d-py_binary_framed-ip", + "d-py_binary_framed-ip-ssl", + "d-py_binary_http-ip", + "d-py_binary_http-ip-ssl", + "d-py_compact-accelc_buffered-ip", + "d-py_compact-accelc_buffered-ip-ssl", + "d-py_compact-accelc_framed-ip", + "d-py_compact-accelc_framed-ip-ssl", + "d-py_compact-accelc_http-ip", + "d-py_compact-accelc_http-ip-ssl", + "d-py_compact_buffered-ip", + "d-py_compact_buffered-ip-ssl", + "d-py_compact_framed-ip", + "d-py_compact_framed-ip-ssl", + "d-py_compact_http-ip", + "d-py_compact_http-ip-ssl", + "d-py_json_buffered-ip", + "d-py_json_buffered-ip-ssl", + "d-py_json_framed-ip", + "d-py_json_framed-ip-ssl", + "d-py_json_http-ip", + "d-py_json_http-ip-ssl", + "erl-cpp_binary_buffered-ip", + "erl-cpp_compact_buffered-ip", + "erl-csharp_binary_buffered-ip", + "erl-csharp_binary_buffered-ip-ssl", + "erl-csharp_binary_framed-ip-ssl", + "erl-csharp_compact_buffered-ip", + "erl-csharp_compact_buffered-ip-ssl", + "erl-csharp_compact_framed-ip-ssl", + "erl-nodejs_binary_buffered-ip", + "erl-nodejs_compact_buffered-ip", + "erl-nodets_binary_buffered-ip", + "erl-rb_binary-accel_buffered-ip", + "erl-rb_binary-accel_buffered-ip-ssl", + "erl-rb_binary-accel_framed-ip", + "erl-rb_binary-accel_framed-ip-ssl", + "erl-rb_binary_buffered-ip", + "erl-rb_binary_buffered-ip-ssl", + "erl-rb_binary_framed-ip", + "erl-rb_binary_framed-ip-ssl", + "erl-rb_compact_buffered-ip", + "erl-rb_compact_buffered-ip-ssl", + "erl-rb_compact_framed-ip", + "erl-rb_compact_framed-ip-ssl", + "go-cpp_binary_http-ip", + "go-cpp_binary_http-ip-ssl", + "go-cpp_compact_http-ip", + "go-cpp_compact_http-ip-ssl", + "go-cpp_header_http-ip", + "go-cpp_header_http-ip-ssl", + "go-cpp_json_http-ip", + "go-cpp_json_http-ip-ssl", + "go-d_binary_http-ip", + "go-d_binary_http-ip-ssl", + "go-d_compact_http-ip", + "go-d_compact_http-ip-ssl", + "go-d_json_http-ip", + "go-d_json_http-ip-ssl", + "go-dart_binary_http-ip", + "go-dart_compact_http-ip", + "go-dart_json_http-ip", + "go-java_binary_http-ip", + "go-java_binary_http-ip-ssl", + "go-java_compact_http-ip", + "go-java_compact_http-ip-ssl", + "go-java_json_http-ip", + "go-java_json_http-ip-ssl", + "go-py3_binary-accel_zlib-ip-ssl", + "go-py3_compact-accelc_zlib-ip-ssl", + "go-py_binary-accel_zlib-ip-ssl", + "go-py_compact-accelc_zlib-ip-ssl", + "hs-csharp_binary_buffered-ip", + "hs-csharp_binary_framed-ip", + "hs-csharp_compact_buffered-ip", + "hs-csharp_compact_framed-ip", + "hs-csharp_json_buffered-ip", + "hs-csharp_json_framed-ip", + "nodejs-cpp_binary_http-domain", + "nodejs-cpp_binary_http-ip", + "nodejs-cpp_binary_http-ip-ssl", + "nodejs-cpp_compact_http-domain", + "nodejs-cpp_compact_http-ip", + "nodejs-cpp_compact_http-ip-ssl", + "nodejs-cpp_header_http-domain", + "nodejs-cpp_header_http-ip", + "nodejs-cpp_header_http-ip-ssl", + "nodejs-cpp_json_buffered-ip-ssl", + "nodejs-cpp_json_http-domain", + "nodejs-cpp_json_http-ip", + "nodejs-cpp_json_http-ip-ssl", + "nodejs-d_binary_http-ip", + "nodejs-d_binary_http-ip-ssl", + "nodejs-d_compact_http-ip", + "nodejs-d_compact_http-ip-ssl", + "nodejs-d_json_http-ip", + "nodejs-d_json_http-ip-ssl", + "nodejs-dart_binary_http-ip", + "nodejs-dart_compact_http-ip", + "nodejs-dart_json_http-ip", + "nodejs-go_binary_http-ip", + "nodejs-go_binary_http-ip-ssl", + "nodejs-go_compact_http-ip", + "nodejs-go_compact_http-ip-ssl", + "nodejs-go_header_http-ip", + "nodejs-go_header_http-ip-ssl", + "nodejs-go_json_http-ip", + "nodejs-go_json_http-ip-ssl", + "nodejs-hs_binary_http-ip", + "nodejs-hs_compact_http-ip", + "nodejs-hs_header_http-ip", + "nodejs-hs_json_http-ip", + "nodejs-java_binary_http-ip", + "nodejs-java_binary_http-ip-ssl", + "nodejs-java_compact_http-ip", + "nodejs-java_compact_http-ip-ssl", + "nodejs-java_json_http-ip", + "nodejs-java_json_http-ip-ssl", + "nodejs-js_json_http-ip", + "nodejs-lua_binary_http-ip", + "nodejs-lua_compact_http-ip", + "nodejs-lua_json_http-ip", + "nodejs-py3_binary-accel_http-ip", + "nodejs-py3_binary-accel_http-ip-ssl", + "nodejs-py3_binary_http-ip", + "nodejs-py3_binary_http-ip-ssl", + "nodejs-py3_compact-accelc_http-ip", + "nodejs-py3_compact-accelc_http-ip-ssl", + "nodejs-py3_compact_http-ip", + "nodejs-py3_compact_http-ip-ssl", + "nodejs-py3_header_http-ip", + "nodejs-py3_header_http-ip-ssl", + "nodejs-py3_json_http-ip", + "nodejs-py3_json_http-ip-ssl", + "nodejs-py_binary-accel_http-ip", + "nodejs-py_binary-accel_http-ip-ssl", + "nodejs-py_binary_http-ip", + "nodejs-py_binary_http-ip-ssl", + "nodejs-py_compact-accelc_http-ip", + "nodejs-py_compact-accelc_http-ip-ssl", + "nodejs-py_compact_http-ip", + "nodejs-py_compact_http-ip-ssl", + "nodejs-py_header_http-ip", + "nodejs-py_header_http-ip-ssl", + "nodejs-py_json_http-ip", + "nodejs-py_json_http-ip-ssl", + "perl-rs_multi_buffered-ip", + "perl-rs_multi_framed-ip", + "py-cpp_accel-binary_http-ip", + "py-cpp_accel-binary_http-ip-ssl", + "py-cpp_accel-binary_zlib-ip", + "py-cpp_accel-binary_zlib-ip-ssl", + "py-cpp_accelc-compact_http-ip", + "py-cpp_accelc-compact_http-ip-ssl", + "py-cpp_accelc-compact_zlib-ip", + "py-cpp_accelc-compact_zlib-ip-ssl", + "py-cpp_binary_http-ip", + "py-cpp_binary_http-ip-ssl", + "py-cpp_compact_http-ip", + "py-cpp_compact_http-ip-ssl", + "py-cpp_header_http-ip", + "py-cpp_header_http-ip-ssl", + "py-cpp_json_http-ip", + "py-cpp_json_http-ip-ssl", + "py-cpp_multi-binary_http-ip", + "py-cpp_multi-binary_http-ip-ssl", + "py-cpp_multi_http-ip", + "py-cpp_multi_http-ip-ssl", + "py-cpp_multia-binary_http-ip", + "py-cpp_multia-binary_http-ip-ssl", + "py-cpp_multia-binary_zlib-ip", + "py-cpp_multia-binary_zlib-ip-ssl", + "py-cpp_multia-multi_http-ip", + "py-cpp_multia-multi_http-ip-ssl", + "py-cpp_multia-multi_zlib-ip", + "py-cpp_multia-multi_zlib-ip-ssl", + "py-cpp_multiac-compact_http-ip", + "py-cpp_multiac-compact_http-ip-ssl", + "py-cpp_multiac-compact_zlib-ip", + "py-cpp_multiac-compact_zlib-ip-ssl", + "py-cpp_multiac-multic_http-ip", + "py-cpp_multiac-multic_http-ip-ssl", + "py-cpp_multiac-multic_zlib-ip", + "py-cpp_multiac-multic_zlib-ip-ssl", + "py-cpp_multic-compact_http-ip", + "py-cpp_multic-compact_http-ip-ssl", + "py-cpp_multic_http-ip", + "py-cpp_multic_http-ip-ssl", + "py-cpp_multih-header_http-ip", + "py-cpp_multih-header_http-ip-ssl", + "py-cpp_multih_http-ip", + "py-cpp_multih_http-ip-ssl", + "py-cpp_multij-json_http-ip", + "py-cpp_multij-json_http-ip-ssl", + "py-cpp_multij_http-ip", + "py-cpp_multij_http-ip-ssl", + "py-d_accel-binary_http-ip", + "py-d_accel-binary_http-ip-ssl", + "py-d_accelc-compact_http-ip", + "py-d_accelc-compact_http-ip-ssl", + "py-d_binary_http-ip", + "py-d_binary_http-ip-ssl", + "py-d_compact_http-ip", + "py-d_compact_http-ip-ssl", + "py-d_json_http-ip", + "py-d_json_http-ip-ssl", + "py-dart_accel-binary_http-ip", + "py-dart_accelc-compact_http-ip", + "py-dart_binary_http-ip", + "py-dart_compact_http-ip", + "py-dart_json_http-ip", + "py-hs_accel-binary_http-ip", + "py-hs_accelc-compact_http-ip", + "py-hs_binary_http-ip", + "py-hs_compact_http-ip", + "py-hs_header_http-ip", + "py-hs_json_http-ip", + "py-java_accel-binary_http-ip-ssl", + "py-java_accelc-compact_http-ip-ssl", + "py-java_binary_http-ip-ssl", + "py-java_compact_http-ip-ssl", + "py-java_json_http-ip-ssl", + "py-java_multi-binary_http-ip-ssl", + "py-java_multi_http-ip-ssl", + "py-java_multia-binary_http-ip-ssl", + "py-java_multia-multi_http-ip-ssl", + "py-java_multiac-compact_http-ip-ssl", + "py-java_multiac-multic_http-ip-ssl", + "py-java_multic-compact_http-ip-ssl", + "py-java_multic_http-ip-ssl", + "py-java_multij-json_http-ip-ssl", + "py-java_multij_http-ip-ssl", + "py-lua_accel-binary_http-ip", + "py-lua_accelc-compact_http-ip", + "py-lua_binary_http-ip", + "py-lua_compact_http-ip", + "py-lua_json_http-ip", + "py-rs_multi_buffered-ip", + "py-rs_multi_framed-ip", + "py-rs_multia-multi_buffered-ip", + "py-rs_multia-multi_framed-ip", + "py-rs_multiac-multic_buffered-ip", + "py-rs_multiac-multic_framed-ip", + "py-rs_multic_buffered-ip", + "py-rs_multic_framed-ip", + "py3-cpp_accel-binary_http-ip", + "py3-cpp_accel-binary_http-ip-ssl", + "py3-cpp_accel-binary_zlib-ip", + "py3-cpp_accel-binary_zlib-ip-ssl", + "py3-cpp_accelc-compact_http-ip", + "py3-cpp_accelc-compact_http-ip-ssl", + "py3-cpp_accelc-compact_zlib-ip", + "py3-cpp_accelc-compact_zlib-ip-ssl", + "py3-cpp_binary_http-ip", + "py3-cpp_binary_http-ip-ssl", + "py3-cpp_compact_http-ip", + "py3-cpp_compact_http-ip-ssl", + "py3-cpp_header_http-ip", + "py3-cpp_header_http-ip-ssl", + "py3-cpp_json_http-ip", + "py3-cpp_json_http-ip-ssl", + "py3-cpp_multi-binary_http-ip", + "py3-cpp_multi-binary_http-ip-ssl", + "py3-cpp_multi_http-ip", + "py3-cpp_multi_http-ip-ssl", + "py3-cpp_multia-binary_http-ip", + "py3-cpp_multia-binary_http-ip-ssl", + "py3-cpp_multia-binary_zlib-ip", + "py3-cpp_multia-binary_zlib-ip-ssl", + "py3-cpp_multia-multi_http-ip", + "py3-cpp_multia-multi_http-ip-ssl", + "py3-cpp_multia-multi_zlib-ip", + "py3-cpp_multia-multi_zlib-ip-ssl", + "py3-cpp_multiac-compact_http-ip", + "py3-cpp_multiac-compact_http-ip-ssl", + "py3-cpp_multiac-compact_zlib-ip", + "py3-cpp_multiac-compact_zlib-ip-ssl", + "py3-cpp_multiac-multic_http-ip", + "py3-cpp_multiac-multic_http-ip-ssl", + "py3-cpp_multiac-multic_zlib-ip", + "py3-cpp_multiac-multic_zlib-ip-ssl", + "py3-cpp_multic-compact_http-ip", + "py3-cpp_multic-compact_http-ip-ssl", + "py3-cpp_multic_http-ip", + "py3-cpp_multic_http-ip-ssl", + "py3-cpp_multih-header_http-ip", + "py3-cpp_multih-header_http-ip-ssl", + "py3-cpp_multih_http-ip", + "py3-cpp_multih_http-ip-ssl", + "py3-cpp_multij-json_http-ip", + "py3-cpp_multij-json_http-ip-ssl", + "py3-cpp_multij_http-ip", + "py3-cpp_multij_http-ip-ssl", + "py3-d_accel-binary_http-ip", + "py3-d_accel-binary_http-ip-ssl", + "py3-d_accelc-compact_http-ip", + "py3-d_accelc-compact_http-ip-ssl", + "py3-d_binary_http-ip", + "py3-d_binary_http-ip-ssl", + "py3-d_compact_http-ip", + "py3-d_compact_http-ip-ssl", + "py3-d_json_http-ip", + "py3-d_json_http-ip-ssl", + "py3-dart_accel-binary_http-ip", + "py3-dart_accelc-compact_http-ip", + "py3-dart_binary_http-ip", + "py3-dart_compact_http-ip", + "py3-dart_json_http-ip", + "py3-hs_accel-binary_http-ip", + "py3-hs_accelc-compact_http-ip", + "py3-hs_binary_http-ip", + "py3-hs_compact_http-ip", + "py3-hs_header_http-ip", + "py3-hs_json_http-ip", + "py3-java_accel-binary_http-ip-ssl", + "py3-java_accelc-compact_http-ip-ssl", + "py3-java_binary_http-ip-ssl", + "py3-java_compact_http-ip-ssl", + "py3-java_json_http-ip-ssl", + "py3-java_multi-binary_http-ip-ssl", + "py3-java_multi_http-ip-ssl", + "py3-java_multia-binary_http-ip-ssl", + "py3-java_multia-multi_http-ip-ssl", + "py3-java_multiac-compact_http-ip-ssl", + "py3-java_multiac-multic_http-ip-ssl", + "py3-java_multic-compact_http-ip-ssl", + "py3-java_multic_http-ip-ssl", + "py3-java_multij-json_http-ip-ssl", + "py3-java_multij_http-ip-ssl", + "py3-lua_accel-binary_http-ip", + "py3-lua_accelc-compact_http-ip", + "py3-lua_binary_http-ip", + "py3-lua_compact_http-ip", + "py3-lua_json_http-ip", + "py3-rs_multi_buffered-ip", + "py3-rs_multi_framed-ip", + "py3-rs_multia-multi_buffered-ip", + "py3-rs_multia-multi_framed-ip", + "py3-rs_multiac-multic_buffered-ip", + "py3-rs_multiac-multic_framed-ip", + "py3-rs_multic_buffered-ip", + "py3-rs_multic_framed-ip", + "rb-cpp_json_buffered-domain", + "rb-cpp_json_buffered-ip", + "rb-cpp_json_buffered-ip-ssl", + "rb-cpp_json_framed-domain", + "rb-cpp_json_framed-ip", + "rb-cpp_json_framed-ip-ssl" +]
\ No newline at end of file diff --git a/src/jaegertracing/thrift/test/lua/Makefile.am b/src/jaegertracing/thrift/test/lua/Makefile.am new file mode 100644 index 000000000..b2683e1b9 --- /dev/null +++ b/src/jaegertracing/thrift/test/lua/Makefile.am @@ -0,0 +1,34 @@ +# +# 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. +# + +THRIFT = $(top_builddir)/compiler/cpp/thrift + +# Remove "MapType =" line to ignore some map bug for now +stubs: ../ThriftTest.thrift $(THRIFT) + $(THRIFT) --gen lua $< + $(SED) -i.bak 's/MapType =//g' gen-lua/ThriftTest_ttypes.lua + $(RM) gen-lua/ThriftTest_ttypes.lua.bak + +precross: stubs + +clean-local: + $(RM) -r gen-lua/ + +dist-hook: + $(RM) -r $(distdir)/gen-lua/ diff --git a/src/jaegertracing/thrift/test/lua/test_basic_client.lua b/src/jaegertracing/thrift/test/lua/test_basic_client.lua new file mode 100644 index 000000000..77d8d078a --- /dev/null +++ b/src/jaegertracing/thrift/test/lua/test_basic_client.lua @@ -0,0 +1,179 @@ +-- 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. + + +require('TSocket') +require('TBufferedTransport') +require('TFramedTransport') +require('THttpTransport') +require('TCompactProtocol') +require('TJsonProtocol') +require('TBinaryProtocol') +require('ThriftTest_ThriftTest') +require('liblualongnumber') + +local client + +function teardown() + if client then + -- close the connection + client:close() + end +end + +function parseArgs(rawArgs) + local opt = { + protocol='binary', + transport='buffered', + port='9090', + } + for i, str in pairs(rawArgs) do + if i > 0 then + k, v = string.match(str, '--(%w+)=(%w+)') + assert(opt[k] ~= nil, 'Unknown argument') + opt[k] = v + end + end + return opt +end + +function assertEqual(val1, val2, msg) + assert(val1 == val2, msg) +end + +function testBasicClient(rawArgs) + local opt = parseArgs(rawArgs) + local socket = TSocket:new{ + port = tonumber(opt.port) + } + assert(socket, 'Failed to create client socket') + socket:setTimeout(5000) + + local transports = { + buffered = TBufferedTransport, + framed = TFramedTransport, + http = THttpTransport, + } + assert(transports[opt.transport] ~= nil) + local transport = transports[opt.transport]:new{ + trans = socket, + isServer = false + } + + local protocols = { + binary = TBinaryProtocol, + compact = TCompactProtocol, + json = TJSONProtocol, + } + assert(protocols[opt.protocol] ~= nil) + local protocol = protocols[opt.protocol]:new{ + trans = transport + } + assert(protocol, 'Failed to create binary protocol') + + client = ThriftTestClient:new{ + protocol = protocol + } + assert(client, 'Failed to create client') + + -- Open the transport + local status, _ = pcall(transport.open, transport) + assert(status, 'Failed to connect to server') + + -- String + assertEqual(client:testString('lala'), 'lala', 'Failed testString') + assertEqual(client:testString('wahoo'), 'wahoo', 'Failed testString') + + -- Bool + assertEqual(client:testBool(true), true, 'Failed testBool true') + assertEqual(client:testBool(false), false, 'Failed testBool false') + + -- Byte + assertEqual(client:testByte(0x01), 1, 'Failed testByte 1') + assertEqual(client:testByte(0x40), 64, 'Failed testByte 2') + assertEqual(client:testByte(0x7f), 127, 'Failed testByte 3') + assertEqual(client:testByte(0x80), -128, 'Failed testByte 4') + assertEqual(client:testByte(0xbf), -65, 'Failed testByte 5') + assertEqual(client:testByte(0xff), -1, 'Failed testByte 6') + assertEqual(client:testByte(128), -128, 'Failed testByte 7') + assertEqual(client:testByte(255), -1, 'Failed testByte 8') + + -- I32 + assertEqual(client:testI32(0x00000001), 1, 'Failed testI32 1') + assertEqual(client:testI32(0x40000000), 1073741824, 'Failed testI32 2') + assertEqual(client:testI32(0x7fffffff), 2147483647, 'Failed testI32 3') + assertEqual(client:testI32(0x80000000), -2147483648, 'Failed testI32 4') + assertEqual(client:testI32(0xbfffffff), -1073741825, 'Failed testI32 5') + assertEqual(client:testI32(0xffffffff), -1, 'Failed testI32 6') + assertEqual(client:testI32(2147483648), -2147483648, 'Failed testI32 7') + assertEqual(client:testI32(4294967295), -1, 'Failed testI32 8') + + -- I64 (lua only supports 16 decimal precision so larger numbers are + -- initialized by their string value) + local long = liblualongnumber.new + assertEqual(client:testI64(long(0x0000000000000001)), + long(1), + 'Failed testI64 1') + assertEqual(client:testI64(long(0x4000000000000000)), + long(4611686018427387904), + 'Failed testI64 2') + assertEqual(client:testI64(long('0x7fffffffffffffff')), + long('9223372036854775807'), + 'Failed testI64 3') + assertEqual(client:testI64(long(0x8000000000000000)), + long(-9223372036854775808), + 'Failed testI64 4') + assertEqual(client:testI64(long('0xbfffffffffffffff')), + long('-4611686018427387905'), + 'Failed testI64 5') + assertEqual(client:testI64(long('0xffffffffffffffff')), + long(-1), + 'Failed testI64 6') + + -- Double + assertEqual( + client:testDouble(1.23456789), 1.23456789, 'Failed testDouble 1') + assertEqual( + client:testDouble(0.123456789), 0.123456789, 'Failed testDouble 2') + assertEqual( + client:testDouble(0.123456789), 0.123456789, 'Failed testDouble 3') + + -- TODO testBinary() ... + + -- Accuracy of 16 decimal digits (rounds) + local a, b = 1.12345678906666663, 1.12345678906666661 + assertEqual(a, b) + assertEqual(client:testDouble(a), b, 'Failed testDouble 5') + + -- Struct + local o = Xtruct:new{ + string_thing = 'Zero', + byte_thing = 1, + i32_thing = -3, + i64_thing = long(-5) + } + local r = client:testStruct(o) + assertEqual(o.string_thing, r.string_thing, 'Failed testStruct 1') + assertEqual(o.byte_thing, r.byte_thing, 'Failed testStruct 2') + assertEqual(o.i32_thing, r.i32_thing, 'Failed testStruct 3') + assertEqual(o.i64_thing, r.i64_thing, 'Failed testStruct 4') + + -- TODO add list map set exception etc etc +end + +testBasicClient(arg) +teardown() diff --git a/src/jaegertracing/thrift/test/lua/test_basic_server.lua b/src/jaegertracing/thrift/test/lua/test_basic_server.lua new file mode 100644 index 000000000..acd2d79b8 --- /dev/null +++ b/src/jaegertracing/thrift/test/lua/test_basic_server.lua @@ -0,0 +1,142 @@ +-- 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. + +require('ThriftTest_ThriftTest') +require('TSocket') +require('TBufferedTransport') +require('TFramedTransport') +require('THttpTransport') +require('TCompactProtocol') +require('TJsonProtocol') +require('TBinaryProtocol') +require('TServer') +require('liblualongnumber') + +-------------------------------------------------------------------------------- +-- Handler +TestHandler = ThriftTestIface:new{} + +-- Stops the server +function TestHandler:testVoid() +end + +function TestHandler:testString(str) + return str +end + +function TestHandler:testBool(bool) + return bool +end + +function TestHandler:testByte(byte) + return byte +end + +function TestHandler:testI32(i32) + return i32 +end + +function TestHandler:testI64(i64) + return i64 +end + +function TestHandler:testDouble(d) + return d +end + +function TestHandler:testBinary(by) + return by +end + +function TestHandler:testStruct(thing) + return thing +end + +-------------------------------------------------------------------------------- +-- Test +local server + +function teardown() + if server then + server:close() + end +end + +function parseArgs(rawArgs) + local opt = { + protocol='binary', + transport='buffered', + port='9090', + } + for i, str in pairs(rawArgs) do + if i > 0 then + k, v = string.match(str, '--(%w+)=(%w+)') + assert(opt[k] ~= nil, 'Unknown argument') + opt[k] = v + end + end + return opt +end + +function testBasicServer(rawArgs) + local opt = parseArgs(rawArgs) + -- Handler & Processor + local handler = TestHandler:new{} + assert(handler, 'Failed to create handler') + local processor = ThriftTestProcessor:new{ + handler = handler + } + assert(processor, 'Failed to create processor') + + -- Server Socket + local socket = TServerSocket:new{ + port = opt.port + } + assert(socket, 'Failed to create server socket') + + -- Transport & Factory + local transports = { + buffered = TBufferedTransportFactory, + framed = TFramedTransportFactory, + http = THttpTransportFactory, + } + assert(transports[opt.transport], 'Failed to create framed transport factory') + local trans_factory = transports[opt.transport]:new{} + local protocols = { + binary = TBinaryProtocolFactory, + compact = TCompactProtocolFactory, + json = TJSONProtocolFactory, + } + local prot_factory = protocols[opt.protocol]:new{} + assert(prot_factory, 'Failed to create binary protocol factory') + + -- Simple Server + server = TSimpleServer:new{ + processor = processor, + serverTransport = socket, + transportFactory = trans_factory, + protocolFactory = prot_factory + } + assert(server, 'Failed to create server') + + -- Serve + server:serve() + server = nil +end + +testBasicServer(arg) +teardown() diff --git a/src/jaegertracing/thrift/test/netcore/Client/.gitignore b/src/jaegertracing/thrift/test/netcore/Client/.gitignore new file mode 100644 index 000000000..67d55106a --- /dev/null +++ b/src/jaegertracing/thrift/test/netcore/Client/.gitignore @@ -0,0 +1,2 @@ +# ignore for autogenerated files +/ThriftTest diff --git a/src/jaegertracing/thrift/test/netcore/Client/Client.csproj b/src/jaegertracing/thrift/test/netcore/Client/Client.csproj new file mode 100644 index 000000000..f16af390a --- /dev/null +++ b/src/jaegertracing/thrift/test/netcore/Client/Client.csproj @@ -0,0 +1,31 @@ +<Project Sdk="Microsoft.NET.Sdk"> + <PropertyGroup> + <TargetFramework>netcoreapp2.0</TargetFramework> + <AssemblyName>Client</AssemblyName> + <PackageId>Client</PackageId> + <OutputType>Exe</OutputType> + <GenerateAssemblyTitleAttribute>false</GenerateAssemblyTitleAttribute> + <GenerateAssemblyDescriptionAttribute>false</GenerateAssemblyDescriptionAttribute> + <GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> + <GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> + <GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> + <GenerateAssemblyCopyrightAttribute>false</GenerateAssemblyCopyrightAttribute> + </PropertyGroup> + <ItemGroup> + <PackageReference Include="System.Net.Http.WinHttpHandler" Version="[4.4,)" /> + <PackageReference Include="System.Runtime.Serialization.Primitives" Version="[4.3,)" /> + <PackageReference Include="System.ServiceModel.Primitives" Version="[4.4,)" /> + <PackageReference Include="System.Threading" Version="[4.3,)" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\..\..\lib\netcore\Thrift\Thrift.csproj" /> + </ItemGroup> + <Target Name="PreBuild" BeforeTargets="_GenerateRestoreProjectSpec;Restore;Compile"> + <Exec Condition="'$(OS)' == 'Windows_NT'" Command="where thrift" ConsoleToMSBuild="true"> + <Output TaskParameter="ConsoleOutput" PropertyName="PathToThrift" /> + </Exec> + <Exec Condition="Exists('$(PathToThrift)')" Command=""$(PathToThrift)" -out $(ProjectDir) -gen netcore:wcf,union,serial,hashcode -r ./../../ThriftTest.thrift" /> + <Exec Condition="Exists('thrift')" Command="thrift -out $(ProjectDir) -gen netcore:wcf,union,serial,hashcode -r ./../../ThriftTest.thrift" /> + <Exec Condition="Exists('$(ProjectDir)/../../../compiler/cpp/thrift')" Command="$(ProjectDir)/../../../compiler/cpp/thrift -out $(ProjectDir) -gen netcore:wcf,union,serial,hashcode -r ./../../ThriftTest.thrift" /> + </Target> +</Project> diff --git a/src/jaegertracing/thrift/test/netcore/Client/Program.cs b/src/jaegertracing/thrift/test/netcore/Client/Program.cs new file mode 100644 index 000000000..72139d9de --- /dev/null +++ b/src/jaegertracing/thrift/test/netcore/Client/Program.cs @@ -0,0 +1,72 @@ +// 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. + +using System; +using System.Collections.Generic; +using ThriftTest; + +namespace Client +{ + public class Program + { + public static int Main(string[] args) + { + try + { + Console.SetBufferSize(Console.BufferWidth, 4096); + } + catch (Exception) + { + Console.WriteLine("Failed to grow scroll-back buffer"); + } + + // split mode and options + var subArgs = new List<string>(args); + var firstArg = string.Empty; + if (subArgs.Count > 0) + { + firstArg = subArgs[0]; + subArgs.RemoveAt(0); + } + + // run whatever mode is choosen + switch(firstArg) + { + case "client": + return TestClient.Execute(subArgs); + case "--help": + PrintHelp(); + return 0; + default: + PrintHelp(); + return -1; + } + } + + private static void PrintHelp() + { + Console.WriteLine("Usage:"); + Console.WriteLine(" Client client [options]'"); + Console.WriteLine(" Client --help"); + Console.WriteLine(""); + + TestClient.PrintOptionsHelp(); + } + } +} + + diff --git a/src/jaegertracing/thrift/test/netcore/Client/Properties/AssemblyInfo.cs b/src/jaegertracing/thrift/test/netcore/Client/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..157152b4d --- /dev/null +++ b/src/jaegertracing/thrift/test/netcore/Client/Properties/AssemblyInfo.cs @@ -0,0 +1,43 @@ +// 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. +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +[assembly: AssemblyTitle("Client")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("The Apache Software Foundation")] +[assembly: AssemblyProduct("Thrift")] +[assembly: AssemblyCopyright("The Apache Software Foundation")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. + +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM + +[assembly: Guid("B0C13DA0-3117-4844-8AE8-B1775E46223D")] + diff --git a/src/jaegertracing/thrift/test/netcore/Client/TestClient.cs b/src/jaegertracing/thrift/test/netcore/Client/TestClient.cs new file mode 100644 index 000000000..8be198c69 --- /dev/null +++ b/src/jaegertracing/thrift/test/netcore/Client/TestClient.cs @@ -0,0 +1,943 @@ +// 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. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Net; +using System.Reflection; +using System.Security.Authentication; +using System.Security.Cryptography.X509Certificates; +using System.ServiceModel; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Thrift.Collections; +using Thrift.Protocols; +using Thrift.Transports; +using Thrift.Transports.Client; + +namespace ThriftTest +{ + public class TestClient + { + private class TestParams + { + public int numIterations = 1; + public IPAddress host = IPAddress.Any; + public int port = 9090; + public int numThreads = 1; + public string url; + public string pipe; + public bool buffered; + public bool framed; + public string protocol; + public bool encrypted = false; + + internal void Parse( List<string> args) + { + for (var i = 0; i < args.Count; ++i) + { + if (args[i] == "-u") + { + url = args[++i]; + } + else if (args[i] == "-n") + { + numIterations = Convert.ToInt32(args[++i]); + } + else if (args[i].StartsWith("--pipe=")) + { + pipe = args[i].Substring(args[i].IndexOf("=") + 1); + Console.WriteLine("Using named pipes transport"); + } + else if (args[i].StartsWith("--host=")) + { + // check there for ipaddress + host = new IPAddress(Encoding.Unicode.GetBytes(args[i].Substring(args[i].IndexOf("=") + 1))); + } + else if (args[i].StartsWith("--port=")) + { + port = int.Parse(args[i].Substring(args[i].IndexOf("=") + 1)); + } + else if (args[i] == "-b" || args[i] == "--buffered" || args[i] == "--transport=buffered") + { + buffered = true; + Console.WriteLine("Using buffered sockets"); + } + else if (args[i] == "-f" || args[i] == "--framed" || args[i] == "--transport=framed") + { + framed = true; + Console.WriteLine("Using framed transport"); + } + else if (args[i] == "-t") + { + numThreads = Convert.ToInt32(args[++i]); + } + else if (args[i] == "--binary" || args[i] == "--protocol=binary") + { + protocol = "binary"; + Console.WriteLine("Using binary protocol"); + } + else if (args[i] == "--compact" || args[i] == "--protocol=compact") + { + protocol = "compact"; + Console.WriteLine("Using compact protocol"); + } + else if (args[i] == "--json" || args[i] == "--protocol=json") + { + protocol = "json"; + Console.WriteLine("Using JSON protocol"); + } + else if (args[i] == "--ssl") + { + encrypted = true; + Console.WriteLine("Using encrypted transport"); + } + else + { + //throw new ArgumentException(args[i]); + } + } + } + + private static X509Certificate2 GetClientCert() + { + var clientCertName = "client.p12"; + var possiblePaths = new List<string> + { + "../../../keys/", + "../../keys/", + "../keys/", + "keys/", + }; + + string existingPath = null; + foreach (var possiblePath in possiblePaths) + { + var path = Path.GetFullPath(possiblePath + clientCertName); + if (File.Exists(path)) + { + existingPath = path; + break; + } + } + + if (string.IsNullOrEmpty(existingPath)) + { + throw new FileNotFoundException($"Cannot find file: {clientCertName}"); + } + + var cert = new X509Certificate2(existingPath, "thrift"); + + return cert; + } + + public TClientTransport CreateTransport() + { + if (url == null) + { + // endpoint transport + TClientTransport trans = null; + + if (pipe != null) + { + trans = new TNamedPipeClientTransport(pipe); + } + else + { + if (encrypted) + { + var cert = GetClientCert(); + + if (cert == null || !cert.HasPrivateKey) + { + throw new InvalidOperationException("Certificate doesn't contain private key"); + } + + trans = new TTlsSocketClientTransport(host, port, 0, cert, + (sender, certificate, chain, errors) => true, + null, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12); + } + else + { + trans = new TSocketClientTransport(host, port); + } + } + + // layered transport + if (buffered) + { + trans = new TBufferedClientTransport(trans); + } + + if (framed) + { + trans = new TFramedClientTransport(trans); + } + + return trans; + } + + return new THttpClientTransport(new Uri(url), null); + } + + public TProtocol CreateProtocol(TClientTransport transport) + { + if (protocol == "compact") + { + return new TCompactProtocol(transport); + } + + if (protocol == "json") + { + return new TJsonProtocol(transport); + } + + return new TBinaryProtocol(transport); + } + } + + + private const int ErrorBaseTypes = 1; + private const int ErrorStructs = 2; + private const int ErrorContainers = 4; + private const int ErrorExceptions = 8; + private const int ErrorUnknown = 64; + + private class ClientTest + { + private readonly TClientTransport transport; + private readonly ThriftTest.Client client; + private readonly int numIterations; + private bool done; + + public int ReturnCode { get; set; } + + public ClientTest(TestParams param) + { + transport = param.CreateTransport(); + client = new ThriftTest.Client(param.CreateProtocol(transport)); + numIterations = param.numIterations; + } + + public void Execute() + { + var token = CancellationToken.None; + + if (done) + { + Console.WriteLine("Execute called more than once"); + throw new InvalidOperationException(); + } + + for (var i = 0; i < numIterations; i++) + { + try + { + if (!transport.IsOpen) + { + transport.OpenAsync(token).GetAwaiter().GetResult(); + } + } + catch (TTransportException ex) + { + Console.WriteLine("*** FAILED ***"); + Console.WriteLine("Connect failed: " + ex.Message); + ReturnCode |= ErrorUnknown; + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + continue; + } + catch (Exception ex) + { + Console.WriteLine("*** FAILED ***"); + Console.WriteLine("Connect failed: " + ex.Message); + ReturnCode |= ErrorUnknown; + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + continue; + } + + try + { + ReturnCode |= ExecuteClientTestAsync(client).GetAwaiter().GetResult(); ; + } + catch (Exception ex) + { + Console.WriteLine("*** FAILED ***"); + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + ReturnCode |= ErrorUnknown; + } + } + try + { + transport.Close(); + } + catch (Exception ex) + { + Console.WriteLine("Error while closing transport"); + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + } + done = true; + } + } + + internal static void PrintOptionsHelp() + { + Console.WriteLine("Client options:"); + Console.WriteLine(" -u <URL>"); + Console.WriteLine(" -t <# of threads to run> default = 1"); + Console.WriteLine(" -n <# of iterations> per thread"); + Console.WriteLine(" --pipe=<pipe name>"); + Console.WriteLine(" --host=<IP address>"); + Console.WriteLine(" --port=<port number>"); + Console.WriteLine(" --transport=<transport name> one of buffered,framed (defaults to none)"); + Console.WriteLine(" --protocol=<protocol name> one of compact,json (defaults to binary)"); + Console.WriteLine(" --ssl"); + Console.WriteLine(); + } + + public static int Execute(List<string> args) + { + try + { + var param = new TestParams(); + + try + { + param.Parse(args); + } + catch (Exception ex) + { + Console.WriteLine("*** FAILED ***"); + Console.WriteLine("Error while parsing arguments"); + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + return ErrorUnknown; + } + + var tests = Enumerable.Range(0, param.numThreads).Select(_ => new ClientTest(param)).ToArray(); + + //issue tests on separate threads simultaneously + var threads = tests.Select(test => new Task(test.Execute)).ToArray(); + var start = DateTime.Now; + foreach (var t in threads) + { + t.Start(); + } + + Task.WaitAll(threads); + + Console.WriteLine("Total time: " + (DateTime.Now - start)); + Console.WriteLine(); + return tests.Select(t => t.ReturnCode).Aggregate((r1, r2) => r1 | r2); + } + catch (Exception outerEx) + { + Console.WriteLine("*** FAILED ***"); + Console.WriteLine("Unexpected error"); + Console.WriteLine(outerEx.Message + " ST: " + outerEx.StackTrace); + return ErrorUnknown; + } + } + + public static string BytesToHex(byte[] data) + { + return BitConverter.ToString(data).Replace("-", string.Empty); + } + + public static byte[] PrepareTestData(bool randomDist) + { + var retval = new byte[0x100]; + var initLen = Math.Min(0x100, retval.Length); + + // linear distribution, unless random is requested + if (!randomDist) + { + for (var i = 0; i < initLen; ++i) + { + retval[i] = (byte)i; + } + return retval; + } + + // random distribution + for (var i = 0; i < initLen; ++i) + { + retval[i] = (byte)0; + } + var rnd = new Random(); + for (var i = 1; i < initLen; ++i) + { + while (true) + { + var nextPos = rnd.Next() % initLen; + if (retval[nextPos] == 0) + { + retval[nextPos] = (byte)i; + break; + } + } + } + return retval; + } + + public static async Task<int> ExecuteClientTestAsync(ThriftTest.Client client) + { + var token = CancellationToken.None; + var returnCode = 0; + + Console.Write("testVoid()"); + await client.testVoidAsync(token); + Console.WriteLine(" = void"); + + Console.Write("testString(\"Test\")"); + var s = await client.testStringAsync("Test", token); + Console.WriteLine(" = \"" + s + "\""); + if ("Test" != s) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + + Console.Write("testBool(true)"); + var t = await client.testBoolAsync((bool)true, token); + Console.WriteLine(" = " + t); + if (!t) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + Console.Write("testBool(false)"); + var f = await client.testBoolAsync((bool)false, token); + Console.WriteLine(" = " + f); + if (f) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + + Console.Write("testByte(1)"); + var i8 = await client.testByteAsync((sbyte)1, token); + Console.WriteLine(" = " + i8); + if (1 != i8) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + + Console.Write("testI32(-1)"); + var i32 = await client.testI32Async(-1, token); + Console.WriteLine(" = " + i32); + if (-1 != i32) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + + Console.Write("testI64(-34359738368)"); + var i64 = await client.testI64Async(-34359738368, token); + Console.WriteLine(" = " + i64); + if (-34359738368 != i64) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + + // TODO: Validate received message + Console.Write("testDouble(5.325098235)"); + var dub = await client.testDoubleAsync(5.325098235, token); + Console.WriteLine(" = " + dub); + if (5.325098235 != dub) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + Console.Write("testDouble(-0.000341012439638598279)"); + dub = await client.testDoubleAsync(-0.000341012439638598279, token); + Console.WriteLine(" = " + dub); + if (-0.000341012439638598279 != dub) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + + var binOut = PrepareTestData(true); + Console.Write("testBinary(" + BytesToHex(binOut) + ")"); + try + { + var binIn = await client.testBinaryAsync(binOut, token); + Console.WriteLine(" = " + BytesToHex(binIn)); + if (binIn.Length != binOut.Length) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + for (var ofs = 0; ofs < Math.Min(binIn.Length, binOut.Length); ++ofs) + if (binIn[ofs] != binOut[ofs]) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + } + catch (Thrift.TApplicationException ex) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + } + + // binary equals? only with hashcode option enabled ... + Console.WriteLine("Test CrazyNesting"); + var one = new CrazyNesting(); + var two = new CrazyNesting(); + one.String_field = "crazy"; + two.String_field = "crazy"; + one.Binary_field = new byte[] { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0xFF }; + two.Binary_field = new byte[10] { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0xFF }; + if (typeof(CrazyNesting).GetMethod("Equals")?.DeclaringType == typeof(CrazyNesting)) + { + if (!one.Equals(two)) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorContainers; + throw new Exception("CrazyNesting.Equals failed"); + } + } + + // TODO: Validate received message + Console.Write("testStruct({\"Zero\", 1, -3, -5})"); + var o = new Xtruct(); + o.String_thing = "Zero"; + o.Byte_thing = (sbyte)1; + o.I32_thing = -3; + o.I64_thing = -5; + var i = await client.testStructAsync(o, token); + Console.WriteLine(" = {\"" + i.String_thing + "\", " + i.Byte_thing + ", " + i.I32_thing + ", " + i.I64_thing + "}"); + + // TODO: Validate received message + Console.Write("testNest({1, {\"Zero\", 1, -3, -5}, 5})"); + var o2 = new Xtruct2(); + o2.Byte_thing = (sbyte)1; + o2.Struct_thing = o; + o2.I32_thing = 5; + var i2 = await client.testNestAsync(o2, token); + i = i2.Struct_thing; + Console.WriteLine(" = {" + i2.Byte_thing + ", {\"" + i.String_thing + "\", " + i.Byte_thing + ", " + i.I32_thing + ", " + i.I64_thing + "}, " + i2.I32_thing + "}"); + + var mapout = new Dictionary<int, int>(); + for (var j = 0; j < 5; j++) + { + mapout[j] = j - 10; + } + Console.Write("testMap({"); + var first = true; + foreach (var key in mapout.Keys) + { + if (first) + { + first = false; + } + else + { + Console.Write(", "); + } + Console.Write(key + " => " + mapout[key]); + } + Console.Write("})"); + + var mapin = await client.testMapAsync(mapout, token); + + Console.Write(" = {"); + first = true; + foreach (var key in mapin.Keys) + { + if (first) + { + first = false; + } + else + { + Console.Write(", "); + } + Console.Write(key + " => " + mapin[key]); + } + Console.WriteLine("}"); + + // TODO: Validate received message + var listout = new List<int>(); + for (var j = -2; j < 3; j++) + { + listout.Add(j); + } + Console.Write("testList({"); + first = true; + foreach (var j in listout) + { + if (first) + { + first = false; + } + else + { + Console.Write(", "); + } + Console.Write(j); + } + Console.Write("})"); + + var listin = await client.testListAsync(listout, token); + + Console.Write(" = {"); + first = true; + foreach (var j in listin) + { + if (first) + { + first = false; + } + else + { + Console.Write(", "); + } + Console.Write(j); + } + Console.WriteLine("}"); + + //set + // TODO: Validate received message + var setout = new THashSet<int>(); + for (var j = -2; j < 3; j++) + { + setout.Add(j); + } + Console.Write("testSet({"); + first = true; + foreach (int j in setout) + { + if (first) + { + first = false; + } + else + { + Console.Write(", "); + } + Console.Write(j); + } + Console.Write("})"); + + var setin = await client.testSetAsync(setout, token); + + Console.Write(" = {"); + first = true; + foreach (int j in setin) + { + if (first) + { + first = false; + } + else + { + Console.Write(", "); + } + Console.Write(j); + } + Console.WriteLine("}"); + + + Console.Write("testEnum(ONE)"); + var ret = await client.testEnumAsync(Numberz.ONE, token); + Console.WriteLine(" = " + ret); + if (Numberz.ONE != ret) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorStructs; + } + + Console.Write("testEnum(TWO)"); + ret = await client.testEnumAsync(Numberz.TWO, token); + Console.WriteLine(" = " + ret); + if (Numberz.TWO != ret) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorStructs; + } + + Console.Write("testEnum(THREE)"); + ret = await client.testEnumAsync(Numberz.THREE, token); + Console.WriteLine(" = " + ret); + if (Numberz.THREE != ret) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorStructs; + } + + Console.Write("testEnum(FIVE)"); + ret = await client.testEnumAsync(Numberz.FIVE, token); + Console.WriteLine(" = " + ret); + if (Numberz.FIVE != ret) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorStructs; + } + + Console.Write("testEnum(EIGHT)"); + ret = await client.testEnumAsync(Numberz.EIGHT, token); + Console.WriteLine(" = " + ret); + if (Numberz.EIGHT != ret) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorStructs; + } + + Console.Write("testTypedef(309858235082523)"); + var uid = await client.testTypedefAsync(309858235082523L, token); + Console.WriteLine(" = " + uid); + if (309858235082523L != uid) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorStructs; + } + + // TODO: Validate received message + Console.Write("testMapMap(1)"); + var mm = await client.testMapMapAsync(1, token); + Console.Write(" = {"); + foreach (var key in mm.Keys) + { + Console.Write(key + " => {"); + var m2 = mm[key]; + foreach (var k2 in m2.Keys) + { + Console.Write(k2 + " => " + m2[k2] + ", "); + } + Console.Write("}, "); + } + Console.WriteLine("}"); + + // TODO: Validate received message + var insane = new Insanity(); + insane.UserMap = new Dictionary<Numberz, long>(); + insane.UserMap[Numberz.FIVE] = 5000L; + var truck = new Xtruct(); + truck.String_thing = "Truck"; + truck.Byte_thing = (sbyte)8; + truck.I32_thing = 8; + truck.I64_thing = 8; + insane.Xtructs = new List<Xtruct>(); + insane.Xtructs.Add(truck); + Console.Write("testInsanity()"); + var whoa = await client.testInsanityAsync(insane, token); + Console.Write(" = {"); + foreach (var key in whoa.Keys) + { + var val = whoa[key]; + Console.Write(key + " => {"); + + foreach (var k2 in val.Keys) + { + var v2 = val[k2]; + + Console.Write(k2 + " => {"); + var userMap = v2.UserMap; + + Console.Write("{"); + if (userMap != null) + { + foreach (var k3 in userMap.Keys) + { + Console.Write(k3 + " => " + userMap[k3] + ", "); + } + } + else + { + Console.Write("null"); + } + Console.Write("}, "); + + var xtructs = v2.Xtructs; + + Console.Write("{"); + if (xtructs != null) + { + foreach (var x in xtructs) + { + Console.Write("{\"" + x.String_thing + "\", " + x.Byte_thing + ", " + x.I32_thing + ", " + x.I32_thing + "}, "); + } + } + else + { + Console.Write("null"); + } + Console.Write("}"); + + Console.Write("}, "); + } + Console.Write("}, "); + } + Console.WriteLine("}"); + + sbyte arg0 = 1; + var arg1 = 2; + var arg2 = long.MaxValue; + var multiDict = new Dictionary<short, string>(); + multiDict[1] = "one"; + + var tmpMultiDict = new List<string>(); + foreach (var pair in multiDict) + tmpMultiDict.Add(pair.Key +" => "+ pair.Value); + + var arg4 = Numberz.FIVE; + long arg5 = 5000000; + Console.Write("Test Multi(" + arg0 + "," + arg1 + "," + arg2 + ",{" + string.Join(",", tmpMultiDict) + "}," + arg4 + "," + arg5 + ")"); + var multiResponse = await client.testMultiAsync(arg0, arg1, arg2, multiDict, arg4, arg5, token); + Console.Write(" = Xtruct(byte_thing:" + multiResponse.Byte_thing + ",String_thing:" + multiResponse.String_thing + + ",i32_thing:" + multiResponse.I32_thing + ",i64_thing:" + multiResponse.I64_thing + ")\n"); + + try + { + Console.WriteLine("testException(\"Xception\")"); + await client.testExceptionAsync("Xception", token); + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + } + catch (Xception ex) + { + if (ex.ErrorCode != 1001 || ex.Message != "Xception") + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + } + } + catch (Exception ex) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + } + try + { + Console.WriteLine("testException(\"TException\")"); + await client.testExceptionAsync("TException", token); + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + } + catch (Thrift.TException) + { + // OK + } + catch (Exception ex) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + } + try + { + Console.WriteLine("testException(\"ok\")"); + await client.testExceptionAsync("ok", token); + // OK + } + catch (Exception ex) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + } + + try + { + Console.WriteLine("testMultiException(\"Xception\", ...)"); + await client.testMultiExceptionAsync("Xception", "ignore", token); + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + } + catch (Xception ex) + { + if (ex.ErrorCode != 1001 || ex.Message != "This is an Xception") + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + } + } + catch (Exception ex) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + } + try + { + Console.WriteLine("testMultiException(\"Xception2\", ...)"); + await client.testMultiExceptionAsync("Xception2", "ignore", token); + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + } + catch (Xception2 ex) + { + if (ex.ErrorCode != 2002 || ex.Struct_thing.String_thing != "This is an Xception2") + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + } + } + catch (Exception ex) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + } + try + { + Console.WriteLine("testMultiException(\"success\", \"OK\")"); + if ("OK" != (await client.testMultiExceptionAsync("success", "OK", token)).String_thing) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + } + } + catch (Exception ex) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + } + + var sw = new Stopwatch(); + sw.Start(); + Console.WriteLine("Test Oneway(1)"); + await client.testOnewayAsync(1, token); + sw.Stop(); + if (sw.ElapsedMilliseconds > 1000) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + + Console.Write("Test Calltime()"); + var times = 50; + sw.Reset(); + sw.Start(); + for (var k = 0; k < times; ++k) + await client.testVoidAsync(token); + sw.Stop(); + Console.WriteLine(" = {0} ms a testVoid() call", sw.ElapsedMilliseconds / times); + return returnCode; + } + } +} diff --git a/src/jaegertracing/thrift/test/netcore/Makefile.am b/src/jaegertracing/thrift/test/netcore/Makefile.am new file mode 100644 index 000000000..2fff4ba3a --- /dev/null +++ b/src/jaegertracing/thrift/test/netcore/Makefile.am @@ -0,0 +1,50 @@ +# +# 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. +# + +SUBDIRS = . + +all-local: + $(DOTNETCORE) build + +precross: + $(DOTNETCORE) build + +clean-local: + $(RM) -r Client/bin + $(RM) -r Client/obj + $(RM) -r Client/ThriftTest + $(RM) -r Server/bin + $(RM) -r Server/obj + $(RM) -r Server/ThriftTest + +dist-hook: + $(RM) -r $(distdir)/Client/bin + $(RM) -r $(distdir)/Client/obj + $(RM) -r $(distdir)/Client/ThriftTest + $(RM) -r $(distdir)/Server/bin + $(RM) -r $(distdir)/Server/obj + $(RM) -r $(distdir)/Server/ThriftTest + +EXTRA_DIST = \ + Client \ + README.md \ + Server \ + ThriftTest.sln \ + build.cmd \ + build.sh diff --git a/src/jaegertracing/thrift/test/netcore/README.md b/src/jaegertracing/thrift/test/netcore/README.md new file mode 100644 index 000000000..ed728d1ba --- /dev/null +++ b/src/jaegertracing/thrift/test/netcore/README.md @@ -0,0 +1,20 @@ +# Apache Thrift net-core-lib tests + +Tests for Thrift client library ported to Microsoft .Net Core + +# Content +- ThriftTest - tests for Thrift library + +# Reused components +- NET Core Standard 1.6 (SDK 2.0.0) + +# How to build on Windows +- Get Thrift IDL compiler executable, add to some folder and add path to this folder into PATH variable +- Open ThriftTest.sln in Visual Studio and build +or +- Build with scripts + +# How to build on Unix +- Ensure you have .NET Core 2.0.0 SDK installed or use the Ubuntu Xenial docker image +- Follow common build practice for Thrift: bootstrap, configure, and make precross + diff --git a/src/jaegertracing/thrift/test/netcore/Server/.gitignore b/src/jaegertracing/thrift/test/netcore/Server/.gitignore new file mode 100644 index 000000000..67d55106a --- /dev/null +++ b/src/jaegertracing/thrift/test/netcore/Server/.gitignore @@ -0,0 +1,2 @@ +# ignore for autogenerated files +/ThriftTest diff --git a/src/jaegertracing/thrift/test/netcore/Server/Program.cs b/src/jaegertracing/thrift/test/netcore/Server/Program.cs new file mode 100644 index 000000000..e647e5b2a --- /dev/null +++ b/src/jaegertracing/thrift/test/netcore/Server/Program.cs @@ -0,0 +1,72 @@ +// 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. + +using System; +using System.Collections.Generic; +using ThriftTest; + +namespace Server +{ + public class Program + { + public static int Main(string[] args) + { + try + { + Console.SetBufferSize(Console.BufferWidth, 4096); + } + catch (Exception) + { + Console.WriteLine("Failed to grow scroll-back buffer"); + } + + // split mode and options + var subArgs = new List<string>(args); + var firstArg = string.Empty; + if (subArgs.Count > 0) + { + firstArg = subArgs[0]; + subArgs.RemoveAt(0); + } + + // run whatever mode is choosen + switch(firstArg) + { + case "server": + return TestServer.Execute(subArgs); + case "--help": + PrintHelp(); + return 0; + default: + PrintHelp(); + return -1; + } + } + + private static void PrintHelp() + { + Console.WriteLine("Usage:"); + Console.WriteLine(" Server server [options]'"); + Console.WriteLine(" Server --help"); + Console.WriteLine(""); + + TestServer.PrintOptionsHelp(); + } + } +} + + diff --git a/src/jaegertracing/thrift/test/netcore/Server/Properties/AssemblyInfo.cs b/src/jaegertracing/thrift/test/netcore/Server/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..265495c05 --- /dev/null +++ b/src/jaegertracing/thrift/test/netcore/Server/Properties/AssemblyInfo.cs @@ -0,0 +1,43 @@ +// 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. +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +[assembly: AssemblyTitle("Server")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("The Apache Software Foundation")] +[assembly: AssemblyProduct("Thrift")] +[assembly: AssemblyCopyright("The Apache Software Foundation")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. + +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM + +[assembly: Guid("B0C13DA0-3117-4844-8AE8-B1775E46223D")] + diff --git a/src/jaegertracing/thrift/test/netcore/Server/Server.csproj b/src/jaegertracing/thrift/test/netcore/Server/Server.csproj new file mode 100644 index 000000000..2f9b4b1f5 --- /dev/null +++ b/src/jaegertracing/thrift/test/netcore/Server/Server.csproj @@ -0,0 +1,31 @@ +<Project Sdk="Microsoft.NET.Sdk"> + <PropertyGroup> + <TargetFramework>netcoreapp2.0</TargetFramework> + <AssemblyName>Server</AssemblyName> + <PackageId>Server</PackageId> + <OutputType>Exe</OutputType> + <GenerateAssemblyTitleAttribute>false</GenerateAssemblyTitleAttribute> + <GenerateAssemblyDescriptionAttribute>false</GenerateAssemblyDescriptionAttribute> + <GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> + <GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> + <GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> + <GenerateAssemblyCopyrightAttribute>false</GenerateAssemblyCopyrightAttribute> + </PropertyGroup> + <ItemGroup> + <PackageReference Include="System.Net.Http.WinHttpHandler" Version="[4.4,)" /> + <PackageReference Include="System.Runtime.Serialization.Primitives" Version="[4.3,)" /> + <PackageReference Include="System.ServiceModel.Primitives" Version="[4.4,)" /> + <PackageReference Include="System.Threading" Version="[4.3,)" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\..\..\lib\netcore\Thrift\Thrift.csproj" /> + </ItemGroup> + <Target Name="PreBuild" BeforeTargets="_GenerateRestoreProjectSpec;Restore;Compile"> + <Exec Condition="'$(OS)' == 'Windows_NT'" Command="where thrift" ConsoleToMSBuild="true"> + <Output TaskParameter="ConsoleOutput" PropertyName="PathToThrift" /> + </Exec> + <Exec Condition="Exists('$(PathToThrift)')" Command=""$(PathToThrift)" -out $(ProjectDir) -gen netcore:wcf,union,serial,hashcode -r ./../../ThriftTest.thrift" /> + <Exec Condition="Exists('thrift')" Command="thrift -out $(ProjectDir) -gen netcore:wcf,union,serial,hashcode -r ./../../ThriftTest.thrift" /> + <Exec Condition="Exists('$(ProjectDir)/../../../compiler/cpp/thrift')" Command="$(ProjectDir)/../../../compiler/cpp/thrift -out $(ProjectDir) -gen netcore:wcf,union,serial,hashcode -r ./../../ThriftTest.thrift" /> + </Target> +</Project>
\ No newline at end of file diff --git a/src/jaegertracing/thrift/test/netcore/Server/TestServer.cs b/src/jaegertracing/thrift/test/netcore/Server/TestServer.cs new file mode 100644 index 000000000..bfd33357f --- /dev/null +++ b/src/jaegertracing/thrift/test/netcore/Server/TestServer.cs @@ -0,0 +1,594 @@ +// 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. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Security.Authentication; +using System.Security.Cryptography.X509Certificates; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Thrift; +using Thrift.Collections; +using Thrift.Protocols; +using Thrift.Server; +using Thrift.Transports; +using Thrift.Transports.Server; + +namespace ThriftTest +{ + internal class ServerParam + { + internal bool useBufferedSockets = false; + internal bool useFramed = false; + internal bool useEncryption = false; + internal bool compact = false; + internal bool json = false; + internal int port = 9090; + internal string pipe = null; + + internal void Parse(List<string> args) + { + for (var i = 0; i < args.Count; i++) + { + if (args[i].StartsWith("--pipe=")) + { + pipe = args[i].Substring(args[i].IndexOf("=") + 1); + } + else if (args[i].StartsWith("--port=")) + { + port = int.Parse(args[i].Substring(args[i].IndexOf("=") + 1)); + } + else if (args[i] == "-b" || args[i] == "--buffered" || args[i] == "--transport=buffered") + { + useBufferedSockets = true; + } + else if (args[i] == "-f" || args[i] == "--framed" || args[i] == "--transport=framed") + { + useFramed = true; + } + else if (args[i] == "--binary" || args[i] == "--protocol=binary") + { + // nothing needed + } + else if (args[i] == "--compact" || args[i] == "--protocol=compact") + { + compact = true; + } + else if (args[i] == "--json" || args[i] == "--protocol=json") + { + json = true; + } + else if (args[i] == "--threaded" || args[i] == "--server-type=threaded") + { + throw new NotImplementedException(args[i]); + } + else if (args[i] == "--threadpool" || args[i] == "--server-type=threadpool") + { + throw new NotImplementedException(args[i]); + } + else if (args[i] == "--prototype" || args[i] == "--processor=prototype") + { + throw new NotImplementedException(args[i]); + } + else if (args[i] == "--ssl") + { + useEncryption = true; + } + else + { + //throw new ArgumentException(args[i]); + } + } + + } + } + + public class TestServer + { + public static int _clientID = -1; + public delegate void TestLogDelegate(string msg, params object[] values); + + public class MyServerEventHandler : TServerEventHandler + { + public int callCount = 0; + + public Task PreServeAsync(CancellationToken cancellationToken) + { + callCount++; + return Task.CompletedTask; + } + + public Task<object> CreateContextAsync(TProtocol input, TProtocol output, CancellationToken cancellationToken) + { + callCount++; + return Task.FromResult<object>(null); + } + + public Task DeleteContextAsync(object serverContext, TProtocol input, TProtocol output, CancellationToken cancellationToken) + { + callCount++; + return Task.CompletedTask; + } + + public Task ProcessContextAsync(object serverContext, TClientTransport transport, CancellationToken cancellationToken) + { + callCount++; + return Task.CompletedTask; + } + } + + public class TestHandlerAsync : ThriftTest.IAsync + { + public TBaseServer server { get; set; } + private int handlerID; + private StringBuilder sb = new StringBuilder(); + private TestLogDelegate logger; + + public TestHandlerAsync() + { + handlerID = Interlocked.Increment(ref _clientID); + logger += testConsoleLogger; + logger.Invoke("New TestHandler instance created"); + } + + public void testConsoleLogger(string msg, params object[] values) + { + sb.Clear(); + sb.AppendFormat("handler{0:D3}:", handlerID); + sb.AppendFormat(msg, values); + sb.AppendLine(); + Console.Write(sb.ToString()); + } + + public Task testVoidAsync(CancellationToken cancellationToken) + { + logger.Invoke("testVoid()"); + return Task.CompletedTask; + } + + public Task<string> testStringAsync(string thing, CancellationToken cancellationToken) + { + logger.Invoke("testString({0})", thing); + return Task.FromResult(thing); + } + + public Task<bool> testBoolAsync(bool thing, CancellationToken cancellationToken) + { + logger.Invoke("testBool({0})", thing); + return Task.FromResult(thing); + } + + public Task<sbyte> testByteAsync(sbyte thing, CancellationToken cancellationToken) + { + logger.Invoke("testByte({0})", thing); + return Task.FromResult(thing); + } + + public Task<int> testI32Async(int thing, CancellationToken cancellationToken) + { + logger.Invoke("testI32({0})", thing); + return Task.FromResult(thing); + } + + public Task<long> testI64Async(long thing, CancellationToken cancellationToken) + { + logger.Invoke("testI64({0})", thing); + return Task.FromResult(thing); + } + + public Task<double> testDoubleAsync(double thing, CancellationToken cancellationToken) + { + logger.Invoke("testDouble({0})", thing); + return Task.FromResult(thing); + } + + public Task<byte[]> testBinaryAsync(byte[] thing, CancellationToken cancellationToken) + { + var hex = BitConverter.ToString(thing).Replace("-", string.Empty); + logger.Invoke("testBinary({0:X})", hex); + return Task.FromResult(thing); + } + + public Task<Xtruct> testStructAsync(Xtruct thing, CancellationToken cancellationToken) + { + logger.Invoke("testStruct({{\"{0}\", {1}, {2}, {3}}})", thing.String_thing, thing.Byte_thing, thing.I32_thing, thing.I64_thing); + return Task.FromResult(thing); + } + + public Task<Xtruct2> testNestAsync(Xtruct2 nest, CancellationToken cancellationToken) + { + var thing = nest.Struct_thing; + logger.Invoke("testNest({{{0}, {{\"{1}\", {2}, {3}, {4}, {5}}}}})", + nest.Byte_thing, + thing.String_thing, + thing.Byte_thing, + thing.I32_thing, + thing.I64_thing, + nest.I32_thing); + return Task.FromResult(nest); + } + + public Task<Dictionary<int, int>> testMapAsync(Dictionary<int, int> thing, CancellationToken cancellationToken) + { + sb.Clear(); + sb.Append("testMap({{"); + var first = true; + foreach (var key in thing.Keys) + { + if (first) + { + first = false; + } + else + { + sb.Append(", "); + } + sb.AppendFormat("{0} => {1}", key, thing[key]); + } + sb.Append("}})"); + logger.Invoke(sb.ToString()); + return Task.FromResult(thing); + } + + public Task<Dictionary<string, string>> testStringMapAsync(Dictionary<string, string> thing, CancellationToken cancellationToken) + { + sb.Clear(); + sb.Append("testStringMap({{"); + var first = true; + foreach (var key in thing.Keys) + { + if (first) + { + first = false; + } + else + { + sb.Append(", "); + } + sb.AppendFormat("{0} => {1}", key, thing[key]); + } + sb.Append("}})"); + logger.Invoke(sb.ToString()); + return Task.FromResult(thing); + } + + public Task<THashSet<int>> testSetAsync(THashSet<int> thing, CancellationToken cancellationToken) + { + sb.Clear(); + sb.Append("testSet({{"); + var first = true; + foreach (int elem in thing) + { + if (first) + { + first = false; + } + else + { + sb.Append(", "); + } + sb.AppendFormat("{0}", elem); + } + sb.Append("}})"); + logger.Invoke(sb.ToString()); + return Task.FromResult(thing); + } + + public Task<List<int>> testListAsync(List<int> thing, CancellationToken cancellationToken) + { + sb.Clear(); + sb.Append("testList({{"); + var first = true; + foreach (var elem in thing) + { + if (first) + { + first = false; + } + else + { + sb.Append(", "); + } + sb.AppendFormat("{0}", elem); + } + sb.Append("}})"); + logger.Invoke(sb.ToString()); + return Task.FromResult(thing); + } + + public Task<Numberz> testEnumAsync(Numberz thing, CancellationToken cancellationToken) + { + logger.Invoke("testEnum({0})", thing); + return Task.FromResult(thing); + } + + public Task<long> testTypedefAsync(long thing, CancellationToken cancellationToken) + { + logger.Invoke("testTypedef({0})", thing); + return Task.FromResult(thing); + } + + public Task<Dictionary<int, Dictionary<int, int>>> testMapMapAsync(int hello, CancellationToken cancellationToken) + { + logger.Invoke("testMapMap({0})", hello); + var mapmap = new Dictionary<int, Dictionary<int, int>>(); + + var pos = new Dictionary<int, int>(); + var neg = new Dictionary<int, int>(); + for (var i = 1; i < 5; i++) + { + pos[i] = i; + neg[-i] = -i; + } + + mapmap[4] = pos; + mapmap[-4] = neg; + + return Task.FromResult(mapmap); + } + + public Task<Dictionary<long, Dictionary<Numberz, Insanity>>> testInsanityAsync(Insanity argument, CancellationToken cancellationToken) + { + logger.Invoke("testInsanity()"); + + /** from ThriftTest.thrift: + * So you think you've got this all worked, out eh? + * + * Creates a the returned map with these values and prints it out: + * { 1 => { 2 => argument, + * 3 => argument, + * }, + * 2 => { 6 => <empty Insanity struct>, }, + * } + * @return map<UserId, map<Numberz,Insanity>> - a map with the above values + */ + + var first_map = new Dictionary<Numberz, Insanity>(); + var second_map = new Dictionary<Numberz, Insanity>(); ; + + first_map[Numberz.TWO] = argument; + first_map[Numberz.THREE] = argument; + + second_map[Numberz.SIX] = new Insanity(); + + var insane = new Dictionary<long, Dictionary<Numberz, Insanity>> + { + [1] = first_map, + [2] = second_map + }; + + return Task.FromResult(insane); + } + + public Task<Xtruct> testMultiAsync(sbyte arg0, int arg1, long arg2, Dictionary<short, string> arg3, Numberz arg4, long arg5, + CancellationToken cancellationToken) + { + logger.Invoke("testMulti()"); + + var hello = new Xtruct(); ; + hello.String_thing = "Hello2"; + hello.Byte_thing = arg0; + hello.I32_thing = arg1; + hello.I64_thing = arg2; + return Task.FromResult(hello); + } + + public Task testExceptionAsync(string arg, CancellationToken cancellationToken) + { + logger.Invoke("testException({0})", arg); + if (arg == "Xception") + { + var x = new Xception + { + ErrorCode = 1001, + Message = arg + }; + throw x; + } + if (arg == "TException") + { + throw new TException(); + } + return Task.CompletedTask; + } + + public Task<Xtruct> testMultiExceptionAsync(string arg0, string arg1, CancellationToken cancellationToken) + { + logger.Invoke("testMultiException({0}, {1})", arg0, arg1); + if (arg0 == "Xception") + { + var x = new Xception + { + ErrorCode = 1001, + Message = "This is an Xception" + }; + throw x; + } + + if (arg0 == "Xception2") + { + var x = new Xception2 + { + ErrorCode = 2002, + Struct_thing = new Xtruct { String_thing = "This is an Xception2" } + }; + throw x; + } + + var result = new Xtruct { String_thing = arg1 }; + return Task.FromResult(result); + } + + public Task testOnewayAsync(int secondsToSleep, CancellationToken cancellationToken) + { + logger.Invoke("testOneway({0}), sleeping...", secondsToSleep); + Task.Delay(secondsToSleep * 1000, cancellationToken).GetAwaiter().GetResult(); + logger.Invoke("testOneway finished"); + + return Task.CompletedTask; + } + } + + internal static void PrintOptionsHelp() + { + Console.WriteLine("Server options:"); + Console.WriteLine(" --pipe=<pipe name>"); + Console.WriteLine(" --port=<port number>"); + Console.WriteLine(" --transport=<transport name> one of buffered,framed (defaults to none)"); + Console.WriteLine(" --protocol=<protocol name> one of compact,json (defaults to binary)"); + Console.WriteLine(" --server-type=<type> one of threaded,threadpool (defaults to simple)"); + Console.WriteLine(" --processor=<prototype>"); + Console.WriteLine(" --ssl"); + Console.WriteLine(); + } + + private static X509Certificate2 GetServerCert() + { + var serverCertName = "server.p12"; + var possiblePaths = new List<string> + { + "../../../keys/", + "../../keys/", + "../keys/", + "keys/", + }; + + string existingPath = null; + foreach (var possiblePath in possiblePaths) + { + var path = Path.GetFullPath(possiblePath + serverCertName); + if (File.Exists(path)) + { + existingPath = path; + break; + } + } + + if (string.IsNullOrEmpty(existingPath)) + { + throw new FileNotFoundException($"Cannot find file: {serverCertName}"); + } + + var cert = new X509Certificate2(existingPath, "thrift"); + + return cert; + } + + public static int Execute(List<string> args) + { + var loggerFactory = new LoggerFactory();//.AddConsole().AddDebug(); + var logger = new LoggerFactory().CreateLogger("Test"); + + try + { + var param = new ServerParam(); + + try + { + param.Parse(args); + } + catch (Exception ex) + { + Console.WriteLine("*** FAILED ***"); + Console.WriteLine("Error while parsing arguments"); + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + return 1; + } + + + // Transport + TServerTransport trans; + if (param.pipe != null) + { + trans = new TNamedPipeServerTransport(param.pipe); + } +// else if (param.useFramed) +// { +// trans = new TServerFramedTransport(param.port); +// } + else + { + if (param.useEncryption) + { + var cert = GetServerCert(); + + if (cert == null || !cert.HasPrivateKey) + { + throw new InvalidOperationException("Certificate doesn't contain private key"); + } + + trans = new TTlsServerSocketTransport(param.port, param.useBufferedSockets, param.useFramed, cert, + (sender, certificate, chain, errors) => true, + null, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12); + } + else + { + trans = new TServerSocketTransport(param.port, 0, param.useBufferedSockets, param.useFramed); + } + } + + ITProtocolFactory proto; + if (param.compact) + proto = new TCompactProtocol.Factory(); + else if (param.json) + proto = new TJsonProtocol.Factory(); + else + proto = new TBinaryProtocol.Factory(); + + ITProcessorFactory processorFactory; + + // Processor + var testHandler = new TestHandlerAsync(); + var testProcessor = new ThriftTest.AsyncProcessor(testHandler); + processorFactory = new SingletonTProcessorFactory(testProcessor); + + TTransportFactory transFactory = new TTransportFactory(); + + TBaseServer serverEngine = new AsyncBaseServer(processorFactory, trans, transFactory, transFactory, proto, proto, logger); + + //Server event handler + var serverEvents = new MyServerEventHandler(); + serverEngine.SetEventHandler(serverEvents); + + // Run it + var where = (! string.IsNullOrEmpty(param.pipe)) ? "on pipe " + param.pipe : "on port " + param.port; + Console.WriteLine("Starting the AsyncBaseServer " + where + + " with processor TPrototypeProcessorFactory prototype factory " + + (param.useBufferedSockets ? " with buffered socket" : "") + + (param.useFramed ? " with framed transport" : "") + + (param.useEncryption ? " with encryption" : "") + + (param.compact ? " with compact protocol" : "") + + (param.json ? " with json protocol" : "") + + "..."); + serverEngine.ServeAsync(CancellationToken.None).GetAwaiter().GetResult(); + Console.ReadLine(); + } + catch (Exception x) + { + Console.Error.Write(x); + return 1; + } + Console.WriteLine("done."); + return 0; + } + } + +} diff --git a/src/jaegertracing/thrift/test/netcore/ThriftTest.sln b/src/jaegertracing/thrift/test/netcore/ThriftTest.sln new file mode 100644 index 000000000..2ab241add --- /dev/null +++ b/src/jaegertracing/thrift/test/netcore/ThriftTest.sln @@ -0,0 +1,64 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26730.12 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift", "..\..\lib\netcore\Thrift\Thrift.csproj", "{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Client", "Client\Client.csproj", "{21039F25-6ED7-4E80-A545-EBC93472EBD1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Server", "Server\Server.csproj", "{0C6E8685-F191-4479-9842-882A38961127}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x64.ActiveCfg = Debug|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x64.Build.0 = Debug|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x86.ActiveCfg = Debug|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x86.Build.0 = Debug|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|Any CPU.Build.0 = Release|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x64.ActiveCfg = Release|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x64.Build.0 = Release|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x86.ActiveCfg = Release|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x86.Build.0 = Release|Any CPU + {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Debug|x64.ActiveCfg = Debug|Any CPU + {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Debug|x64.Build.0 = Debug|Any CPU + {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Debug|x86.ActiveCfg = Debug|Any CPU + {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Debug|x86.Build.0 = Debug|Any CPU + {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Release|Any CPU.Build.0 = Release|Any CPU + {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Release|x64.ActiveCfg = Release|Any CPU + {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Release|x64.Build.0 = Release|Any CPU + {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Release|x86.ActiveCfg = Release|Any CPU + {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Release|x86.Build.0 = Release|Any CPU + {0C6E8685-F191-4479-9842-882A38961127}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0C6E8685-F191-4479-9842-882A38961127}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0C6E8685-F191-4479-9842-882A38961127}.Debug|x64.ActiveCfg = Debug|Any CPU + {0C6E8685-F191-4479-9842-882A38961127}.Debug|x64.Build.0 = Debug|Any CPU + {0C6E8685-F191-4479-9842-882A38961127}.Debug|x86.ActiveCfg = Debug|Any CPU + {0C6E8685-F191-4479-9842-882A38961127}.Debug|x86.Build.0 = Debug|Any CPU + {0C6E8685-F191-4479-9842-882A38961127}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0C6E8685-F191-4479-9842-882A38961127}.Release|Any CPU.Build.0 = Release|Any CPU + {0C6E8685-F191-4479-9842-882A38961127}.Release|x64.ActiveCfg = Release|Any CPU + {0C6E8685-F191-4479-9842-882A38961127}.Release|x64.Build.0 = Release|Any CPU + {0C6E8685-F191-4479-9842-882A38961127}.Release|x86.ActiveCfg = Release|Any CPU + {0C6E8685-F191-4479-9842-882A38961127}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {52CE9A12-F6CB-4F0C-BB42-0105612F5FF4} + EndGlobalSection +EndGlobal diff --git a/src/jaegertracing/thrift/test/netcore/build.cmd b/src/jaegertracing/thrift/test/netcore/build.cmd new file mode 100644 index 000000000..9b84ef276 --- /dev/null +++ b/src/jaegertracing/thrift/test/netcore/build.cmd @@ -0,0 +1,25 @@ +@echo off +rem /* +rem * Licensed to the Apache Software Foundation (ASF) under one +rem * or more contributor license agreements. See the NOTICE file +rem * distributed with this work for additional information +rem * regarding copyright ownership. The ASF licenses this file +rem * to you under the Apache License, Version 2.0 (the +rem * "License"); you may not use this file except in compliance +rem * with the License. You may obtain a copy of the License at +rem * +rem * http://www.apache.org/licenses/LICENSE-2.0 +rem * +rem * Unless required by applicable law or agreed to in writing, +rem * software distributed under the License is distributed on an +rem * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +rem * KIND, either express or implied. See the License for the +rem * specific language governing permissions and limitations +rem * under the License. +rem */ +setlocal + +dotnet --info +dotnet build + +:eof diff --git a/src/jaegertracing/thrift/test/netcore/build.sh b/src/jaegertracing/thrift/test/netcore/build.sh new file mode 100755 index 000000000..c97e310f0 --- /dev/null +++ b/src/jaegertracing/thrift/test/netcore/build.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +# +# 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. +# + +#exit if any command fails +set -e + +dotnet --info +dotnet build diff --git a/src/jaegertracing/thrift/test/netstd/Client/.gitignore b/src/jaegertracing/thrift/test/netstd/Client/.gitignore new file mode 100644 index 000000000..67d55106a --- /dev/null +++ b/src/jaegertracing/thrift/test/netstd/Client/.gitignore @@ -0,0 +1,2 @@ +# ignore for autogenerated files +/ThriftTest diff --git a/src/jaegertracing/thrift/test/netstd/Client/Client.csproj b/src/jaegertracing/thrift/test/netstd/Client/Client.csproj new file mode 100644 index 000000000..ed30c30dd --- /dev/null +++ b/src/jaegertracing/thrift/test/netstd/Client/Client.csproj @@ -0,0 +1,50 @@ +<Project Sdk="Microsoft.NET.Sdk"> + <!-- + 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. + --> + + <PropertyGroup> + <TargetFramework>netcoreapp2.0</TargetFramework> + <AssemblyName>Client</AssemblyName> + <PackageId>Client</PackageId> + <OutputType>Exe</OutputType> + <GenerateAssemblyTitleAttribute>false</GenerateAssemblyTitleAttribute> + <GenerateAssemblyDescriptionAttribute>false</GenerateAssemblyDescriptionAttribute> + <GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> + <GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> + <GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> + <GenerateAssemblyCopyrightAttribute>false</GenerateAssemblyCopyrightAttribute> + </PropertyGroup> + <ItemGroup> + <PackageReference Include="System.Net.Http.WinHttpHandler" Version="4.5.2" /> + <PackageReference Include="System.Runtime.Serialization.Primitives" Version="[4.3,)" /> + <PackageReference Include="System.ServiceModel.Primitives" Version="4.5.3" /> + <PackageReference Include="System.Threading" Version="[4.3,)" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\..\..\lib\netstd\Thrift\Thrift.csproj" /> + </ItemGroup> + <Target Name="PreBuild" BeforeTargets="_GenerateRestoreProjectSpec;Restore;Compile"> + <Exec Condition="'$(OS)' == 'Windows_NT'" Command="where thrift" ConsoleToMSBuild="true"> + <Output TaskParameter="ConsoleOutput" PropertyName="PathToThrift" /> + </Exec> + <Exec Condition="Exists('$(PathToThrift)')" Command=""$(PathToThrift)" -out $(ProjectDir) -gen netstd:wcf,union,serial -r ./../../ThriftTest.thrift" /> + <Exec Condition="Exists('thrift')" Command="thrift -out $(ProjectDir) -gen netstd:wcf,union,serial -r ./../../ThriftTest.thrift" /> + <Exec Condition="Exists('$(ProjectDir)/../../../compiler/cpp/thrift')" Command="$(ProjectDir)/../../../compiler/cpp/thrift -out $(ProjectDir) -gen netstd:wcf,union,serial -r ./../../ThriftTest.thrift" /> + </Target> +</Project> diff --git a/src/jaegertracing/thrift/test/netstd/Client/Performance/PerformanceTests.cs b/src/jaegertracing/thrift/test/netstd/Client/Performance/PerformanceTests.cs new file mode 100644 index 000000000..041d12eae --- /dev/null +++ b/src/jaegertracing/thrift/test/netstd/Client/Performance/PerformanceTests.cs @@ -0,0 +1,150 @@ +// 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. + +using System; +using System.Collections.Generic; +using System.Text; +using ThriftTest; +using Thrift.Collections; +using Thrift.Protocol; +using System.Threading; +using Thrift.Transport.Client; +using System.Threading.Tasks; +using System.Diagnostics; +using Thrift.Transport; + +namespace Client.Tests +{ + public class PerformanceTests + { + private CancellationTokenSource Cancel; + private CrazyNesting Testdata; + private TMemoryBufferTransport MemBuffer; + private TTransport Transport; + private LayeredChoice Layered; + + internal static int Execute() + { + var instance = new PerformanceTests(); + instance.ProtocolPeformanceTestAsync().Wait(); + + // debug only + if (Debugger.IsAttached) + { + Console.Write("Hit ENTER ..."); + Console.ReadKey(); + } + + return 0; + } + + private async Task ProtocolPeformanceTestAsync() + { + Console.WriteLine("Setting up for ProtocolPeformanceTestAsync ..."); + Cancel = new CancellationTokenSource(); + Testdata = TestDataFactory.CreateCrazyNesting(); + + foreach (var layered in Enum.GetValues(typeof(LayeredChoice))) + { + Layered = (LayeredChoice)layered; + + await RunTestAsync(async (bool b) => { return await GenericProtocolFactory<TBinaryProtocol>(b); }); + await RunTestAsync(async (bool b) => { return await GenericProtocolFactory<TCompactProtocol>(b); }); + //await RunTestAsync(async (bool b) => { return await GenericProtocolFactory<TJsonProtocol>(b); }); + } + } + + private Task<TProtocol> GenericProtocolFactory<T>(bool forWrite) + where T : TProtocol + { + var oldTrans = Transport; + try + { + // read happens after write here, so let's take over the written bytes + if (forWrite) + MemBuffer = new TMemoryBufferTransport(); + else + MemBuffer = new TMemoryBufferTransport(MemBuffer.GetBuffer()); + + // layered transports anyone? + switch (Layered) + { + case LayeredChoice.None: + Transport = MemBuffer; + break; + case LayeredChoice.Framed: + Transport = new TFramedTransport(MemBuffer); + break; + case LayeredChoice.Buffered: + Transport = new TBufferedTransport(MemBuffer); + break; + default: + Debug.Assert(false); + break; + } + + if (!Transport.IsOpen) + Transport.OpenAsync().Wait(); + + var instance = (T)Activator.CreateInstance(typeof(T), Transport); + return Task.FromResult<TProtocol>(instance); + } + finally + { + if (oldTrans is IDisposable) + (oldTrans as IDisposable).Dispose(); + } + } + + private string GetProtocolTransportName(TProtocol proto) + { + var name = Transport.GetType().Name; + if (name.Equals(MemBuffer.GetType().Name)) + name = string.Empty; + else + name = " + " + name; + + name = proto.GetType().Name + name; + return name; + } + + + private async Task RunTestAsync(Func<bool, Task<TProtocol>> factory) + { + var stop = new Stopwatch(); + + var proto = await factory(true); + stop.Start(); + await Testdata.WriteAsync(proto, Cancel.Token); + await Transport.FlushAsync(Cancel.Token); + stop.Stop(); + Console.WriteLine("RunTestAsync({0}): write = {1} msec", + GetProtocolTransportName(proto), + stop.ElapsedMilliseconds); + + var restored = new CrazyNesting(); + proto = await factory(false); + stop.Start(); + await restored.ReadAsync(proto, Cancel.Token); + stop.Stop(); + Console.WriteLine("RunTestAsync({0}): read = {1} msec", + GetProtocolTransportName(proto), + stop.ElapsedMilliseconds); + } + + } +} diff --git a/src/jaegertracing/thrift/test/netstd/Client/Performance/TestDataFactory.cs b/src/jaegertracing/thrift/test/netstd/Client/Performance/TestDataFactory.cs new file mode 100644 index 000000000..98962857c --- /dev/null +++ b/src/jaegertracing/thrift/test/netstd/Client/Performance/TestDataFactory.cs @@ -0,0 +1,154 @@ +// 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. + +using System; +using System.Collections.Generic; +using System.Text; +using ThriftTest; +using Thrift.Collections; + +namespace Client.Tests +{ + + static class TestDataFactory + { + public static CrazyNesting CreateCrazyNesting(int count = 10) + { + if (count <= 0) + return null; + + return new CrazyNesting() + { + Binary_field = CreateBytesArray(count), + List_field = CreateListField(count), + Set_field = CreateSetField(count), + String_field = string.Format("data level {0}", count) + }; + } + + private static THashSet<Insanity> CreateSetField(int count) + { + var retval = new THashSet<Insanity>(); + for (var i = 0; i < count; ++i) + retval.Add(CreateInsanity(count)); + return retval; + } + + private static Insanity CreateInsanity(int count) + { + return new Insanity() + { + UserMap = CreateUserMap(count), + Xtructs = CreateXtructs(count) + }; + } + + private static List<Xtruct> CreateXtructs(int count) + { + var retval = new List<Xtruct>(); + for (var i = 0; i < count; ++i) + retval.Add(CreateXtruct(count)); + return retval; + } + + private static Xtruct CreateXtruct(int count) + { + return new Xtruct() + { + Byte_thing = (sbyte)(count % 128), + I32_thing = count, + I64_thing = count, + String_thing = string.Format("data level {0}", count) + }; + } + + private static Dictionary<Numberz, long> CreateUserMap(int count) + { + var retval = new Dictionary<Numberz, long>(); + retval.Add(Numberz.ONE, count); + retval.Add(Numberz.TWO, count); + retval.Add(Numberz.THREE, count); + retval.Add(Numberz.FIVE, count); + retval.Add(Numberz.SIX, count); + retval.Add(Numberz.EIGHT, count); + return retval; + } + + private static List<Dictionary<THashSet<int>, Dictionary<int, THashSet<List<Dictionary<Insanity, string>>>>>> CreateListField(int count) + { + var retval = new List<Dictionary<THashSet<int>, Dictionary<int, THashSet<List<Dictionary<Insanity, string>>>>>>(); + for (var i = 0; i < count; ++i) + retval.Add(CreateListFieldData(count)); + return retval; + } + + private static Dictionary<THashSet<int>, Dictionary<int, THashSet<List<Dictionary<Insanity, string>>>>> CreateListFieldData(int count) + { + var retval = new Dictionary<THashSet<int>, Dictionary<int, THashSet<List<Dictionary<Insanity, string>>>>>(); + for (var i = 0; i < count; ++i) + retval.Add( CreateIntHashSet(count), CreateListFieldDataDict(count)); + return retval; + } + + private static THashSet<int> CreateIntHashSet(int count) + { + var retval = new THashSet<int>(); + for (var i = 0; i < count; ++i) + retval.Add(i); + return retval; + } + + private static Dictionary<int, THashSet<List<Dictionary<Insanity, string>>>> CreateListFieldDataDict(int count) + { + var retval = new Dictionary<int, THashSet<List<Dictionary<Insanity, string>>>>(); + for (var i = 0; i < count; ++i) + retval.Add(i, CreateListFieldDataDictValue(count)); + return retval; + } + + private static THashSet<List<Dictionary<Insanity, string>>> CreateListFieldDataDictValue(int count) + { + var retval = new THashSet<List<Dictionary<Insanity, string>>>(); + for (var i = 0; i < count; ++i) + retval.Add( CreateListFieldDataDictValueList(count)); + return retval; + } + + private static List<Dictionary<Insanity, string>> CreateListFieldDataDictValueList(int count) + { + var retval = new List<Dictionary<Insanity, string>>(); + for (var i = 0; i < count; ++i) + retval.Add(CreateListFieldDataDictValueListDict(count)); + return retval; + } + + private static Dictionary<Insanity, string> CreateListFieldDataDictValueListDict(int count) + { + var retval = new Dictionary<Insanity, string>(); + retval.Add(CreateInsanity(count), string.Format("data level {0}", count)); + return retval; + } + + private static byte[] CreateBytesArray(int count) + { + var retval = new byte[count]; + for (var i = 0; i < count; ++i) + retval[i] = (byte)(i % 0xFF); + return retval; + } + } +} diff --git a/src/jaegertracing/thrift/test/netstd/Client/Program.cs b/src/jaegertracing/thrift/test/netstd/Client/Program.cs new file mode 100644 index 000000000..62933e62e --- /dev/null +++ b/src/jaegertracing/thrift/test/netstd/Client/Program.cs @@ -0,0 +1,76 @@ +// 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. + +using System; +using System.Collections.Generic; +using ThriftTest; + +namespace Client +{ + public class Program + { + public static int Main(string[] args) + { + try + { + Console.SetBufferSize(Console.BufferWidth, 4096); + } + catch (Exception) + { + Console.WriteLine("Failed to grow scroll-back buffer"); + } + + // split mode and options + var subArgs = new List<string>(args); + var firstArg = string.Empty; + if (subArgs.Count > 0) + { + firstArg = subArgs[0]; + subArgs.RemoveAt(0); + } + + // run whatever mode is choosen + switch(firstArg) + { + case "client": + return TestClient.Execute(subArgs); + case "performance": + return Tests.PerformanceTests.Execute(); + case "--help": + PrintHelp(); + return 0; + default: + Console.WriteLine("Invalid argument: {0}", firstArg); + PrintHelp(); + return -1; + } + } + + private static void PrintHelp() + { + Console.WriteLine("Usage:"); + Console.WriteLine(" Client client [options]"); + Console.WriteLine(" Client performance"); + Console.WriteLine(" Client --help"); + Console.WriteLine(""); + + TestClient.PrintOptionsHelp(); + } + } +} + + diff --git a/src/jaegertracing/thrift/test/netstd/Client/Properties/AssemblyInfo.cs b/src/jaegertracing/thrift/test/netstd/Client/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..157152b4d --- /dev/null +++ b/src/jaegertracing/thrift/test/netstd/Client/Properties/AssemblyInfo.cs @@ -0,0 +1,43 @@ +// 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. +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +[assembly: AssemblyTitle("Client")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("The Apache Software Foundation")] +[assembly: AssemblyProduct("Thrift")] +[assembly: AssemblyCopyright("The Apache Software Foundation")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. + +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM + +[assembly: Guid("B0C13DA0-3117-4844-8AE8-B1775E46223D")] + diff --git a/src/jaegertracing/thrift/test/netstd/Client/TestClient.cs b/src/jaegertracing/thrift/test/netstd/Client/TestClient.cs new file mode 100644 index 000000000..0f58f95ed --- /dev/null +++ b/src/jaegertracing/thrift/test/netstd/Client/TestClient.cs @@ -0,0 +1,1051 @@ +// 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. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Net; +using System.Reflection; +using System.Security.Authentication; +using System.Security.Cryptography.X509Certificates; +using System.ServiceModel; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Thrift.Collections; +using Thrift.Protocol; +using Thrift.Transport; +using Thrift.Transport.Client; + +namespace ThriftTest +{ + internal enum ProtocolChoice + { + Binary, + Compact, + Json + } + + // it does not make much sense to use buffered when we already use framed + internal enum LayeredChoice + { + None, + Buffered, + Framed + } + + + internal enum TransportChoice + { + Socket, + TlsSocket, + Http, + NamedPipe + } + + public class TestClient + { + private class TestParams + { + public int numIterations = 1; + public string host = "localhost"; + public int port = 9090; + public int numThreads = 1; + public string url; + public string pipe; + public LayeredChoice layered = LayeredChoice.None; + public ProtocolChoice protocol = ProtocolChoice.Binary; + public TransportChoice transport = TransportChoice.Socket; + + internal void Parse(List<string> args) + { + for (var i = 0; i < args.Count; ++i) + { + if (args[i] == "-u") + { + url = args[++i]; + transport = TransportChoice.Http; + } + else if (args[i] == "-n") + { + numIterations = Convert.ToInt32(args[++i]); + } + else if (args[i].StartsWith("--pipe=")) + { + pipe = args[i].Substring(args[i].IndexOf("=") + 1); + transport = TransportChoice.NamedPipe; + } + else if (args[i].StartsWith("--host=")) + { + // check there for ipaddress + host = args[i].Substring(args[i].IndexOf("=") + 1); + if (transport != TransportChoice.TlsSocket) + transport = TransportChoice.Socket; + } + else if (args[i].StartsWith("--port=")) + { + port = int.Parse(args[i].Substring(args[i].IndexOf("=") + 1)); + if (transport != TransportChoice.TlsSocket) + transport = TransportChoice.Socket; + } + else if (args[i] == "-b" || args[i] == "--buffered" || args[i] == "--transport=buffered") + { + layered = LayeredChoice.Buffered; + } + else if (args[i] == "-f" || args[i] == "--framed" || args[i] == "--transport=framed") + { + layered = LayeredChoice.Framed; + } + else if (args[i] == "-t") + { + numThreads = Convert.ToInt32(args[++i]); + } + else if (args[i] == "--binary" || args[i] == "--protocol=binary") + { + protocol = ProtocolChoice.Binary; + } + else if (args[i] == "--compact" || args[i] == "--protocol=compact") + { + protocol = ProtocolChoice.Compact; + } + else if (args[i] == "--json" || args[i] == "--protocol=json") + { + protocol = ProtocolChoice.Json; + } + else if (args[i] == "--ssl") + { + transport = TransportChoice.TlsSocket; + } + else if (args[i] == "--help") + { + PrintOptionsHelp(); + return; + } + else + { + Console.WriteLine("Invalid argument: {0}", args[i]); + PrintOptionsHelp(); + return; + } + } + + switch (transport) + { + case TransportChoice.Socket: + Console.WriteLine("Using socket transport"); + break; + case TransportChoice.TlsSocket: + Console.WriteLine("Using encrypted transport"); + break; + case TransportChoice.Http: + Console.WriteLine("Using HTTP transport"); + break; + case TransportChoice.NamedPipe: + Console.WriteLine("Using named pipes transport"); + break; + default: // unhandled case + Debug.Assert(false); + break; + } + + switch (layered) + { + case LayeredChoice.Framed: + Console.WriteLine("Using framed transport"); + break; + case LayeredChoice.Buffered: + Console.WriteLine("Using buffered transport"); + break; + default: // unhandled case? + Debug.Assert(layered == LayeredChoice.None); + break; + } + + switch (protocol) + { + case ProtocolChoice.Binary: + Console.WriteLine("Using binary protocol"); + break; + case ProtocolChoice.Compact: + Console.WriteLine("Using compact protocol"); + break; + case ProtocolChoice.Json: + Console.WriteLine("Using JSON protocol"); + break; + default: // unhandled case? + Debug.Assert(false); + break; + } + } + + private static X509Certificate2 GetClientCert() + { + var clientCertName = "client.p12"; + var possiblePaths = new List<string> + { + "../../../keys/", + "../../keys/", + "../keys/", + "keys/", + }; + + string existingPath = null; + foreach (var possiblePath in possiblePaths) + { + var path = Path.GetFullPath(possiblePath + clientCertName); + if (File.Exists(path)) + { + existingPath = path; + break; + } + } + + if (string.IsNullOrEmpty(existingPath)) + { + throw new FileNotFoundException($"Cannot find file: {clientCertName}"); + } + + var cert = new X509Certificate2(existingPath, "thrift"); + + return cert; + } + + public TTransport CreateTransport() + { + // endpoint transport + TTransport trans = null; + + switch (transport) + { + case TransportChoice.Http: + Debug.Assert(url != null); + trans = new THttpTransport(new Uri(url), null); + break; + + case TransportChoice.NamedPipe: + Debug.Assert(pipe != null); + trans = new TNamedPipeTransport(pipe); + break; + + case TransportChoice.TlsSocket: + var cert = GetClientCert(); + if (cert == null || !cert.HasPrivateKey) + { + throw new InvalidOperationException("Certificate doesn't contain private key"); + } + + trans = new TTlsSocketTransport(host, port, 0, cert, + (sender, certificate, chain, errors) => true, + null, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12); + break; + + case TransportChoice.Socket: + default: + trans = new TSocketTransport(host, port); + break; + } + + + // layered transport + switch (layered) + { + case LayeredChoice.Buffered: + trans = new TBufferedTransport(trans); + break; + case LayeredChoice.Framed: + trans = new TFramedTransport(trans); + break; + default: + Debug.Assert(layered == LayeredChoice.None); + break; + } + + return trans; + } + + public TProtocol CreateProtocol(TTransport transport) + { + switch (protocol) + { + case ProtocolChoice.Compact: + return new TCompactProtocol(transport); + case ProtocolChoice.Json: + return new TJsonProtocol(transport); + case ProtocolChoice.Binary: + default: + return new TBinaryProtocol(transport); + } + } + } + + + private const int ErrorBaseTypes = 1; + private const int ErrorStructs = 2; + private const int ErrorContainers = 4; + private const int ErrorExceptions = 8; + private const int ErrorUnknown = 64; + + private class ClientTest + { + private readonly TTransport transport; + private readonly ThriftTest.Client client; + private readonly int numIterations; + private bool done; + + public int ReturnCode { get; set; } + + public ClientTest(TestParams param) + { + transport = param.CreateTransport(); + client = new ThriftTest.Client(param.CreateProtocol(transport)); + numIterations = param.numIterations; + } + + public void Execute() + { + if (done) + { + Console.WriteLine("Execute called more than once"); + throw new InvalidOperationException(); + } + + for (var i = 0; i < numIterations; i++) + { + try + { + if (!transport.IsOpen) + transport.OpenAsync(MakeTimeoutToken()).GetAwaiter().GetResult(); + } + catch (TTransportException ex) + { + Console.WriteLine("*** FAILED ***"); + Console.WriteLine("Connect failed: " + ex.Message); + ReturnCode |= ErrorUnknown; + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + continue; + } + catch (Exception ex) + { + Console.WriteLine("*** FAILED ***"); + Console.WriteLine("Connect failed: " + ex.Message); + ReturnCode |= ErrorUnknown; + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + continue; + } + + try + { + ReturnCode |= ExecuteClientTestAsync(client).GetAwaiter().GetResult(); ; + } + catch (Exception ex) + { + Console.WriteLine("*** FAILED ***"); + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + ReturnCode |= ErrorUnknown; + } + } + try + { + transport.Close(); + } + catch (Exception ex) + { + Console.WriteLine("Error while closing transport"); + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + } + done = true; + } + } + + internal static void PrintOptionsHelp() + { + Console.WriteLine("Client options:"); + Console.WriteLine(" -u <URL>"); + Console.WriteLine(" -t <# of threads to run> default = 1"); + Console.WriteLine(" -n <# of iterations> per thread"); + Console.WriteLine(" --pipe=<pipe name>"); + Console.WriteLine(" --host=<IP address>"); + Console.WriteLine(" --port=<port number>"); + Console.WriteLine(" --transport=<transport name> one of buffered,framed (defaults to none)"); + Console.WriteLine(" --protocol=<protocol name> one of compact,json (defaults to binary)"); + Console.WriteLine(" --ssl"); + Console.WriteLine(); + } + + public static int Execute(List<string> args) + { + try + { + var param = new TestParams(); + + try + { + param.Parse(args); + } + catch (Exception ex) + { + Console.WriteLine("*** FAILED ***"); + Console.WriteLine("Error while parsing arguments"); + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + return ErrorUnknown; + } + + var tests = Enumerable.Range(0, param.numThreads).Select(_ => new ClientTest(param)).ToArray(); + + //issue tests on separate threads simultaneously + var threads = tests.Select(test => new Task(test.Execute)).ToArray(); + var start = DateTime.Now; + foreach (var t in threads) + { + t.Start(); + } + + Task.WaitAll(threads); + + Console.WriteLine("Total time: " + (DateTime.Now - start)); + Console.WriteLine(); + return tests.Select(t => t.ReturnCode).Aggregate((r1, r2) => r1 | r2); + } + catch (Exception outerEx) + { + Console.WriteLine("*** FAILED ***"); + Console.WriteLine("Unexpected error"); + Console.WriteLine(outerEx.Message + " ST: " + outerEx.StackTrace); + return ErrorUnknown; + } + } + + public static string BytesToHex(byte[] data) + { + return BitConverter.ToString(data).Replace("-", string.Empty); + } + + + public enum BinaryTestSize + { + Empty, // Edge case: the zero-length empty binary + Normal, // Fairly small array of usual size (256 bytes) + Large, // Large writes/reads may cause range check errors + PipeWriteLimit, // Windows Limit: Pipe write operations across a network are limited to 65,535 bytes per write. + TwentyMB // that's quite a bit of data + }; + + public static byte[] PrepareTestData(bool randomDist, BinaryTestSize testcase) + { + int amount = -1; + switch (testcase) + { + case BinaryTestSize.Empty: + amount = 0; + break; + case BinaryTestSize.Normal: + amount = 0x100; + break; + case BinaryTestSize.Large: + amount = 0x8000 + 128; + break; + case BinaryTestSize.PipeWriteLimit: + amount = 0xFFFF + 128; + break; + case BinaryTestSize.TwentyMB: + amount = 20 * 1024 * 1024; + break; + default: + throw new ArgumentException(nameof(testcase)); + } + + var retval = new byte[amount]; + + // linear distribution, unless random is requested + if (!randomDist) + { + for (var i = 0; i < retval.Length; ++i) + { + retval[i] = (byte)i; + } + return retval; + } + + // random distribution + var rnd = new Random(); + for (var i = 1; i < retval.Length; ++i) + { + retval[i] = (byte)rnd.Next(0x100); + } + return retval; + } + + private static CancellationToken MakeTimeoutToken(int msec = 5000) + { + var token = new CancellationTokenSource(msec); + return token.Token; + } + + public static async Task<int> ExecuteClientTestAsync(ThriftTest.Client client) + { + var returnCode = 0; + + Console.Write("testVoid()"); + await client.testVoidAsync(MakeTimeoutToken()); + Console.WriteLine(" = void"); + + Console.Write("testString(\"Test\")"); + var s = await client.testStringAsync("Test", MakeTimeoutToken()); + Console.WriteLine(" = \"" + s + "\""); + if ("Test" != s) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + + Console.Write("testBool(true)"); + var t = await client.testBoolAsync((bool)true, MakeTimeoutToken()); + Console.WriteLine(" = " + t); + if (!t) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + Console.Write("testBool(false)"); + var f = await client.testBoolAsync((bool)false, MakeTimeoutToken()); + Console.WriteLine(" = " + f); + if (f) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + + Console.Write("testByte(1)"); + var i8 = await client.testByteAsync((sbyte)1, MakeTimeoutToken()); + Console.WriteLine(" = " + i8); + if (1 != i8) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + + Console.Write("testI32(-1)"); + var i32 = await client.testI32Async(-1, MakeTimeoutToken()); + Console.WriteLine(" = " + i32); + if (-1 != i32) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + + Console.Write("testI64(-34359738368)"); + var i64 = await client.testI64Async(-34359738368, MakeTimeoutToken()); + Console.WriteLine(" = " + i64); + if (-34359738368 != i64) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + + // TODO: Validate received message + Console.Write("testDouble(5.325098235)"); + var dub = await client.testDoubleAsync(5.325098235, MakeTimeoutToken()); + Console.WriteLine(" = " + dub); + if (5.325098235 != dub) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + Console.Write("testDouble(-0.000341012439638598279)"); + dub = await client.testDoubleAsync(-0.000341012439638598279, MakeTimeoutToken()); + Console.WriteLine(" = " + dub); + if (-0.000341012439638598279 != dub) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + + // testBinary() + foreach(BinaryTestSize binTestCase in Enum.GetValues(typeof(BinaryTestSize))) + { + var binOut = PrepareTestData(true, binTestCase); + + Console.Write("testBinary({0} bytes)", binOut.Length); + try + { + var binIn = await client.testBinaryAsync(binOut, MakeTimeoutToken()); + Console.WriteLine(" = {0} bytes", binIn.Length); + if (binIn.Length != binOut.Length) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + for (var ofs = 0; ofs < Math.Min(binIn.Length, binOut.Length); ++ofs) + { + if (binIn[ofs] != binOut[ofs]) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + } + } + catch (Thrift.TApplicationException ex) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + } + } + + // CrazyNesting + Console.WriteLine("Test CrazyNesting"); + var one = new CrazyNesting(); + var two = new CrazyNesting(); + one.String_field = "crazy"; + two.String_field = "crazy"; + one.Binary_field = new byte[] { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0xFF }; + two.Binary_field = new byte[10] { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0xFF }; + if (typeof(CrazyNesting).GetMethod("Equals")?.DeclaringType == typeof(CrazyNesting)) + { + if (!one.Equals(two)) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorContainers; + throw new Exception("CrazyNesting.Equals failed"); + } + } + + // TODO: Validate received message + Console.Write("testStruct({\"Zero\", 1, -3, -5})"); + var o = new Xtruct(); + o.String_thing = "Zero"; + o.Byte_thing = (sbyte)1; + o.I32_thing = -3; + o.I64_thing = -5; + var i = await client.testStructAsync(o, MakeTimeoutToken()); + Console.WriteLine(" = {\"" + i.String_thing + "\", " + i.Byte_thing + ", " + i.I32_thing + ", " + i.I64_thing + "}"); + + // TODO: Validate received message + Console.Write("testNest({1, {\"Zero\", 1, -3, -5}, 5})"); + var o2 = new Xtruct2(); + o2.Byte_thing = (sbyte)1; + o2.Struct_thing = o; + o2.I32_thing = 5; + var i2 = await client.testNestAsync(o2, MakeTimeoutToken()); + i = i2.Struct_thing; + Console.WriteLine(" = {" + i2.Byte_thing + ", {\"" + i.String_thing + "\", " + i.Byte_thing + ", " + i.I32_thing + ", " + i.I64_thing + "}, " + i2.I32_thing + "}"); + + var mapout = new Dictionary<int, int>(); + for (var j = 0; j < 5; j++) + { + mapout[j] = j - 10; + } + Console.Write("testMap({"); + var first = true; + foreach (var key in mapout.Keys) + { + if (first) + { + first = false; + } + else + { + Console.Write(", "); + } + Console.Write(key + " => " + mapout[key]); + } + Console.Write("})"); + + var mapin = await client.testMapAsync(mapout, MakeTimeoutToken()); + + Console.Write(" = {"); + first = true; + foreach (var key in mapin.Keys) + { + if (first) + { + first = false; + } + else + { + Console.Write(", "); + } + Console.Write(key + " => " + mapin[key]); + } + Console.WriteLine("}"); + + // TODO: Validate received message + var listout = new List<int>(); + for (var j = -2; j < 3; j++) + { + listout.Add(j); + } + Console.Write("testList({"); + first = true; + foreach (var j in listout) + { + if (first) + { + first = false; + } + else + { + Console.Write(", "); + } + Console.Write(j); + } + Console.Write("})"); + + var listin = await client.testListAsync(listout, MakeTimeoutToken()); + + Console.Write(" = {"); + first = true; + foreach (var j in listin) + { + if (first) + { + first = false; + } + else + { + Console.Write(", "); + } + Console.Write(j); + } + Console.WriteLine("}"); + + //set + // TODO: Validate received message + var setout = new THashSet<int>(); + for (var j = -2; j < 3; j++) + { + setout.Add(j); + } + Console.Write("testSet({"); + first = true; + foreach (int j in setout) + { + if (first) + { + first = false; + } + else + { + Console.Write(", "); + } + Console.Write(j); + } + Console.Write("})"); + + var setin = await client.testSetAsync(setout, MakeTimeoutToken()); + + Console.Write(" = {"); + first = true; + foreach (int j in setin) + { + if (first) + { + first = false; + } + else + { + Console.Write(", "); + } + Console.Write(j); + } + Console.WriteLine("}"); + + + Console.Write("testEnum(ONE)"); + var ret = await client.testEnumAsync(Numberz.ONE, MakeTimeoutToken()); + Console.WriteLine(" = " + ret); + if (Numberz.ONE != ret) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorStructs; + } + + Console.Write("testEnum(TWO)"); + ret = await client.testEnumAsync(Numberz.TWO, MakeTimeoutToken()); + Console.WriteLine(" = " + ret); + if (Numberz.TWO != ret) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorStructs; + } + + Console.Write("testEnum(THREE)"); + ret = await client.testEnumAsync(Numberz.THREE, MakeTimeoutToken()); + Console.WriteLine(" = " + ret); + if (Numberz.THREE != ret) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorStructs; + } + + Console.Write("testEnum(FIVE)"); + ret = await client.testEnumAsync(Numberz.FIVE, MakeTimeoutToken()); + Console.WriteLine(" = " + ret); + if (Numberz.FIVE != ret) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorStructs; + } + + Console.Write("testEnum(EIGHT)"); + ret = await client.testEnumAsync(Numberz.EIGHT, MakeTimeoutToken()); + Console.WriteLine(" = " + ret); + if (Numberz.EIGHT != ret) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorStructs; + } + + Console.Write("testTypedef(309858235082523)"); + var uid = await client.testTypedefAsync(309858235082523L, MakeTimeoutToken()); + Console.WriteLine(" = " + uid); + if (309858235082523L != uid) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorStructs; + } + + // TODO: Validate received message + Console.Write("testMapMap(1)"); + var mm = await client.testMapMapAsync(1, MakeTimeoutToken()); + Console.Write(" = {"); + foreach (var key in mm.Keys) + { + Console.Write(key + " => {"); + var m2 = mm[key]; + foreach (var k2 in m2.Keys) + { + Console.Write(k2 + " => " + m2[k2] + ", "); + } + Console.Write("}, "); + } + Console.WriteLine("}"); + + // TODO: Validate received message + var insane = new Insanity(); + insane.UserMap = new Dictionary<Numberz, long>(); + insane.UserMap[Numberz.FIVE] = 5000L; + var truck = new Xtruct(); + truck.String_thing = "Truck"; + truck.Byte_thing = (sbyte)8; + truck.I32_thing = 8; + truck.I64_thing = 8; + insane.Xtructs = new List<Xtruct>(); + insane.Xtructs.Add(truck); + Console.Write("testInsanity()"); + var whoa = await client.testInsanityAsync(insane, MakeTimeoutToken()); + Console.Write(" = {"); + foreach (var key in whoa.Keys) + { + var val = whoa[key]; + Console.Write(key + " => {"); + + foreach (var k2 in val.Keys) + { + var v2 = val[k2]; + + Console.Write(k2 + " => {"); + var userMap = v2.UserMap; + + Console.Write("{"); + if (userMap != null) + { + foreach (var k3 in userMap.Keys) + { + Console.Write(k3 + " => " + userMap[k3] + ", "); + } + } + else + { + Console.Write("null"); + } + Console.Write("}, "); + + var xtructs = v2.Xtructs; + + Console.Write("{"); + if (xtructs != null) + { + foreach (var x in xtructs) + { + Console.Write("{\"" + x.String_thing + "\", " + x.Byte_thing + ", " + x.I32_thing + ", " + x.I32_thing + "}, "); + } + } + else + { + Console.Write("null"); + } + Console.Write("}"); + + Console.Write("}, "); + } + Console.Write("}, "); + } + Console.WriteLine("}"); + + sbyte arg0 = 1; + var arg1 = 2; + var arg2 = long.MaxValue; + var multiDict = new Dictionary<short, string>(); + multiDict[1] = "one"; + + var tmpMultiDict = new List<string>(); + foreach (var pair in multiDict) + tmpMultiDict.Add(pair.Key +" => "+ pair.Value); + + var arg4 = Numberz.FIVE; + long arg5 = 5000000; + Console.Write("Test Multi(" + arg0 + "," + arg1 + "," + arg2 + ",{" + string.Join(",", tmpMultiDict) + "}," + arg4 + "," + arg5 + ")"); + var multiResponse = await client.testMultiAsync(arg0, arg1, arg2, multiDict, arg4, arg5, MakeTimeoutToken()); + Console.Write(" = Xtruct(byte_thing:" + multiResponse.Byte_thing + ",String_thing:" + multiResponse.String_thing + + ",i32_thing:" + multiResponse.I32_thing + ",i64_thing:" + multiResponse.I64_thing + ")\n"); + + try + { + Console.WriteLine("testException(\"Xception\")"); + await client.testExceptionAsync("Xception", MakeTimeoutToken()); + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + } + catch (Xception ex) + { + if (ex.ErrorCode != 1001 || ex.Message != "Xception") + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + } + } + catch (Exception ex) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + } + try + { + Console.WriteLine("testException(\"TException\")"); + await client.testExceptionAsync("TException", MakeTimeoutToken()); + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + } + catch (Thrift.TException) + { + // OK + } + catch (Exception ex) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + } + try + { + Console.WriteLine("testException(\"ok\")"); + await client.testExceptionAsync("ok", MakeTimeoutToken()); + // OK + } + catch (Exception ex) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + } + + try + { + Console.WriteLine("testMultiException(\"Xception\", ...)"); + await client.testMultiExceptionAsync("Xception", "ignore", MakeTimeoutToken()); + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + } + catch (Xception ex) + { + if (ex.ErrorCode != 1001 || ex.Message != "This is an Xception") + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + } + } + catch (Exception ex) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + } + try + { + Console.WriteLine("testMultiException(\"Xception2\", ...)"); + await client.testMultiExceptionAsync("Xception2", "ignore", MakeTimeoutToken()); + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + } + catch (Xception2 ex) + { + if (ex.ErrorCode != 2002 || ex.Struct_thing.String_thing != "This is an Xception2") + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + } + } + catch (Exception ex) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + } + try + { + Console.WriteLine("testMultiException(\"success\", \"OK\")"); + if ("OK" != (await client.testMultiExceptionAsync("success", "OK", MakeTimeoutToken())).String_thing) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + } + } + catch (Exception ex) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + } + + Console.WriteLine("Test Oneway(1)"); + var sw = new Stopwatch(); + sw.Start(); + await client.testOnewayAsync(1, MakeTimeoutToken()); + sw.Stop(); + if (sw.ElapsedMilliseconds > 1000) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + + Console.Write("Test Calltime()"); + var times = 50; + sw.Reset(); + sw.Start(); + var token = MakeTimeoutToken(20000); + for (var k = 0; k < times; ++k) + await client.testVoidAsync(token); + sw.Stop(); + Console.WriteLine(" = {0} ms a testVoid() call", sw.ElapsedMilliseconds / times); + return returnCode; + } + } +} diff --git a/src/jaegertracing/thrift/test/netstd/Makefile.am b/src/jaegertracing/thrift/test/netstd/Makefile.am new file mode 100644 index 000000000..376ffb71e --- /dev/null +++ b/src/jaegertracing/thrift/test/netstd/Makefile.am @@ -0,0 +1,41 @@ +# +# 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. +# + +SUBDIRS = . + +all-local: + $(DOTNETCORE) build + +precross: + $(DOTNETCORE) build + +clean-local: + $(RM) -r Client/bin + $(RM) -r Server/bin + $(RM) -r Client/obj + $(RM) -r Server/obj + $(RM) -r ThriftTest/ThriftTest + +EXTRA_DIST = \ + Client \ + README.md \ + Server \ + ThriftTest.sln \ + build.cmd \ + build.sh diff --git a/src/jaegertracing/thrift/test/netstd/README.md b/src/jaegertracing/thrift/test/netstd/README.md new file mode 100644 index 000000000..ed728d1ba --- /dev/null +++ b/src/jaegertracing/thrift/test/netstd/README.md @@ -0,0 +1,20 @@ +# Apache Thrift net-core-lib tests + +Tests for Thrift client library ported to Microsoft .Net Core + +# Content +- ThriftTest - tests for Thrift library + +# Reused components +- NET Core Standard 1.6 (SDK 2.0.0) + +# How to build on Windows +- Get Thrift IDL compiler executable, add to some folder and add path to this folder into PATH variable +- Open ThriftTest.sln in Visual Studio and build +or +- Build with scripts + +# How to build on Unix +- Ensure you have .NET Core 2.0.0 SDK installed or use the Ubuntu Xenial docker image +- Follow common build practice for Thrift: bootstrap, configure, and make precross + diff --git a/src/jaegertracing/thrift/test/netstd/Server/.gitignore b/src/jaegertracing/thrift/test/netstd/Server/.gitignore new file mode 100644 index 000000000..67d55106a --- /dev/null +++ b/src/jaegertracing/thrift/test/netstd/Server/.gitignore @@ -0,0 +1,2 @@ +# ignore for autogenerated files +/ThriftTest diff --git a/src/jaegertracing/thrift/test/netstd/Server/Program.cs b/src/jaegertracing/thrift/test/netstd/Server/Program.cs new file mode 100644 index 000000000..8bfa3714f --- /dev/null +++ b/src/jaegertracing/thrift/test/netstd/Server/Program.cs @@ -0,0 +1,73 @@ +// 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. + +using System; +using System.Collections.Generic; +using ThriftTest; + +namespace Server +{ + public class Program + { + public static int Main(string[] args) + { + try + { + Console.SetBufferSize(Console.BufferWidth, 4096); + } + catch (Exception) + { + Console.WriteLine("Failed to grow scroll-back buffer"); + } + + // split mode and options + var subArgs = new List<string>(args); + var firstArg = string.Empty; + if (subArgs.Count > 0) + { + firstArg = subArgs[0]; + subArgs.RemoveAt(0); + } + + // run whatever mode is choosen + switch(firstArg) + { + case "server": + return TestServer.Execute(subArgs); + case "--help": + PrintHelp(); + return 0; + default: + Console.WriteLine("Invalid argument: {0}", firstArg); + PrintHelp(); + return -1; + } + } + + private static void PrintHelp() + { + Console.WriteLine("Usage:"); + Console.WriteLine(" Server server [options]'"); + Console.WriteLine(" Server --help"); + Console.WriteLine(""); + + ServerParam.PrintOptionsHelp(); + } + } +} + + diff --git a/src/jaegertracing/thrift/test/netstd/Server/Properties/AssemblyInfo.cs b/src/jaegertracing/thrift/test/netstd/Server/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..265495c05 --- /dev/null +++ b/src/jaegertracing/thrift/test/netstd/Server/Properties/AssemblyInfo.cs @@ -0,0 +1,43 @@ +// 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. +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +[assembly: AssemblyTitle("Server")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("The Apache Software Foundation")] +[assembly: AssemblyProduct("Thrift")] +[assembly: AssemblyCopyright("The Apache Software Foundation")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. + +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM + +[assembly: Guid("B0C13DA0-3117-4844-8AE8-B1775E46223D")] + diff --git a/src/jaegertracing/thrift/test/netstd/Server/Server.csproj b/src/jaegertracing/thrift/test/netstd/Server/Server.csproj new file mode 100644 index 000000000..44f46c90c --- /dev/null +++ b/src/jaegertracing/thrift/test/netstd/Server/Server.csproj @@ -0,0 +1,52 @@ +<Project Sdk="Microsoft.NET.Sdk"> + <!-- + 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. + --> + + <PropertyGroup> + <TargetFramework>netcoreapp2.0</TargetFramework> + <AssemblyName>Server</AssemblyName> + <PackageId>Server</PackageId> + <OutputType>Exe</OutputType> + <GenerateAssemblyTitleAttribute>false</GenerateAssemblyTitleAttribute> + <GenerateAssemblyDescriptionAttribute>false</GenerateAssemblyDescriptionAttribute> + <GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> + <GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> + <GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> + <GenerateAssemblyCopyrightAttribute>false</GenerateAssemblyCopyrightAttribute> + </PropertyGroup> + <ItemGroup> + <PackageReference Include="System.IO.Pipes" Version="4.3.0" /> + <PackageReference Include="System.IO.Pipes.AccessControl" Version="4.5.1" /> + <PackageReference Include="System.Net.Http.WinHttpHandler" Version="4.5.2" /> + <PackageReference Include="System.Runtime.Serialization.Primitives" Version="[4.3,)" /> + <PackageReference Include="System.ServiceModel.Primitives" Version="4.5.3" /> + <PackageReference Include="System.Threading" Version="[4.3,)" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\..\..\lib\netstd\Thrift\Thrift.csproj" /> + </ItemGroup> + <Target Name="PreBuild" BeforeTargets="_GenerateRestoreProjectSpec;Restore;Compile"> + <Exec Condition="'$(OS)' == 'Windows_NT'" Command="where thrift" ConsoleToMSBuild="true"> + <Output TaskParameter="ConsoleOutput" PropertyName="PathToThrift" /> + </Exec> + <Exec Condition="Exists('$(PathToThrift)')" Command=""$(PathToThrift)" -out $(ProjectDir) -gen netstd:wcf,union,serial -r ./../../ThriftTest.thrift" /> + <Exec Condition="Exists('thrift')" Command="thrift -out $(ProjectDir) -gen netstd:wcf,union,serial -r ./../../ThriftTest.thrift" /> + <Exec Condition="Exists('$(ProjectDir)/../../../compiler/cpp/thrift')" Command="$(ProjectDir)/../../../compiler/cpp/thrift -out $(ProjectDir) -gen netstd:wcf,union,serial -r ./../../ThriftTest.thrift" /> + </Target> +</Project>
\ No newline at end of file diff --git a/src/jaegertracing/thrift/test/netstd/Server/TestServer.cs b/src/jaegertracing/thrift/test/netstd/Server/TestServer.cs new file mode 100644 index 000000000..25c2afc1f --- /dev/null +++ b/src/jaegertracing/thrift/test/netstd/Server/TestServer.cs @@ -0,0 +1,642 @@ +// 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. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Security.Authentication; +using System.Security.Cryptography.X509Certificates; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Thrift; +using Thrift.Collections; +using Thrift.Processor; +using Thrift.Protocol; +using Thrift.Server; +using Thrift.Transport; +using Thrift.Transport.Server; + +namespace ThriftTest +{ + internal enum ProtocolChoice + { + Binary, + Compact, + Json + } + + internal enum TransportChoice + { + Socket, + TlsSocket, + NamedPipe + } + + internal enum BufferChoice + { + None, + Buffered, + Framed + } + + internal class ServerParam + { + internal BufferChoice buffering = BufferChoice.None; + internal ProtocolChoice protocol = ProtocolChoice.Binary; + internal TransportChoice transport = TransportChoice.Socket; + internal int port = 9090; + internal string pipe = null; + + internal void Parse(List<string> args) + { + for (var i = 0; i < args.Count; i++) + { + if (args[i].StartsWith("--pipe=")) + { + pipe = args[i].Substring(args[i].IndexOf("=") + 1); + transport = TransportChoice.NamedPipe; + } + else if (args[i].StartsWith("--port=")) + { + port = int.Parse(args[i].Substring(args[i].IndexOf("=") + 1)); + if(transport != TransportChoice.TlsSocket) + transport = TransportChoice.Socket; + } + else if (args[i] == "-b" || args[i] == "--buffered" || args[i] == "--transport=buffered") + { + buffering = BufferChoice.Buffered; + } + else if (args[i] == "-f" || args[i] == "--framed" || args[i] == "--transport=framed") + { + buffering = BufferChoice.Framed; + } + else if (args[i] == "--binary" || args[i] == "--protocol=binary") + { + protocol = ProtocolChoice.Binary; + } + else if (args[i] == "--compact" || args[i] == "--protocol=compact") + { + protocol = ProtocolChoice.Compact; + } + else if (args[i] == "--json" || args[i] == "--protocol=json") + { + protocol = ProtocolChoice.Json; + } + else if (args[i] == "--threaded" || args[i] == "--server-type=threaded") + { + throw new NotImplementedException(args[i]); + } + else if (args[i] == "--threadpool" || args[i] == "--server-type=threadpool") + { + throw new NotImplementedException(args[i]); + } + else if (args[i] == "--prototype" || args[i] == "--processor=prototype") + { + throw new NotImplementedException(args[i]); + } + else if (args[i] == "--ssl") + { + transport = TransportChoice.TlsSocket; + } + else if (args[i] == "--help") + { + PrintOptionsHelp(); + return; + } + else + { + Console.WriteLine("Invalid argument: {0}", args[i]); + PrintOptionsHelp(); + return; + } + } + + } + + internal static void PrintOptionsHelp() + { + Console.WriteLine("Server options:"); + Console.WriteLine(" --pipe=<pipe name>"); + Console.WriteLine(" --port=<port number>"); + Console.WriteLine(" --transport=<transport name> one of buffered,framed (defaults to none)"); + Console.WriteLine(" --protocol=<protocol name> one of compact,json (defaults to binary)"); + Console.WriteLine(" --server-type=<type> one of threaded,threadpool (defaults to simple)"); + Console.WriteLine(" --processor=<prototype>"); + Console.WriteLine(" --ssl"); + Console.WriteLine(); + } + } + + public class TestServer + { + public static int _clientID = -1; + public delegate void TestLogDelegate(string msg, params object[] values); + + public class MyServerEventHandler : TServerEventHandler + { + public int callCount = 0; + + public Task PreServeAsync(CancellationToken cancellationToken) + { + callCount++; + return Task.CompletedTask; + } + + public Task<object> CreateContextAsync(TProtocol input, TProtocol output, CancellationToken cancellationToken) + { + callCount++; + return Task.FromResult<object>(null); + } + + public Task DeleteContextAsync(object serverContext, TProtocol input, TProtocol output, CancellationToken cancellationToken) + { + callCount++; + return Task.CompletedTask; + } + + public Task ProcessContextAsync(object serverContext, TTransport transport, CancellationToken cancellationToken) + { + callCount++; + return Task.CompletedTask; + } + } + + public class TestHandlerAsync : ThriftTest.IAsync + { + public TServer server { get; set; } + private int handlerID; + private StringBuilder sb = new StringBuilder(); + private TestLogDelegate logger; + + public TestHandlerAsync() + { + handlerID = Interlocked.Increment(ref _clientID); + logger += testConsoleLogger; + logger.Invoke("New TestHandler instance created"); + } + + public void testConsoleLogger(string msg, params object[] values) + { + sb.Clear(); + sb.AppendFormat("handler{0:D3}:", handlerID); + sb.AppendFormat(msg, values); + sb.AppendLine(); + Console.Write(sb.ToString()); + } + + public Task testVoidAsync(CancellationToken cancellationToken) + { + logger.Invoke("testVoid()"); + return Task.CompletedTask; + } + + public Task<string> testStringAsync(string thing, CancellationToken cancellationToken) + { + logger.Invoke("testString({0})", thing); + return Task.FromResult(thing); + } + + public Task<bool> testBoolAsync(bool thing, CancellationToken cancellationToken) + { + logger.Invoke("testBool({0})", thing); + return Task.FromResult(thing); + } + + public Task<sbyte> testByteAsync(sbyte thing, CancellationToken cancellationToken) + { + logger.Invoke("testByte({0})", thing); + return Task.FromResult(thing); + } + + public Task<int> testI32Async(int thing, CancellationToken cancellationToken) + { + logger.Invoke("testI32({0})", thing); + return Task.FromResult(thing); + } + + public Task<long> testI64Async(long thing, CancellationToken cancellationToken) + { + logger.Invoke("testI64({0})", thing); + return Task.FromResult(thing); + } + + public Task<double> testDoubleAsync(double thing, CancellationToken cancellationToken) + { + logger.Invoke("testDouble({0})", thing); + return Task.FromResult(thing); + } + + public Task<byte[]> testBinaryAsync(byte[] thing, CancellationToken cancellationToken) + { + logger.Invoke("testBinary({0} bytes)", thing.Length); + return Task.FromResult(thing); + } + + public Task<Xtruct> testStructAsync(Xtruct thing, CancellationToken cancellationToken) + { + logger.Invoke("testStruct({{\"{0}\", {1}, {2}, {3}}})", thing.String_thing, thing.Byte_thing, thing.I32_thing, thing.I64_thing); + return Task.FromResult(thing); + } + + public Task<Xtruct2> testNestAsync(Xtruct2 nest, CancellationToken cancellationToken) + { + var thing = nest.Struct_thing; + logger.Invoke("testNest({{{0}, {{\"{1}\", {2}, {3}, {4}, {5}}}}})", + nest.Byte_thing, + thing.String_thing, + thing.Byte_thing, + thing.I32_thing, + thing.I64_thing, + nest.I32_thing); + return Task.FromResult(nest); + } + + public Task<Dictionary<int, int>> testMapAsync(Dictionary<int, int> thing, CancellationToken cancellationToken) + { + sb.Clear(); + sb.Append("testMap({{"); + var first = true; + foreach (var key in thing.Keys) + { + if (first) + { + first = false; + } + else + { + sb.Append(", "); + } + sb.AppendFormat("{0} => {1}", key, thing[key]); + } + sb.Append("}})"); + logger.Invoke(sb.ToString()); + return Task.FromResult(thing); + } + + public Task<Dictionary<string, string>> testStringMapAsync(Dictionary<string, string> thing, CancellationToken cancellationToken) + { + sb.Clear(); + sb.Append("testStringMap({{"); + var first = true; + foreach (var key in thing.Keys) + { + if (first) + { + first = false; + } + else + { + sb.Append(", "); + } + sb.AppendFormat("{0} => {1}", key, thing[key]); + } + sb.Append("}})"); + logger.Invoke(sb.ToString()); + return Task.FromResult(thing); + } + + public Task<THashSet<int>> testSetAsync(THashSet<int> thing, CancellationToken cancellationToken) + { + sb.Clear(); + sb.Append("testSet({{"); + var first = true; + foreach (int elem in thing) + { + if (first) + { + first = false; + } + else + { + sb.Append(", "); + } + sb.AppendFormat("{0}", elem); + } + sb.Append("}})"); + logger.Invoke(sb.ToString()); + return Task.FromResult(thing); + } + + public Task<List<int>> testListAsync(List<int> thing, CancellationToken cancellationToken) + { + sb.Clear(); + sb.Append("testList({{"); + var first = true; + foreach (var elem in thing) + { + if (first) + { + first = false; + } + else + { + sb.Append(", "); + } + sb.AppendFormat("{0}", elem); + } + sb.Append("}})"); + logger.Invoke(sb.ToString()); + return Task.FromResult(thing); + } + + public Task<Numberz> testEnumAsync(Numberz thing, CancellationToken cancellationToken) + { + logger.Invoke("testEnum({0})", thing); + return Task.FromResult(thing); + } + + public Task<long> testTypedefAsync(long thing, CancellationToken cancellationToken) + { + logger.Invoke("testTypedef({0})", thing); + return Task.FromResult(thing); + } + + public Task<Dictionary<int, Dictionary<int, int>>> testMapMapAsync(int hello, CancellationToken cancellationToken) + { + logger.Invoke("testMapMap({0})", hello); + var mapmap = new Dictionary<int, Dictionary<int, int>>(); + + var pos = new Dictionary<int, int>(); + var neg = new Dictionary<int, int>(); + for (var i = 1; i < 5; i++) + { + pos[i] = i; + neg[-i] = -i; + } + + mapmap[4] = pos; + mapmap[-4] = neg; + + return Task.FromResult(mapmap); + } + + public Task<Dictionary<long, Dictionary<Numberz, Insanity>>> testInsanityAsync(Insanity argument, CancellationToken cancellationToken) + { + logger.Invoke("testInsanity()"); + + /** from ThriftTest.thrift: + * So you think you've got this all worked, out eh? + * + * Creates a the returned map with these values and prints it out: + * { 1 => { 2 => argument, + * 3 => argument, + * }, + * 2 => { 6 => <empty Insanity struct>, }, + * } + * @return map<UserId, map<Numberz,Insanity>> - a map with the above values + */ + + var first_map = new Dictionary<Numberz, Insanity>(); + var second_map = new Dictionary<Numberz, Insanity>(); ; + + first_map[Numberz.TWO] = argument; + first_map[Numberz.THREE] = argument; + + second_map[Numberz.SIX] = new Insanity(); + + var insane = new Dictionary<long, Dictionary<Numberz, Insanity>> + { + [1] = first_map, + [2] = second_map + }; + + return Task.FromResult(insane); + } + + public Task<Xtruct> testMultiAsync(sbyte arg0, int arg1, long arg2, Dictionary<short, string> arg3, Numberz arg4, long arg5, + CancellationToken cancellationToken) + { + logger.Invoke("testMulti()"); + + var hello = new Xtruct(); ; + hello.String_thing = "Hello2"; + hello.Byte_thing = arg0; + hello.I32_thing = arg1; + hello.I64_thing = arg2; + return Task.FromResult(hello); + } + + public Task testExceptionAsync(string arg, CancellationToken cancellationToken) + { + logger.Invoke("testException({0})", arg); + if (arg == "Xception") + { + var x = new Xception + { + ErrorCode = 1001, + Message = arg + }; + throw x; + } + if (arg == "TException") + { + throw new TException(); + } + return Task.CompletedTask; + } + + public Task<Xtruct> testMultiExceptionAsync(string arg0, string arg1, CancellationToken cancellationToken) + { + logger.Invoke("testMultiException({0}, {1})", arg0, arg1); + if (arg0 == "Xception") + { + var x = new Xception + { + ErrorCode = 1001, + Message = "This is an Xception" + }; + throw x; + } + + if (arg0 == "Xception2") + { + var x = new Xception2 + { + ErrorCode = 2002, + Struct_thing = new Xtruct { String_thing = "This is an Xception2" } + }; + throw x; + } + + var result = new Xtruct { String_thing = arg1 }; + return Task.FromResult(result); + } + + public Task testOnewayAsync(int secondsToSleep, CancellationToken cancellationToken) + { + logger.Invoke("testOneway({0}), sleeping...", secondsToSleep); + Task.Delay(secondsToSleep * 1000, cancellationToken).GetAwaiter().GetResult(); + logger.Invoke("testOneway finished"); + + return Task.CompletedTask; + } + } + + + private static X509Certificate2 GetServerCert() + { + var serverCertName = "server.p12"; + var possiblePaths = new List<string> + { + "../../../keys/", + "../../keys/", + "../keys/", + "keys/", + }; + + string existingPath = null; + foreach (var possiblePath in possiblePaths) + { + var path = Path.GetFullPath(possiblePath + serverCertName); + if (File.Exists(path)) + { + existingPath = path; + break; + } + } + + if (string.IsNullOrEmpty(existingPath)) + { + throw new FileNotFoundException($"Cannot find file: {serverCertName}"); + } + + var cert = new X509Certificate2(existingPath, "thrift"); + + return cert; + } + + public static int Execute(List<string> args) + { + var loggerFactory = new LoggerFactory();//.AddConsole().AddDebug(); + var logger = new LoggerFactory().CreateLogger("Test"); + + try + { + var param = new ServerParam(); + + try + { + param.Parse(args); + } + catch (Exception ex) + { + Console.WriteLine("*** FAILED ***"); + Console.WriteLine("Error while parsing arguments"); + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + return 1; + } + + + // Endpoint transport (mandatory) + TServerTransport trans; + switch (param.transport) + { + case TransportChoice.NamedPipe: + Debug.Assert(param.pipe != null); + trans = new TNamedPipeServerTransport(param.pipe); + break; + + + case TransportChoice.TlsSocket: + var cert = GetServerCert(); + if (cert == null || !cert.HasPrivateKey) + { + throw new InvalidOperationException("Certificate doesn't contain private key"); + } + + trans = new TTlsServerSocketTransport( param.port, cert, + (sender, certificate, chain, errors) => true, + null, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12); + break; + + case TransportChoice.Socket: + default: + trans = new TServerSocketTransport(param.port, 0); + break; + } + + // Layered transport (mandatory) + TTransportFactory transFactory = null; + switch (param.buffering) + { + case BufferChoice.Framed: + transFactory = new TFramedTransport.Factory(); + break; + case BufferChoice.Buffered: + transFactory = new TBufferedTransport.Factory(); + break; + default: + Debug.Assert(param.buffering == BufferChoice.None, "unhandled case"); + transFactory = null; // no layered transprt + break; + } + + // Protocol (mandatory) + TProtocolFactory proto; + switch (param.protocol) + { + case ProtocolChoice.Compact: + proto = new TCompactProtocol.Factory(); + break; + case ProtocolChoice.Json: + proto = new TJsonProtocol.Factory(); + break; + case ProtocolChoice.Binary: + default: + proto = new TBinaryProtocol.Factory(); + break; + } + + // Processor + var testHandler = new TestHandlerAsync(); + var testProcessor = new ThriftTest.AsyncProcessor(testHandler); + var processorFactory = new TSingletonProcessorFactory(testProcessor); + + TServer serverEngine = new TSimpleAsyncServer(processorFactory, trans, transFactory, transFactory, proto, proto, logger); + + //Server event handler + var serverEvents = new MyServerEventHandler(); + serverEngine.SetEventHandler(serverEvents); + + // Run it + var where = (! string.IsNullOrEmpty(param.pipe)) ? "on pipe " + param.pipe : "on port " + param.port; + Console.WriteLine("Starting the AsyncBaseServer " + where + + " with processor TPrototypeProcessorFactory prototype factory " + + (param.buffering == BufferChoice.Buffered ? " with buffered transport" : "") + + (param.buffering == BufferChoice.Framed ? " with framed transport" : "") + + (param.transport == TransportChoice.TlsSocket ? " with encryption" : "") + + (param.protocol == ProtocolChoice.Compact ? " with compact protocol" : "") + + (param.protocol == ProtocolChoice.Json ? " with json protocol" : "") + + "..."); + serverEngine.ServeAsync(CancellationToken.None).GetAwaiter().GetResult(); + Console.ReadLine(); + } + catch (Exception x) + { + Console.Error.Write(x); + return 1; + } + Console.WriteLine("done."); + return 0; + } + } + +} diff --git a/src/jaegertracing/thrift/test/netstd/ThriftTest.sln b/src/jaegertracing/thrift/test/netstd/ThriftTest.sln new file mode 100644 index 000000000..6bd08555b --- /dev/null +++ b/src/jaegertracing/thrift/test/netstd/ThriftTest.sln @@ -0,0 +1,64 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26730.12 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift", "..\..\lib\netstd\Thrift\Thrift.csproj", "{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Client", "Client\Client.csproj", "{21039F25-6ED7-4E80-A545-EBC93472EBD1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Server", "Server\Server.csproj", "{0C6E8685-F191-4479-9842-882A38961127}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x64.ActiveCfg = Debug|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x64.Build.0 = Debug|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x86.ActiveCfg = Debug|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x86.Build.0 = Debug|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|Any CPU.Build.0 = Release|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x64.ActiveCfg = Release|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x64.Build.0 = Release|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x86.ActiveCfg = Release|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x86.Build.0 = Release|Any CPU + {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Debug|x64.ActiveCfg = Debug|Any CPU + {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Debug|x64.Build.0 = Debug|Any CPU + {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Debug|x86.ActiveCfg = Debug|Any CPU + {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Debug|x86.Build.0 = Debug|Any CPU + {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Release|Any CPU.Build.0 = Release|Any CPU + {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Release|x64.ActiveCfg = Release|Any CPU + {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Release|x64.Build.0 = Release|Any CPU + {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Release|x86.ActiveCfg = Release|Any CPU + {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Release|x86.Build.0 = Release|Any CPU + {0C6E8685-F191-4479-9842-882A38961127}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0C6E8685-F191-4479-9842-882A38961127}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0C6E8685-F191-4479-9842-882A38961127}.Debug|x64.ActiveCfg = Debug|Any CPU + {0C6E8685-F191-4479-9842-882A38961127}.Debug|x64.Build.0 = Debug|Any CPU + {0C6E8685-F191-4479-9842-882A38961127}.Debug|x86.ActiveCfg = Debug|Any CPU + {0C6E8685-F191-4479-9842-882A38961127}.Debug|x86.Build.0 = Debug|Any CPU + {0C6E8685-F191-4479-9842-882A38961127}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0C6E8685-F191-4479-9842-882A38961127}.Release|Any CPU.Build.0 = Release|Any CPU + {0C6E8685-F191-4479-9842-882A38961127}.Release|x64.ActiveCfg = Release|Any CPU + {0C6E8685-F191-4479-9842-882A38961127}.Release|x64.Build.0 = Release|Any CPU + {0C6E8685-F191-4479-9842-882A38961127}.Release|x86.ActiveCfg = Release|Any CPU + {0C6E8685-F191-4479-9842-882A38961127}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {52CE9A12-F6CB-4F0C-BB42-0105612F5FF4} + EndGlobalSection +EndGlobal diff --git a/src/jaegertracing/thrift/test/netstd/build.cmd b/src/jaegertracing/thrift/test/netstd/build.cmd new file mode 100644 index 000000000..9b84ef276 --- /dev/null +++ b/src/jaegertracing/thrift/test/netstd/build.cmd @@ -0,0 +1,25 @@ +@echo off +rem /* +rem * Licensed to the Apache Software Foundation (ASF) under one +rem * or more contributor license agreements. See the NOTICE file +rem * distributed with this work for additional information +rem * regarding copyright ownership. The ASF licenses this file +rem * to you under the Apache License, Version 2.0 (the +rem * "License"); you may not use this file except in compliance +rem * with the License. You may obtain a copy of the License at +rem * +rem * http://www.apache.org/licenses/LICENSE-2.0 +rem * +rem * Unless required by applicable law or agreed to in writing, +rem * software distributed under the License is distributed on an +rem * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +rem * KIND, either express or implied. See the License for the +rem * specific language governing permissions and limitations +rem * under the License. +rem */ +setlocal + +dotnet --info +dotnet build + +:eof diff --git a/src/jaegertracing/thrift/test/netstd/build.sh b/src/jaegertracing/thrift/test/netstd/build.sh new file mode 100644 index 000000000..c97e310f0 --- /dev/null +++ b/src/jaegertracing/thrift/test/netstd/build.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +# +# 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. +# + +#exit if any command fails +set -e + +dotnet --info +dotnet build diff --git a/src/jaegertracing/thrift/test/ocaml/Makefile b/src/jaegertracing/thrift/test/ocaml/Makefile new file mode 100644 index 000000000..a543ce587 --- /dev/null +++ b/src/jaegertracing/thrift/test/ocaml/Makefile @@ -0,0 +1,24 @@ +# +# 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. +# + +all: + cd client; make; cd ..; cd server; make +clean: + cd client; make clean; cd ..; cd server; make clean + diff --git a/src/jaegertracing/thrift/test/ocaml/client/Makefile b/src/jaegertracing/thrift/test/ocaml/client/Makefile new file mode 100644 index 000000000..806ed20a9 --- /dev/null +++ b/src/jaegertracing/thrift/test/ocaml/client/Makefile @@ -0,0 +1,26 @@ +# +# 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. +# + +SOURCES = ../gen-ocaml/ThriftTest_types.ml ../gen-ocaml/ThriftTest_consts.ml ../gen-ocaml/SecondService.ml ../gen-ocaml/ThriftTest.ml TestClient.ml +RESULT = tc +INCDIRS = "../../../lib/ocaml/src/" "../gen-ocaml/" +LIBS = unix thrift +all: nc +OCAMLMAKEFILE = ../../../lib/ocaml/OCamlMakefile +include $(OCAMLMAKEFILE) diff --git a/src/jaegertracing/thrift/test/ocaml/client/TestClient.ml b/src/jaegertracing/thrift/test/ocaml/client/TestClient.ml new file mode 100644 index 000000000..91783ae42 --- /dev/null +++ b/src/jaegertracing/thrift/test/ocaml/client/TestClient.ml @@ -0,0 +1,82 @@ +(* + 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. +*) + +open Thrift;; +open ThriftTest_types;; + +let s = new TSocket.t "127.0.0.1" 9090;; +let p = new TBinaryProtocol.t s;; +let c = new ThriftTest.client p p;; +let sod = function + Some v -> v + | None -> raise Thrift_error;; + +s#opn; +print_string (c#testString "bya"); +print_char '\n'; +print_int (c#testByte 8); +print_char '\n'; +print_int (c#testByte (-8)); +print_char '\n'; +print_int (c#testI32 32); +print_char '\n'; +print_string (Int64.to_string (c#testI64 64L)); +print_char '\n'; +print_float (c#testDouble 3.14); +print_char '\n'; + +let l = [1;2;3;4] in + if l = (c#testList l) then print_string "list ok\n" else print_string "list fail\n";; +let h = Hashtbl.create 5 in +let a = Hashtbl.add h in + for i=1 to 10 do + a i (10*i) + done; + let r = c#testMap h in + for i=1 to 10 do + try + let g = Hashtbl.find r i in + print_int i; + print_char ' '; + print_int g; + print_char '\n' + with Not_found -> print_string ("Can't find "^(string_of_int i)^"\n") + done;; + +let s = Hashtbl.create 5 in +let a = Hashtbl.add s in + for i = 1 to 10 do + a i true + done; + let r = c#testSet s in + for i = 1 to 10 do + try + let g = Hashtbl.find r i in + print_int i; + print_char '\n' + with Not_found -> print_string ("Can't find "^(string_of_int i)^"\n") + done;; +try + c#testException "Xception" +with Xception _ -> print_string "testException ok\n";; +try + ignore(c#testMultiException "Xception" "bya") +with Xception e -> Printf.printf "%d %s\n" (sod e#get_errorCode) (sod e#get_message);; + + diff --git a/src/jaegertracing/thrift/test/ocaml/server/Makefile b/src/jaegertracing/thrift/test/ocaml/server/Makefile new file mode 100644 index 000000000..44dcac761 --- /dev/null +++ b/src/jaegertracing/thrift/test/ocaml/server/Makefile @@ -0,0 +1,27 @@ +# +# 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. +# + +SOURCES = ../gen-ocaml/ThriftTest_types.ml ../gen-ocaml/ThriftTest_consts.ml ../gen-ocaml/SecondService.ml ../gen-ocaml/ThriftTest.ml TestServer.ml +RESULT = ts +INCDIRS = "../../../lib/ocaml/src/" "../gen-ocaml/" +LIBS = thrift +THREADS = yes +all: nc +OCAMLMAKEFILE = ../../../lib/ocaml/OCamlMakefile +include $(OCAMLMAKEFILE) diff --git a/src/jaegertracing/thrift/test/ocaml/server/TestServer.ml b/src/jaegertracing/thrift/test/ocaml/server/TestServer.ml new file mode 100644 index 000000000..efe0f4b2b --- /dev/null +++ b/src/jaegertracing/thrift/test/ocaml/server/TestServer.ml @@ -0,0 +1,137 @@ +(* + 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. +*) + +open Thrift +open ThriftTest_types + +let p = Printf.printf;; +exception Die;; +let sod = function + Some v -> v + | None -> raise Die;; + + +class test_handler = +object (self) + inherit ThriftTest.iface + method testVoid = p "testVoid()\n" + method testString x = p "testString(%s)\n" (sod x); (sod x) + method testByte x = p "testByte(%d)\n" (sod x); (sod x) + method testI32 x = p "testI32(%d)\n" (sod x); (sod x) + method testI64 x = p "testI64(%s)\n" (Int64.to_string (sod x)); (sod x) + method testDouble x = p "testDouble(%f)\n" (sod x); (sod x) + method testBinary x = p "testBinary(%s)\n" (sod x); (sod x) + method testStruct x = p "testStruct(---)\n"; (sod x) + method testNest x = p "testNest(---)\n"; (sod x) + method testMap x = p "testMap(---)\n"; (sod x) + method testSet x = p "testSet(---)\n"; (sod x) + method testList x = p "testList(---)\n"; (sod x) + method testEnum x = p "testEnum(---)\n"; (sod x) + method testTypedef x = p "testTypedef(---)\n"; (sod x) + method testMapMap x = p "testMapMap(%d)\n" (sod x); + let mm = Hashtbl.create 3 in + let pos = Hashtbl.create 7 in + let neg = Hashtbl.create 7 in + for i=1 to 4 do + Hashtbl.add pos i i; + Hashtbl.add neg (-i) (-i); + done; + Hashtbl.add mm 4 pos; + Hashtbl.add mm (-4) neg; + mm + method testInsanity x = p "testInsanity()\n"; + p "testinsanity()\n"; + let hello = new xtruct in + let goodbye = new xtruct in + let crazy = new insanity in + let looney = new insanity in + let cumap = Hashtbl.create 7 in + let insane = Hashtbl.create 7 in + let firstmap = Hashtbl.create 7 in + let secondmap = Hashtbl.create 7 in + hello#set_string_thing "Hello2"; + hello#set_byte_thing 2; + hello#set_i32_thing 2; + hello#set_i64_thing 2L; + goodbye#set_string_thing "Goodbye4"; + goodbye#set_byte_thing 4; + goodbye#set_i32_thing 4; + goodbye#set_i64_thing 4L; + Hashtbl.add cumap Numberz.EIGHT 8L; + Hashtbl.add cumap Numberz.FIVE 5L; + crazy#set_userMap cumap; + crazy#set_xtructs [goodbye; hello]; + Hashtbl.add firstmap Numberz.TWO crazy; + Hashtbl.add firstmap Numberz.THREE crazy; + Hashtbl.add secondmap Numberz.SIX looney; + Hashtbl.add insane 1L firstmap; + Hashtbl.add insane 2L secondmap; + insane + method testMulti a0 a1 a2 a3 a4 a5 = + p "testMulti()\n"; + let hello = new xtruct in + hello#set_string_thing "Hello2"; + hello#set_byte_thing (sod a0); + hello#set_i32_thing (sod a1); + hello#set_i64_thing (sod a2); + hello + method testException s = + p "testException(%S)\n" (sod s); + if (sod s) = "Xception" then + let x = new xception in + x#set_errorCode 1001; + x#set_message "This is an Xception"; + raise (Xception x) + else () + method testMultiException a0 a1 = + p "testMultiException(%S, %S)\n" (sod a0) (sod a1); + if (sod a0) = "Xception" then + let x = new xception in + x#set_errorCode 1001; + x#set_message "This is an Xception"; + raise (Xception x) + else (if (sod a0) = "Xception2" then + let x = new xception2 in + let s = new xtruct in + x#set_errorCode 2002; + s#set_string_thing "This as an Xception2"; + x#set_struct_thing s; + raise (Xception2 x) + else ()); + let res = new xtruct in + res#set_string_thing (sod a1); + res + method testOneway i = + Unix.sleep (sod i) +end;; + +let h = new test_handler in +let proc = new ThriftTest.processor h in +let port = 9090 in +let pf = new TBinaryProtocol.factory in +let server = new TThreadedServer.t + proc + (new TServerSocket.t port) + (new Transport.factory) + pf + pf +in + server#serve + + diff --git a/src/jaegertracing/thrift/test/perl/Makefile.am b/src/jaegertracing/thrift/test/perl/Makefile.am new file mode 100644 index 000000000..1dbaf28b0 --- /dev/null +++ b/src/jaegertracing/thrift/test/perl/Makefile.am @@ -0,0 +1,31 @@ +# +# 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. +# + +stubs: ../ThriftTest.thrift + $(THRIFT) --gen perl ../ThriftTest.thrift + +precross: stubs + +check: stubs + +clean-local: + $(RM) -r gen-perl/ + +dist-hook: + $(RM) -r $(distdir)/gen-perl/ diff --git a/src/jaegertracing/thrift/test/perl/TestClient.pl b/src/jaegertracing/thrift/test/perl/TestClient.pl new file mode 100755 index 000000000..96e3bec77 --- /dev/null +++ b/src/jaegertracing/thrift/test/perl/TestClient.pl @@ -0,0 +1,470 @@ +#!/usr/bin/env perl + +# +# 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. +# + +use 5.10.0; +use strict; +use warnings; +use Data::Dumper; +use Getopt::Long qw(GetOptions); +use Time::HiRes qw(gettimeofday); + +use lib '../../lib/perl/lib'; +use lib 'gen-perl'; + +use Thrift; +use Thrift::BinaryProtocol; +use Thrift::BufferedTransport; +use Thrift::FramedTransport; +use Thrift::MultiplexedProtocol; +use Thrift::SSLSocket; +use Thrift::Socket; +use Thrift::UnixSocket; + +use ThriftTest::SecondService; +use ThriftTest::ThriftTest; +use ThriftTest::Types; + +$|++; + +sub usage { + print <<"EOF"; +Usage: $0 [OPTIONS] + +Options: (default) + --ca CA to validate server with. + --cert Certificate to use. + Required if using --ssl. + --ciphers Acceptable cipher list. + --domain-socket <file> Use a unix domain socket. + --help Show usage. + --key Certificate key. + Required if using --ssl. + --port <portnum> 9090 Port to use. + --protocol {binary} binary Protocol to use. + --ssl If present, use SSL. + --transport {buffered|framed} buffered Transport to use. + +EOF +} + +my %opts = ( + 'port' => 9090, + 'protocol' => 'binary', + 'transport' => 'buffered' +); + +GetOptions(\%opts, qw ( + ca=s + cert=s + ciphers=s + key=s + domain-socket=s + help + host=s + port=i + protocol=s + ssl + transport=s +)) || exit 1; + +if ($opts{help}) { + usage(); + exit 0; +} + +my $socket = undef; +if ($opts{'domain-socket'}) { + $socket = Thrift::UnixSocket->new($opts{'domain-socket'}); +} +elsif ($opts{ssl}) { + $socket = Thrift::SSLSocket->new(\%opts); +} +else { + $socket = Thrift::Socket->new($opts{host}, $opts{port}); +} + +my $transport; +if ($opts{transport} eq 'buffered') { + $transport = Thrift::BufferedTransport->new($socket, 1024, 1024); +} +elsif ($opts{transport} eq 'framed') { + $transport = Thrift::FramedTransport->new($socket); +} +else { + usage(); + exit 1; +} + +my $protocol; +my $protocol2; +if ($opts{protocol} eq 'binary' || $opts{protocol} eq 'multi') { + $protocol = Thrift::BinaryProtocol->new($transport); +} +else { + usage(); + exit 1; +} + +my $secondService = undef; +if (index($opts{protocol}, 'multi') == 0) { + $protocol2 = Thrift::MultiplexedProtocol->new($protocol, 'SecondService'); + $protocol = Thrift::MultiplexedProtocol->new($protocol, 'ThriftTest'); + $secondService = ThriftTest::SecondServiceClient->new($protocol2); +} + +my $testClient = ThriftTest::ThriftTestClient->new($protocol); + +eval { + $transport->open(); +}; +if($@){ + die(Dumper($@)); +} + +use constant ERR_BASETYPES => 1; +use constant ERR_STRUCTS => 2; +use constant ERR_CONTAINERS => 4; +use constant ERR_EXCEPTIONS => 8; +use constant ERR_PROTOCOL => 16; +use constant ERR_UNKNOWN => 64; + +my $start = gettimeofday(); + +# +# VOID TEST +# +print('testVoid()'); +$testClient->testVoid(); +print(" = void\n"); + +# +# STRING TEST +# +print('testString("Test")'); +my $s = $testClient->testString('Test'); +print(qq| = "$s"\n|); +exit(ERR_BASETYPES) if ($s ne 'Test'); + +# +# MULTIPLEXED TEST +# +if (index($opts{protocol}, 'multi') == 0) { + print('secondtestString("Test2")'); + $s = $secondService->secondtestString('Test2'); + print(qq| = "$s"\n|); + exit(ERR_PROTOCOL) if ($s ne 'testString("Test2")'); +} + +# +# BOOL TEST +# +print('testBool(1)'); +my $t = $testClient->testBool(1); +print(" = $t\n"); +exit(ERR_BASETYPES) if ($t ne 1); +print('testBool(0)'); +my $f = $testClient->testBool(0); +print(" = $f\n"); +exit(ERR_BASETYPES) if ($f ne q||); + + +# +# BYTE TEST +# +print('testByte(1)'); +my $u8 = $testClient->testByte(1); +print(" = $u8\n"); + +# +# I32 TEST +# +print('testI32(-1)'); +my $i32 = $testClient->testI32(-1); +print(" = $i32\n"); +exit(ERR_BASETYPES) if ($i32 ne -1); + +# +# I64 TEST +# +print('testI64(-34359738368)'); +my $i64 = $testClient->testI64(-34359738368); +print(" = $i64\n"); +exit(ERR_BASETYPES) if ($i64 ne -34359738368); + +# +# DOUBLE TEST +# +print('testDouble(-852.234234234)'); +my $dub = $testClient->testDouble(-852.234234234); +print(" = $dub\n"); +exit(ERR_BASETYPES) if ($dub ne -852.234234234); + +# +# BINARY TEST --- TODO +# + + +# +# STRUCT TEST +# +print('testStruct({"Zero", 1, -3, -5})'); +my $out = ThriftTest::Xtruct->new(); +$out->string_thing('Zero'); +$out->byte_thing(1); +$out->i32_thing(-3); +$out->i64_thing(-5); +my $in = $testClient->testStruct($out); +print(' = {"'.$in->string_thing.'", '. + $in->byte_thing.', '. + $in->i32_thing.', '. + $in->i64_thing."}\n"); + +# +# NESTED STRUCT TEST +# +print('testNest({1, {"Zero", 1, -3, -5}, 5}'); +my $out2 = ThriftTest::Xtruct2->new(); +$out2->byte_thing(1); +$out2->struct_thing($out); +$out2->i32_thing(5); +my $in2 = $testClient->testNest($out2); +$in = $in2->struct_thing; +print(' = {'.$in2->byte_thing.', {"'. + $in->string_thing.'", '. + $in->byte_thing.', '. + $in->i32_thing.', '. + $in->i64_thing.'}, '. + $in2->i32_thing."}\n"); + +# +# MAP TEST +# +my $mapout = {}; +for (my $i = 0; $i < 5; ++$i) { + $mapout->{$i} = $i-10; +} +print('testMap({'); +my $first = 1; +while( my($key,$val) = each %$mapout) { + if ($first) { + $first = 0; + } + else { + print(', '); + } + print("$key => $val"); +} +print('})'); + + +my $mapin = $testClient->testMap($mapout); +print(' = {'); + +$first = 1; +while( my($key,$val) = each %$mapin){ + if ($first) { + $first = 0; + } + else { + print(', '); + } + print("$key => $val"); +} +print("}\n"); + +# +# SET TEST +# +my $setout = []; +for (my $i = -2; $i < 3; ++$i) { + push(@$setout, $i); +} + +print('testSet({'.join(',',@$setout).'})'); + +my $setin = $testClient->testSet($setout); + +print(' = {'.join(',',@$setout)."}\n"); + +# +# LIST TEST +# +my $listout = []; +for (my $i = -2; $i < 3; ++$i) { + push(@$listout, $i); +} + +print('testList({'.join(',',@$listout).'})'); + +my $listin = $testClient->testList($listout); + +print(' = {'.join(',',@$listin)."}\n"); + +# +# ENUM TEST +# +print('testEnum(ONE)'); +my $ret = $testClient->testEnum(ThriftTest::Numberz::ONE); +print(" = $ret\n"); + +print('testEnum(TWO)'); +$ret = $testClient->testEnum(ThriftTest::Numberz::TWO); +print(" = $ret\n"); + +print('testEnum(THREE)'); +$ret = $testClient->testEnum(ThriftTest::Numberz::THREE); +print(" = $ret\n"); + +print('testEnum(FIVE)'); +$ret = $testClient->testEnum(ThriftTest::Numberz::FIVE); +print(" = $ret\n"); + +print('testEnum(EIGHT)'); +$ret = $testClient->testEnum(ThriftTest::Numberz::EIGHT); +print(" = $ret\n"); + +# +# TYPEDEF TEST +# +print('testTypedef(309858235082523)'); +my $uid = $testClient->testTypedef(309858235082523); +print(" = $uid\n"); + +# +# NESTED MAP TEST +# +print('testMapMap(1)'); +my $mm = $testClient->testMapMap(1); +print(' = {'); +while( my ($key,$val) = each %$mm) { + print("$key => {"); + while( my($k2,$v2) = each %$val) { + print("$k2 => $v2, "); + } + print('}, '); +} +print("}\n"); + +# +# INSANITY TEST +# +my $insane = ThriftTest::Insanity->new(); +$insane->{userMap}->{ThriftTest::Numberz::FIVE} = 5000; +my $truck = ThriftTest::Xtruct->new(); +$truck->string_thing('Hello2'); +$truck->byte_thing(2); +$truck->i32_thing(2); +$truck->i64_thing(2); +my $truck2 = ThriftTest::Xtruct->new(); +$truck2->string_thing('Goodbye4'); +$truck2->byte_thing(4); +$truck2->i32_thing(4); +$truck2->i64_thing(4); +push(@{$insane->{xtructs}}, $truck); +push(@{$insane->{xtructs}}, $truck2); + +print('testInsanity()'); +my $whoa = $testClient->testInsanity($insane); +print(' = {'); +while( my ($key,$val) = each %$whoa) { + print("$key => {"); + while( my($k2,$v2) = each %$val) { + print("$k2 => {"); + my $userMap = $v2->{userMap}; + print('{'); + if (ref($userMap) eq 'HASH') { + while( my($k3,$v3) = each %$userMap) { + print("$k3 => $v3, "); + } + } + print('}, '); + + my $xtructs = $v2->{xtructs}; + print('{'); + if (ref($xtructs) eq 'ARRAY') { + foreach my $x (@$xtructs) { + print('{"'.$x->{string_thing}.'", '. + $x->{byte_thing}.', '.$x->{i32_thing}.', '.$x->{i64_thing}.'}, '); + } + } + print('}'); + + print('}, '); + } + print('}, '); +} +print("}\n"); + +# +# EXCEPTION TEST +# +print(q|testException('Xception')|); +eval { + $testClient->testException('Xception'); + print(" void\nFAILURE\n"); +}; if($@ && $@->UNIVERSAL::isa('ThriftTest::Xception')) { + print(' caught xception '.$@->{errorCode}.': '.$@->{message}."\n"); +} + + +# +# Normal tests done. +# +my $stop = gettimeofday(); +my $elp = sprintf('%d',1000*($stop - $start), 0); +print("Total time: $elp ms\n"); + +# +# Extraneous "I don't trust PHP to pack/unpack integer" tests +# + +# Max I32 +my $num = 2**30 + 2**30 - 1; +my $num2 = $testClient->testI32($num); +if ($num != $num2) { + print "Missed max32 $num = $num2\n"; +} + +# Min I32 +$num = 0 - 2**31; +$num2 = $testClient->testI32($num); +if ($num != $num2) { + print "Missed min32 $num = $num2\n"; +} + +# Max Number I can get out of my perl +$num = 2**40; +$num2 = $testClient->testI64($num); +if ($num != $num2) { + print "Missed max64 $num = $num2\n"; +} + +# Max Number I can get out of my perl +$num = 0 - 2**40; +$num2 = $testClient->testI64($num); +if ($num != $num2) { + print "Missed min64 $num = $num2\n"; +} + +$transport->close(); + + + diff --git a/src/jaegertracing/thrift/test/perl/TestServer.pl b/src/jaegertracing/thrift/test/perl/TestServer.pl new file mode 100644 index 000000000..d2b9a38ab --- /dev/null +++ b/src/jaegertracing/thrift/test/perl/TestServer.pl @@ -0,0 +1,411 @@ +#!/usr/bin/env perl + +# +# 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. +# + +use 5.10.0; +use strict; +use warnings; +use Data::Dumper; +use Getopt::Long qw(GetOptions); +use Time::HiRes qw(gettimeofday); + +$SIG{INT} = \&sigint_handler; + +use lib '../../lib/perl/lib'; +use lib 'gen-perl'; + +use Thrift; +use Thrift::BinaryProtocol; +use Thrift::BufferedTransport; +use Thrift::FramedTransport; +use Thrift::MultiplexedProcessor; +use Thrift::SSLServerSocket; +use Thrift::ServerSocket; +use Thrift::Server; +use Thrift::UnixServerSocket; + +use ThriftTest::SecondService; +use ThriftTest::ThriftTest; +use ThriftTest::Types; + +$|++; + +sub usage { + print <<"EOF"; +Usage: $0 [OPTIONS] + +Options: (default) + --ca Certificate authority file (optional). + --cert Certificate file. + Required if using --ssl. + --ciphers Acceptable cipher list. + --domain-socket <file> Use a unix domain socket. + --help Show usage. + --key Private key file for certificate. + Required if using --ssl and private key is + not in the certificate file. + --port <portnum> 9090 Port to use. + --protocol {binary} binary Protocol to use. + --ssl If present, use SSL/TLS. + --transport {buffered|framed} buffered Transport to use. + +EOF +} + +my %opts = ( + 'port' => 9090, + 'protocol' => 'binary', + 'transport' => 'buffered' +); + +GetOptions(\%opts, qw ( + ca=s + cert=s + ciphers=s + domain-socket=s + help + host=s + key=s + port=i + protocol=s + ssl + transport=s +)) || exit 1; + +if ($opts{help}) { + usage(); + exit 0; +} + +if ($opts{ssl} and not defined $opts{cert}) { + usage(); + exit 1; +} + +my $handler = ThriftTestHandler->new(); +my $handler2 = SecondServiceHandler->new(); +my $processor = ThriftTest::ThriftTestProcessor->new($handler); +my $processor2 = ThriftTest::SecondServiceProcessor->new($handler2); + +my $serversocket; +if ($opts{'domain-socket'}) { + unlink($opts{'domain-socket'}); + $serversocket = Thrift::UnixServerSocket->new($opts{'domain-socket'}); +} +elsif ($opts{ssl}) { + $serversocket = Thrift::SSLServerSocket->new(\%opts); +} +else { + $serversocket = Thrift::ServerSocket->new(\%opts); +} +my $transport; +if ($opts{transport} eq 'buffered') { + $transport = Thrift::BufferedTransportFactory->new(); +} +elsif ($opts{transport} eq 'framed') { + $transport = Thrift::FramedTransportFactory->new(); +} +else { + usage(); + exit 1; +} +my $protocol; +if ($opts{protocol} eq 'binary' || $opts{protocol} eq 'multi') { + $protocol = Thrift::BinaryProtocolFactory->new(); +} +else { + usage(); + exit 1; +} + +if (index($opts{protocol}, 'multi') == 0) { + my $newProcessor = Thrift::MultiplexedProcessor->new($protocol); + $newProcessor->defaultProcessor($processor); + $newProcessor->registerProcessor('ThriftTest', $processor); + $newProcessor->registerProcessor('SecondService', $processor2); + $processor = $newProcessor; +} + +my $ssltag = ''; +if ($opts{ssl}) { + $ssltag = '(SSL)'; +} +my $listening_on = "$opts{port} $ssltag"; +if ($opts{'domain-socket'}) { + $listening_on = $opts{'domain-socket'}; +} +my $server = Thrift::SimpleServer->new($processor, $serversocket, $transport, $protocol); +print qq|Starting "simple" server ($opts{transport}/$opts{protocol}) listen on: $listening_on\n|; +$server->serve(); +print "done.\n"; + +sub sigint_handler { + print "received SIGINT, stopping...\n"; + $server->stop(); +} + +### +### Test server implementation +### + +package ThriftTestHandler; + +use base qw( ThriftTest::ThriftTestIf ); + +sub new { + my $classname = shift; + my $self = {}; + return bless($self, $classname); +} + +sub testVoid { + print("testVoid()\n"); +} + +sub testString { + my $self = shift; + my $thing = shift; + print("testString($thing)\n"); + return $thing; +} + +sub testBool { + my $self = shift; + my $thing = shift; + my $str = $thing ? 'true' : 'false'; + print("testBool($str)\n"); + return $thing; +} + +sub testByte { + my $self = shift; + my $thing = shift; + print("testByte($thing)\n"); + return $thing; +} + +sub testI32 { + my $self = shift; + my $thing = shift; + print("testI32($thing)\n"); + return $thing; +} + +sub testI64 { + my $self = shift; + my $thing = shift; + print("testI64($thing)\n"); + return $thing; +} + +sub testDouble { + my $self = shift; + my $thing = shift; + print("testDouble($thing)\n"); + return $thing; +} + +sub testBinary { + my $self = shift; + my $thing = shift; + my @bytes = split //, $thing; + print 'testBinary('; + printf( '%02lx', ord $_ ) foreach (@bytes); + print ")\n"; + return $thing; +} + +sub testStruct { + my $self = shift; + my $thing = shift; + printf(qq|testStruct({"%s", %d, %d, %lld})\n|, + $thing->{string_thing}, + $thing->{byte_thing}, + $thing->{i32_thing}, + $thing->{i64_thing}); + return $thing; +} + +sub testNest { + my $self = shift; + my $nest = shift; + my $thing = $nest->{struct_thing}; + printf(qq|testNest({%d, {"%s", %d, %d, %lld}, %d})\n|, + $nest->{byte_thing}, + $thing->{string_thing}, + $thing->{byte_thing}, + $thing->{i32_thing}, + $thing->{i64_thing}, + $nest->{i32_thing}); + return $nest; +} + +sub testMap { + my $self = shift; + my $thing = shift; + printf "testMap({%s})\n", + join( ', ', + map { $_ . ' => ' . $thing->{$_} } + sort keys %$thing + ); + return $thing; +} + +sub testStringMap { + my $self = shift; + my $thing = shift; + printf "testStringMap({%s})\n", + join( ', ', + map { $_ . ' => ' . $thing->{$_} } + sort keys %$thing + ); + return $thing; +} + +sub testSet { + my $self = shift; + my $thing = shift; + my @result = sort keys %$thing; + printf "testSet({%s})\n", join(', ', @result ); + return \@result; +} + +sub testList { + my $self = shift; + my $thing = shift; + print "testList({%s})\n", join(', ', @$thing); + return $thing; +} + +sub testEnum { + my $self = shift; + my $thing = shift; + print "testEnum($thing)\n"; + return $thing; +} + +sub testTypedef { + my $self = shift; + my $thing = shift; + print("testTypedef($thing)\n"); + return $thing; +} + +sub testMapMap { + my $self = shift; + my $hello = shift; + + printf("testMapMap(%d)\n", $hello); + my $result = { 4 => { 1 => 1, 2 => 2, 3 => 3, 4 => 4 }, -4 => { -1 => -1, -2 => -2, -3 => -3, -4 => -4 } }; + return $result; +} + +sub testInsanity { + my $self = shift; + my $argument = shift; + print("testInsanity()\n"); + + my $hello = ThriftTest::Xtruct->new({string_thing => 'Hello2', byte_thing => 2, i32_thing => 2, i64_thing => 2}); + my @hellos; + push(@hellos, $hello); + my $goodbye = ThriftTest::Xtruct->new({string_thing => 'Goodbye4', byte_thing => 4, i32_thing => 4, i64_thing => 4}); + my @goodbyes; + push(@goodbyes, $goodbye); + my $crazy = ThriftTest::Insanity->new({userMap => { ThriftTest::Numberz::EIGHT => 8 }, xtructs => \@goodbyes}); + my $loony = ThriftTest::Insanity->new(); + my $result = { 1 => { ThriftTest::Numberz::TWO => $argument, ThriftTest::Numberz::THREE => $argument }, + 2 => { ThriftTest::Numberz::SIX => $loony } }; + return $result; +} + +sub testMulti { + my $self = shift; + my $arg0 = shift; + my $arg1 = shift; + my $arg2 = shift; + my $arg3 = shift; + my $arg4 = shift; + my $arg5 = shift; + + print("testMulti()\n"); + return ThriftTest::Xtruct->new({string_thing => 'Hello2', byte_thing => $arg0, i32_thing => $arg1, i64_thing => $arg2}); +} + +sub testException { + my $self = shift; + my $arg = shift; + print("testException($arg)\n"); + if ($arg eq 'Xception') { + die ThriftTest::Xception->new({errorCode => 1001, message => $arg}); + } + elsif ($arg eq 'TException') { + die 'astring'; # all unhandled exceptions become TExceptions + } + else { + return ThriftTest::Xtruct->new({string_thing => $arg}); + } +} + +sub testMultiException { + my $self = shift; + my $arg0 = shift; + my $arg1 = shift; + + printf("testMultiException(%s, %s)\n", $arg0, $arg1); + if ($arg0 eq 'Xception') { + die ThriftTest::Xception->new({errorCode => 1001, message => 'This is an Xception'}); + } + elsif ($arg0 eq 'Xception2') { + my $struct_thing = ThriftTest::Xtruct->new({string_thing => 'This is an Xception2'}); + die ThriftTest::Xception2->new({errorCode => 2002, struct_thing => $struct_thing}); + } + else { + return ThriftTest::Xtruct->new({string_thing => $arg1}); + } +} + +sub testOneway { + my $self = shift; + my $num = shift; + print("testOneway($num): received\n"); +} + +### +### Test server implementation +### + +package SecondServiceHandler; + +use base qw( ThriftTest::SecondServiceIf ); + +sub new { + my $classname = shift; + my $self = {}; + return bless($self, $classname); +} + +sub secondtestString { + my $self = shift; + my $thing = shift; + print("testString($thing)\n"); + return qq|testString("$thing")|; +} + +1; diff --git a/src/jaegertracing/thrift/test/php/Makefile.am b/src/jaegertracing/thrift/test/php/Makefile.am new file mode 100755 index 000000000..9e13affa1 --- /dev/null +++ b/src/jaegertracing/thrift/test/php/Makefile.am @@ -0,0 +1,45 @@ +# +# 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. +# + +stubs: ../ThriftTest.thrift + $(THRIFT) --gen php ../ThriftTest.thrift + $(THRIFT) --gen php:inlined ../ThriftTest.thrift + $(MKDIR_P) gen-php-classmap + $(THRIFT) -out gen-php-classmap --gen php:classmap ../ThriftTest.thrift + +php_ext_dir: + mkdir -p php_ext_dir + ln -s ../../../lib/php/src/ext/thrift_protocol/modules/thrift_protocol.so php_ext_dir/ + ln -s "$$(php-config --extension-dir)/json.so" php_ext_dir/ + ln -s "$$(php-config --extension-dir)/sockets.so" php_ext_dir/ + +precross: stubs php_ext_dir + +check: stubs php_ext_dir + +clean-local: + $(RM) -r gen-*/ + $(RM) -r php_ext_dir + +dist-hook: + $(RM) -r $(distdir)/gen-*/ + $(RM) -r $(distdir)/php_ext_dir/ + +client: stubs php_ext_dir + php TestClient.php diff --git a/src/jaegertracing/thrift/test/php/TestClassmap.php b/src/jaegertracing/thrift/test/php/TestClassmap.php new file mode 100644 index 000000000..6fd159437 --- /dev/null +++ b/src/jaegertracing/thrift/test/php/TestClassmap.php @@ -0,0 +1,23 @@ +/* + * 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. + */ + +<?php +$GEN_DIR = 'gen-php-classmap'; +include_once('TestClient.php'); +?> diff --git a/src/jaegertracing/thrift/test/php/TestClient.php b/src/jaegertracing/thrift/test/php/TestClient.php new file mode 100755 index 000000000..acd901d88 --- /dev/null +++ b/src/jaegertracing/thrift/test/php/TestClient.php @@ -0,0 +1,557 @@ +<?php + +namespace test\php; + +/** @var \Composer\Autoload\ClassLoader $loader */ +$loader = require __DIR__ . '/../../vendor/autoload.php'; + +use Thrift\ClassLoader\ThriftClassLoader; + +if (!isset($GEN_DIR)) { + $GEN_DIR = 'gen-php'; +} +if (!isset($MODE)) { + $MODE = 'normal'; +} + + +if ($GEN_DIR == 'gen-php') { + $loader->addPsr4('', $GEN_DIR); +} else { + $loader = new ThriftClassLoader(); + $loader->registerDefinition('ThriftTest', $GEN_DIR); + $loader->register(); +} + +/* + * 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. + */ + +/** Include the Thrift base */ +/** Include the protocols */ +use Thrift\Protocol\TBinaryProtocol; +use Thrift\Protocol\TBinaryProtocolAccelerated; +use Thrift\Protocol\TCompactProtocol; +use Thrift\Protocol\TJSONProtocol; + +/** Include the socket layer */ +use Thrift\Transport\TSocket; +use Thrift\Transport\TSocketPool; + +/** Include the socket layer */ +use Thrift\Transport\TFramedTransport; +use Thrift\Transport\TBufferedTransport; + +function makeProtocol($transport, $PROTO) +{ + if ($PROTO == 'binary') { + return new TBinaryProtocol($transport); + } else if ($PROTO == 'compact') { + return new TCompactProtocol($transport); + } else if ($PROTO == 'json') { + return new TJSONProtocol($transport); + } else if ($PROTO == 'accel') { + if (!function_exists('thrift_protocol_write_binary')) { + echo "Acceleration extension is not loaded\n"; + exit(1); + } + return new TBinaryProtocolAccelerated($transport); + } + + echo "--protocol must be one of {binary|compact|json|accel}\n"; + exit(1); +} + +$host = 'localhost'; +$port = 9090; + +if ($argc > 1) { + $host = $argv[0]; +} + +if ($argc > 2) { + $host = $argv[1]; +} + +foreach ($argv as $arg) { + if (substr($arg, 0, 7) == '--port=') { + $port = substr($arg, 7); + } else if (substr($arg, 0, 12) == '--transport=') { + $MODE = substr($arg, 12); + } else if (substr($arg, 0, 11) == '--protocol=') { + $PROTO = substr($arg, 11); + } +} + +$hosts = array('localhost'); + +$socket = new TSocket($host, $port); +$socket = new TSocketPool($hosts, $port); +$socket->setDebug(TRUE); + +if ($MODE == 'inline') { + $transport = $socket; + $testClient = new \ThriftTest\ThriftTestClient($transport); +} else if ($MODE == 'framed') { + $framedSocket = new TFramedTransport($socket); + $transport = $framedSocket; + $protocol = makeProtocol($transport, $PROTO); + $testClient = new \ThriftTest\ThriftTestClient($protocol); +} else { + $bufferedSocket = new TBufferedTransport($socket, 1024, 1024); + $transport = $bufferedSocket; + $protocol = makeProtocol($transport, $PROTO); + $testClient = new \ThriftTest\ThriftTestClient($protocol); +} + +$transport->open(); + +$start = microtime(true); + +define('ERR_BASETYPES', 1); +define('ERR_STRUCTS', 2); +define('ERR_CONTAINERS', 4); +define('ERR_EXCEPTIONS', 8); +define('ERR_UNKNOWN', 64); +$exitcode = 0; +/** + * VOID TEST + */ +print_r("testVoid()"); +$testClient->testVoid(); +print_r(" = void\n"); + +function roundtrip($testClient, $method, $value) { + global $exitcode; + print_r("$method($value)"); + $ret = $testClient->$method($value); + print_r(" = \"$ret\"\n"); + if ($value !== $ret) { + print_r("*** FAILED ***\n"); + $exitcode |= ERR_BASETYPES; + } +} + +/** + * STRING TEST + */ +roundtrip($testClient, 'testString', "Test"); + +/** + * BOOL TEST + */ +roundtrip($testClient, 'testBool', true); +roundtrip($testClient, 'testBool', false); + +/** + * BYTE TEST + */ +roundtrip($testClient, 'testByte', 1); +roundtrip($testClient, 'testByte', -1); +roundtrip($testClient, 'testByte', 127); +roundtrip($testClient, 'testByte', -128); + +/** + * I32 TEST + */ +roundtrip($testClient, 'testI32', -1); + +/** + * I64 TEST + */ +roundtrip($testClient, 'testI64', 0); +roundtrip($testClient, 'testI64', 1); +roundtrip($testClient, 'testI64', -1); +roundtrip($testClient, 'testI64', -34359738368); + +/** + * DOUBLE TEST + */ +roundtrip($testClient, 'testDouble', -852.234234234); + +/** + * BINARY TEST -- TODO + */ + +/** + * STRUCT TEST + */ +print_r("testStruct({\"Zero\", 1, -3, -5})"); +$out = new \ThriftTest\Xtruct(); +$out->string_thing = "Zero"; +$out->byte_thing = 1; +$out->i32_thing = -3; +$out->i64_thing = -5; +$in = $testClient->testStruct($out); +print_r(" = {\"".$in->string_thing."\", ". + $in->byte_thing.", ". + $in->i32_thing.", ". + $in->i64_thing."}\n"); + +if ($in != $out) { + echo "**FAILED**\n"; + $exitcode |= ERR_STRUCTS; +} + +/** + * NESTED STRUCT TEST + */ +print_r("testNest({1, {\"Zero\", 1, -3, -5}), 5}"); +$out2 = new \ThriftTest\Xtruct2(); +$out2->byte_thing = 1; +$out2->struct_thing = $out; +$out2->i32_thing = 5; +$in2 = $testClient->testNest($out2); +$in = $in2->struct_thing; +print_r(" = {".$in2->byte_thing.", {\"". + $in->string_thing."\", ". + $in->byte_thing.", ". + $in->i32_thing.", ". + $in->i64_thing."}, ". + $in2->i32_thing."}\n"); + +if ($in2 != $out2) { + echo "**FAILED**\n"; + $exitcode |= ERR_STRUCTS; +} + +/** + * MAP TEST + */ +$mapout = array(); +for ($i = 0; $i < 5; ++$i) { + $mapout[$i] = $i-10; +} +print_r("testMap({"); +$first = true; +foreach ($mapout as $key => $val) { + if ($first) { + $first = false; + } else { + print_r(", "); + } + print_r("$key => $val"); +} +print_r("})"); + +$mapin = $testClient->testMap($mapout); +print_r(" = {"); +$first = true; +foreach ($mapin as $key => $val) { + if ($first) { + $first = false; + } else { + print_r(", "); + } + print_r("$key => $val"); +} +print_r("}\n"); + +if ($mapin != $mapout) { + echo "**FAILED**\n"; + $exitcode |= ERR_CONTAINERS; +} + +$mapout = array(); +for ($i = 0; $i < 10; $i++) { + $mapout["key$i"] = "val$i"; +} +print_r('testStringMap({'); +$first = true; +foreach ($mapout as $key => $val) { + if ($first) { + $first = false; + } else { + print_r(", "); + } + print_r("\"$key\" => \"$val\""); +} +print_r("})"); +$mapin = $testClient->testStringMap($mapout); +print_r(" = {"); +$first = true; +foreach ($mapin as $key => $val) { + if ($first) { + $first = false; + } else { + print_r(", "); + } + print_r("\"$key\" => \"$val\""); +} +print_r("}\n"); +ksort($mapin); +if ($mapin != $mapout) { + echo "**FAILED**\n"; + $exitcode |= ERR_CONTAINERS; +} + +/** + * SET TEST + */ +$setout = array();; +for ($i = -2; $i < 3; ++$i) { + $setout[$i]= true; +} +print_r("testSet({"); +echo implode(',', array_keys($setout)); +print_r("})"); +$setin = $testClient->testSet($setout); +print_r(" = {"); +echo implode(', ', array_keys($setin)); +print_r("}\n"); +// Order of keys in set does not matter +ksort($setin); +if ($setout !== $setin) { + echo "**FAILED**\n"; + $exitcode |= ERR_CONTAINERS; +} +// Regression test for corrupted array +if ($setin[2] !== $setout[2] || is_int($setin[2])) { + echo "**FAILED**\n"; + $exitcode |= ERR_CONTAINERS; +} + +/** + * LIST TEST + */ +$listout = array(); +for ($i = -2; $i < 3; ++$i) { + $listout []= $i; +} +print_r("testList({"); +$first = true; +foreach ($listout as $val) { + if ($first) { + $first = false; + } else { + print_r(", "); + } + print_r($val); +} +print_r("})"); +$listin = $testClient->testList($listout); +print_r(" = {"); +$first = true; +foreach ($listin as $val) { + if ($first) { + $first = false; + } else { + print_r(", "); + } + print_r($val); +} +print_r("}\n"); +if ($listin !== $listout) { + echo "**FAILED**\n"; + $exitcode |= ERR_CONTAINERS; +} + +/** + * ENUM TEST + */ +print_r("testEnum(ONE)"); +$ret = $testClient->testEnum(\ThriftTest\Numberz::ONE); +print_r(" = $ret\n"); +if ($ret != \ThriftTest\Numberz::ONE) { + echo "**FAILED**\n"; + $exitcode |= ERR_STRUCTS; +} + +print_r("testEnum(TWO)"); +$ret = $testClient->testEnum(\ThriftTest\Numberz::TWO); +print_r(" = $ret\n"); +if ($ret != \ThriftTest\Numberz::TWO) { + echo "**FAILED**\n"; + $exitcode |= ERR_STRUCTS; +} + +print_r("testEnum(THREE)"); +$ret = $testClient->testEnum(\ThriftTest\Numberz::THREE); +print_r(" = $ret\n"); +if ($ret != \ThriftTest\Numberz::THREE) { + echo "**FAILED**\n"; + $exitcode |= ERR_STRUCTS; +} + +print_r("testEnum(FIVE)"); +$ret = $testClient->testEnum(\ThriftTest\Numberz::FIVE); +print_r(" = $ret\n"); +if ($ret != \ThriftTest\Numberz::FIVE) { + echo "**FAILED**\n"; + $exitcode |= ERR_STRUCTS; +} + +print_r("testEnum(EIGHT)"); +$ret = $testClient->testEnum(\ThriftTest\Numberz::EIGHT); +print_r(" = $ret\n"); +if ($ret != \ThriftTest\Numberz::EIGHT) { + echo "**FAILED**\n"; + $exitcode |= ERR_STRUCTS; +} + +/** + * TYPEDEF TEST + */ +print_r("testTypedef(309858235082523)"); +$uid = $testClient->testTypedef(309858235082523); +print_r(" = $uid\n"); +if ($uid !== 309858235082523) { + echo "**FAILED**\n"; + $exitcode |= ERR_STRUCTS; +} + +/** + * NESTED MAP TEST + */ +print_r("testMapMap(1)"); +$mm = $testClient->testMapMap(1); +print_r(" = {"); +foreach ($mm as $key => $val) { + print_r("$key => {"); + foreach ($val as $k2 => $v2) { + print_r("$k2 => $v2, "); + } + print_r("}, "); +} +print_r("}\n"); +$expected_mm = [ + -4 => [-4 => -4, -3 => -3, -2 => -2, -1 => -1], + 4 => [4 => 4, 3 => 3, 2 => 2, 1 => 1], +]; +if ($mm != $expected_mm) { + echo "**FAILED**\n"; + $exitcode |= ERR_CONTAINERS; +} + +/** + * INSANITY TEST + */ +$insane = new \ThriftTest\Insanity(); +$insane->userMap[\ThriftTest\Numberz::FIVE] = 5000; +$truck = new \ThriftTest\Xtruct(); +$truck->string_thing = "Truck"; +$truck->byte_thing = 8; +$truck->i32_thing = 8; +$truck->i64_thing = 8; +$insane->xtructs []= $truck; +print_r("testInsanity()"); +$whoa = $testClient->testInsanity($insane); +print_r(" = {"); +foreach ($whoa as $key => $val) { + print_r("$key => {"); + foreach ($val as $k2 => $v2) { + print_r("$k2 => {"); + $userMap = $v2->userMap; + print_r("{"); + if (is_array($userMap)) { + foreach ($userMap as $k3 => $v3) { + print_r("$k3 => $v3, "); + } + } + print_r("}, "); + + $xtructs = $v2->xtructs; + print_r("{"); + if (is_array($xtructs)) { + foreach ($xtructs as $x) { + print_r("{\"".$x->string_thing."\", ". + $x->byte_thing.", ".$x->i32_thing.", ".$x->i64_thing."}, "); + } + } + print_r("}"); + + print_r("}, "); + } + print_r("}, "); +} +print_r("}\n"); + +/** + * EXCEPTION TEST + */ +print_r("testException('Xception')"); +try { + $testClient->testException('Xception'); + print_r(" void\nFAILURE\n"); + $exitcode |= ERR_EXCEPTIONS; +} catch (\ThriftTest\Xception $x) { + print_r(' caught xception '.$x->errorCode.': '.$x->message."\n"); +} + +// Regression test for THRIFT-4263 +print_r("testBinarySerializer_Deserialize('foo')"); +try { + \Thrift\Serializer\TBinarySerializer::deserialize(base64_decode('foo'), \ThriftTest\Xtruct2::class); + echo "**FAILED**\n"; + $exitcode |= ERR_STRUCTS; +} catch (\Thrift\Exception\TTransportException $happy_exception) { + // We expected this due to binary data of base64_decode('foo') is less then 4 + // bytes and it tries to find thrift version number in the transport by + // reading i32() at the beginning. Casting to string validates that + // exception is still accessible in memory and not corrupted. Without patch, + // PHP will error log that the exception doesn't have any tostring method, + // which is a lie due to corrupted memory. + for($i=99; $i > 0; $i--) { + (string)$happy_exception; + } + print_r(" SUCCESS\n"); +} + +/** + * Normal tests done. + */ + +$stop = microtime(true); +$elp = round(1000*($stop - $start), 0); +print_r("Total time: $elp ms\n"); + +/** + * Extraneous "I don't trust PHP to pack/unpack integer" tests + */ + +if ($protocol instanceof TBinaryProtocolAccelerated) { + // Regression check: check that method name is not double-freed + // Method name should not be an interned string. + $method_name = "Void"; + $method_name = "test$method_name"; + + $seqid = 0; + $args = new \ThriftTest\ThriftTest_testVoid_args(); + thrift_protocol_write_binary($protocol, $method_name, \Thrift\Type\TMessageType::CALL, $args, $seqid, $protocol->isStrictWrite()); + $testClient->recv_testVoid(); + +} + +// Max I32 +$num = pow(2, 30) + (pow(2, 30) - 1); +roundtrip($testClient, 'testI32', $num); + +// Min I32 +$num = 0 - pow(2, 31); +roundtrip($testClient, 'testI32', $num); + +// Max I64 +$num = pow(2, 62) + (pow(2, 62) - 1); +roundtrip($testClient, 'testI64', $num); + +// Min I64 +$num = 0 - pow(2, 62) - pow(2, 62); +roundtrip($testClient, 'testI64', $num); + +$transport->close(); +exit($exitcode); diff --git a/src/jaegertracing/thrift/test/php/TestInline.php b/src/jaegertracing/thrift/test/php/TestInline.php new file mode 100644 index 000000000..7066c461f --- /dev/null +++ b/src/jaegertracing/thrift/test/php/TestInline.php @@ -0,0 +1,24 @@ +/* + * 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. + */ + +<?php +$GEN_DIR = 'gen-phpi'; +$MODE = 'inline'; +include_once('TestClient.php'); +?> diff --git a/src/jaegertracing/thrift/test/php/test_php.ini b/src/jaegertracing/thrift/test/php/test_php.ini new file mode 100644 index 000000000..aeb67cbd4 --- /dev/null +++ b/src/jaegertracing/thrift/test/php/test_php.ini @@ -0,0 +1,3 @@ +extension=thrift_protocol.so +extension=json.so +extension=sockets.so diff --git a/src/jaegertracing/thrift/test/py.tornado/Makefile.am b/src/jaegertracing/thrift/test/py.tornado/Makefile.am new file mode 100644 index 000000000..e962f0cfc --- /dev/null +++ b/src/jaegertracing/thrift/test/py.tornado/Makefile.am @@ -0,0 +1,38 @@ +# +# 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. +# + +THRIFT = $(top_srcdir)/compiler/cpp/thrift + +thrift_gen: ../ThriftTest.thrift ../SmallTest.thrift + $(THRIFT) --gen py:tornado ../ThriftTest.thrift + $(THRIFT) --gen py:tornado ../SmallTest.thrift + +check: thrift_gen + ./test_suite.py + +clean-local: + $(RM) -r build + find . -type f \( -iname "*.pyc" \) | xargs rm -f + find . -type d \( -iname "__pycache__" -or -iname "_trial_temp" \) | xargs rm -rf + $(RM) -r gen-py*/ + +dist-hook: + find $(distdir) -type f \( -iname "*.pyc" \) | xargs rm -f + find $(distdir) -type d \( -iname "__pycache__" -or -iname "_trial_temp" \) | xargs rm -rf + $(RM) -r $(distdir)/gen-py*/ diff --git a/src/jaegertracing/thrift/test/py.tornado/setup.cfg b/src/jaegertracing/thrift/test/py.tornado/setup.cfg new file mode 100644 index 000000000..ae587c4f4 --- /dev/null +++ b/src/jaegertracing/thrift/test/py.tornado/setup.cfg @@ -0,0 +1,3 @@ +[flake8] +ignore = E402 +max-line-length = 100 diff --git a/src/jaegertracing/thrift/test/py.tornado/test_suite.py b/src/jaegertracing/thrift/test/py.tornado/test_suite.py new file mode 100755 index 000000000..447fde61b --- /dev/null +++ b/src/jaegertracing/thrift/test/py.tornado/test_suite.py @@ -0,0 +1,236 @@ +#!/usr/bin/env python + +# +# 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. +# + +import datetime +import glob +import os +import sys +import time +import unittest + +basepath = os.path.abspath(os.path.dirname(__file__)) +sys.path.insert(0, basepath + '/gen-py.tornado') +sys.path.insert(0, glob.glob(os.path.join(basepath, '../../lib/py/build/lib*'))[0]) + +try: + __import__('tornado') +except ImportError: + print("module `tornado` not found, skipping test") + sys.exit(0) + +from tornado import gen +from tornado.testing import AsyncTestCase, get_unused_port, gen_test + +from thrift import TTornado +from thrift.Thrift import TApplicationException +from thrift.protocol import TBinaryProtocol + +from ThriftTest import ThriftTest +from ThriftTest.ttypes import Xception, Xtruct + + +class TestHandler(object): + def __init__(self, test_instance): + self.test_instance = test_instance + + def testVoid(self): + pass + + def testString(self, s): + if s == 'unexpected_error': + raise Exception(s) + return s + + def testByte(self, b): + return b + + def testI16(self, i16): + return i16 + + def testI32(self, i32): + return i32 + + def testI64(self, i64): + return i64 + + def testDouble(self, dub): + return dub + + def testBinary(self, thing): + return thing + + def testStruct(self, thing): + return thing + + def testException(self, s): + if s == 'Xception': + x = Xception() + x.errorCode = 1001 + x.message = s + raise x + elif s == 'throw_undeclared': + raise ValueError('testing undeclared exception') + + def testOneway(self, seconds): + start = time.time() + + def fire_oneway(): + end = time.time() + self.test_instance.stop((start, end, seconds)) + + self.test_instance.io_loop.add_timeout( + datetime.timedelta(seconds=seconds), + fire_oneway) + raise Exception('testing exception in oneway method') + + def testNest(self, thing): + return thing + + @gen.coroutine + def testMap(self, thing): + yield gen.moment + raise gen.Return(thing) + + def testSet(self, thing): + return thing + + def testList(self, thing): + return thing + + def testEnum(self, thing): + return thing + + def testTypedef(self, thing): + return thing + + +class ThriftTestCase(AsyncTestCase): + def setUp(self): + super(ThriftTestCase, self).setUp() + + self.port = get_unused_port() + + # server + self.handler = TestHandler(self) + self.processor = ThriftTest.Processor(self.handler) + self.pfactory = TBinaryProtocol.TBinaryProtocolFactory() + + self.server = TTornado.TTornadoServer(self.processor, self.pfactory, io_loop=self.io_loop) + self.server.bind(self.port) + self.server.start(1) + + # client + transport = TTornado.TTornadoStreamTransport('localhost', self.port, io_loop=self.io_loop) + pfactory = TBinaryProtocol.TBinaryProtocolFactory() + self.io_loop.run_sync(transport.open) + self.client = ThriftTest.Client(transport, pfactory) + + @gen_test + def test_void(self): + v = yield self.client.testVoid() + self.assertEqual(v, None) + + @gen_test + def test_string(self): + v = yield self.client.testString('Python') + self.assertEqual(v, 'Python') + + @gen_test + def test_byte(self): + v = yield self.client.testByte(63) + self.assertEqual(v, 63) + + @gen_test + def test_i32(self): + v = yield self.client.testI32(-1) + self.assertEqual(v, -1) + + v = yield self.client.testI32(0) + self.assertEqual(v, 0) + + @gen_test + def test_i64(self): + v = yield self.client.testI64(-34359738368) + self.assertEqual(v, -34359738368) + + @gen_test + def test_double(self): + v = yield self.client.testDouble(-5.235098235) + self.assertEqual(v, -5.235098235) + + @gen_test + def test_struct(self): + x = Xtruct() + x.string_thing = "Zero" + x.byte_thing = 1 + x.i32_thing = -3 + x.i64_thing = -5 + y = yield self.client.testStruct(x) + + self.assertEqual(y.string_thing, "Zero") + self.assertEqual(y.byte_thing, 1) + self.assertEqual(y.i32_thing, -3) + self.assertEqual(y.i64_thing, -5) + + @gen_test + def test_oneway(self): + self.client.testOneway(1) + v = yield self.client.testI32(-1) + self.assertEqual(v, -1) + + @gen_test + def test_map(self): + """ + TestHandler.testMap is a coroutine, this test checks if gen.Return() from a coroutine works. + """ + expected = {1: 1} + res = yield self.client.testMap(expected) + self.assertEqual(res, expected) + + @gen_test + def test_exception(self): + try: + yield self.client.testException('Xception') + except Xception as ex: + self.assertEqual(ex.errorCode, 1001) + self.assertEqual(ex.message, 'Xception') + else: + self.fail("should have gotten exception") + try: + yield self.client.testException('throw_undeclared') + except TApplicationException: + pass + else: + self.fail("should have gotten exception") + + yield self.client.testException('Safe') + + +def suite(): + suite = unittest.TestSuite() + loader = unittest.TestLoader() + suite.addTest(loader.loadTestsFromTestCase(ThriftTestCase)) + return suite + + +if __name__ == '__main__': + unittest.TestProgram(defaultTest='suite', + testRunner=unittest.TextTestRunner(verbosity=1)) diff --git a/src/jaegertracing/thrift/test/py.twisted/Makefile.am b/src/jaegertracing/thrift/test/py.twisted/Makefile.am new file mode 100644 index 000000000..dee8e2f69 --- /dev/null +++ b/src/jaegertracing/thrift/test/py.twisted/Makefile.am @@ -0,0 +1,38 @@ +# +# 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. +# + +TRIAL ?= trial + +stubs: ../ThriftTest.thrift ../SmallTest.thrift + $(THRIFT) --gen py:twisted ../ThriftTest.thrift + $(THRIFT) --gen py:twisted ../SmallTest.thrift + +check: stubs + $(TRIAL) ./test_suite.py + +clean-local: + $(RM) -r build + find . -type f \( -iname "*.pyc" \) | xargs rm -f + find . -type d \( -iname "__pycache__" -or -iname "_trial_temp" \) | xargs rm -rf + $(RM) -r gen-py*/ + +dist-hook: + find $(distdir) -type f \( -iname "*.pyc" \) | xargs rm -f + find $(distdir) -type d \( -iname "__pycache__" -or -iname "_trial_temp" \) | xargs rm -rf + $(RM) -r $(distdir)/gen-py*/ diff --git a/src/jaegertracing/thrift/test/py.twisted/setup.cfg b/src/jaegertracing/thrift/test/py.twisted/setup.cfg new file mode 100644 index 000000000..ae587c4f4 --- /dev/null +++ b/src/jaegertracing/thrift/test/py.twisted/setup.cfg @@ -0,0 +1,3 @@ +[flake8] +ignore = E402 +max-line-length = 100 diff --git a/src/jaegertracing/thrift/test/py.twisted/test_suite.py b/src/jaegertracing/thrift/test/py.twisted/test_suite.py new file mode 100755 index 000000000..02eb7f14f --- /dev/null +++ b/src/jaegertracing/thrift/test/py.twisted/test_suite.py @@ -0,0 +1,198 @@ +#!/usr/bin/env python + +# +# 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. +# + +import glob +import os +import sys +import time + +basepath = os.path.abspath(os.path.dirname(__file__)) +sys.path.insert(0, os.path.join(basepath, 'gen-py.twisted')) +sys.path.insert(0, glob.glob(os.path.join(basepath, '../../lib/py/build/lib.*'))[0]) + +from thrift.Thrift import TApplicationException + +from ThriftTest import ThriftTest +from ThriftTest.ttypes import Xception, Xtruct +from thrift.transport import TTwisted +from thrift.protocol import TBinaryProtocol + +from twisted.trial import unittest +from twisted.internet import defer, reactor +from twisted.internet.protocol import ClientCreator + +from zope.interface import implementer + + +@implementer(ThriftTest.Iface) +class TestHandler: + def __init__(self): + self.onewaysQueue = defer.DeferredQueue() + + def testVoid(self): + pass + + def testString(self, s): + return s + + def testByte(self, b): + return b + + def testI16(self, i16): + return i16 + + def testI32(self, i32): + return i32 + + def testI64(self, i64): + return i64 + + def testDouble(self, dub): + return dub + + def testBinary(self, thing): + return thing + + def testStruct(self, thing): + return thing + + def testException(self, s): + if s == 'Xception': + x = Xception() + x.errorCode = 1001 + x.message = s + raise x + elif s == "throw_undeclared": + raise ValueError("foo") + + def testOneway(self, seconds): + def fireOneway(t): + self.onewaysQueue.put((t, time.time(), seconds)) + reactor.callLater(seconds, fireOneway, time.time()) + raise Exception('') + + def testNest(self, thing): + return thing + + def testMap(self, thing): + return thing + + def testSet(self, thing): + return thing + + def testList(self, thing): + return thing + + def testEnum(self, thing): + return thing + + def testTypedef(self, thing): + return thing + + +class ThriftTestCase(unittest.TestCase): + + @defer.inlineCallbacks + def setUp(self): + self.handler = TestHandler() + self.processor = ThriftTest.Processor(self.handler) + self.pfactory = TBinaryProtocol.TBinaryProtocolFactory() + + self.server = reactor.listenTCP( + 0, TTwisted.ThriftServerFactory(self.processor, self.pfactory), interface="127.0.0.1") + + self.portNo = self.server.getHost().port + + self.txclient = yield ClientCreator(reactor, + TTwisted.ThriftClientProtocol, + ThriftTest.Client, + self.pfactory).connectTCP("127.0.0.1", self.portNo) + self.client = self.txclient.client + + @defer.inlineCallbacks + def tearDown(self): + yield self.server.stopListening() + self.txclient.transport.loseConnection() + + @defer.inlineCallbacks + def testVoid(self): + self.assertEquals((yield self.client.testVoid()), None) + + @defer.inlineCallbacks + def testString(self): + self.assertEquals((yield self.client.testString('Python')), 'Python') + + @defer.inlineCallbacks + def testByte(self): + self.assertEquals((yield self.client.testByte(63)), 63) + + @defer.inlineCallbacks + def testI32(self): + self.assertEquals((yield self.client.testI32(-1)), -1) + self.assertEquals((yield self.client.testI32(0)), 0) + + @defer.inlineCallbacks + def testI64(self): + self.assertEquals((yield self.client.testI64(-34359738368)), -34359738368) + + @defer.inlineCallbacks + def testDouble(self): + self.assertEquals((yield self.client.testDouble(-5.235098235)), -5.235098235) + + # TODO: def testBinary(self) ... + + @defer.inlineCallbacks + def testStruct(self): + x = Xtruct() + x.string_thing = "Zero" + x.byte_thing = 1 + x.i32_thing = -3 + x.i64_thing = -5 + y = yield self.client.testStruct(x) + + self.assertEquals(y.string_thing, "Zero") + self.assertEquals(y.byte_thing, 1) + self.assertEquals(y.i32_thing, -3) + self.assertEquals(y.i64_thing, -5) + + @defer.inlineCallbacks + def testException(self): + try: + yield self.client.testException('Xception') + self.fail("should have gotten exception") + except Xception as x: + self.assertEquals(x.errorCode, 1001) + self.assertEquals(x.message, 'Xception') + + try: + yield self.client.testException("throw_undeclared") + self.fail("should have gotten exception") + except TApplicationException: + pass + + yield self.client.testException('Safe') + + @defer.inlineCallbacks + def testOneway(self): + yield self.client.testOneway(1) + start, end, seconds = yield self.handler.onewaysQueue.get() + self.assertAlmostEquals(seconds, (end - start), places=1) + self.assertEquals((yield self.client.testI32(-1)), -1) diff --git a/src/jaegertracing/thrift/test/py/CMakeLists.txt b/src/jaegertracing/thrift/test/py/CMakeLists.txt new file mode 100644 index 000000000..fbc221738 --- /dev/null +++ b/src/jaegertracing/thrift/test/py/CMakeLists.txt @@ -0,0 +1,34 @@ +# +# 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. +# + +add_test(NAME python_test_generate + COMMAND ${CMAKE_COMMAND} + -DTHRIFTCOMPILER=$<TARGET_FILE:thrift-compiler> + -DMY_PROJECT_DIR=${PROJECT_SOURCE_DIR} + -DMY_CURRENT_SOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR} + -DMY_CURRENT_BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR} + -P ${CMAKE_CURRENT_SOURCE_DIR}/generate.cmake +) + +add_test(NAME python_test + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/RunClientServer.py --gen-base=${CMAKE_CURRENT_BINARY_DIR} + DEPENDS python_test_generate + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +) + diff --git a/src/jaegertracing/thrift/test/py/FastbinaryTest.py b/src/jaegertracing/thrift/test/py/FastbinaryTest.py new file mode 100755 index 000000000..05c0bb6d1 --- /dev/null +++ b/src/jaegertracing/thrift/test/py/FastbinaryTest.py @@ -0,0 +1,256 @@ +#!/usr/bin/env python + +# +# 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. +# + +r""" +PYTHONPATH=./gen-py:../../lib/py/build/lib... ./FastbinaryTest.py +""" + +# TODO(dreiss): Test error cases. Check for memory leaks. + +from __future__ import print_function + +import math +import os +import sys +import timeit + +from copy import deepcopy +from pprint import pprint + +from thrift.transport import TTransport +from thrift.protocol.TBinaryProtocol import TBinaryProtocol, TBinaryProtocolAccelerated +from thrift.protocol.TCompactProtocol import TCompactProtocol, TCompactProtocolAccelerated + +from DebugProtoTest import Srv +from DebugProtoTest.ttypes import Backwards, Bonk, Empty, HolyMoley, OneOfEach, RandomStuff, Wrapper + + +class TDevNullTransport(TTransport.TTransportBase): + def __init__(self): + pass + + def isOpen(self): + return True + + +ooe1 = OneOfEach() +ooe1.im_true = True +ooe1.im_false = False +ooe1.a_bite = 0xd6 +ooe1.integer16 = 27000 +ooe1.integer32 = 1 << 24 +ooe1.integer64 = 6000 * 1000 * 1000 +ooe1.double_precision = math.pi +ooe1.some_characters = "Debug THIS!" +ooe1.zomg_unicode = u"\xd7\n\a\t" + +ooe2 = OneOfEach() +ooe2.integer16 = 16 +ooe2.integer32 = 32 +ooe2.integer64 = 64 +ooe2.double_precision = (math.sqrt(5) + 1) / 2 +ooe2.some_characters = ":R (me going \"rrrr\")" +ooe2.zomg_unicode = u"\xd3\x80\xe2\x85\xae\xce\x9d\x20"\ + u"\xd0\x9d\xce\xbf\xe2\x85\xbf\xd0\xbe"\ + u"\xc9\xa1\xd0\xb3\xd0\xb0\xcf\x81\xe2\x84\x8e"\ + u"\x20\xce\x91\x74\x74\xce\xb1\xe2\x85\xbd\xce\xba"\ + u"\xc7\x83\xe2\x80\xbc" + +if sys.version_info[0] == 2 and os.environ.get('THRIFT_TEST_PY_NO_UTF8STRINGS'): + ooe1.zomg_unicode = ooe1.zomg_unicode.encode('utf8') + ooe2.zomg_unicode = ooe2.zomg_unicode.encode('utf8') + +hm = HolyMoley(**{"big": [], "contain": set(), "bonks": {}}) +hm.big.append(ooe1) +hm.big.append(ooe2) +hm.big[0].a_bite = 0x22 +hm.big[1].a_bite = 0x22 + +hm.contain.add(("and a one", "and a two")) +hm.contain.add(("then a one, two", "three!", "FOUR!")) +if sys.version_info[0] == 2 and os.environ.get('THRIFT_TEST_PY_NO_UTF8STRINGS'): + hm.contain.add((u"\xd7\n\a\t".encode('utf8'),)) +else: + hm.contain.add((u"\xd7\n\a\t",)) +hm.contain.add(()) + +hm.bonks["nothing"] = [] +hm.bonks["something"] = [ + Bonk(**{"type": 1, "message": "Wait."}), + Bonk(**{"type": 2, "message": "What?"}), +] +hm.bonks["poe"] = [ + Bonk(**{"type": 3, "message": "quoth"}), + Bonk(**{"type": 4, "message": "the raven"}), + Bonk(**{"type": 5, "message": "nevermore"}), +] + +rs = RandomStuff() +rs.a = 1 +rs.b = 2 +rs.c = 3 +rs.myintlist = list(range(20)) +rs.maps = {1: Wrapper(**{"foo": Empty()}), 2: Wrapper(**{"foo": Empty()})} +rs.bigint = 124523452435 +rs.triple = 3.14 + +# make sure this splits two buffers in a buffered protocol +rshuge = RandomStuff() +rshuge.myintlist = list(range(10000)) + +my_zero = Srv.Janky_result(**{"success": 5}) + + +class Test(object): + def __init__(self, fast, slow): + self._fast = fast + self._slow = slow + + def _check_write(self, o): + trans_fast = TTransport.TMemoryBuffer() + trans_slow = TTransport.TMemoryBuffer() + prot_fast = self._fast(trans_fast, fallback=False) + prot_slow = self._slow(trans_slow) + + o.write(prot_fast) + o.write(prot_slow) + ORIG = trans_slow.getvalue() + MINE = trans_fast.getvalue() + if ORIG != MINE: + print("actual : %s\nexpected: %s" % (repr(MINE), repr(ORIG))) + raise Exception('write value mismatch') + + def _check_read(self, o): + prot = self._slow(TTransport.TMemoryBuffer()) + o.write(prot) + + slow_version_binary = prot.trans.getvalue() + + prot = self._fast( + TTransport.TMemoryBuffer(slow_version_binary), fallback=False) + c = o.__class__() + c.read(prot) + if c != o: + print("actual : ") + pprint(repr(c)) + print("expected: ") + pprint(repr(o)) + raise Exception('read value mismatch') + + prot = self._fast( + TTransport.TBufferedTransport( + TTransport.TMemoryBuffer(slow_version_binary)), fallback=False) + c = o.__class__() + c.read(prot) + if c != o: + print("actual : ") + pprint(repr(c)) + print("expected: ") + pprint(repr(o)) + raise Exception('read value mismatch') + + def do_test(self): + self._check_write(HolyMoley()) + self._check_read(HolyMoley()) + + self._check_write(hm) + no_set = deepcopy(hm) + no_set.contain = set() + self._check_read(no_set) + self._check_read(hm) + + self._check_write(rs) + self._check_read(rs) + + self._check_write(rshuge) + self._check_read(rshuge) + + self._check_write(my_zero) + self._check_read(my_zero) + + self._check_read(Backwards(**{"first_tag2": 4, "second_tag1": 2})) + + # One case where the serialized form changes, but only superficially. + o = Backwards(**{"first_tag2": 4, "second_tag1": 2}) + trans_fast = TTransport.TMemoryBuffer() + trans_slow = TTransport.TMemoryBuffer() + prot_fast = self._fast(trans_fast, fallback=False) + prot_slow = self._slow(trans_slow) + + o.write(prot_fast) + o.write(prot_slow) + ORIG = trans_slow.getvalue() + MINE = trans_fast.getvalue() + assert id(ORIG) != id(MINE) + + prot = self._fast(TTransport.TMemoryBuffer(), fallback=False) + o.write(prot) + prot = self._slow( + TTransport.TMemoryBuffer(prot.trans.getvalue())) + c = o.__class__() + c.read(prot) + if c != o: + print("copy: ") + pprint(repr(c)) + print("orig: ") + pprint(repr(o)) + + +def do_test(fast, slow): + Test(fast, slow).do_test() + + +def do_benchmark(protocol, iters=5000, skip_slow=False): + setup = """ +from __main__ import hm, rs, TDevNullTransport +from thrift.protocol.{0} import {0}{1} +trans = TDevNullTransport() +prot = {0}{1}(trans{2}) +""" + + setup_fast = setup.format(protocol, 'Accelerated', ', fallback=False') + if not skip_slow: + setup_slow = setup.format(protocol, '', '') + + print("Starting Benchmarks") + + if not skip_slow: + print("HolyMoley Standard = %f" % + timeit.Timer('hm.write(prot)', setup_slow).timeit(number=iters)) + + print("HolyMoley Acceler. = %f" % + timeit.Timer('hm.write(prot)', setup_fast).timeit(number=iters)) + + if not skip_slow: + print("FastStruct Standard = %f" % + timeit.Timer('rs.write(prot)', setup_slow).timeit(number=iters)) + + print("FastStruct Acceler. = %f" % + timeit.Timer('rs.write(prot)', setup_fast).timeit(number=iters)) + + +if __name__ == '__main__': + print('Testing TBinaryAccelerated') + do_test(TBinaryProtocolAccelerated, TBinaryProtocol) + do_benchmark('TBinaryProtocol') + print('Testing TCompactAccelerated') + do_test(TCompactProtocolAccelerated, TCompactProtocol) + do_benchmark('TCompactProtocol') diff --git a/src/jaegertracing/thrift/test/py/Makefile.am b/src/jaegertracing/thrift/test/py/Makefile.am new file mode 100644 index 000000000..9433e5907 --- /dev/null +++ b/src/jaegertracing/thrift/test/py/Makefile.am @@ -0,0 +1,105 @@ +# +# 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. +# +AUTOMAKE_OPTIONS = serial-tests + +py_unit_tests = RunClientServer.py + +thrift_gen = \ + gen-py/ThriftTest/__init__.py \ + gen-py/DebugProtoTest/__init__.py \ + gen-py/DoubleConstantsTest/__init__.py \ + gen-py/Recursive/__init__.py \ + gen-py-default/ThriftTest/__init__.py \ + gen-py-default/DebugProtoTest/__init__.py \ + gen-py-default/DoubleConstantsTest/__init__.py \ + gen-py-default/Recursive/__init__.py \ + gen-py-slots/ThriftTest/__init__.py \ + gen-py-slots/DebugProtoTest/__init__.py \ + gen-py-slots/DoubleConstantsTest/__init__.py \ + gen-py-slots/Recursive/__init__.py \ + gen-py-oldstyle/ThriftTest/__init__.py \ + gen-py-oldstyle/DebugProtoTest/__init__.py \ + gen-py-oldstyle/DoubleConstantsTest/__init__.py \ + gen-py-oldstyle/Recursive/__init__.py \ + gen-py-no_utf8strings/ThriftTest/__init__.py \ + gen-py-no_utf8strings/DebugProtoTest/__init__.py \ + gen-py-no_utf8strings/DoubleConstantsTest/__init__.py \ + gen-py-no_utf8strings/Recursive/__init__.py \ + gen-py-dynamic/ThriftTest/__init__.py \ + gen-py-dynamic/DebugProtoTest/__init__.py \ + gen-py-dynamic/DoubleConstantsTest/__init__.py \ + gen-py-dynamic/Recursive/__init__.py \ + gen-py-dynamicslots/ThriftTest/__init__.py \ + gen-py-dynamicslots/DebugProtoTest/__init__.py \ + gen-py-dynamicslots/DoubleConstantsTest/__init__.py \ + gen-py-dynamicslots/Recursive/__init__.py + + +precross: $(thrift_gen) +BUILT_SOURCES = $(thrift_gen) + +helper_scripts= \ + TestClient.py \ + TestServer.py + +check_SCRIPTS= \ + $(thrift_gen) \ + $(py_unit_tests) \ + $(helper_scripts) + +TESTS= $(py_unit_tests) + + +gen-py/%/__init__.py: ../%.thrift $(THRIFT) + $(THRIFT) --gen py $< + +gen-py-default/%/__init__.py: ../%.thrift $(THRIFT) + test -d gen-py-default || $(MKDIR_P) gen-py-default + $(THRIFT) --gen py -out gen-py-default $< + +gen-py-slots/%/__init__.py: ../%.thrift $(THRIFT) + test -d gen-py-slots || $(MKDIR_P) gen-py-slots + $(THRIFT) --gen py:slots -out gen-py-slots $< + +gen-py-oldstyle/%/__init__.py: ../%.thrift $(THRIFT) + test -d gen-py-oldstyle || $(MKDIR_P) gen-py-oldstyle + $(THRIFT) --gen py:old_style -out gen-py-oldstyle $< + +gen-py-no_utf8strings/%/__init__.py: ../%.thrift $(THRIFT) + test -d gen-py-no_utf8strings || $(MKDIR_P) gen-py-no_utf8strings + $(THRIFT) --gen py:no_utf8strings -out gen-py-no_utf8strings $< + +gen-py-dynamic/%/__init__.py: ../%.thrift $(THRIFT) + test -d gen-py-dynamic || $(MKDIR_P) gen-py-dynamic + $(THRIFT) --gen py:dynamic -out gen-py-dynamic $< + +gen-py-dynamicslots/%/__init__.py: ../%.thrift $(THRIFT) + test -d gen-py-dynamicslots || $(MKDIR_P) gen-py-dynamicslots + $(THRIFT) --gen py:dynamic,slots -out gen-py-dynamicslots $< + +clean-local: + $(RM) -r build + find . -type f \( -iname "*.pyc" \) | xargs rm -f + find . -type d \( -iname "__pycache__" -or -iname "_trial_temp" \) | xargs rm -rf + $(RM) -r gen-py*/ + +dist-hook: + find $(distdir) -type f \( -iname "*.pyc" \) | xargs rm -f + find $(distdir) -type d \( -iname "__pycache__" -or -iname "_trial_temp" \) | xargs rm -rf + $(RM) -r $(distdir)/gen-py*/ diff --git a/src/jaegertracing/thrift/test/py/RunClientServer.py b/src/jaegertracing/thrift/test/py/RunClientServer.py new file mode 100755 index 000000000..56a408e60 --- /dev/null +++ b/src/jaegertracing/thrift/test/py/RunClientServer.py @@ -0,0 +1,323 @@ +#!/usr/bin/env python + +# +# 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. +# + +from __future__ import division +from __future__ import print_function +import platform +import copy +import os +import signal +import socket +import subprocess +import sys +import time +from optparse import OptionParser + +from util import local_libpath + +SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__)) + +SCRIPTS = [ + 'FastbinaryTest.py', + 'TestFrozen.py', + 'TestRenderedDoubleConstants.py', + 'TSimpleJSONProtocolTest.py', + 'SerializationTest.py', + 'TestEof.py', + 'TestSyntax.py', + 'TestSocket.py', +] +FRAMED = ["TNonblockingServer"] +SKIP_ZLIB = ['TNonblockingServer', 'THttpServer'] +SKIP_SSL = ['THttpServer'] +EXTRA_DELAY = dict(TProcessPoolServer=5.5) + +PROTOS = [ + 'accel', + 'accelc', + 'binary', + 'compact', + 'json', + 'header', +] + + +def default_servers(): + servers = [ + 'TSimpleServer', + 'TThreadedServer', + 'TThreadPoolServer', + 'TNonblockingServer', + 'THttpServer', + ] + if platform.system() != 'Windows': + servers.append('TProcessPoolServer') + servers.append('TForkingServer') + return servers + + +def relfile(fname): + return os.path.join(SCRIPT_DIR, fname) + + +def setup_pypath(libdir, gendir): + dirs = [libdir, gendir] + env = copy.deepcopy(os.environ) + pypath = env.get('PYTHONPATH', None) + if pypath: + dirs.append(pypath) + env['PYTHONPATH'] = os.pathsep.join(dirs) + if gendir.endswith('gen-py-no_utf8strings'): + env['THRIFT_TEST_PY_NO_UTF8STRINGS'] = '1' + return env + + +def runScriptTest(libdir, genbase, genpydir, script): + env = setup_pypath(libdir, os.path.join(genbase, genpydir)) + script_args = [sys.executable, relfile(script)] + print('\nTesting script: %s\n----' % (' '.join(script_args))) + ret = subprocess.call(script_args, env=env) + if ret != 0: + print('*** FAILED ***', file=sys.stderr) + print('LIBDIR: %s' % libdir, file=sys.stderr) + print('PY_GEN: %s' % genpydir, file=sys.stderr) + print('SCRIPT: %s' % script, file=sys.stderr) + raise Exception("Script subprocess failed, retcode=%d, args: %s" % (ret, ' '.join(script_args))) + + +def runServiceTest(libdir, genbase, genpydir, server_class, proto, port, use_zlib, use_ssl, verbose): + env = setup_pypath(libdir, os.path.join(genbase, genpydir)) + # Build command line arguments + server_args = [sys.executable, relfile('TestServer.py')] + cli_args = [sys.executable, relfile('TestClient.py')] + for which in (server_args, cli_args): + which.append('--protocol=%s' % proto) # accel, binary, compact or json + which.append('--port=%d' % port) # default to 9090 + if use_zlib: + which.append('--zlib') + if use_ssl: + which.append('--ssl') + if verbose == 0: + which.append('-q') + if verbose == 2: + which.append('-v') + # server-specific option to select server class + server_args.append(server_class) + # client-specific cmdline options + if server_class in FRAMED: + cli_args.append('--transport=framed') + else: + cli_args.append('--transport=buffered') + if server_class == 'THttpServer': + cli_args.append('--http=/') + if verbose > 0: + print('Testing server %s: %s' % (server_class, ' '.join(server_args))) + serverproc = subprocess.Popen(server_args, env=env) + + def ensureServerAlive(): + if serverproc.poll() is not None: + print(('FAIL: Server process (%s) failed with retcode %d') + % (' '.join(server_args), serverproc.returncode)) + raise Exception('Server subprocess %s died, args: %s' + % (server_class, ' '.join(server_args))) + + # Wait for the server to start accepting connections on the given port. + sleep_time = 0.1 # Seconds + max_attempts = 100 + attempt = 0 + while True: + sock4 = socket.socket() + sock6 = socket.socket(socket.AF_INET6) + try: + if sock4.connect_ex(('127.0.0.1', port)) == 0 \ + or sock6.connect_ex(('::1', port)) == 0: + break + attempt += 1 + if attempt >= max_attempts: + raise Exception("TestServer not ready on port %d after %.2f seconds" + % (port, sleep_time * attempt)) + ensureServerAlive() + time.sleep(sleep_time) + finally: + sock4.close() + sock6.close() + + try: + if verbose > 0: + print('Testing client: %s' % (' '.join(cli_args))) + ret = subprocess.call(cli_args, env=env) + if ret != 0: + print('*** FAILED ***', file=sys.stderr) + print('LIBDIR: %s' % libdir, file=sys.stderr) + print('PY_GEN: %s' % genpydir, file=sys.stderr) + raise Exception("Client subprocess failed, retcode=%d, args: %s" % (ret, ' '.join(cli_args))) + finally: + # check that server didn't die + ensureServerAlive() + extra_sleep = EXTRA_DELAY.get(server_class, 0) + if extra_sleep > 0 and verbose > 0: + print('Giving %s (proto=%s,zlib=%s,ssl=%s) an extra %d seconds for child' + 'processes to terminate via alarm' + % (server_class, proto, use_zlib, use_ssl, extra_sleep)) + time.sleep(extra_sleep) + sig = signal.SIGKILL if platform.system() != 'Windows' else signal.SIGABRT + os.kill(serverproc.pid, sig) + serverproc.wait() + + +class TestCases(object): + def __init__(self, genbase, libdir, port, gendirs, servers, verbose): + self.genbase = genbase + self.libdir = libdir + self.port = port + self.verbose = verbose + self.gendirs = gendirs + self.servers = servers + + def default_conf(self): + return { + 'gendir': self.gendirs[0], + 'server': self.servers[0], + 'proto': PROTOS[0], + 'zlib': False, + 'ssl': False, + } + + def run(self, conf, test_count): + with_zlib = conf['zlib'] + with_ssl = conf['ssl'] + try_server = conf['server'] + try_proto = conf['proto'] + genpydir = conf['gendir'] + # skip any servers that don't work with the Zlib transport + if with_zlib and try_server in SKIP_ZLIB: + return False + # skip any servers that don't work with SSL + if with_ssl and try_server in SKIP_SSL: + return False + if self.verbose > 0: + print('\nTest run #%d: (includes %s) Server=%s, Proto=%s, zlib=%s, SSL=%s' + % (test_count, genpydir, try_server, try_proto, with_zlib, with_ssl)) + runServiceTest(self.libdir, self.genbase, genpydir, try_server, try_proto, self.port, with_zlib, with_ssl, self.verbose) + if self.verbose > 0: + print('OK: Finished (includes %s) %s / %s proto / zlib=%s / SSL=%s. %d combinations tested.' + % (genpydir, try_server, try_proto, with_zlib, with_ssl, test_count)) + return True + + def test_feature(self, name, values): + test_count = 0 + conf = self.default_conf() + for try_server in values: + conf[name] = try_server + if self.run(conf, test_count): + test_count += 1 + return test_count + + def run_all_tests(self): + test_count = 0 + for try_server in self.servers: + for genpydir in self.gendirs: + for try_proto in PROTOS: + for with_zlib in (False, True): + # skip any servers that don't work with the Zlib transport + if with_zlib and try_server in SKIP_ZLIB: + continue + for with_ssl in (False, True): + # skip any servers that don't work with SSL + if with_ssl and try_server in SKIP_SSL: + continue + test_count += 1 + if self.verbose > 0: + print('\nTest run #%d: (includes %s) Server=%s, Proto=%s, zlib=%s, SSL=%s' + % (test_count, genpydir, try_server, try_proto, with_zlib, with_ssl)) + runServiceTest(self.libdir, self.genbase, genpydir, try_server, try_proto, self.port, with_zlib, with_ssl) + if self.verbose > 0: + print('OK: Finished (includes %s) %s / %s proto / zlib=%s / SSL=%s. %d combinations tested.' + % (genpydir, try_server, try_proto, with_zlib, with_ssl, test_count)) + return test_count + + +def main(): + parser = OptionParser() + parser.add_option('--all', action="store_true", dest='all') + parser.add_option('--genpydirs', type='string', dest='genpydirs', + default='default,slots,oldstyle,no_utf8strings,dynamic,dynamicslots', + help='directory extensions for generated code, used as suffixes for \"gen-py-*\" added sys.path for individual tests') + parser.add_option("--port", type="int", dest="port", default=9090, + help="port number for server to listen on") + parser.add_option('-v', '--verbose', action="store_const", + dest="verbose", const=2, + help="verbose output") + parser.add_option('-q', '--quiet', action="store_const", + dest="verbose", const=0, + help="minimal output") + parser.add_option('-L', '--libdir', dest="libdir", default=local_libpath(), + help="directory path that contains Thrift Python library") + parser.add_option('--gen-base', dest="gen_base", default=SCRIPT_DIR, + help="directory path that contains Thrift Python library") + parser.set_defaults(verbose=1) + options, args = parser.parse_args() + + generated_dirs = [] + for gp_dir in options.genpydirs.split(','): + generated_dirs.append('gen-py-%s' % (gp_dir)) + + # commandline permits a single class name to be specified to override SERVERS=[...] + servers = default_servers() + if len(args) == 1: + if args[0] in servers: + servers = args + else: + print('Unavailable server type "%s", please choose one of: %s' % (args[0], servers)) + sys.exit(0) + + tests = TestCases(options.gen_base, options.libdir, options.port, generated_dirs, servers, options.verbose) + + # run tests without a client/server first + print('----------------') + print(' Executing individual test scripts with various generated code directories') + print(' Directories to be tested: ' + ', '.join(generated_dirs)) + print(' Scripts to be tested: ' + ', '.join(SCRIPTS)) + print('----------------') + for genpydir in generated_dirs: + for script in SCRIPTS: + runScriptTest(options.libdir, options.gen_base, genpydir, script) + + print('----------------') + print(' Executing Client/Server tests with various generated code directories') + print(' Servers to be tested: ' + ', '.join(servers)) + print(' Directories to be tested: ' + ', '.join(generated_dirs)) + print(' Protocols to be tested: ' + ', '.join(PROTOS)) + print(' Options to be tested: ZLIB(yes/no), SSL(yes/no)') + print('----------------') + + if options.all: + tests.run_all_tests() + else: + tests.test_feature('gendir', generated_dirs) + tests.test_feature('server', servers) + tests.test_feature('proto', PROTOS) + tests.test_feature('zlib', [False, True]) + tests.test_feature('ssl', [False, True]) + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/src/jaegertracing/thrift/test/py/SerializationTest.py b/src/jaegertracing/thrift/test/py/SerializationTest.py new file mode 100755 index 000000000..ef7983568 --- /dev/null +++ b/src/jaegertracing/thrift/test/py/SerializationTest.py @@ -0,0 +1,457 @@ +#!/usr/bin/env python + +# +# 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. +# + +from ThriftTest.ttypes import ( + Bonk, + Bools, + LargeDeltas, + ListBonks, + NestedListsBonk, + NestedListsI32x2, + NestedListsI32x3, + NestedMixedx2, + Numberz, + VersioningTestV1, + VersioningTestV2, + Xtruct, + Xtruct2, +) + +from Recursive.ttypes import RecTree +from Recursive.ttypes import RecList +from Recursive.ttypes import CoRec +from Recursive.ttypes import CoRec2 +from Recursive.ttypes import VectorTest +from DebugProtoTest.ttypes import CompactProtoTestStruct, Empty +from thrift.transport import TTransport +from thrift.protocol import TBinaryProtocol, TCompactProtocol, TJSONProtocol +from thrift.TSerialization import serialize, deserialize +import sys +import unittest + + +class AbstractTest(unittest.TestCase): + + def setUp(self): + self.v1obj = VersioningTestV1( + begin_in_both=12345, + old_string='aaa', + end_in_both=54321, + ) + + self.v2obj = VersioningTestV2( + begin_in_both=12345, + newint=1, + newbyte=2, + newshort=3, + newlong=4, + newdouble=5.0, + newstruct=Bonk(message="Hello!", type=123), + newlist=[7, 8, 9], + newset=set([42, 1, 8]), + newmap={1: 2, 2: 3}, + newstring="Hola!", + end_in_both=54321, + ) + + self.bools = Bools(im_true=True, im_false=False) + self.bools_flipped = Bools(im_true=False, im_false=True) + + self.large_deltas = LargeDeltas( + b1=self.bools, + b10=self.bools_flipped, + b100=self.bools, + check_true=True, + b1000=self.bools_flipped, + check_false=False, + vertwo2000=VersioningTestV2(newstruct=Bonk(message='World!', type=314)), + a_set2500=set(['lazy', 'brown', 'cow']), + vertwo3000=VersioningTestV2(newset=set([2, 3, 5, 7, 11])), + big_numbers=[2 ** 8, 2 ** 16, 2 ** 31 - 1, -(2 ** 31 - 1)] + ) + + self.compact_struct = CompactProtoTestStruct( + a_byte=127, + a_i16=32000, + a_i32=1000000000, + a_i64=0xffffffffff, + a_double=5.6789, + a_string="my string", + true_field=True, + false_field=False, + empty_struct_field=Empty(), + byte_list=[-127, -1, 0, 1, 127], + i16_list=[-1, 0, 1, 0x7fff], + i32_list=[-1, 0, 0xff, 0xffff, 0xffffff, 0x7fffffff], + i64_list=[-1, 0, 0xff, 0xffff, 0xffffff, 0xffffffff, 0xffffffffff, 0xffffffffffff, 0xffffffffffffff, 0x7fffffffffffffff], + double_list=[0.1, 0.2, 0.3], + string_list=["first", "second", "third"], + boolean_list=[True, True, True, False, False, False], + struct_list=[Empty(), Empty()], + byte_set=set([-127, -1, 0, 1, 127]), + i16_set=set([-1, 0, 1, 0x7fff]), + i32_set=set([1, 2, 3]), + i64_set=set([-1, 0, 0xff, 0xffff, 0xffffff, 0xffffffff, 0xffffffffff, 0xffffffffffff, 0xffffffffffffff, 0x7fffffffffffffff]), + double_set=set([0.1, 0.2, 0.3]), + string_set=set(["first", "second", "third"]), + boolean_set=set([True, False]), + # struct_set=set([Empty()]), # unhashable instance + byte_byte_map={1: 2}, + i16_byte_map={1: 1, -1: 1, 0x7fff: 1}, + i32_byte_map={1: 1, -1: 1, 0x7fffffff: 1}, + i64_byte_map={0: 1, 1: 1, -1: 1, 0x7fffffffffffffff: 1}, + double_byte_map={-1.1: 1, 1.1: 1}, + string_byte_map={"first": 1, "second": 2, "third": 3, "": 0}, + boolean_byte_map={True: 1, False: 0}, + byte_i16_map={1: 1, 2: -1, 3: 0x7fff}, + byte_i32_map={1: 1, 2: -1, 3: 0x7fffffff}, + byte_i64_map={1: 1, 2: -1, 3: 0x7fffffffffffffff}, + byte_double_map={1: 0.1, 2: -0.1, 3: 1000000.1}, + byte_string_map={1: "", 2: "blah", 3: "loooooooooooooong string"}, + byte_boolean_map={1: True, 2: False}, + # list_byte_map # unhashable + # set_byte_map={set([1, 2, 3]) : 1, set([0, 1]) : 2, set([]) : 0}, # unhashable + # map_byte_map # unhashable + byte_map_map={0: {}, 1: {1: 1}, 2: {1: 1, 2: 2}}, + byte_set_map={0: set([]), 1: set([1]), 2: set([1, 2])}, + byte_list_map={0: [], 1: [1], 2: [1, 2]}, + ) + + self.nested_lists_i32x2 = NestedListsI32x2( + [ + [1, 1, 2], + [2, 7, 9], + [3, 5, 8] + ] + ) + + self.nested_lists_i32x3 = NestedListsI32x3( + [ + [ + [2, 7, 9], + [3, 5, 8] + ], + [ + [1, 1, 2], + [1, 4, 9] + ] + ] + ) + + self.nested_mixedx2 = NestedMixedx2(int_set_list=[ + set([1, 2, 3]), + set([1, 4, 9]), + set([1, 2, 3, 5, 8, 13, 21]), + set([-1, 0, 1]) + ], + # note, the sets below are sets of chars, since the strings are iterated + map_int_strset={10: set('abc'), 20: set('def'), 30: set('GHI')}, + map_int_strset_list=[ + {10: set('abc'), 20: set('def'), 30: set('GHI')}, + {100: set('lmn'), 200: set('opq'), 300: set('RST')}, + {1000: set('uvw'), 2000: set('wxy'), 3000: set('XYZ')}] + ) + + self.nested_lists_bonk = NestedListsBonk( + [ + [ + [ + Bonk(message='inner A first', type=1), + Bonk(message='inner A second', type=1) + ], + [ + Bonk(message='inner B first', type=2), + Bonk(message='inner B second', type=2) + ] + ] + ] + ) + + self.list_bonks = ListBonks( + [ + Bonk(message='inner A', type=1), + Bonk(message='inner B', type=2), + Bonk(message='inner C', type=0) + ] + ) + + def _serialize(self, obj): + trans = TTransport.TMemoryBuffer() + prot = self.protocol_factory.getProtocol(trans) + obj.write(prot) + return trans.getvalue() + + def _deserialize(self, objtype, data): + prot = self.protocol_factory.getProtocol(TTransport.TMemoryBuffer(data)) + ret = objtype() + ret.read(prot) + return ret + + def testForwards(self): + obj = self._deserialize(VersioningTestV2, self._serialize(self.v1obj)) + self.assertEquals(obj.begin_in_both, self.v1obj.begin_in_both) + self.assertEquals(obj.end_in_both, self.v1obj.end_in_both) + + def testBackwards(self): + obj = self._deserialize(VersioningTestV1, self._serialize(self.v2obj)) + self.assertEquals(obj.begin_in_both, self.v2obj.begin_in_both) + self.assertEquals(obj.end_in_both, self.v2obj.end_in_both) + + def testSerializeV1(self): + obj = self._deserialize(VersioningTestV1, self._serialize(self.v1obj)) + self.assertEquals(obj, self.v1obj) + + def testSerializeV2(self): + obj = self._deserialize(VersioningTestV2, self._serialize(self.v2obj)) + self.assertEquals(obj, self.v2obj) + + def testBools(self): + self.assertNotEquals(self.bools, self.bools_flipped) + self.assertNotEquals(self.bools, self.v1obj) + obj = self._deserialize(Bools, self._serialize(self.bools)) + self.assertEquals(obj, self.bools) + obj = self._deserialize(Bools, self._serialize(self.bools_flipped)) + self.assertEquals(obj, self.bools_flipped) + rep = repr(self.bools) + self.assertTrue(len(rep) > 0) + + def testLargeDeltas(self): + # test large field deltas (meaningful in CompactProto only) + obj = self._deserialize(LargeDeltas, self._serialize(self.large_deltas)) + self.assertEquals(obj, self.large_deltas) + rep = repr(self.large_deltas) + self.assertTrue(len(rep) > 0) + + def testNestedListsI32x2(self): + obj = self._deserialize(NestedListsI32x2, self._serialize(self.nested_lists_i32x2)) + self.assertEquals(obj, self.nested_lists_i32x2) + rep = repr(self.nested_lists_i32x2) + self.assertTrue(len(rep) > 0) + + def testNestedListsI32x3(self): + obj = self._deserialize(NestedListsI32x3, self._serialize(self.nested_lists_i32x3)) + self.assertEquals(obj, self.nested_lists_i32x3) + rep = repr(self.nested_lists_i32x3) + self.assertTrue(len(rep) > 0) + + def testNestedMixedx2(self): + obj = self._deserialize(NestedMixedx2, self._serialize(self.nested_mixedx2)) + self.assertEquals(obj, self.nested_mixedx2) + rep = repr(self.nested_mixedx2) + self.assertTrue(len(rep) > 0) + + def testNestedListsBonk(self): + obj = self._deserialize(NestedListsBonk, self._serialize(self.nested_lists_bonk)) + self.assertEquals(obj, self.nested_lists_bonk) + rep = repr(self.nested_lists_bonk) + self.assertTrue(len(rep) > 0) + + def testListBonks(self): + obj = self._deserialize(ListBonks, self._serialize(self.list_bonks)) + self.assertEquals(obj, self.list_bonks) + rep = repr(self.list_bonks) + self.assertTrue(len(rep) > 0) + + def testCompactStruct(self): + # test large field deltas (meaningful in CompactProto only) + obj = self._deserialize(CompactProtoTestStruct, self._serialize(self.compact_struct)) + self.assertEquals(obj, self.compact_struct) + rep = repr(self.compact_struct) + self.assertTrue(len(rep) > 0) + + def testIntegerLimits(self): + if (sys.version_info[0] == 2 and sys.version_info[1] <= 6): + print('Skipping testIntegerLimits for Python 2.6') + return + bad_values = [CompactProtoTestStruct(a_byte=128), CompactProtoTestStruct(a_byte=-129), + CompactProtoTestStruct(a_i16=32768), CompactProtoTestStruct(a_i16=-32769), + CompactProtoTestStruct(a_i32=2147483648), CompactProtoTestStruct(a_i32=-2147483649), + CompactProtoTestStruct(a_i64=9223372036854775808), CompactProtoTestStruct(a_i64=-9223372036854775809) + ] + + for value in bad_values: + self.assertRaises(Exception, self._serialize, value) + + def testRecTree(self): + """Ensure recursive tree node can be created.""" + children = [] + for idx in range(1, 5): + node = RecTree(item=idx, children=None) + children.append(node) + + parent = RecTree(item=0, children=children) + serde_parent = self._deserialize(RecTree, self._serialize(parent)) + self.assertEquals(0, serde_parent.item) + self.assertEquals(4, len(serde_parent.children)) + for child in serde_parent.children: + # Cannot use assertIsInstance in python 2.6? + self.assertTrue(isinstance(child, RecTree)) + + def _buildLinkedList(self): + head = cur = RecList(item=0) + for idx in range(1, 5): + node = RecList(item=idx) + cur.nextitem = node + cur = node + return head + + def _collapseLinkedList(self, head): + out_list = [] + cur = head + while cur is not None: + out_list.append(cur.item) + cur = cur.nextitem + return out_list + + def testRecList(self): + """Ensure recursive linked list can be created.""" + rec_list = self._buildLinkedList() + serde_list = self._deserialize(RecList, self._serialize(rec_list)) + out_list = self._collapseLinkedList(serde_list) + self.assertEquals([0, 1, 2, 3, 4], out_list) + + def testCoRec(self): + """Ensure co-recursive structures can be created.""" + item1 = CoRec() + item2 = CoRec2() + + item1.other = item2 + item2.other = item1 + + # NOTE [econner724,2017-06-21]: These objects cannot be serialized as serialization + # results in an infinite loop. fbthrift also suffers from this + # problem. + + def testRecVector(self): + """Ensure a list of recursive nodes can be created.""" + mylist = [self._buildLinkedList(), self._buildLinkedList()] + myvec = VectorTest(lister=mylist) + + serde_vec = self._deserialize(VectorTest, self._serialize(myvec)) + golden_list = [0, 1, 2, 3, 4] + for cur_list in serde_vec.lister: + out_list = self._collapseLinkedList(cur_list) + self.assertEqual(golden_list, out_list) + + +class NormalBinaryTest(AbstractTest): + protocol_factory = TBinaryProtocol.TBinaryProtocolFactory() + + +class AcceleratedBinaryTest(AbstractTest): + protocol_factory = TBinaryProtocol.TBinaryProtocolAcceleratedFactory(fallback=False) + + +class CompactProtocolTest(AbstractTest): + protocol_factory = TCompactProtocol.TCompactProtocolFactory() + + +class AcceleratedCompactTest(AbstractTest): + protocol_factory = TCompactProtocol.TCompactProtocolAcceleratedFactory(fallback=False) + + +class JSONProtocolTest(AbstractTest): + protocol_factory = TJSONProtocol.TJSONProtocolFactory() + + +class AcceleratedFramedTest(unittest.TestCase): + def testSplit(self): + """Test FramedTransport and BinaryProtocolAccelerated + + Tests that TBinaryProtocolAccelerated and TFramedTransport + play nicely together when a read spans a frame""" + + protocol_factory = TBinaryProtocol.TBinaryProtocolAcceleratedFactory() + bigstring = "".join(chr(byte) for byte in range(ord("a"), ord("z") + 1)) + + databuf = TTransport.TMemoryBuffer() + prot = protocol_factory.getProtocol(databuf) + prot.writeI32(42) + prot.writeString(bigstring) + prot.writeI16(24) + data = databuf.getvalue() + cutpoint = len(data) // 2 + parts = [data[:cutpoint], data[cutpoint:]] + + framed_buffer = TTransport.TMemoryBuffer() + framed_writer = TTransport.TFramedTransport(framed_buffer) + for part in parts: + framed_writer.write(part) + framed_writer.flush() + self.assertEquals(len(framed_buffer.getvalue()), len(data) + 8) + + # Recreate framed_buffer so we can read from it. + framed_buffer = TTransport.TMemoryBuffer(framed_buffer.getvalue()) + framed_reader = TTransport.TFramedTransport(framed_buffer) + prot = protocol_factory.getProtocol(framed_reader) + self.assertEqual(prot.readI32(), 42) + self.assertEqual(prot.readString(), bigstring) + self.assertEqual(prot.readI16(), 24) + + +class SerializersTest(unittest.TestCase): + + def testSerializeThenDeserialize(self): + obj = Xtruct2(i32_thing=1, + struct_thing=Xtruct(string_thing="foo")) + + s1 = serialize(obj) + for i in range(10): + self.assertEquals(s1, serialize(obj)) + objcopy = Xtruct2() + deserialize(objcopy, serialize(obj)) + self.assertEquals(obj, objcopy) + + obj = Xtruct(string_thing="bar") + objcopy = Xtruct() + deserialize(objcopy, serialize(obj)) + self.assertEquals(obj, objcopy) + + # test booleans + obj = Bools(im_true=True, im_false=False) + objcopy = Bools() + deserialize(objcopy, serialize(obj)) + self.assertEquals(obj, objcopy) + + # test enums + for num, name in Numberz._VALUES_TO_NAMES.items(): + obj = Bonk(message='enum Numberz value %d is string %s' % (num, name), type=num) + objcopy = Bonk() + deserialize(objcopy, serialize(obj)) + self.assertEquals(obj, objcopy) + + +def suite(): + suite = unittest.TestSuite() + loader = unittest.TestLoader() + + suite.addTest(loader.loadTestsFromTestCase(NormalBinaryTest)) + suite.addTest(loader.loadTestsFromTestCase(AcceleratedBinaryTest)) + suite.addTest(loader.loadTestsFromTestCase(AcceleratedCompactTest)) + suite.addTest(loader.loadTestsFromTestCase(CompactProtocolTest)) + suite.addTest(loader.loadTestsFromTestCase(JSONProtocolTest)) + suite.addTest(loader.loadTestsFromTestCase(AcceleratedFramedTest)) + suite.addTest(loader.loadTestsFromTestCase(SerializersTest)) + return suite + + +if __name__ == "__main__": + unittest.main(defaultTest="suite", testRunner=unittest.TextTestRunner(verbosity=2)) diff --git a/src/jaegertracing/thrift/test/py/TSimpleJSONProtocolTest.py b/src/jaegertracing/thrift/test/py/TSimpleJSONProtocolTest.py new file mode 100644 index 000000000..72987602b --- /dev/null +++ b/src/jaegertracing/thrift/test/py/TSimpleJSONProtocolTest.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python + +# +# 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. +# + +from ThriftTest.ttypes import Bonk, VersioningTestV1, VersioningTestV2 +from thrift.protocol import TJSONProtocol +from thrift.transport import TTransport + +import json +import unittest + + +class SimpleJSONProtocolTest(unittest.TestCase): + protocol_factory = TJSONProtocol.TSimpleJSONProtocolFactory() + + def _assertDictEqual(self, a, b, msg=None): + if hasattr(self, 'assertDictEqual'): + # assertDictEqual only in Python 2.7. Depends on your machine. + self.assertDictEqual(a, b, msg) + return + + # Substitute implementation not as good as unittest library's + self.assertEquals(len(a), len(b), msg) + for k, v in a.iteritems(): + self.assertTrue(k in b, msg) + self.assertEquals(b.get(k), v, msg) + + def _serialize(self, obj): + trans = TTransport.TMemoryBuffer() + prot = self.protocol_factory.getProtocol(trans) + obj.write(prot) + return trans.getvalue() + + def _deserialize(self, objtype, data): + prot = self.protocol_factory.getProtocol(TTransport.TMemoryBuffer(data)) + ret = objtype() + ret.read(prot) + return ret + + def testWriteOnly(self): + self.assertRaises(NotImplementedError, + self._deserialize, VersioningTestV1, b'{}') + + def testSimpleMessage(self): + v1obj = VersioningTestV1( + begin_in_both=12345, + old_string='aaa', + end_in_both=54321) + expected = dict(begin_in_both=v1obj.begin_in_both, + old_string=v1obj.old_string, + end_in_both=v1obj.end_in_both) + actual = json.loads(self._serialize(v1obj).decode('ascii')) + + self._assertDictEqual(expected, actual) + + def testComplicated(self): + v2obj = VersioningTestV2( + begin_in_both=12345, + newint=1, + newbyte=2, + newshort=3, + newlong=4, + newdouble=5.0, + newstruct=Bonk(message="Hello!", type=123), + newlist=[7, 8, 9], + newset=set([42, 1, 8]), + newmap={1: 2, 2: 3}, + newstring="Hola!", + end_in_both=54321) + expected = dict(begin_in_both=v2obj.begin_in_both, + newint=v2obj.newint, + newbyte=v2obj.newbyte, + newshort=v2obj.newshort, + newlong=v2obj.newlong, + newdouble=v2obj.newdouble, + newstruct=dict(message=v2obj.newstruct.message, + type=v2obj.newstruct.type), + newlist=v2obj.newlist, + newset=list(v2obj.newset), + newmap=v2obj.newmap, + newstring=v2obj.newstring, + end_in_both=v2obj.end_in_both) + + # Need to load/dump because map keys get escaped. + expected = json.loads(json.dumps(expected)) + actual = json.loads(self._serialize(v2obj).decode('ascii')) + self._assertDictEqual(expected, actual) + + +if __name__ == '__main__': + unittest.main() diff --git a/src/jaegertracing/thrift/test/py/TestClient.py b/src/jaegertracing/thrift/test/py/TestClient.py new file mode 100755 index 000000000..e7a9a1a0e --- /dev/null +++ b/src/jaegertracing/thrift/test/py/TestClient.py @@ -0,0 +1,500 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# 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. +# + +import os +import sys +import time +import unittest + +from optparse import OptionParser +from util import local_libpath +sys.path.insert(0, local_libpath()) +from thrift.protocol import TProtocol, TProtocolDecorator + +SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__)) + + +class AbstractTest(unittest.TestCase): + def setUp(self): + if options.trans == 'http': + uri = '{0}://{1}:{2}{3}'.format(('https' if options.ssl else 'http'), + options.host, + options.port, + (options.http_path if options.http_path else '/')) + if options.ssl: + __cafile = os.path.join(os.path.dirname(SCRIPT_DIR), "keys", "CA.pem") + __certfile = os.path.join(os.path.dirname(SCRIPT_DIR), "keys", "client.crt") + __keyfile = os.path.join(os.path.dirname(SCRIPT_DIR), "keys", "client.key") + self.transport = THttpClient.THttpClient(uri, cafile=__cafile, cert_file=__certfile, key_file=__keyfile) + else: + self.transport = THttpClient.THttpClient(uri) + else: + if options.ssl: + from thrift.transport import TSSLSocket + socket = TSSLSocket.TSSLSocket(options.host, options.port, validate=False) + else: + socket = TSocket.TSocket(options.host, options.port) + # frame or buffer depending upon args + self.transport = TTransport.TBufferedTransport(socket) + if options.trans == 'framed': + self.transport = TTransport.TFramedTransport(socket) + elif options.trans == 'buffered': + self.transport = TTransport.TBufferedTransport(socket) + elif options.trans == '': + raise AssertionError('Unknown --transport option: %s' % options.trans) + if options.zlib: + self.transport = TZlibTransport.TZlibTransport(self.transport, 9) + self.transport.open() + protocol = self.get_protocol(self.transport) + self.client = ThriftTest.Client(protocol) + # for multiplexed services: + protocol2 = self.get_protocol2(self.transport) + self.client2 = SecondService.Client(protocol2) if protocol2 is not None else None + + def tearDown(self): + self.transport.close() + + def testVoid(self): + print('testVoid') + self.client.testVoid() + + def testString(self): + print('testString') + self.assertEqual(self.client.testString('Python' * 20), 'Python' * 20) + self.assertEqual(self.client.testString(''), '') + s1 = u'\b\t\n/\\\\\r{}:パイソン"' + s2 = u"""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 sys.version_info[0] == 2 and os.environ.get('THRIFT_TEST_PY_NO_UTF8STRINGS'): + s1 = s1.encode('utf8') + s2 = s2.encode('utf8') + self.assertEqual(self.client.testString(s1), s1) + self.assertEqual(self.client.testString(s2), s2) + + def testMultiplexed(self): + if self.client2 is not None: + print('testMultiplexed') + self.assertEqual(self.client2.secondtestString('foobar'), 'testString("foobar")') + + def testBool(self): + print('testBool') + self.assertEqual(self.client.testBool(True), True) + self.assertEqual(self.client.testBool(False), False) + + def testByte(self): + print('testByte') + self.assertEqual(self.client.testByte(63), 63) + self.assertEqual(self.client.testByte(-127), -127) + + def testI32(self): + print('testI32') + self.assertEqual(self.client.testI32(-1), -1) + self.assertEqual(self.client.testI32(0), 0) + + def testI64(self): + print('testI64') + self.assertEqual(self.client.testI64(1), 1) + self.assertEqual(self.client.testI64(-34359738368), -34359738368) + + def testDouble(self): + print('testDouble') + self.assertEqual(self.client.testDouble(-5.235098235), -5.235098235) + self.assertEqual(self.client.testDouble(0), 0) + self.assertEqual(self.client.testDouble(-1), -1) + self.assertEqual(self.client.testDouble(-0.000341012439638598279), -0.000341012439638598279) + + def testBinary(self): + print('testBinary') + val = bytearray([i for i in range(0, 256)]) + self.assertEqual(bytearray(self.client.testBinary(bytes(val))), val) + + def testStruct(self): + print('testStruct') + x = Xtruct() + x.string_thing = "Zero" + x.byte_thing = 1 + x.i32_thing = -3 + x.i64_thing = -5 + y = self.client.testStruct(x) + self.assertEqual(y, x) + + def testNest(self): + print('testNest') + inner = Xtruct(string_thing="Zero", byte_thing=1, i32_thing=-3, i64_thing=-5) + x = Xtruct2(struct_thing=inner, byte_thing=0, i32_thing=0) + y = self.client.testNest(x) + self.assertEqual(y, x) + + def testMap(self): + print('testMap') + x = {0: 1, 1: 2, 2: 3, 3: 4, -1: -2} + y = self.client.testMap(x) + self.assertEqual(y, x) + + def testSet(self): + print('testSet') + x = set([8, 1, 42]) + y = self.client.testSet(x) + self.assertEqual(y, x) + + def testList(self): + print('testList') + x = [1, 4, 9, -42] + y = self.client.testList(x) + self.assertEqual(y, x) + + def testEnum(self): + print('testEnum') + x = Numberz.FIVE + y = self.client.testEnum(x) + self.assertEqual(y, x) + + def testTypedef(self): + print('testTypedef') + x = 0xffffffffffffff # 7 bytes of 0xff + y = self.client.testTypedef(x) + self.assertEqual(y, x) + + def testMapMap(self): + print('testMapMap') + x = { + -4: {-4: -4, -3: -3, -2: -2, -1: -1}, + 4: {4: 4, 3: 3, 2: 2, 1: 1}, + } + y = self.client.testMapMap(42) + self.assertEqual(y, x) + + def testMulti(self): + print('testMulti') + xpected = Xtruct(string_thing='Hello2', byte_thing=74, i32_thing=0xff00ff, i64_thing=0xffffffffd0d0) + y = self.client.testMulti(xpected.byte_thing, + xpected.i32_thing, + xpected.i64_thing, + {0: 'abc'}, + Numberz.FIVE, + 0xf0f0f0) + self.assertEqual(y, xpected) + + def testException(self): + print('testException') + self.client.testException('Safe') + try: + self.client.testException('Xception') + self.fail("should have gotten exception") + except Xception as x: + self.assertEqual(x.errorCode, 1001) + self.assertEqual(x.message, 'Xception') + # TODO ensure same behavior for repr within generated python variants + # ensure exception's repr method works + # x_repr = repr(x) + # self.assertEqual(x_repr, 'Xception(errorCode=1001, message=\'Xception\')') + + try: + self.client.testException('TException') + self.fail("should have gotten exception") + except TException as x: + pass + + # Should not throw + self.client.testException('success') + + def testMultiException(self): + print('testMultiException') + try: + self.client.testMultiException('Xception', 'ignore') + except Xception as ex: + self.assertEqual(ex.errorCode, 1001) + self.assertEqual(ex.message, 'This is an Xception') + + try: + self.client.testMultiException('Xception2', 'ignore') + except Xception2 as ex: + self.assertEqual(ex.errorCode, 2002) + self.assertEqual(ex.struct_thing.string_thing, 'This is an Xception2') + + y = self.client.testMultiException('success', 'foobar') + self.assertEqual(y.string_thing, 'foobar') + + def testOneway(self): + print('testOneway') + start = time.time() + self.client.testOneway(1) # type is int, not float + end = time.time() + self.assertTrue(end - start < 3, + "oneway sleep took %f sec" % (end - start)) + + def testOnewayThenNormal(self): + print('testOnewayThenNormal') + self.client.testOneway(1) # type is int, not float + self.assertEqual(self.client.testString('Python'), 'Python') + + +# LAST_SEQID is a global because we have one transport and multiple protocols +# running on it (when multiplexed) +LAST_SEQID = None + + +class TPedanticSequenceIdProtocolWrapper(TProtocolDecorator.TProtocolDecorator): + """ + Wraps any protocol with sequence ID checking: looks for outbound + uniqueness as well as request/response alignment. + """ + def __init__(self, protocol): + # TProtocolDecorator.__new__ does all the heavy lifting + pass + + def writeMessageBegin(self, name, type, seqid): + global LAST_SEQID + if LAST_SEQID and LAST_SEQID == seqid: + raise TProtocol.TProtocolException( + TProtocol.TProtocolException.INVALID_DATA, + "Python client reused sequence ID {0}".format(seqid)) + LAST_SEQID = seqid + super(TPedanticSequenceIdProtocolWrapper, self).writeMessageBegin( + name, type, seqid) + + def readMessageBegin(self): + global LAST_SEQID + (name, type, seqid) =\ + super(TPedanticSequenceIdProtocolWrapper, self).readMessageBegin() + if LAST_SEQID != seqid: + raise TProtocol.TProtocolException( + TProtocol.TProtocolException.INVALID_DATA, + "We sent seqid {0} and server returned seqid {1}".format( + self.last, seqid)) + return (name, type, seqid) + + +def make_pedantic(proto): + """ Wrap a protocol in the pedantic sequence ID wrapper. """ + return TPedanticSequenceIdProtocolWrapper(proto) + + +class MultiplexedOptionalTest(AbstractTest): + def get_protocol2(self, transport): + return None + + +class BinaryTest(MultiplexedOptionalTest): + def get_protocol(self, transport): + return make_pedantic(TBinaryProtocol.TBinaryProtocolFactory().getProtocol(transport)) + + +class MultiplexedBinaryTest(MultiplexedOptionalTest): + def get_protocol(self, transport): + wrapped_proto = make_pedantic(TBinaryProtocol.TBinaryProtocolFactory().getProtocol(transport)) + return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "ThriftTest") + + def get_protocol2(self, transport): + wrapped_proto = make_pedantic(TBinaryProtocol.TBinaryProtocolFactory().getProtocol(transport)) + return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "SecondService") + + +class AcceleratedBinaryTest(MultiplexedOptionalTest): + def get_protocol(self, transport): + return make_pedantic(TBinaryProtocol.TBinaryProtocolAcceleratedFactory(fallback=False).getProtocol(transport)) + + +class MultiplexedAcceleratedBinaryTest(MultiplexedOptionalTest): + def get_protocol(self, transport): + wrapped_proto = make_pedantic(TBinaryProtocol.TBinaryProtocolAcceleratedFactory(fallback=False).getProtocol(transport)) + return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "ThriftTest") + + def get_protocol2(self, transport): + wrapped_proto = make_pedantic(TBinaryProtocol.TBinaryProtocolAcceleratedFactory(fallback=False).getProtocol(transport)) + return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "SecondService") + + +class CompactTest(MultiplexedOptionalTest): + def get_protocol(self, transport): + return make_pedantic(TCompactProtocol.TCompactProtocolFactory().getProtocol(transport)) + + +class MultiplexedCompactTest(MultiplexedOptionalTest): + def get_protocol(self, transport): + wrapped_proto = make_pedantic(TCompactProtocol.TCompactProtocolFactory().getProtocol(transport)) + return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "ThriftTest") + + def get_protocol2(self, transport): + wrapped_proto = make_pedantic(TCompactProtocol.TCompactProtocolFactory().getProtocol(transport)) + return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "SecondService") + + +class AcceleratedCompactTest(MultiplexedOptionalTest): + def get_protocol(self, transport): + return make_pedantic(TCompactProtocol.TCompactProtocolAcceleratedFactory(fallback=False).getProtocol(transport)) + + +class MultiplexedAcceleratedCompactTest(MultiplexedOptionalTest): + def get_protocol(self, transport): + wrapped_proto = make_pedantic(TCompactProtocol.TCompactProtocolAcceleratedFactory(fallback=False).getProtocol(transport)) + return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "ThriftTest") + + def get_protocol2(self, transport): + wrapped_proto = make_pedantic(TCompactProtocol.TCompactProtocolAcceleratedFactory(fallback=False).getProtocol(transport)) + return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "SecondService") + + +class JSONTest(MultiplexedOptionalTest): + def get_protocol(self, transport): + return make_pedantic(TJSONProtocol.TJSONProtocolFactory().getProtocol(transport)) + + +class MultiplexedJSONTest(MultiplexedOptionalTest): + def get_protocol(self, transport): + wrapped_proto = make_pedantic(TJSONProtocol.TJSONProtocolFactory().getProtocol(transport)) + return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "ThriftTest") + + def get_protocol2(self, transport): + wrapped_proto = make_pedantic(TJSONProtocol.TJSONProtocolFactory().getProtocol(transport)) + return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "SecondService") + + +class HeaderTest(MultiplexedOptionalTest): + def get_protocol(self, transport): + factory = THeaderProtocol.THeaderProtocolFactory() + return make_pedantic(factory.getProtocol(transport)) + + +class MultiplexedHeaderTest(MultiplexedOptionalTest): + def get_protocol(self, transport): + wrapped_proto = make_pedantic(THeaderProtocol.THeaderProtocolFactory().getProtocol(transport)) + return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "ThriftTest") + + def get_protocol2(self, transport): + wrapped_proto = make_pedantic(THeaderProtocol.THeaderProtocolFactory().getProtocol(transport)) + return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "SecondService") + + +def suite(): + suite = unittest.TestSuite() + loader = unittest.TestLoader() + if options.proto == 'binary': # look for --proto on cmdline + suite.addTest(loader.loadTestsFromTestCase(BinaryTest)) + elif options.proto == 'accel': + suite.addTest(loader.loadTestsFromTestCase(AcceleratedBinaryTest)) + elif options.proto == 'accelc': + suite.addTest(loader.loadTestsFromTestCase(AcceleratedCompactTest)) + elif options.proto == 'compact': + suite.addTest(loader.loadTestsFromTestCase(CompactTest)) + elif options.proto == 'header': + suite.addTest(loader.loadTestsFromTestCase(HeaderTest)) + elif options.proto == 'json': + suite.addTest(loader.loadTestsFromTestCase(JSONTest)) + elif options.proto == 'multi': + suite.addTest(loader.loadTestsFromTestCase(MultiplexedBinaryTest)) + elif options.proto == 'multia': + suite.addTest(loader.loadTestsFromTestCase(MultiplexedAcceleratedBinaryTest)) + elif options.proto == 'multiac': + suite.addTest(loader.loadTestsFromTestCase(MultiplexedAcceleratedCompactTest)) + elif options.proto == 'multic': + suite.addTest(loader.loadTestsFromTestCase(MultiplexedCompactTest)) + elif options.proto == 'multih': + suite.addTest(loader.loadTestsFromTestCase(MultiplexedHeaderTest)) + elif options.proto == 'multij': + suite.addTest(loader.loadTestsFromTestCase(MultiplexedJSONTest)) + else: + raise AssertionError('Unknown protocol given with --protocol: %s' % options.proto) + return suite + + +class OwnArgsTestProgram(unittest.TestProgram): + def parseArgs(self, argv): + if args: + self.testNames = args + else: + self.testNames = ([self.defaultTest]) + self.createTests() + + +if __name__ == "__main__": + parser = OptionParser() + parser.add_option('--libpydir', type='string', dest='libpydir', + help='include this directory in sys.path for locating library code') + parser.add_option('--genpydir', type='string', dest='genpydir', + help='include this directory in sys.path for locating generated code') + parser.add_option("--port", type="int", dest="port", + help="connect to server at port") + parser.add_option("--host", type="string", dest="host", + help="connect to server") + parser.add_option("--zlib", action="store_true", dest="zlib", + help="use zlib wrapper for compressed transport") + parser.add_option("--ssl", action="store_true", dest="ssl", + help="use SSL for encrypted transport") + parser.add_option("--http", dest="http_path", + help="Use the HTTP transport with the specified path") + parser.add_option('-v', '--verbose', action="store_const", + dest="verbose", const=2, + help="verbose output") + parser.add_option('-q', '--quiet', action="store_const", + dest="verbose", const=0, + help="minimal output") + parser.add_option('--protocol', dest="proto", type="string", + help="protocol to use, one of: accel, accelc, binary, compact, header, json, multi, multia, multiac, multic, multih, multij") + parser.add_option('--transport', dest="trans", type="string", + help="transport to use, one of: buffered, framed, http") + parser.set_defaults(framed=False, http_path=None, verbose=1, host='localhost', port=9090, proto='binary') + options, args = parser.parse_args() + + if options.genpydir: + sys.path.insert(0, os.path.join(SCRIPT_DIR, options.genpydir)) + + if options.http_path: + options.trans = 'http' + + from ThriftTest import SecondService + from ThriftTest import ThriftTest + from ThriftTest.ttypes import Xtruct, Xtruct2, Numberz, Xception, Xception2 + from thrift.Thrift import TException + from thrift.transport import TTransport + from thrift.transport import TSocket + from thrift.transport import THttpClient + from thrift.transport import TZlibTransport + from thrift.protocol import TBinaryProtocol + from thrift.protocol import TCompactProtocol + from thrift.protocol import THeaderProtocol + from thrift.protocol import TJSONProtocol + from thrift.protocol import TMultiplexedProtocol + + OwnArgsTestProgram(defaultTest="suite", testRunner=unittest.TextTestRunner(verbosity=1)) diff --git a/src/jaegertracing/thrift/test/py/TestEof.py b/src/jaegertracing/thrift/test/py/TestEof.py new file mode 100755 index 000000000..0b4a82960 --- /dev/null +++ b/src/jaegertracing/thrift/test/py/TestEof.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python + +# +# 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. +# + +from ThriftTest.ttypes import Xtruct +from thrift.transport import TTransport +from thrift.protocol import TBinaryProtocol +from thrift.protocol import TCompactProtocol +import unittest + + +class TestEof(unittest.TestCase): + + def make_data(self, pfactory=None): + trans = TTransport.TMemoryBuffer() + if pfactory: + prot = pfactory.getProtocol(trans) + else: + prot = TBinaryProtocol.TBinaryProtocol(trans) + + x = Xtruct() + x.string_thing = "Zero" + x.byte_thing = 0 + + x.write(prot) + + x = Xtruct() + x.string_thing = "One" + x.byte_thing = 1 + + x.write(prot) + + return trans.getvalue() + + def testTransportReadAll(self): + """Test that readAll on any type of transport throws an EOFError""" + trans = TTransport.TMemoryBuffer(self.make_data()) + trans.readAll(1) + + try: + trans.readAll(10000) + except EOFError: + return + + self.fail("Should have gotten EOFError") + + def eofTestHelper(self, pfactory): + trans = TTransport.TMemoryBuffer(self.make_data(pfactory)) + prot = pfactory.getProtocol(trans) + + x = Xtruct() + x.read(prot) + self.assertEqual(x.string_thing, "Zero") + self.assertEqual(x.byte_thing, 0) + + x = Xtruct() + x.read(prot) + self.assertEqual(x.string_thing, "One") + self.assertEqual(x.byte_thing, 1) + + try: + x = Xtruct() + x.read(prot) + except EOFError: + return + + self.fail("Should have gotten EOFError") + + def eofTestHelperStress(self, pfactory): + """Test the ability of TBinaryProtocol to deal with the removal of every byte in the file""" + # TODO: we should make sure this covers more of the code paths + + data = self.make_data(pfactory) + for i in range(0, len(data) + 1): + trans = TTransport.TMemoryBuffer(data[0:i]) + prot = pfactory.getProtocol(trans) + try: + x = Xtruct() + x.read(prot) + x.read(prot) + x.read(prot) + except EOFError: + continue + self.fail("Should have gotten an EOFError") + + def testBinaryProtocolEof(self): + """Test that TBinaryProtocol throws an EOFError when it reaches the end of the stream""" + self.eofTestHelper(TBinaryProtocol.TBinaryProtocolFactory()) + self.eofTestHelperStress(TBinaryProtocol.TBinaryProtocolFactory()) + + def testBinaryProtocolAcceleratedBinaryEof(self): + """Test that TBinaryProtocolAccelerated throws an EOFError when it reaches the end of the stream""" + self.eofTestHelper(TBinaryProtocol.TBinaryProtocolAcceleratedFactory(fallback=False)) + self.eofTestHelperStress(TBinaryProtocol.TBinaryProtocolAcceleratedFactory(fallback=False)) + + def testCompactProtocolEof(self): + """Test that TCompactProtocol throws an EOFError when it reaches the end of the stream""" + self.eofTestHelper(TCompactProtocol.TCompactProtocolFactory()) + self.eofTestHelperStress(TCompactProtocol.TCompactProtocolFactory()) + + def testCompactProtocolAcceleratedCompactEof(self): + """Test that TCompactProtocolAccelerated throws an EOFError when it reaches the end of the stream""" + self.eofTestHelper(TCompactProtocol.TCompactProtocolAcceleratedFactory(fallback=False)) + self.eofTestHelperStress(TCompactProtocol.TCompactProtocolAcceleratedFactory(fallback=False)) + + +def suite(): + suite = unittest.TestSuite() + loader = unittest.TestLoader() + suite.addTest(loader.loadTestsFromTestCase(TestEof)) + return suite + + +if __name__ == "__main__": + unittest.main(defaultTest="suite", testRunner=unittest.TextTestRunner(verbosity=2)) diff --git a/src/jaegertracing/thrift/test/py/TestFrozen.py b/src/jaegertracing/thrift/test/py/TestFrozen.py new file mode 100755 index 000000000..6d2595cf2 --- /dev/null +++ b/src/jaegertracing/thrift/test/py/TestFrozen.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python + +# +# 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. +# + +from DebugProtoTest.ttypes import CompactProtoTestStruct, Empty, Wrapper +from thrift.Thrift import TFrozenDict +from thrift.transport import TTransport +from thrift.protocol import TBinaryProtocol, TCompactProtocol +import collections +import unittest + + +class TestFrozenBase(unittest.TestCase): + def _roundtrip(self, src, dst): + otrans = TTransport.TMemoryBuffer() + optoro = self.protocol(otrans) + src.write(optoro) + itrans = TTransport.TMemoryBuffer(otrans.getvalue()) + iproto = self.protocol(itrans) + return dst.read(iproto) or dst + + def test_dict_is_hashable_only_after_frozen(self): + d0 = {} + self.assertFalse(isinstance(d0, collections.Hashable)) + d1 = TFrozenDict(d0) + self.assertTrue(isinstance(d1, collections.Hashable)) + + def test_struct_with_collection_fields(self): + pass + + def test_set(self): + """Test that annotated set field can be serialized and deserialized""" + x = CompactProtoTestStruct(set_byte_map={ + frozenset([42, 100, -100]): 99, + frozenset([0]): 100, + frozenset([]): 0, + }) + x2 = self._roundtrip(x, CompactProtoTestStruct()) + self.assertEqual(x2.set_byte_map[frozenset([42, 100, -100])], 99) + self.assertEqual(x2.set_byte_map[frozenset([0])], 100) + self.assertEqual(x2.set_byte_map[frozenset([])], 0) + + def test_map(self): + """Test that annotated map field can be serialized and deserialized""" + x = CompactProtoTestStruct(map_byte_map={ + TFrozenDict({42: 42, 100: -100}): 99, + TFrozenDict({0: 0}): 100, + TFrozenDict({}): 0, + }) + x2 = self._roundtrip(x, CompactProtoTestStruct()) + self.assertEqual(x2.map_byte_map[TFrozenDict({42: 42, 100: -100})], 99) + self.assertEqual(x2.map_byte_map[TFrozenDict({0: 0})], 100) + self.assertEqual(x2.map_byte_map[TFrozenDict({})], 0) + + def test_list(self): + """Test that annotated list field can be serialized and deserialized""" + x = CompactProtoTestStruct(list_byte_map={ + (42, 100, -100): 99, + (0,): 100, + (): 0, + }) + x2 = self._roundtrip(x, CompactProtoTestStruct()) + self.assertEqual(x2.list_byte_map[(42, 100, -100)], 99) + self.assertEqual(x2.list_byte_map[(0,)], 100) + self.assertEqual(x2.list_byte_map[()], 0) + + def test_empty_struct(self): + """Test that annotated empty struct can be serialized and deserialized""" + x = CompactProtoTestStruct(empty_struct_field=Empty()) + x2 = self._roundtrip(x, CompactProtoTestStruct()) + self.assertEqual(x2.empty_struct_field, Empty()) + + def test_struct(self): + """Test that annotated struct can be serialized and deserialized""" + x = Wrapper(foo=Empty()) + self.assertEqual(x.foo, Empty()) + x2 = self._roundtrip(x, Wrapper) + self.assertEqual(x2.foo, Empty()) + + +class TestFrozen(TestFrozenBase): + def protocol(self, trans): + return TBinaryProtocol.TBinaryProtocolFactory().getProtocol(trans) + + +class TestFrozenAcceleratedBinary(TestFrozenBase): + def protocol(self, trans): + return TBinaryProtocol.TBinaryProtocolAcceleratedFactory(fallback=False).getProtocol(trans) + + +class TestFrozenAcceleratedCompact(TestFrozenBase): + def protocol(self, trans): + return TCompactProtocol.TCompactProtocolAcceleratedFactory(fallback=False).getProtocol(trans) + + +def suite(): + suite = unittest.TestSuite() + loader = unittest.TestLoader() + suite.addTest(loader.loadTestsFromTestCase(TestFrozen)) + suite.addTest(loader.loadTestsFromTestCase(TestFrozenAcceleratedBinary)) + suite.addTest(loader.loadTestsFromTestCase(TestFrozenAcceleratedCompact)) + return suite + + +if __name__ == "__main__": + unittest.main(defaultTest="suite", testRunner=unittest.TextTestRunner(verbosity=2)) diff --git a/src/jaegertracing/thrift/test/py/TestRenderedDoubleConstants.py b/src/jaegertracing/thrift/test/py/TestRenderedDoubleConstants.py new file mode 100644 index 000000000..20903d81b --- /dev/null +++ b/src/jaegertracing/thrift/test/py/TestRenderedDoubleConstants.py @@ -0,0 +1,177 @@ +# +# 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. +# + +import unittest + +from DoubleConstantsTest import constants + +# +# In order to run the test under Windows. We need to create symbolic link +# name 'thrift' to '../src' folder by using: +# +# mklink /D thrift ..\src +# + + +class TestRenderedDoubleConstants(unittest.TestCase): + ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST = \ + "failed to verify a double constant generated by Thrift (expected = %f, got = %f)" + ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_LIST_TEST =\ + "failed to verify a list item by Thrift (expected = %f, got = %f)" + ASSERTION_MESSAGE_FOR_TYPE_CHECKS = "the rendered variable with name %s is not of double type" + + # to make sure the variables inside Thrift files are generated correctly + def test_rendered_double_constants(self): + EXPECTED_DOUBLE_ASSIGNED_TO_INT_CONSTANT = 1.0 + EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT = -100.0 + EXPECTED_DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT = 9223372036854775807.0 + EXPECTED_DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT = -9223372036854775807.0 + EXPECTED_DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS = 3.14159265359 + EXPECTED_DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE = 1000000.1 + EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE = -1000000.1 + EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_DOUBLE = 1.7e+308 + EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE = 9223372036854775816.43 + EXPECTED_DOUBLE_ASSIGNED_TO_SMALL_DOUBLE = -1.7e+308 + EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE = -9223372036854775816.43 + self.assertAlmostEqual( + constants.DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_INT_CONSTANT, places=7, + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % ( + EXPECTED_DOUBLE_ASSIGNED_TO_INT_CONSTANT, constants.DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST)) + self.assertAlmostEqual( + constants.DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT, + places=7, + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % ( + EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT, + constants.DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST)) + self.assertAlmostEqual( + constants.DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT, + places=7, + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % ( + EXPECTED_DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT, + constants.DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST)) + self.assertAlmostEqual( + constants.DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT, + places=7, + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % ( + EXPECTED_DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT, + constants.DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST)) + self.assertAlmostEqual( + constants.DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST, + EXPECTED_DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS, places=7, + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % ( + EXPECTED_DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS, + constants.DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST)) + self.assertAlmostEqual( + constants.DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE, + places=7, + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % ( + EXPECTED_DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE, + constants.DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST)) + self.assertAlmostEqual( + constants.DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST, + EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE, places=7, + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % ( + EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE, + constants.DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST)) + self.assertAlmostEqual( + constants.DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_DOUBLE, places=7, + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % ( + EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_DOUBLE, + constants.DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST)) + self.assertAlmostEqual( + constants.DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST, + EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE, places=7, + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % ( + EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE, + constants.DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST)) + self.assertAlmostEqual( + constants.DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_SMALL_DOUBLE, places=7, + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % ( + EXPECTED_DOUBLE_ASSIGNED_TO_SMALL_DOUBLE, + constants.DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST)) + self.assertAlmostEqual( + constants.DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST, + EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE, places=7, + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % ( + EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE, + constants.DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST)) + self.assertTrue( + isinstance(constants.DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST, float), + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS % + "DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST") + self.assertTrue( + isinstance(constants.DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST, float), + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS % + "DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST") + self.assertTrue( + isinstance(constants.DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST, float), + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS % + "DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST") + self.assertTrue( + isinstance(constants.DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST, float), + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS % + "DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST") + self.assertTrue( + isinstance(constants.DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST, float), + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS % + "DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST") + self.assertTrue( + isinstance(constants.DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST, float), + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS % + "DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST") + self.assertTrue( + isinstance(constants.DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST, float), + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS % + "DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST") + self.assertTrue( + isinstance(constants.DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST, float), + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS % + "DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST") + self.assertTrue( + isinstance(constants.DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST, float), + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS % + "DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST") + self.assertTrue( + isinstance(constants.DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST, float), + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS % + "DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST") + self.assertTrue( + isinstance(constants.DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST, float), + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS % + "DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST") + + # to make sure the variables inside Thrift files are generated correctly + def test_rendered_double_list(self): + EXPECTED_DOUBLE_LIST = [1.0, -100.0, 100.0, 9223372036854775807.0, -9223372036854775807.0, 3.14159265359, + 1000000.1, -1000000.1, 1.7e+308, -1.7e+308, 9223372036854775816.43, + -9223372036854775816.43] + self.assertEqual(len(constants.DOUBLE_LIST_TEST), len(EXPECTED_DOUBLE_LIST)) + for i, expectedValue in enumerate(EXPECTED_DOUBLE_LIST): + self.assertAlmostEqual(constants.DOUBLE_LIST_TEST[i], expectedValue, places=7) + + +def suite(): + suite = unittest.TestSuite() + loader = unittest.TestLoader() + suite.addTest(loader.loadTestsFromTestCase(TestRenderedDoubleConstants)) + return suite + + +if __name__ == "__main__": + unittest.main(defaultTest="suite", testRunner=unittest.TextTestRunner(verbosity=2)) diff --git a/src/jaegertracing/thrift/test/py/TestServer.py b/src/jaegertracing/thrift/test/py/TestServer.py new file mode 100755 index 000000000..d0a13e5f7 --- /dev/null +++ b/src/jaegertracing/thrift/test/py/TestServer.py @@ -0,0 +1,412 @@ +#!/usr/bin/env python + +# +# 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. +# +from __future__ import division +import logging +import os +import signal +import sys +import time +from optparse import OptionParser + +from util import local_libpath +sys.path.insert(0, local_libpath()) +from thrift.protocol import TProtocol, TProtocolDecorator + +SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__)) + + +class TestHandler(object): + def testVoid(self): + if options.verbose > 1: + logging.info('testVoid()') + + def testString(self, str): + if options.verbose > 1: + logging.info('testString(%s)' % str) + return str + + def testBool(self, boolean): + if options.verbose > 1: + logging.info('testBool(%s)' % str(boolean).lower()) + return boolean + + def testByte(self, byte): + if options.verbose > 1: + logging.info('testByte(%d)' % byte) + return byte + + def testI16(self, i16): + if options.verbose > 1: + logging.info('testI16(%d)' % i16) + return i16 + + def testI32(self, i32): + if options.verbose > 1: + logging.info('testI32(%d)' % i32) + return i32 + + def testI64(self, i64): + if options.verbose > 1: + logging.info('testI64(%d)' % i64) + return i64 + + def testDouble(self, dub): + if options.verbose > 1: + logging.info('testDouble(%f)' % dub) + return dub + + def testBinary(self, thing): + if options.verbose > 1: + logging.info('testBinary()') # TODO: hex output + return thing + + def testStruct(self, thing): + if options.verbose > 1: + logging.info('testStruct({%s, %s, %s, %s})' % (thing.string_thing, thing.byte_thing, thing.i32_thing, thing.i64_thing)) + return thing + + def testException(self, arg): + # if options.verbose > 1: + logging.info('testException(%s)' % arg) + if arg == 'Xception': + raise Xception(errorCode=1001, message=arg) + elif arg == 'TException': + raise TException(message='This is a TException') + + def testMultiException(self, arg0, arg1): + if options.verbose > 1: + logging.info('testMultiException(%s, %s)' % (arg0, arg1)) + if arg0 == 'Xception': + raise Xception(errorCode=1001, message='This is an Xception') + elif arg0 == 'Xception2': + raise Xception2( + errorCode=2002, + struct_thing=Xtruct(string_thing='This is an Xception2')) + return Xtruct(string_thing=arg1) + + def testOneway(self, seconds): + if options.verbose > 1: + logging.info('testOneway(%d) => sleeping...' % seconds) + time.sleep(seconds / 3) # be quick + if options.verbose > 1: + logging.info('done sleeping') + + def testNest(self, thing): + if options.verbose > 1: + logging.info('testNest(%s)' % thing) + return thing + + def testMap(self, thing): + if options.verbose > 1: + logging.info('testMap(%s)' % thing) + return thing + + def testStringMap(self, thing): + if options.verbose > 1: + logging.info('testStringMap(%s)' % thing) + return thing + + def testSet(self, thing): + if options.verbose > 1: + logging.info('testSet(%s)' % thing) + return thing + + def testList(self, thing): + if options.verbose > 1: + logging.info('testList(%s)' % thing) + return thing + + def testEnum(self, thing): + if options.verbose > 1: + logging.info('testEnum(%s)' % thing) + return thing + + def testTypedef(self, thing): + if options.verbose > 1: + logging.info('testTypedef(%s)' % thing) + return thing + + def testMapMap(self, thing): + if options.verbose > 1: + logging.info('testMapMap(%s)' % thing) + return { + -4: { + -4: -4, + -3: -3, + -2: -2, + -1: -1, + }, + 4: { + 4: 4, + 3: 3, + 2: 2, + 1: 1, + }, + } + + def testInsanity(self, argument): + if options.verbose > 1: + logging.info('testInsanity(%s)' % argument) + return { + 1: { + 2: argument, + 3: argument, + }, + 2: {6: Insanity()}, + } + + def testMulti(self, arg0, arg1, arg2, arg3, arg4, arg5): + if options.verbose > 1: + logging.info('testMulti(%s)' % [arg0, arg1, arg2, arg3, arg4, arg5]) + return Xtruct(string_thing='Hello2', + byte_thing=arg0, i32_thing=arg1, i64_thing=arg2) + + +class SecondHandler(object): + def secondtestString(self, argument): + return "testString(\"" + argument + "\")" + + +# LAST_SEQID is a global because we have one transport and multiple protocols +# running on it (when multiplexed) +LAST_SEQID = None + + +class TPedanticSequenceIdProtocolWrapper(TProtocolDecorator.TProtocolDecorator): + """ + Wraps any protocol with sequence ID checking: looks for outbound + uniqueness as well as request/response alignment. + """ + def __init__(self, protocol): + # TProtocolDecorator.__new__ does all the heavy lifting + pass + + def readMessageBegin(self): + global LAST_SEQID + (name, type, seqid) =\ + super(TPedanticSequenceIdProtocolWrapper, self).readMessageBegin() + if LAST_SEQID is not None and LAST_SEQID == seqid: + raise TProtocol.TProtocolException( + TProtocol.TProtocolException.INVALID_DATA, + "We received the same seqid {0} twice in a row".format(seqid)) + LAST_SEQID = seqid + return (name, type, seqid) + + +def make_pedantic(proto): + """ Wrap a protocol in the pedantic sequence ID wrapper. """ + # NOTE: this is disabled for now as many clients send seqid + # of zero and that is okay, need a way to identify + # clients that MUST send seqid unique to function right + # or just force all implementations to send unique seqids (preferred) + return proto # TPedanticSequenceIdProtocolWrapper(proto) + + +class TPedanticSequenceIdProtocolFactory(TProtocol.TProtocolFactory): + def __init__(self, encapsulated): + super(TPedanticSequenceIdProtocolFactory, self).__init__() + self.encapsulated = encapsulated + + def getProtocol(self, trans): + return make_pedantic(self.encapsulated.getProtocol(trans)) + + +def main(options): + # common header allowed client types + allowed_client_types = [ + THeaderTransport.THeaderClientType.HEADERS, + THeaderTransport.THeaderClientType.FRAMED_BINARY, + THeaderTransport.THeaderClientType.UNFRAMED_BINARY, + THeaderTransport.THeaderClientType.FRAMED_COMPACT, + THeaderTransport.THeaderClientType.UNFRAMED_COMPACT, + ] + + # set up the protocol factory form the --protocol option + prot_factories = { + 'accel': TBinaryProtocol.TBinaryProtocolAcceleratedFactory(), + 'multia': TBinaryProtocol.TBinaryProtocolAcceleratedFactory(), + 'accelc': TCompactProtocol.TCompactProtocolAcceleratedFactory(), + 'multiac': TCompactProtocol.TCompactProtocolAcceleratedFactory(), + 'binary': TPedanticSequenceIdProtocolFactory(TBinaryProtocol.TBinaryProtocolFactory()), + 'multi': TPedanticSequenceIdProtocolFactory(TBinaryProtocol.TBinaryProtocolFactory()), + 'compact': TCompactProtocol.TCompactProtocolFactory(), + 'multic': TCompactProtocol.TCompactProtocolFactory(), + 'header': THeaderProtocol.THeaderProtocolFactory(allowed_client_types), + 'multih': THeaderProtocol.THeaderProtocolFactory(allowed_client_types), + 'json': TJSONProtocol.TJSONProtocolFactory(), + 'multij': TJSONProtocol.TJSONProtocolFactory(), + } + pfactory = prot_factories.get(options.proto, None) + if pfactory is None: + raise AssertionError('Unknown --protocol option: %s' % options.proto) + try: + pfactory.string_length_limit = options.string_limit + pfactory.container_length_limit = options.container_limit + except Exception: + # Ignore errors for those protocols that does not support length limit + pass + + # get the server type (TSimpleServer, TNonblockingServer, etc...) + if len(args) > 1: + raise AssertionError('Only one server type may be specified, not multiple types.') + server_type = args[0] + if options.trans == 'http': + server_type = 'THttpServer' + + # Set up the handler and processor objects + handler = TestHandler() + processor = ThriftTest.Processor(handler) + + if options.proto.startswith('multi'): + secondHandler = SecondHandler() + secondProcessor = SecondService.Processor(secondHandler) + + multiplexedProcessor = TMultiplexedProcessor() + multiplexedProcessor.registerDefault(processor) + multiplexedProcessor.registerProcessor('ThriftTest', processor) + multiplexedProcessor.registerProcessor('SecondService', secondProcessor) + processor = multiplexedProcessor + + global server + + # Handle THttpServer as a special case + if server_type == 'THttpServer': + if options.ssl: + __certfile = os.path.join(os.path.dirname(SCRIPT_DIR), "keys", "server.crt") + __keyfile = os.path.join(os.path.dirname(SCRIPT_DIR), "keys", "server.key") + server = THttpServer.THttpServer(processor, ('', options.port), pfactory, cert_file=__certfile, key_file=__keyfile) + else: + server = THttpServer.THttpServer(processor, ('', options.port), pfactory) + server.serve() + sys.exit(0) + + # set up server transport and transport factory + + abs_key_path = os.path.join(os.path.dirname(SCRIPT_DIR), 'keys', 'server.pem') + + host = None + if options.ssl: + from thrift.transport import TSSLSocket + transport = TSSLSocket.TSSLServerSocket(host, options.port, certfile=abs_key_path) + else: + transport = TSocket.TServerSocket(host, options.port) + tfactory = TTransport.TBufferedTransportFactory() + if options.trans == 'buffered': + tfactory = TTransport.TBufferedTransportFactory() + elif options.trans == 'framed': + tfactory = TTransport.TFramedTransportFactory() + elif options.trans == '': + raise AssertionError('Unknown --transport option: %s' % options.trans) + else: + tfactory = TTransport.TBufferedTransportFactory() + # if --zlib, then wrap server transport, and use a different transport factory + if options.zlib: + transport = TZlibTransport.TZlibTransport(transport) # wrap with zlib + tfactory = TZlibTransport.TZlibTransportFactory() + + # do server-specific setup here: + if server_type == "TNonblockingServer": + server = TNonblockingServer.TNonblockingServer(processor, transport, inputProtocolFactory=pfactory) + elif server_type == "TProcessPoolServer": + import signal + from thrift.server import TProcessPoolServer + server = TProcessPoolServer.TProcessPoolServer(processor, transport, tfactory, pfactory) + server.setNumWorkers(5) + + def set_alarm(): + def clean_shutdown(signum, frame): + for worker in server.workers: + if options.verbose > 0: + logging.info('Terminating worker: %s' % worker) + worker.terminate() + if options.verbose > 0: + logging.info('Requesting server to stop()') + try: + server.stop() + except Exception: + pass + signal.signal(signal.SIGALRM, clean_shutdown) + signal.alarm(4) + set_alarm() + else: + # look up server class dynamically to instantiate server + ServerClass = getattr(TServer, server_type) + server = ServerClass(processor, transport, tfactory, pfactory) + # enter server main loop + server.serve() + + +def exit_gracefully(signum, frame): + print("SIGINT received\n") + server.shutdown() # doesn't work properly, yet + sys.exit(0) + + +if __name__ == '__main__': + signal.signal(signal.SIGINT, exit_gracefully) + + parser = OptionParser() + parser.add_option('--libpydir', type='string', dest='libpydir', + help='include this directory to sys.path for locating library code') + parser.add_option('--genpydir', type='string', dest='genpydir', + default='gen-py', + help='include this directory to sys.path for locating generated code') + parser.add_option("--port", type="int", dest="port", + help="port number for server to listen on") + parser.add_option("--zlib", action="store_true", dest="zlib", + help="use zlib wrapper for compressed transport") + parser.add_option("--ssl", action="store_true", dest="ssl", + help="use SSL for encrypted transport") + parser.add_option('-v', '--verbose', action="store_const", + dest="verbose", const=2, + help="verbose output") + parser.add_option('-q', '--quiet', action="store_const", + dest="verbose", const=0, + help="minimal output") + parser.add_option('--protocol', dest="proto", type="string", + help="protocol to use, one of: accel, accelc, binary, compact, json, multi, multia, multiac, multic, multih, multij") + parser.add_option('--transport', dest="trans", type="string", + help="transport to use, one of: buffered, framed, http") + parser.add_option('--container-limit', dest='container_limit', type='int', default=None) + parser.add_option('--string-limit', dest='string_limit', type='int', default=None) + parser.set_defaults(port=9090, verbose=1, proto='binary', transport='buffered') + options, args = parser.parse_args() + + # Print TServer log to stdout so that the test-runner can redirect it to log files + logging.basicConfig(level=options.verbose) + + sys.path.insert(0, os.path.join(SCRIPT_DIR, options.genpydir)) + + from ThriftTest import ThriftTest, SecondService + from ThriftTest.ttypes import Xtruct, Xception, Xception2, Insanity + from thrift.Thrift import TException + from thrift.TMultiplexedProcessor import TMultiplexedProcessor + from thrift.transport import THeaderTransport + from thrift.transport import TTransport + from thrift.transport import TSocket + from thrift.transport import TZlibTransport + from thrift.protocol import TBinaryProtocol + from thrift.protocol import TCompactProtocol + from thrift.protocol import THeaderProtocol + from thrift.protocol import TJSONProtocol + from thrift.server import TServer, TNonblockingServer, THttpServer + + sys.exit(main(options)) diff --git a/src/jaegertracing/thrift/test/py/TestSocket.py b/src/jaegertracing/thrift/test/py/TestSocket.py new file mode 100755 index 000000000..619eb1002 --- /dev/null +++ b/src/jaegertracing/thrift/test/py/TestSocket.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python + +# +# 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. +# + +from thrift.transport import TSocket +import unittest +import time +import socket +import random + + +class TimeoutTest(unittest.TestCase): + def setUp(self): + for i in range(50): + try: + # find a port we can use + self.listen_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.port = random.randint(10000, 30000) + self.listen_sock.bind(('localhost', self.port)) + self.listen_sock.listen(5) + break + except Exception: + if i == 49: + raise + + def testConnectTimeout(self): + starttime = time.time() + + try: + leaky = [] + for i in range(100): + socket = TSocket.TSocket('localhost', self.port) + socket.setTimeout(10) + socket.open() + leaky.append(socket) + except Exception: + self.assert_(time.time() - starttime < 5.0) + + def testWriteTimeout(self): + starttime = time.time() + + try: + socket = TSocket.TSocket('localhost', self.port) + socket.setTimeout(10) + socket.open() + lsock = self.listen_sock.accept() + while True: + lsock.write("hi" * 100) + + except Exception: + self.assert_(time.time() - starttime < 5.0) + + +if __name__ == '__main__': + suite = unittest.TestSuite() + loader = unittest.TestLoader() + + suite.addTest(loader.loadTestsFromTestCase(TimeoutTest)) + + testRunner = unittest.TextTestRunner(verbosity=2) + testRunner.run(suite) diff --git a/src/jaegertracing/thrift/test/py/TestSyntax.py b/src/jaegertracing/thrift/test/py/TestSyntax.py new file mode 100755 index 000000000..dbe7975e2 --- /dev/null +++ b/src/jaegertracing/thrift/test/py/TestSyntax.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python + +# +# 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. +# + +# Just import these generated files to make sure they are syntactically valid +from DebugProtoTest import EmptyService # noqa +from DebugProtoTest import Inherited # noqa diff --git a/src/jaegertracing/thrift/test/py/explicit_module/runtest.sh b/src/jaegertracing/thrift/test/py/explicit_module/runtest.sh new file mode 100755 index 000000000..6d7346283 --- /dev/null +++ b/src/jaegertracing/thrift/test/py/explicit_module/runtest.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +# +# 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. +# + +rm -rf gen-py +../../../compiler/cpp/thrift --gen py test1.thrift || exit 1 +../../../compiler/cpp/thrift --gen py test2.thrift || exit 1 +../../../compiler/cpp/thrift --gen py test3.thrift && exit 1 # Fail since test3.thrift has python keywords +PYTHONPATH=./gen-py python -c 'import foo.bar.baz' || exit 1 +PYTHONPATH=./gen-py python -c 'import test2' || exit 1 +PYTHONPATH=./gen-py python -c 'import test1' &>/dev/null && exit 1 # Should fail. +cp -r gen-py simple +../../../compiler/cpp/thrift -r --gen py test2.thrift || exit 1 +PYTHONPATH=./gen-py python -c 'import test2' || exit 1 +diff -ur simple gen-py > thediffs +file thediffs | grep -s -q empty || exit 1 +rm -rf simple thediffs +echo 'All tests pass!' diff --git a/src/jaegertracing/thrift/test/py/explicit_module/test1.thrift b/src/jaegertracing/thrift/test/py/explicit_module/test1.thrift new file mode 100644 index 000000000..ec600d7d4 --- /dev/null +++ b/src/jaegertracing/thrift/test/py/explicit_module/test1.thrift @@ -0,0 +1,24 @@ +/* + * 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. + */ + +namespace py foo.bar.baz + +struct astruct { + 1: i32 how_unoriginal; +} diff --git a/src/jaegertracing/thrift/test/py/explicit_module/test2.thrift b/src/jaegertracing/thrift/test/py/explicit_module/test2.thrift new file mode 100644 index 000000000..68f9da4dd --- /dev/null +++ b/src/jaegertracing/thrift/test/py/explicit_module/test2.thrift @@ -0,0 +1,24 @@ +/* + * 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. + */ + +include "test1.thrift" + +struct another { + 1: test1.astruct something; +} diff --git a/src/jaegertracing/thrift/test/py/explicit_module/test3.thrift b/src/jaegertracing/thrift/test/py/explicit_module/test3.thrift new file mode 100644 index 000000000..154786bf8 --- /dev/null +++ b/src/jaegertracing/thrift/test/py/explicit_module/test3.thrift @@ -0,0 +1,25 @@ +/* + * 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. + */ + +namespace py validations + +struct from { + 1: i32 def; +} + diff --git a/src/jaegertracing/thrift/test/py/generate.cmake b/src/jaegertracing/thrift/test/py/generate.cmake new file mode 100644 index 000000000..4ed14cc52 --- /dev/null +++ b/src/jaegertracing/thrift/test/py/generate.cmake @@ -0,0 +1,36 @@ +macro(GENERATE FILENAME GENERATOR OUTPUTDIR) + file(MAKE_DIRECTORY ${MY_CURRENT_BINARY_DIR}/${OUTPUTDIR}) + execute_process(COMMAND ${THRIFTCOMPILER} --gen ${GENERATOR} -out ${MY_CURRENT_BINARY_DIR}/${OUTPUTDIR} ${FILENAME} + RESULT_VARIABLE CMD_RESULT) + if(CMD_RESULT) + message(FATAL_ERROR "Error generating ${FILENAME} with generator ${GENERATOR}") + endif() +endmacro(GENERATE) + +generate(${MY_PROJECT_DIR}/test/ThriftTest.thrift py gen-py-default) +generate(${MY_PROJECT_DIR}/test/ThriftTest.thrift py:slots gen-py-slots) +generate(${MY_PROJECT_DIR}/test/ThriftTest.thrift py:old_style gen-py-oldstyle) +generate(${MY_PROJECT_DIR}/test/ThriftTest.thrift py:no_utf8strings gen-py-no_utf8strings) +generate(${MY_PROJECT_DIR}/test/ThriftTest.thrift py:dynamic gen-py-dynamic) +generate(${MY_PROJECT_DIR}/test/ThriftTest.thrift py:dynamic,slots gen-py-dynamicslots) + +generate(${MY_PROJECT_DIR}/test/DebugProtoTest.thrift py gen-py-default) +generate(${MY_PROJECT_DIR}/test/DebugProtoTest.thrift py:slots gen-py-slots) +generate(${MY_PROJECT_DIR}/test/DebugProtoTest.thrift py:old_style gen-py-oldstyle) +generate(${MY_PROJECT_DIR}/test/DebugProtoTest.thrift py:no_utf8strings gen-py-no_utf8strings) +generate(${MY_PROJECT_DIR}/test/DebugProtoTest.thrift py:dynamic gen-py-dynamic) +generate(${MY_PROJECT_DIR}/test/DebugProtoTest.thrift py:dynamic,slots gen-py-dynamicslots) + +generate(${MY_PROJECT_DIR}/test/DoubleConstantsTest.thrift py gen-py-default) +generate(${MY_PROJECT_DIR}/test/DoubleConstantsTest.thrift py:slots gen-py-slots) +generate(${MY_PROJECT_DIR}/test/DoubleConstantsTest.thrift py:old_style gen-py-oldstyle) +generate(${MY_PROJECT_DIR}/test/DoubleConstantsTest.thrift py:no_utf8strings gen-py-no_utf8strings) +generate(${MY_PROJECT_DIR}/test/DoubleConstantsTest.thrift py:dynamic gen-py-dynamic) +generate(${MY_PROJECT_DIR}/test/DoubleConstantsTest.thrift py:dynamic,slots gen-py-dynamicslots) + +generate(${MY_PROJECT_DIR}/test/Recursive.thrift py gen-py-default) +generate(${MY_PROJECT_DIR}/test/Recursive.thrift py:slots gen-py-slots) +generate(${MY_PROJECT_DIR}/test/Recursive.thrift py:old_style gen-py-oldstyle) +generate(${MY_PROJECT_DIR}/test/Recursive.thrift py:no_utf8strings gen-py-no_utf8strings) +generate(${MY_PROJECT_DIR}/test/Recursive.thrift py:dynamic gen-py-dynamic) +generate(${MY_PROJECT_DIR}/test/Recursive.thrift py:dynamic,slots gen-py-dynamicslots) diff --git a/src/jaegertracing/thrift/test/py/setup.cfg b/src/jaegertracing/thrift/test/py/setup.cfg new file mode 100644 index 000000000..7da1f9608 --- /dev/null +++ b/src/jaegertracing/thrift/test/py/setup.cfg @@ -0,0 +1,2 @@ +[flake8] +max-line-length = 100 diff --git a/src/jaegertracing/thrift/test/py/util.py b/src/jaegertracing/thrift/test/py/util.py new file mode 100644 index 000000000..c2b3f5cba --- /dev/null +++ b/src/jaegertracing/thrift/test/py/util.py @@ -0,0 +1,32 @@ +# +# 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. +# + +import glob +import os +import sys + +_SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__)) +_ROOT_DIR = os.path.dirname(os.path.dirname(_SCRIPT_DIR)) + + +def local_libpath(): + globdir = os.path.join(_ROOT_DIR, 'lib', 'py', 'build', 'lib.*') + for libpath in glob.glob(globdir): + if libpath.endswith('-%d.%d' % (sys.version_info[0], sys.version_info[1])): + return libpath diff --git a/src/jaegertracing/thrift/test/rb/Gemfile b/src/jaegertracing/thrift/test/rb/Gemfile new file mode 100644 index 000000000..4ff0539fd --- /dev/null +++ b/src/jaegertracing/thrift/test/rb/Gemfile @@ -0,0 +1,7 @@ +source "http://rubygems.org" + +require "rubygems" + +gem 'rack', '~> 2.0', '>= 2.0.4' +gem 'thin', '~> 1.7', '>= 1.7.2' +gem 'test-unit', '~> 3.2', '>= 3.2.7' diff --git a/src/jaegertracing/thrift/test/rb/Makefile.am b/src/jaegertracing/thrift/test/rb/Makefile.am new file mode 100644 index 000000000..39109340d --- /dev/null +++ b/src/jaegertracing/thrift/test/rb/Makefile.am @@ -0,0 +1,37 @@ +# +# 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. +# + +stubs: $(THRIFT) ../ThriftTest.thrift ../SmallTest.thrift + $(THRIFT) --gen rb ../ThriftTest.thrift + $(THRIFT) --gen rb ../SmallTest.thrift + $(THRIFT) --gen rb ../Recursive.thrift + +precross: stubs + +check: stubs +if HAVE_BUNDLER + $(BUNDLER) install + $(BUNDLER) exec $(RUBY) -I. test_suite.rb +endif + +clean-local: + $(RM) -r gen-rb/ + +dist-hook: + $(RM) -r $(distdir)/gen-rb/ diff --git a/src/jaegertracing/thrift/test/rb/benchmarks/protocol_benchmark.rb b/src/jaegertracing/thrift/test/rb/benchmarks/protocol_benchmark.rb new file mode 100644 index 000000000..05a8ee534 --- /dev/null +++ b/src/jaegertracing/thrift/test/rb/benchmarks/protocol_benchmark.rb @@ -0,0 +1,174 @@ +# +# 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. +# + +$LOAD_PATH.unshift File.join(File.dirname(__FILE__), *%w[.. .. .. lib rb lib]) +$LOAD_PATH.unshift File.join(File.dirname(__FILE__), *%w[.. .. .. lib rb ext]) + +require 'thrift' + +require 'benchmark' +require 'rubygems' +require 'set' +require 'pp' + +# require 'ruby-debug' +# require 'ruby-prof' + +require File.join(File.dirname(__FILE__), '../fixtures/structs') + +transport1 = Thrift::MemoryBuffer.new +ruby_binary_protocol = Thrift::BinaryProtocol.new(transport1) + +transport2 = Thrift::MemoryBuffer.new +c_fast_binary_protocol = Thrift::BinaryProtocolAccelerated.new(transport2) + + +ooe = Fixtures::Structs::OneOfEach.new +ooe.im_true = true +ooe.im_false = false +ooe.a_bite = -42 +ooe.integer16 = 27000 +ooe.integer32 = 1<<24 +ooe.integer64 = 6000 * 1000 * 1000 +ooe.double_precision = Math::PI +ooe.some_characters = "Debug THIS!" +ooe.zomg_unicode = "\xd7\n\a\t" + +n1 = Fixtures::Structs::Nested1.new +n1.a_list = [] +n1.a_list << ooe << ooe << ooe << ooe +n1.i32_map = {} +n1.i32_map[1234] = ooe +n1.i32_map[46345] = ooe +n1.i32_map[-34264] = ooe +n1.i64_map = {} +n1.i64_map[43534986783945] = ooe +n1.i64_map[-32434639875122] = ooe +n1.dbl_map = {} +n1.dbl_map[324.65469834] = ooe +n1.dbl_map[-9458672340.4986798345112] = ooe +n1.str_map = {} +n1.str_map['sdoperuix'] = ooe +n1.str_map['pwoerxclmn'] = ooe + +n2 = Fixtures::Structs::Nested2.new +n2.a_list = [] +n2.a_list << n1 << n1 << n1 << n1 << n1 +n2.i32_map = {} +n2.i32_map[398345] = n1 +n2.i32_map[-2345] = n1 +n2.i32_map[12312] = n1 +n2.i64_map = {} +n2.i64_map[2349843765934] = n1 +n2.i64_map[-123234985495] = n1 +n2.i64_map[0] = n1 +n2.dbl_map = {} +n2.dbl_map[23345345.38927834] = n1 +n2.dbl_map[-1232349.5489345] = n1 +n2.dbl_map[-234984574.23498725] = n1 +n2.str_map = {} +n2.str_map[''] = n1 +n2.str_map['sdflkertpioux'] = n1 +n2.str_map['sdfwepwdcjpoi'] = n1 + +n3 = Fixtures::Structs::Nested3.new +n3.a_list = [] +n3.a_list << n2 << n2 << n2 << n2 << n2 +n3.i32_map = {} +n3.i32_map[398345] = n2 +n3.i32_map[-2345] = n2 +n3.i32_map[12312] = n2 +n3.i64_map = {} +n3.i64_map[2349843765934] = n2 +n3.i64_map[-123234985495] = n2 +n3.i64_map[0] = n2 +n3.dbl_map = {} +n3.dbl_map[23345345.38927834] = n2 +n3.dbl_map[-1232349.5489345] = n2 +n3.dbl_map[-234984574.23498725] = n2 +n3.str_map = {} +n3.str_map[''] = n2 +n3.str_map['sdflkertpioux'] = n2 +n3.str_map['sdfwepwdcjpoi'] = n2 + +n4 = Fixtures::Structs::Nested4.new +n4.a_list = [] +n4.a_list << n3 +n4.i32_map = {} +n4.i32_map[-2345] = n3 +n4.i64_map = {} +n4.i64_map[2349843765934] = n3 +n4.dbl_map = {} +n4.dbl_map[-1232349.5489345] = n3 +n4.str_map = {} +n4.str_map[''] = n3 + + +# prof = RubyProf.profile do +# n4.write(c_fast_binary_protocol) +# Fixtures::Structs::Nested4.new.read(c_fast_binary_protocol) +# end +# +# printer = RubyProf::GraphHtmlPrinter.new(prof) +# printer.print(STDOUT, :min_percent=>0) + +Benchmark.bmbm do |x| + x.report("ruby write large (1MB) structure once") do + n4.write(ruby_binary_protocol) + end + + x.report("ruby read large (1MB) structure once") do + Fixtures::Structs::Nested4.new.read(ruby_binary_protocol) + end + + x.report("c write large (1MB) structure once") do + n4.write(c_fast_binary_protocol) + end + + x.report("c read large (1MB) structure once") do + Fixtures::Structs::Nested4.new.read(c_fast_binary_protocol) + end + + + + x.report("ruby write 10_000 small structures") do + 10_000.times do + ooe.write(ruby_binary_protocol) + end + end + + x.report("ruby read 10_000 small structures") do + 10_000.times do + Fixtures::Structs::OneOfEach.new.read(ruby_binary_protocol) + end + end + + x.report("c write 10_000 small structures") do + 10_000.times do + ooe.write(c_fast_binary_protocol) + end + end + + x.report("c read 10_000 small structures") do + 10_000.times do + Fixtures::Structs::OneOfEach.new.read(c_fast_binary_protocol) + end + end + +end diff --git a/src/jaegertracing/thrift/test/rb/core/test_backwards_compatability.rb b/src/jaegertracing/thrift/test/rb/core/test_backwards_compatability.rb new file mode 100644 index 000000000..0577515d3 --- /dev/null +++ b/src/jaegertracing/thrift/test/rb/core/test_backwards_compatability.rb @@ -0,0 +1,30 @@ +# +# 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. +# + +require File.join(File.dirname(__FILE__), '../test_helper') + +require 'thrift' + +class TestThriftException < Test::Unit::TestCase + def test_has_accessible_message + msg = "hi there thrift" + assert_equal msg, Thrift::Exception.new(msg).message + end +end + diff --git a/src/jaegertracing/thrift/test/rb/core/test_exceptions.rb b/src/jaegertracing/thrift/test/rb/core/test_exceptions.rb new file mode 100644 index 000000000..f41587a7b --- /dev/null +++ b/src/jaegertracing/thrift/test/rb/core/test_exceptions.rb @@ -0,0 +1,30 @@ +# +# 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. +# + +require File.join(File.dirname(__FILE__), '../test_helper') + +require 'thrift' + +class TestException < Test::Unit::TestCase + def test_has_accessible_message + msg = "hi there thrift" + assert_equal msg, Thrift::Exception.new(msg).message + end +end + diff --git a/src/jaegertracing/thrift/test/rb/core/transport/test_transport.rb b/src/jaegertracing/thrift/test/rb/core/transport/test_transport.rb new file mode 100644 index 000000000..37afa858b --- /dev/null +++ b/src/jaegertracing/thrift/test/rb/core/transport/test_transport.rb @@ -0,0 +1,70 @@ +# +# 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. +# + +require File.join(File.dirname(__FILE__), '../../test_helper') + +require 'thrift' + +class DummyTransport < Thrift::BaseTransport + def initialize(data) + @data = data + end + + def read(size) + @data.slice!(0, size) + end +end + +# TTransport is basically an abstract class, but isn't raising NotImplementedError +class TestThriftTransport < Test::Unit::TestCase + def setup + @trans = Thrift::BaseTransport.new + end + + def test_open? + assert_nil @trans.open? + end + + def test_open + assert_nil @trans.open + end + + def test_close + assert_nil @trans.close + end + + # TODO: + # This doesn't necessarily test he right thing. + # It _looks_ like read isn't guaranteed to return the length + # you ask for and read_all is. This means our test needs to check + # for blocking. -- Kevin Clark 3/27/08 + def test_read_all + # Implements read + t = DummyTransport.new("hello") + assert_equal "hello", t.read_all(5) + end + + def test_write + assert_nil @trans.write(5) # arbitrary value + end + + def test_flush + assert_nil @trans.flush + end +end diff --git a/src/jaegertracing/thrift/test/rb/fixtures/structs.rb b/src/jaegertracing/thrift/test/rb/fixtures/structs.rb new file mode 100644 index 000000000..ebbeb0a7d --- /dev/null +++ b/src/jaegertracing/thrift/test/rb/fixtures/structs.rb @@ -0,0 +1,298 @@ +# +# 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. +# + +require 'thrift' + +module Fixtures + module Structs + class OneBool + include Thrift::Struct + attr_accessor :bool + FIELDS = { + 1 => {:type => Thrift::Types::BOOL, :name => 'bool'} + } + + def validate + end + end + + class OneByte + include Thrift::Struct + attr_accessor :byte + FIELDS = { + 1 => {:type => Thrift::Types::BYTE, :name => 'byte'} + } + + def validate + end + end + + class OneI16 + include Thrift::Struct + attr_accessor :i16 + FIELDS = { + 1 => {:type => Thrift::Types::I16, :name => 'i16'} + } + + def validate + end + end + + class OneI32 + include Thrift::Struct + attr_accessor :i32 + FIELDS = { + 1 => {:type => Thrift::Types::I32, :name => 'i32'} + } + + def validate + end + end + + class OneI64 + include Thrift::Struct + attr_accessor :i64 + FIELDS = { + 1 => {:type => Thrift::Types::I64, :name => 'i64'} + } + + def validate + end + end + + class OneDouble + include Thrift::Struct + attr_accessor :double + FIELDS = { + 1 => {:type => Thrift::Types::DOUBLE, :name => 'double'} + } + + def validate + end + end + + class OneString + include Thrift::Struct + attr_accessor :string + FIELDS = { + 1 => {:type => Thrift::Types::STRING, :name => 'string'} + } + + def validate + end + end + + class OneMap + include Thrift::Struct + attr_accessor :map + FIELDS = { + 1 => {:type => Thrift::Types::MAP, :name => 'map', :key => {:type => Thrift::Types::STRING}, :value => {:type => Thrift::Types::STRING}} + } + + def validate + end + end + + class NestedMap + include Thrift::Struct + attr_accessor :map + FIELDS = { + 0 => {:type => Thrift::Types::MAP, :name => 'map', :key => {:type => Thrift::Types::I32}, :value => {:type => Thrift::Types::MAP, :key => {:type => Thrift::Types::I32}, :value => {:type => Thrift::Types::I32}}} + } + + def validate + end + end + + class OneList + include Thrift::Struct + attr_accessor :list + FIELDS = { + 1 => {:type => Thrift::Types::LIST, :name => 'list', :element => {:type => Thrift::Types::STRING}} + } + + def validate + end + end + + class NestedList + include Thrift::Struct + attr_accessor :list + FIELDS = { + 0 => {:type => Thrift::Types::LIST, :name => 'list', :element => {:type => Thrift::Types::LIST, :element => { :type => Thrift::Types::I32 } } } + } + + def validate + end + end + + class OneSet + include Thrift::Struct + attr_accessor :set + FIELDS = { + 1 => {:type => Thrift::Types::SET, :name => 'set', :element => {:type => Thrift::Types::STRING}} + } + + def validate + end + end + + class NestedSet + include Thrift::Struct + attr_accessor :set + FIELDS = { + 1 => {:type => Thrift::Types::SET, :name => 'set', :element => {:type => Thrift::Types::SET, :element => { :type => Thrift::Types::STRING } }} + } + + def validate + end + end + + # struct OneOfEach { + # 1: bool im_true, + # 2: bool im_false, + # 3: byte a_bite, + # 4: i16 integer16, + # 5: i32 integer32, + # 6: i64 integer64, + # 7: double double_precision, + # 8: string some_characters, + # 9: string zomg_unicode, + # 10: bool what_who, + # 11: binary base64, + # } + class OneOfEach + include Thrift::Struct + attr_accessor :im_true, :im_false, :a_bite, :integer16, :integer32, :integer64, :double_precision, :some_characters, :zomg_unicode, :what_who, :base64 + FIELDS = { + 1 => {:type => Thrift::Types::BOOL, :name => 'im_true'}, + 2 => {:type => Thrift::Types::BOOL, :name => 'im_false'}, + 3 => {:type => Thrift::Types::BYTE, :name => 'a_bite'}, + 4 => {:type => Thrift::Types::I16, :name => 'integer16'}, + 5 => {:type => Thrift::Types::I32, :name => 'integer32'}, + 6 => {:type => Thrift::Types::I64, :name => 'integer64'}, + 7 => {:type => Thrift::Types::DOUBLE, :name => 'double_precision'}, + 8 => {:type => Thrift::Types::STRING, :name => 'some_characters'}, + 9 => {:type => Thrift::Types::STRING, :name => 'zomg_unicode'}, + 10 => {:type => Thrift::Types::BOOL, :name => 'what_who'}, + 11 => {:type => Thrift::Types::STRING, :name => 'base64'} + } + + # Added for assert_equal + def ==(other) + [:im_true, :im_false, :a_bite, :integer16, :integer32, :integer64, :double_precision, :some_characters, :zomg_unicode, :what_who, :base64].each do |f| + var = "@#{f}" + return false if instance_variable_get(var) != other.instance_variable_get(var) + end + true + end + + def validate + end + end + + # struct Nested1 { + # 1: list<OneOfEach> a_list + # 2: map<i32, OneOfEach> i32_map + # 3: map<i64, OneOfEach> i64_map + # 4: map<double, OneOfEach> dbl_map + # 5: map<string, OneOfEach> str_map + # } + class Nested1 + include Thrift::Struct + attr_accessor :a_list, :i32_map, :i64_map, :dbl_map, :str_map + FIELDS = { + 1 => {:type => Thrift::Types::LIST, :name => 'a_list', :element => {:type => Thrift::Types::STRUCT, :class => OneOfEach}}, + 2 => {:type => Thrift::Types::MAP, :name => 'i32_map', :key => {:type => Thrift::Types::I32}, :value => {:type => Thrift::Types::STRUCT, :class => OneOfEach}}, + 3 => {:type => Thrift::Types::MAP, :name => 'i64_map', :key => {:type => Thrift::Types::I64}, :value => {:type => Thrift::Types::STRUCT, :class => OneOfEach}}, + 4 => {:type => Thrift::Types::MAP, :name => 'dbl_map', :key => {:type => Thrift::Types::DOUBLE}, :value => {:type => Thrift::Types::STRUCT, :class => OneOfEach}}, + 5 => {:type => Thrift::Types::MAP, :name => 'str_map', :key => {:type => Thrift::Types::STRING}, :value => {:type => Thrift::Types::STRUCT, :class => OneOfEach}} + } + + def validate + end + end + + # struct Nested2 { + # 1: list<Nested1> a_list + # 2: map<i32, Nested1> i32_map + # 3: map<i64, Nested1> i64_map + # 4: map<double, Nested1> dbl_map + # 5: map<string, Nested1> str_map + # } + class Nested2 + include Thrift::Struct + attr_accessor :a_list, :i32_map, :i64_map, :dbl_map, :str_map + FIELDS = { + 1 => {:type => Thrift::Types::LIST, :name => 'a_list', :element => {:type => Thrift::Types::STRUCT, :class => Nested1}}, + 2 => {:type => Thrift::Types::MAP, :name => 'i32_map', :key => {:type => Thrift::Types::I32}, :value => {:type => Thrift::Types::STRUCT, :class => Nested1}}, + 3 => {:type => Thrift::Types::MAP, :name => 'i64_map', :key => {:type => Thrift::Types::I64}, :value => {:type => Thrift::Types::STRUCT, :class => Nested1}}, + 4 => {:type => Thrift::Types::MAP, :name => 'dbl_map', :key => {:type => Thrift::Types::DOUBLE}, :value => {:type => Thrift::Types::STRUCT, :class => Nested1}}, + 5 => {:type => Thrift::Types::MAP, :name => 'str_map', :key => {:type => Thrift::Types::STRING}, :value => {:type => Thrift::Types::STRUCT, :class => Nested1}} + } + + def validate + end + end + + # struct Nested3 { + # 1: list<Nested2> a_list + # 2: map<i32, Nested2> i32_map + # 3: map<i64, Nested2> i64_map + # 4: map<double, Nested2> dbl_map + # 5: map<string, Nested2> str_map + # } + class Nested3 + include Thrift::Struct + attr_accessor :a_list, :i32_map, :i64_map, :dbl_map, :str_map + FIELDS = { + 1 => {:type => Thrift::Types::LIST, :name => 'a_list', :element => {:type => Thrift::Types::STRUCT, :class => Nested2}}, + 2 => {:type => Thrift::Types::MAP, :name => 'i32_map', :key => {:type => Thrift::Types::I32}, :value => {:type => Thrift::Types::STRUCT, :class => Nested2}}, + 3 => {:type => Thrift::Types::MAP, :name => 'i64_map', :key => {:type => Thrift::Types::I64}, :value => {:type => Thrift::Types::STRUCT, :class => Nested2}}, + 4 => {:type => Thrift::Types::MAP, :name => 'dbl_map', :key => {:type => Thrift::Types::DOUBLE}, :value => {:type => Thrift::Types::STRUCT, :class => Nested2}}, + 5 => {:type => Thrift::Types::MAP, :name => 'str_map', :key => {:type => Thrift::Types::STRING}, :value => {:type => Thrift::Types::STRUCT, :class => Nested2}} + } + + def validate + end + end + + # struct Nested4 { + # 1: list<Nested3> a_list + # 2: map<i32, Nested3> i32_map + # 3: map<i64, Nested3> i64_map + # 4: map<double, Nested3> dbl_map + # 5: map<string, Nested3> str_map + # } + class Nested4 + include Thrift::Struct + attr_accessor :a_list, :i32_map, :i64_map, :dbl_map, :str_map + FIELDS = { + 1 => {:type => Thrift::Types::LIST, :name => 'a_list', :element => {:type => Thrift::Types::STRUCT, :class => Nested3}}, + 2 => {:type => Thrift::Types::MAP, :name => 'i32_map', :key => {:type => Thrift::Types::I32}, :value => {:type => Thrift::Types::STRUCT, :class => Nested3}}, + 3 => {:type => Thrift::Types::MAP, :name => 'i64_map', :key => {:type => Thrift::Types::I64}, :value => {:type => Thrift::Types::STRUCT, :class => Nested3}}, + 4 => {:type => Thrift::Types::MAP, :name => 'dbl_map', :key => {:type => Thrift::Types::DOUBLE}, :value => {:type => Thrift::Types::STRUCT, :class => Nested3}}, + 5 => {:type => Thrift::Types::MAP, :name => 'str_map', :key => {:type => Thrift::Types::STRING}, :value => {:type => Thrift::Types::STRUCT, :class => Nested3}} + } + + def validate + end + end + end +end diff --git a/src/jaegertracing/thrift/test/rb/generation/test_enum.rb b/src/jaegertracing/thrift/test/rb/generation/test_enum.rb new file mode 100644 index 000000000..607ea66b9 --- /dev/null +++ b/src/jaegertracing/thrift/test/rb/generation/test_enum.rb @@ -0,0 +1,34 @@ +# +# 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. +# + +require File.join(File.dirname(__FILE__), '../test_helper') +require 'thrift_test' + +class TestEnumGeneration < Test::Unit::TestCase + include Thrift::Test + def test_enum_valid_values + assert_equal(Numberz::VALID_VALUES, Set.new([Numberz::ONE, Numberz::TWO, Numberz::THREE, Numberz::FIVE, Numberz::SIX, Numberz::EIGHT])) + end + + def test_enum_hash + Numberz::VALID_VALUES.each do |value| + assert_equal(Numberz.const_get(Numberz::VALUE_MAP[value].to_sym), value) + end + end +end
\ No newline at end of file diff --git a/src/jaegertracing/thrift/test/rb/generation/test_recursive.rb b/src/jaegertracing/thrift/test/rb/generation/test_recursive.rb new file mode 100644 index 000000000..e912f72f5 --- /dev/null +++ b/src/jaegertracing/thrift/test/rb/generation/test_recursive.rb @@ -0,0 +1,41 @@ +# +# 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. +# + +require File.join(File.dirname(__FILE__), '../test_helper') +require 'recursive_types' + +class TestRecursiveGeneration < Test::Unit::TestCase + CHILD_ITEM = "child item" + PARENT_ITEM = "parent item" + + def test_can_create_recursive_tree + + child_tree = RecTree.new + child_tree.item = CHILD_ITEM + + parent_tree = RecTree.new + parent_tree.item = PARENT_ITEM + parent_tree.children = [child_tree] + + assert_equal(PARENT_ITEM, parent_tree.item) + assert_equal(1, parent_tree.children.length) + assert_equal(CHILD_ITEM, parent_tree.children.first.item) + assert_nil(parent_tree.children.first.children) + end +end diff --git a/src/jaegertracing/thrift/test/rb/generation/test_struct.rb b/src/jaegertracing/thrift/test/rb/generation/test_struct.rb new file mode 100644 index 000000000..3bd4fc9bb --- /dev/null +++ b/src/jaegertracing/thrift/test/rb/generation/test_struct.rb @@ -0,0 +1,48 @@ +# +# 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. +# + +require File.join(File.dirname(__FILE__), '../test_helper') +require 'small_service' + +class TestStructGeneration < Test::Unit::TestCase + + def test_default_values + hello = TestNamespace::Hello.new + + assert_kind_of(TestNamespace::Hello, hello) + assert_nil(hello.complexer) + + assert_equal(hello.simple, 53) + assert_equal(hello.words, 'words') + + assert_kind_of(TestNamespace::Goodbyez, hello.thinz) + assert_equal(hello.thinz.val, 36632) + + assert_kind_of(Hash, hello.complex) + assert_equal(hello.complex, { 6243 => 632, 2355 => 532, 23 => 532}) + + bool_passer = TestNamespace::BoolPasser.new(:value => false) + assert_equal false, bool_passer.value + end + + def test_goodbyez + assert_equal(TestNamespace::Goodbyez.new.val, 325) + end + +end diff --git a/src/jaegertracing/thrift/test/rb/integration/TestClient.rb b/src/jaegertracing/thrift/test/rb/integration/TestClient.rb new file mode 100755 index 000000000..639aca99e --- /dev/null +++ b/src/jaegertracing/thrift/test/rb/integration/TestClient.rb @@ -0,0 +1,381 @@ +#!/usr/bin/env ruby +# encoding: utf-8 + +# +# 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. +# + +$:.push File.dirname(__FILE__) + '/..' + +require 'test_helper' +require 'thrift' +require 'thrift_test' + +$domain_socket = nil +$host = "localhost" +$port = 9090 +$protocolType = "binary" +$ssl = false +$transport = "buffered" + +ARGV.each do|a| + if a == "--help" + puts "Allowed options:" + puts "\t -h [ --help ] \t produce help message" + puts "\t--domain-socket arg (=) \t Unix domain socket path" + puts "\t--host arg (=localhost) \t Host to connect \t not valid with domain-socket" + puts "\t--port arg (=9090) \t Port number to listen \t not valid with domain-socket" + puts "\t--protocol arg (=binary) \t protocol: accel, binary, compact, json" + puts "\t--ssl \t use ssl \t not valid with domain-socket" + puts "\t--transport arg (=buffered) transport: buffered, framed, http" + exit + elsif a.start_with?("--domain-socket") + $domain_socket = a.split("=")[1] + elsif a.start_with?("--host") + $host = a.split("=")[1] + elsif a.start_with?("--protocol") + $protocolType = a.split("=")[1] + elsif a == "--ssl" + $ssl = true + elsif a.start_with?("--transport") + $transport = a.split("=")[1] + elsif a.start_with?("--port") + $port = a.split("=")[1].to_i + end +end + +class SimpleClientTest < Test::Unit::TestCase + def setup + unless @socket + if $domain_socket.to_s.strip.empty? + if $ssl + # the working directory for ruby crosstest is test/rb/gen-rb + keysDir = File.join(File.dirname(File.dirname(Dir.pwd)), "keys") + ctx = OpenSSL::SSL::SSLContext.new + ctx.ca_file = File.join(keysDir, "CA.pem") + ctx.cert = OpenSSL::X509::Certificate.new(File.open(File.join(keysDir, "client.crt"))) + ctx.cert_store = OpenSSL::X509::Store.new + ctx.cert_store.add_file(File.join(keysDir, 'server.pem')) + ctx.key = OpenSSL::PKey::RSA.new(File.open(File.join(keysDir, "client.key"))) + ctx.options = OpenSSL::SSL::OP_NO_SSLv2 | OpenSSL::SSL::OP_NO_SSLv3 + ctx.ssl_version = :SSLv23 + ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER + @socket = Thrift::SSLSocket.new($host, $port, nil, ctx) + else + @socket = Thrift::Socket.new($host, $port) + end + else + @socket = Thrift::UNIXSocket.new($domain_socket) + end + + if $transport == "buffered" + transportFactory = Thrift::BufferedTransport.new(@socket) + elsif $transport == "framed" + transportFactory = Thrift::FramedTransport.new(@socket) + else + raise 'Unknown transport type' + end + + if $protocolType == "binary" + @protocol = Thrift::BinaryProtocol.new(transportFactory) + elsif $protocolType == "compact" + @protocol = Thrift::CompactProtocol.new(transportFactory) + elsif $protocolType == "json" + @protocol = Thrift::JsonProtocol.new(transportFactory) + elsif $protocolType == "accel" + @protocol = Thrift::BinaryProtocolAccelerated.new(transportFactory) + else + raise 'Unknown protocol type' + end + @client = Thrift::Test::ThriftTest::Client.new(@protocol) + @socket.open + end + end + + def teardown + @socket.close + end + + def test_void + p 'test_void' + @client.testVoid() + end + + def test_string + p 'test_string' + test_string = + 'quote: \" backslash:' + + ' forwardslash-escaped: \/ ' + + ' 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: ]] \"]] \\" }}}{ [[[ ' + test_string = "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ú, 粵語" + + result_string = @client.testString(test_string) + assert_equal(test_string, result_string.force_encoding(Encoding::UTF_8)) + end + + def test_bool + p 'test_bool' + assert_equal(@client.testBool(true), true) + assert_equal(@client.testBool(false), false) + end + + def test_byte + p 'test_byte' + val = 120 + assert_equal(@client.testByte(val), val) + assert_equal(@client.testByte(-val), -val) + end + + def test_i32 + p 'test_i32' + val = 2000000032 + assert_equal(@client.testI32(val), val) + assert_equal(@client.testI32(-val), -val) + end + + def test_i64 + p 'test_i64' + val = 9000000000000000064 + assert_equal(@client.testI64(val), val) + assert_equal(@client.testI64(-val), -val) + end + + def test_double + p 'test_double' + val = 3.14159265358979323846 + assert_equal(@client.testDouble(val), val) + assert_equal(@client.testDouble(-val), -val) + assert_kind_of(Float, @client.testDouble(val)) + end + + def test_binary + p 'test_binary' + val = (0...256).reverse_each.to_a + ret = @client.testBinary(val.pack('C*')) + assert_equal(val, ret.bytes.to_a) + end + + def test_map + p 'test_map' + val = {1 => 1, 2 => 2, 3 => 3} + assert_equal(@client.testMap(val), val) + assert_kind_of(Hash, @client.testMap(val)) + end + + def test_string_map + p 'test_string_map' + val = {'a' => '2', 'b' => 'blah', 'some' => 'thing'} + ret = @client.testStringMap(val) + assert_equal(val, ret) + assert_kind_of(Hash, ret) + end + + def test_list + p 'test_list' + val = [1,2,3,4,5] + assert_equal(@client.testList(val), val) + assert_kind_of(Array, @client.testList(val)) + end + + def test_enum + p 'test_enum' + val = Thrift::Test::Numberz::SIX + ret = @client.testEnum(val) + + assert_equal(ret, 6) + assert_kind_of(Fixnum, ret) + end + + def test_typedef + p 'test_typedef' + #UserId testTypedef(1: UserId thing), + assert_equal(@client.testTypedef(309858235082523), 309858235082523) + assert_kind_of(Fixnum, @client.testTypedef(309858235082523)) + true + end + + def test_set + p 'test_set' + val = Set.new([1,2,3]) + assert_equal(@client.testSet(val), val) + assert_kind_of(Set, @client.testSet(val)) + end + + def get_struct + Thrift::Test::Xtruct.new({'string_thing' => 'hi!', 'i32_thing' => 4 }) + end + + def test_struct + p 'test_struct' + ret = @client.testStruct(get_struct) + + # TODO: not sure what unspecified "default" requiredness values should be + assert(ret.byte_thing == nil || ret.byte_thing == 0) + assert(ret.i64_thing == nil || ret.i64_thing == 0) + + assert_equal(ret.string_thing, 'hi!') + assert_equal(ret.i32_thing, 4) + assert_kind_of(Thrift::Test::Xtruct, ret) + end + + def test_nest + p 'test_nest' + struct2 = Thrift::Test::Xtruct2.new({'struct_thing' => get_struct, 'i32_thing' => 10}) + + ret = @client.testNest(struct2) + + # TODO: not sure what unspecified "default" requiredness values should be + assert(ret.struct_thing.byte_thing == nil || ret.struct_thing.byte_thing == 0) + assert(ret.struct_thing.i64_thing == nil || ret.struct_thing.i64_thing == 0) + + assert_equal(ret.struct_thing.string_thing, 'hi!') + assert_equal(ret.struct_thing.i32_thing, 4) + assert_equal(ret.i32_thing, 10) + + assert_kind_of(Thrift::Test::Xtruct, ret.struct_thing) + assert_kind_of(Thrift::Test::Xtruct2, ret) + end + + def test_insanity + p 'test_insanity' + insane = Thrift::Test::Insanity.new({ + 'userMap' => { + Thrift::Test::Numberz::FIVE => 5, + Thrift::Test::Numberz::EIGHT => 8, + }, + 'xtructs' => [ + Thrift::Test::Xtruct.new({ + 'string_thing' => 'Goodbye4', + 'byte_thing' => 4, + 'i32_thing' => 4, + 'i64_thing' => 4, + }), + Thrift::Test::Xtruct.new({ + 'string_thing' => 'Hello2', + 'byte_thing' => 2, + 'i32_thing' => 2, + 'i64_thing' => 2, + }) + ] + }) + + ret = @client.testInsanity(insane) + + assert_equal(insane, ret[1][2]) + assert_equal(insane, ret[1][3]) + + assert(ret[2][6].userMap == nil || ret[2][6].userMap.length == 0) + assert(ret[2][6].xtructs == nil || ret[2][6].xtructs.length == 0) + end + + def test_map_map + p 'test_map_map' + ret = @client.testMapMap(4) + assert_kind_of(Hash, ret) + expected = { + -4 => { + -4 => -4, + -3 => -3, + -2 => -2, + -1 => -1, + }, + 4 => { + 4 => 4, + 3 => 3, + 2 => 2, + 1 => 1, + } + } + assert_equal(expected, ret) + end + + def test_multi + p 'test_multi' + ret = @client.testMulti(42, 4242, 424242, {1 => 'blah', 2 => 'thing'}, Thrift::Test::Numberz::EIGHT, 24) + expected = Thrift::Test::Xtruct.new({ + :string_thing => 'Hello2', + :byte_thing => 42, + :i32_thing => 4242, + :i64_thing => 424242 + }) + assert_equal(expected, ret) + end + + def test_exception + p 'test_exception' + assert_raise Thrift::Test::Xception do + @client.testException('Xception') + end + begin + @client.testException('TException') + rescue => e + assert e.class.ancestors.include?(Thrift::Exception) + end + assert_nothing_raised do + @client.testException('test') + end + end + + def test_multi_exception + p 'test_multi_exception' + assert_raise Thrift::Test::Xception do + @client.testMultiException("Xception", "test 1") + end + assert_raise Thrift::Test::Xception2 do + @client.testMultiException("Xception2", "test 2") + end + assert_equal( @client.testMultiException("Success", "test 3").string_thing, "test 3") + end + + def test_oneway + p 'test_oneway' + time1 = Time.now.to_f + @client.testOneway(1) + time2 = Time.now.to_f + assert_operator (time2-time1), :<, 0.1 + end + +end + diff --git a/src/jaegertracing/thrift/test/rb/integration/TestServer.rb b/src/jaegertracing/thrift/test/rb/integration/TestServer.rb new file mode 100755 index 000000000..7caf6a8cb --- /dev/null +++ b/src/jaegertracing/thrift/test/rb/integration/TestServer.rb @@ -0,0 +1,188 @@ +#!/usr/bin/env ruby + +# +# 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. +# + +$:.push File.dirname(__FILE__) + '/..' + +require 'test_helper' +require 'thrift' +require 'thrift_test' +require 'thrift_test_types' + +class SimpleHandler + [:testVoid, :testString, :testBool, :testByte, :testI32, :testI64, :testDouble, :testBinary, + :testStruct, :testMap, :testStringMap, :testSet, :testList, :testNest, :testEnum, :testTypedef, + :testEnum, :testTypedef, :testMultiException].each do |meth| + + define_method(meth) do |thing| + p meth + p thing + thing + end + + end + + def testVoid() + end + + def testInsanity(thing) + return { + 1 => { + 2 => thing, + 3 => thing + }, + 2 => { + 6 => Thrift::Test::Insanity::new() + } + } + end + + def testMapMap(thing) + return { + -4 => { + -4 => -4, + -3 => -3, + -2 => -2, + -1 => -1, + }, + 4 => { + 4 => 4, + 3 => 3, + 2 => 2, + 1 => 1, + } + } + end + + def testMulti(arg0, arg1, arg2, arg3, arg4, arg5) + return Thrift::Test::Xtruct.new({ + 'string_thing' => 'Hello2', + 'byte_thing' => arg0, + 'i32_thing' => arg1, + 'i64_thing' => arg2, + }) + end + + def testException(thing) + if thing == "Xception" + raise Thrift::Test::Xception, :errorCode => 1001, :message => thing + elsif thing == "TException" + raise Thrift::Exception, :message => thing + else + # no-op + end + end + + def testMultiException(arg0, arg1) + if arg0 == "Xception2" + raise Thrift::Test::Xception2, :errorCode => 2002, :struct_thing => ::Thrift::Test::Xtruct.new({ :string_thing => 'This is an Xception2' }) + elsif arg0 == "Xception" + raise Thrift::Test::Xception, :errorCode => 1001, :message => 'This is an Xception' + else + return ::Thrift::Test::Xtruct.new({'string_thing' => arg1}) + end + end + + def testOneway(arg0) + sleep(arg0) + end + +end + +domain_socket = nil +port = 9090 +protocol = "binary" +@protocolFactory = nil +ssl = false +transport = "buffered" +@transportFactory = nil + +ARGV.each do|a| + if a == "--help" + puts "Allowed options:" + puts "\t -h [ --help ] \t produce help message" + puts "\t--domain-socket arg (=) \t Unix domain socket path" + puts "\t--port arg (=9090) \t Port number to listen \t not valid with domain-socket" + puts "\t--protocol arg (=binary) \t protocol: accel, binary, compact, json" + puts "\t--ssl \t use ssl \t not valid with domain-socket" + puts "\t--transport arg (=buffered) transport: buffered, framed, http" + exit + elsif a.start_with?("--domain-socket") + domain_socket = a.split("=")[1] + elsif a.start_with?("--protocol") + protocol = a.split("=")[1] + elsif a == "--ssl" + ssl = true + elsif a.start_with?("--transport") + transport = a.split("=")[1] + elsif a.start_with?("--port") + port = a.split("=")[1].to_i + end +end + +if protocol == "binary" || protocol.to_s.strip.empty? + @protocolFactory = Thrift::BinaryProtocolFactory.new +elsif protocol == "compact" + @protocolFactory = Thrift::CompactProtocolFactory.new +elsif protocol == "json" + @protocolFactory = Thrift::JsonProtocolFactory.new +elsif protocol == "accel" + @protocolFactory = Thrift::BinaryProtocolAcceleratedFactory.new +else + raise 'Unknown protocol type' +end + +if transport == "buffered" || transport.to_s.strip.empty? + @transportFactory = Thrift::BufferedTransportFactory.new +elsif transport == "framed" + @transportFactory = Thrift::FramedTransportFactory.new +else + raise 'Unknown transport type' +end + +@handler = SimpleHandler.new +@processor = Thrift::Test::ThriftTest::Processor.new(@handler) +@transport = nil +if domain_socket.to_s.strip.empty? + if ssl + # the working directory for ruby crosstest is test/rb/gen-rb + keysDir = File.join(File.dirname(File.dirname(Dir.pwd)), "keys") + ctx = OpenSSL::SSL::SSLContext.new + ctx.ca_file = File.join(keysDir, "CA.pem") + ctx.cert = OpenSSL::X509::Certificate.new(File.open(File.join(keysDir, "server.crt"))) + ctx.cert_store = OpenSSL::X509::Store.new + ctx.cert_store.add_file(File.join(keysDir, 'client.pem')) + ctx.key = OpenSSL::PKey::RSA.new(File.open(File.join(keysDir, "server.key"))) + ctx.options = OpenSSL::SSL::OP_NO_SSLv2 | OpenSSL::SSL::OP_NO_SSLv3 + ctx.ssl_version = :SSLv23 + ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER + @transport = Thrift::SSLServerSocket.new(nil, port, ctx) + else + @transport = Thrift::ServerSocket.new(port) + end +else + @transport = Thrift::UNIXServerSocket.new(domain_socket) +end + +@server = Thrift::ThreadedServer.new(@processor, @transport, @transportFactory, @protocolFactory) + +puts "Starting TestServer #{@server.to_s}" +@server.serve +puts "done." diff --git a/src/jaegertracing/thrift/test/rb/test_helper.rb b/src/jaegertracing/thrift/test/rb/test_helper.rb new file mode 100644 index 000000000..c1ed779ef --- /dev/null +++ b/src/jaegertracing/thrift/test/rb/test_helper.rb @@ -0,0 +1,35 @@ +# +# 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. +# + +$:.unshift File.dirname(__FILE__) + '/gen-rb' +$:.unshift File.join(File.dirname(__FILE__), '../../lib/rb/lib') +$:.unshift File.join(File.dirname(__FILE__), '../../lib/rb/ext') + +require 'test/unit' + +module Thrift + module Struct + def ==(other) + return false unless other.is_a? self.class + self.class.const_get(:FIELDS).collect {|fid, data| data[:name] }.all? do |field| + send(field) == other.send(field) + end + end + end +end diff --git a/src/jaegertracing/thrift/test/rb/test_suite.rb b/src/jaegertracing/thrift/test/rb/test_suite.rb new file mode 100644 index 000000000..b157c2c50 --- /dev/null +++ b/src/jaegertracing/thrift/test/rb/test_suite.rb @@ -0,0 +1,20 @@ +# +# 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. +# + +Dir["{core,generation}/**/*.rb"].each {|f| require f }
\ No newline at end of file diff --git a/src/jaegertracing/thrift/test/rebuild_known_failures.sh b/src/jaegertracing/thrift/test/rebuild_known_failures.sh new file mode 100644 index 000000000..08869fe58 --- /dev/null +++ b/src/jaegertracing/thrift/test/rebuild_known_failures.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +if [ -z $1 ]; then + echo Usage: $0 LANGUAGE + echo Re-list all failures of a specific LANGUAGE into known_failures_Linux.json + echo LANGUAGE should be library name like cpp, java, py etc + exit 1 +fi + +if [ -z $PYTHON]; then + PYTHON=python +fi + +TARGET_LANG=$1 +OUT_FILE=known_failures_Linux.json +echo Rebuilding known failures for $TARGET_LANG + +TMPFILE=.__tmp__rebuild__ +grep -v -e "\"$1-" -e "\-$1_" $OUT_FILE > $TMPFILE +mv $TMPFILE $OUT_FILE +$PYTHON test.py --client $1 +$PYTHON test.py -U merge +$PYTHON test.py --server $1 +$PYTHON test.py -U merge diff --git a/src/jaegertracing/thrift/test/result.js b/src/jaegertracing/thrift/test/result.js new file mode 100644 index 000000000..18b1a593d --- /dev/null +++ b/src/jaegertracing/thrift/test/result.js @@ -0,0 +1,64 @@ +/* + 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. + +*/ + +$.getJSON('results.json', function(results) { + $(document).ready(function() { + var transport = 3; + var socket = 4; + var success = 5; + var expected = 6; + var returnCode = 7; + var logFile = 8; + testTable = $('#test_results').DataTable({ + data: results['results'], + columnDefs: [ + { + targets: 3, + render: function(data, type, row) { + return row[transport] + '-' + row[socket]; + }, + }, + { + targets: 4, + render: function(data, type, row) { + return (row[success] ? 'success' : 'failure') + + '(' + (row[returnCode] == 128 ? 'timeout' : row[returnCode]) + ')' + + '(<a href="' + row[logFile].server + '">Server</a>, ' + + '<a href="' + row[logFile].client + '">Client</a>)'; + }, + }, + { + targets: 5, + render: function(data, type, row) { + // 'yes' rather than 'expected' to ease search + return row[expected] ? 'yes' : 'unexpected'; + }, + } + ], + }); + $('#test_results_filter label input').focus().val('unexpected failure'); + $('#test_info').text( + "Test Date: " + results['date'] + "\n" + + "Revision: " + results['revision'] + "\n" + + "Platform: " + results['platform'] + "\n" + + "Test duration: " + results['duration']) + " seconds"; + }); +}); + diff --git a/src/jaegertracing/thrift/test/rs/Cargo.toml b/src/jaegertracing/thrift/test/rs/Cargo.toml new file mode 100644 index 000000000..c1058f91f --- /dev/null +++ b/src/jaegertracing/thrift/test/rs/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "thrift-test" +version = "0.1.0" +license = "Apache-2.0" +authors = ["Apache Thrift Developers <dev@thrift.apache.org>"] +publish = false + +[dependencies] +clap = "2.33" +env_logger = "0.4.0" +log = "0.4" +ordered-float = "1.0" +try_from = "0.3" + +[dependencies.thrift] +path = "../../lib/rs" + diff --git a/src/jaegertracing/thrift/test/rs/Makefile.am b/src/jaegertracing/thrift/test/rs/Makefile.am new file mode 100644 index 000000000..4b061eae0 --- /dev/null +++ b/src/jaegertracing/thrift/test/rs/Makefile.am @@ -0,0 +1,40 @@ +# +# 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. +# + +stubs: ../ThriftTest.thrift + $(THRIFT) -I ./thrifts -out src --gen rs ../ThriftTest.thrift + +precross: stubs + $(CARGO) build + [ -d bin ] || mkdir bin + cp target/debug/test_server bin/test_server + cp target/debug/test_client bin/test_client + +clean-local: + $(CARGO) clean + -$(RM) Cargo.lock + -$(RM) src/thrift_test.rs + -$(RM) -r bin + +EXTRA_DIST = \ + Cargo.toml \ + src/lib.rs \ + src/bin/test_server.rs \ + src/bin/test_client.rs + diff --git a/src/jaegertracing/thrift/test/rs/src/bin/test_client.rs b/src/jaegertracing/thrift/test/rs/src/bin/test_client.rs new file mode 100644 index 000000000..8016ca674 --- /dev/null +++ b/src/jaegertracing/thrift/test/rs/src/bin/test_client.rs @@ -0,0 +1,605 @@ +// 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. + +#[macro_use] +extern crate log; +extern crate env_logger; + +#[macro_use] +extern crate clap; +extern crate ordered_float; +extern crate thrift; +extern crate thrift_test; // huh. I have to do this to use my lib + +use ordered_float::OrderedFloat; +use std::collections::{BTreeMap, BTreeSet}; +use std::fmt::Debug; + +use thrift::protocol::{TBinaryInputProtocol, TBinaryOutputProtocol, TCompactInputProtocol, + TCompactOutputProtocol, TInputProtocol, TMultiplexedOutputProtocol, + TOutputProtocol}; +use thrift::transport::{ReadHalf, TBufferedReadTransport, TBufferedWriteTransport, + TFramedReadTransport, TFramedWriteTransport, TIoChannel, TReadTransport, + TTcpChannel, TWriteTransport, WriteHalf}; +use thrift_test::*; + +fn main() { + env_logger::init().expect("logger setup failed"); + + debug!("initialized logger - running cross-test client"); + + match run() { + Ok(()) => info!("cross-test client succeeded"), + Err(e) => { + info!("cross-test client failed with error {:?}", e); + std::process::exit(1); + } + } +} + +fn run() -> thrift::Result<()> { + // unsupported options: + // --domain-socket + // --named-pipe + // --anon-pipes + // --ssl + // --threads + let matches = clap_app!(rust_test_client => + (version: "1.0") + (author: "Apache Thrift Developers <dev@thrift.apache.org>") + (about: "Rust Thrift test client") + (@arg host: --host +takes_value "Host on which the Thrift test server is located") + (@arg port: --port +takes_value "Port on which the Thrift test server is listening") + (@arg transport: --transport +takes_value "Thrift transport implementation to use (\"buffered\", \"framed\")") + (@arg protocol: --protocol +takes_value "Thrift protocol implementation to use (\"binary\", \"compact\", \"multi\", \"multic\")") + (@arg testloops: -n --testloops +takes_value "Number of times to run tests") + ) + .get_matches(); + + let host = matches.value_of("host").unwrap_or("127.0.0.1"); + let port = value_t!(matches, "port", u16).unwrap_or(9090); + let testloops = value_t!(matches, "testloops", u8).unwrap_or(1); + let transport = matches.value_of("transport").unwrap_or("buffered"); + let protocol = matches.value_of("protocol").unwrap_or("binary"); + + + let mut thrift_test_client = { + let (i_prot, o_prot) = build_protocols(host, port, transport, protocol, "ThriftTest")?; + ThriftTestSyncClient::new(i_prot, o_prot) + }; + + let mut second_service_client = if protocol.starts_with("multi") { + let (i_prot, o_prot) = build_protocols(host, port, transport, protocol, "SecondService")?; + Some(SecondServiceSyncClient::new(i_prot, o_prot)) + } else { + None + }; + + info!( + "connecting to {}:{} with {}+{} stack", + host, + port, + protocol, + transport + ); + + for _ in 0..testloops { + make_thrift_calls(&mut thrift_test_client, &mut second_service_client)? + } + + Ok(()) +} + +fn build_protocols( + host: &str, + port: u16, + transport: &str, + protocol: &str, + service_name: &str, +) -> thrift::Result<(Box<TInputProtocol>, Box<TOutputProtocol>)> { + let (i_chan, o_chan) = tcp_channel(host, port)?; + + let (i_tran, o_tran): (Box<TReadTransport>, Box<TWriteTransport>) = match transport { + "buffered" => { + (Box::new(TBufferedReadTransport::new(i_chan)), + Box::new(TBufferedWriteTransport::new(o_chan))) + } + "framed" => { + (Box::new(TFramedReadTransport::new(i_chan)), + Box::new(TFramedWriteTransport::new(o_chan))) + } + unmatched => return Err(format!("unsupported transport {}", unmatched).into()), + }; + + let (i_prot, o_prot): (Box<TInputProtocol>, Box<TOutputProtocol>) = match protocol { + "binary" => { + (Box::new(TBinaryInputProtocol::new(i_tran, true)), + Box::new(TBinaryOutputProtocol::new(o_tran, true))) + } + "multi" => { + (Box::new(TBinaryInputProtocol::new(i_tran, true)), + Box::new( + TMultiplexedOutputProtocol::new( + service_name, + TBinaryOutputProtocol::new(o_tran, true), + ), + )) + } + "compact" => { + (Box::new(TCompactInputProtocol::new(i_tran)), + Box::new(TCompactOutputProtocol::new(o_tran))) + } + "multic" => { + (Box::new(TCompactInputProtocol::new(i_tran)), + Box::new(TMultiplexedOutputProtocol::new(service_name, TCompactOutputProtocol::new(o_tran)),)) + } + unmatched => return Err(format!("unsupported protocol {}", unmatched).into()), + }; + + Ok((i_prot, o_prot)) +} + +// FIXME: expose "open" through the client interface so I don't have to early +// open +fn tcp_channel( + host: &str, + port: u16, +) -> thrift::Result<(ReadHalf<TTcpChannel>, WriteHalf<TTcpChannel>)> { + let mut c = TTcpChannel::new(); + c.open(&format!("{}:{}", host, port))?; + c.split() +} + +type BuildThriftTestClient = ThriftTestSyncClient<Box<TInputProtocol>, Box<TOutputProtocol>>; +type BuiltSecondServiceClient = SecondServiceSyncClient<Box<TInputProtocol>, Box<TOutputProtocol>>; + +#[cfg_attr(feature = "cargo-clippy", allow(cyclomatic_complexity))] +fn make_thrift_calls( + thrift_test_client: &mut BuildThriftTestClient, + second_service_client: &mut Option<BuiltSecondServiceClient>, +) -> Result<(), thrift::Error> { + info!("testVoid"); + thrift_test_client.test_void()?; + + info!("testString"); + verify_expected_result( + thrift_test_client.test_string("thing".to_owned()), + "thing".to_owned(), + )?; + + info!("testBool"); + verify_expected_result(thrift_test_client.test_bool(true), true)?; + + info!("testBool"); + verify_expected_result(thrift_test_client.test_bool(false), false)?; + + info!("testByte"); + verify_expected_result(thrift_test_client.test_byte(42), 42)?; + + info!("testi32"); + verify_expected_result(thrift_test_client.test_i32(1159348374), 1159348374)?; + + info!("testi64"); + // try!(verify_expected_result(thrift_test_client.test_i64(-8651829879438294565), + // -8651829879438294565)); + verify_expected_result( + thrift_test_client.test_i64(i64::min_value()), + i64::min_value(), + )?; + + info!("testDouble"); + verify_expected_result( + thrift_test_client.test_double(OrderedFloat::from(42.42)), + OrderedFloat::from(42.42), + )?; + + info!("testTypedef"); + { + let u_snd: UserId = 2348; + let u_cmp: UserId = 2348; + verify_expected_result(thrift_test_client.test_typedef(u_snd), u_cmp)?; + } + + info!("testEnum"); + { + verify_expected_result(thrift_test_client.test_enum(Numberz::Two), Numberz::Two)?; + } + + info!("testBinary"); + { + let b_snd = vec![0x77, 0x30, 0x30, 0x74, 0x21, 0x20, 0x52, 0x75, 0x73, 0x74]; + let b_cmp = vec![0x77, 0x30, 0x30, 0x74, 0x21, 0x20, 0x52, 0x75, 0x73, 0x74]; + verify_expected_result(thrift_test_client.test_binary(b_snd), b_cmp)?; + } + + info!("testStruct"); + { + let x_snd = Xtruct { + string_thing: Some("foo".to_owned()), + byte_thing: Some(12), + i32_thing: Some(219129), + i64_thing: Some(12938492818), + }; + let x_cmp = Xtruct { + string_thing: Some("foo".to_owned()), + byte_thing: Some(12), + i32_thing: Some(219129), + i64_thing: Some(12938492818), + }; + verify_expected_result(thrift_test_client.test_struct(x_snd), x_cmp)?; + } + + // Xtruct again, with optional values + // FIXME: apparently the erlang thrift server does not like opt-in-req-out + // parameters that are undefined. Joy. + // { + // let x_snd = Xtruct { string_thing: Some("foo".to_owned()), byte_thing: None, + // i32_thing: None, i64_thing: Some(12938492818) }; + // let x_cmp = Xtruct { string_thing: Some("foo".to_owned()), byte_thing: + // Some(0), i32_thing: Some(0), i64_thing: Some(12938492818) }; // the C++ + // server is responding correctly + // try!(verify_expected_result(thrift_test_client.test_struct(x_snd), x_cmp)); + // } + // + + info!("testNest"); // (FIXME: try Xtruct2 with optional values) + { + let x_snd = Xtruct2 { + byte_thing: Some(32), + struct_thing: Some( + Xtruct { + string_thing: Some("foo".to_owned()), + byte_thing: Some(1), + i32_thing: Some(324382098), + i64_thing: Some(12938492818), + }, + ), + i32_thing: Some(293481098), + }; + let x_cmp = Xtruct2 { + byte_thing: Some(32), + struct_thing: Some( + Xtruct { + string_thing: Some("foo".to_owned()), + byte_thing: Some(1), + i32_thing: Some(324382098), + i64_thing: Some(12938492818), + }, + ), + i32_thing: Some(293481098), + }; + verify_expected_result(thrift_test_client.test_nest(x_snd), x_cmp)?; + } + + // do the multiplexed calls while making the main ThriftTest calls + if let Some(ref mut client) = second_service_client.as_mut() { + info!("SecondService secondtestString"); + { + verify_expected_result( + client.secondtest_string("test_string".to_owned()), + "testString(\"test_string\")".to_owned(), + )?; + } + } + + info!("testList"); + { + let mut v_snd: Vec<i32> = Vec::new(); + v_snd.push(29384); + v_snd.push(238); + v_snd.push(32498); + + let mut v_cmp: Vec<i32> = Vec::new(); + v_cmp.push(29384); + v_cmp.push(238); + v_cmp.push(32498); + + verify_expected_result(thrift_test_client.test_list(v_snd), v_cmp)?; + } + + info!("testSet"); + { + let mut s_snd: BTreeSet<i32> = BTreeSet::new(); + s_snd.insert(293481); + s_snd.insert(23); + s_snd.insert(3234); + + let mut s_cmp: BTreeSet<i32> = BTreeSet::new(); + s_cmp.insert(293481); + s_cmp.insert(23); + s_cmp.insert(3234); + + verify_expected_result(thrift_test_client.test_set(s_snd), s_cmp)?; + } + + info!("testMap"); + { + let mut m_snd: BTreeMap<i32, i32> = BTreeMap::new(); + m_snd.insert(2, 4); + m_snd.insert(4, 6); + m_snd.insert(8, 7); + + let mut m_cmp: BTreeMap<i32, i32> = BTreeMap::new(); + m_cmp.insert(2, 4); + m_cmp.insert(4, 6); + m_cmp.insert(8, 7); + + verify_expected_result(thrift_test_client.test_map(m_snd), m_cmp)?; + } + + info!("testStringMap"); + { + let mut m_snd: BTreeMap<String, String> = BTreeMap::new(); + m_snd.insert("2".to_owned(), "4_string".to_owned()); + m_snd.insert("4".to_owned(), "6_string".to_owned()); + m_snd.insert("8".to_owned(), "7_string".to_owned()); + + let mut m_rcv: BTreeMap<String, String> = BTreeMap::new(); + m_rcv.insert("2".to_owned(), "4_string".to_owned()); + m_rcv.insert("4".to_owned(), "6_string".to_owned()); + m_rcv.insert("8".to_owned(), "7_string".to_owned()); + + verify_expected_result(thrift_test_client.test_string_map(m_snd), m_rcv)?; + } + + // nested map + // expect : {-4 => {-4 => -4, -3 => -3, -2 => -2, -1 => -1, }, 4 => {1 => 1, 2 + // => 2, 3 => 3, 4 => 4, }, } + info!("testMapMap"); + { + let mut m_cmp_nested_0: BTreeMap<i32, i32> = BTreeMap::new(); + for i in (-4 as i32)..0 { + m_cmp_nested_0.insert(i, i); + } + let mut m_cmp_nested_1: BTreeMap<i32, i32> = BTreeMap::new(); + for i in 1..5 { + m_cmp_nested_1.insert(i, i); + } + + let mut m_cmp: BTreeMap<i32, BTreeMap<i32, i32>> = BTreeMap::new(); + m_cmp.insert(-4, m_cmp_nested_0); + m_cmp.insert(4, m_cmp_nested_1); + + verify_expected_result(thrift_test_client.test_map_map(42), m_cmp)?; + } + + info!("testMulti"); + { + let mut m_snd: BTreeMap<i16, String> = BTreeMap::new(); + m_snd.insert(1298, "fizz".to_owned()); + m_snd.insert(-148, "buzz".to_owned()); + + let s_cmp = Xtruct { + string_thing: Some("Hello2".to_owned()), + byte_thing: Some(1), + i32_thing: Some(-123948), + i64_thing: Some(-19234123981), + }; + + verify_expected_result( + thrift_test_client.test_multi(1, -123948, -19234123981, m_snd, Numberz::Eight, 81), + s_cmp, + )?; + } + + // Insanity + // returns: + // { 1 => { 2 => argument, + // 3 => argument, + // }, + // 2 => { 6 => <empty Insanity struct>, }, + // } + { + let mut arg_map_usermap: BTreeMap<Numberz, i64> = BTreeMap::new(); + arg_map_usermap.insert(Numberz::One, 4289); + arg_map_usermap.insert(Numberz::Eight, 19); + + let mut arg_vec_xtructs: Vec<Xtruct> = Vec::new(); + arg_vec_xtructs.push( + Xtruct { + string_thing: Some("foo".to_owned()), + byte_thing: Some(8), + i32_thing: Some(29), + i64_thing: Some(92384), + }, + ); + arg_vec_xtructs.push( + Xtruct { + string_thing: Some("bar".to_owned()), + byte_thing: Some(28), + i32_thing: Some(2), + i64_thing: Some(-1281), + }, + ); + arg_vec_xtructs.push( + Xtruct { + string_thing: Some("baz".to_owned()), + byte_thing: Some(0), + i32_thing: Some(3948539), + i64_thing: Some(-12938492), + }, + ); + + let mut s_cmp_nested_1: BTreeMap<Numberz, Insanity> = BTreeMap::new(); + let insanity = Insanity { + user_map: Some(arg_map_usermap), + xtructs: Some(arg_vec_xtructs), + }; + s_cmp_nested_1.insert(Numberz::Two, insanity.clone()); + s_cmp_nested_1.insert(Numberz::Three, insanity.clone()); + + let mut s_cmp_nested_2: BTreeMap<Numberz, Insanity> = BTreeMap::new(); + let empty_insanity = Insanity { + user_map: Some(BTreeMap::new()), + xtructs: Some(Vec::new()), + }; + s_cmp_nested_2.insert(Numberz::Six, empty_insanity); + + let mut s_cmp: BTreeMap<UserId, BTreeMap<Numberz, Insanity>> = BTreeMap::new(); + s_cmp.insert(1 as UserId, s_cmp_nested_1); + s_cmp.insert(2 as UserId, s_cmp_nested_2); + + verify_expected_result(thrift_test_client.test_insanity(insanity.clone()), s_cmp)?; + } + + info!("testException - remote throws Xception"); + { + let r = thrift_test_client.test_exception("Xception".to_owned()); + let x = match r { + Err(thrift::Error::User(ref e)) => { + match e.downcast_ref::<Xception>() { + Some(x) => Ok(x), + None => Err(thrift::Error::User("did not get expected Xception struct".into()),), + } + } + _ => Err(thrift::Error::User("did not get exception".into())), + }?; + + let x_cmp = Xception { + error_code: Some(1001), + message: Some("Xception".to_owned()), + }; + + verify_expected_result(Ok(x), &x_cmp)?; + } + + info!("testException - remote throws TApplicationException"); + { + let r = thrift_test_client.test_exception("TException".to_owned()); + match r { + Err(thrift::Error::Application(ref e)) => { + info!("received an {:?}", e); + Ok(()) + } + _ => Err(thrift::Error::User("did not get exception".into())), + }?; + } + + info!("testException - remote succeeds"); + { + let r = thrift_test_client.test_exception("foo".to_owned()); + match r { + Ok(_) => Ok(()), + _ => Err(thrift::Error::User("received an exception".into())), + }?; + } + + info!("testMultiException - remote throws Xception"); + { + let r = + thrift_test_client.test_multi_exception("Xception".to_owned(), "ignored".to_owned()); + let x = match r { + Err(thrift::Error::User(ref e)) => { + match e.downcast_ref::<Xception>() { + Some(x) => Ok(x), + None => Err(thrift::Error::User("did not get expected Xception struct".into()),), + } + } + _ => Err(thrift::Error::User("did not get exception".into())), + }?; + + let x_cmp = Xception { + error_code: Some(1001), + message: Some("This is an Xception".to_owned()), + }; + + verify_expected_result(Ok(x), &x_cmp)?; + } + + info!("testMultiException - remote throws Xception2"); + { + let r = + thrift_test_client.test_multi_exception("Xception2".to_owned(), "ignored".to_owned()); + let x = match r { + Err(thrift::Error::User(ref e)) => { + match e.downcast_ref::<Xception2>() { + Some(x) => Ok(x), + None => Err(thrift::Error::User("did not get expected Xception struct".into()),), + } + } + _ => Err(thrift::Error::User("did not get exception".into())), + }?; + + let x_cmp = Xception2 { + error_code: Some(2002), + struct_thing: Some( + Xtruct { + string_thing: Some("This is an Xception2".to_owned()), + // since this is an OPT_IN_REQ_OUT field the sender sets a default + byte_thing: Some(0), + // since this is an OPT_IN_REQ_OUT field the sender sets a default + i32_thing: Some(0), + // since this is an OPT_IN_REQ_OUT field the sender sets a default + i64_thing: Some(0), + }, + ), + }; + + verify_expected_result(Ok(x), &x_cmp)?; + } + + info!("testMultiException - remote succeeds"); + { + let r = thrift_test_client.test_multi_exception("haha".to_owned(), "RETURNED".to_owned()); + let x = match r { + Err(e) => Err(thrift::Error::User(format!("received an unexpected exception {:?}", e).into(),),), + _ => r, + }?; + + let x_cmp = Xtruct { + string_thing: Some("RETURNED".to_owned()), + // since this is an OPT_IN_REQ_OUT field the sender sets a default + byte_thing: Some(0), + // since this is an OPT_IN_REQ_OUT field the sender sets a default + i32_thing: Some(0), + // since this is an OPT_IN_REQ_OUT field the sender sets a default + i64_thing: Some(0), + }; + + verify_expected_result(Ok(x), x_cmp)?; + } + + info!("testOneWay - remote sleeps for 1 second"); + { + thrift_test_client.test_oneway(1)?; + } + + // final test to verify that the connection is still writable after the one-way + // call + thrift_test_client.test_void() +} + +#[cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))] +fn verify_expected_result<T: Debug + PartialEq + Sized>( + actual: Result<T, thrift::Error>, + expected: T, +) -> Result<(), thrift::Error> { + info!("*** EXPECTED: Ok({:?})", expected); + info!("*** ACTUAL : {:?}", actual); + match actual { + Ok(v) => { + if v == expected { + info!("*** OK ***"); + Ok(()) + } else { + info!("*** FAILED ***"); + Err(thrift::Error::User(format!("expected {:?} but got {:?}", &expected, &v).into()),) + } + } + Err(e) => Err(e), + } +} diff --git a/src/jaegertracing/thrift/test/rs/src/bin/test_server.rs b/src/jaegertracing/thrift/test/rs/src/bin/test_server.rs new file mode 100644 index 000000000..81c1ec704 --- /dev/null +++ b/src/jaegertracing/thrift/test/rs/src/bin/test_server.rs @@ -0,0 +1,398 @@ +// 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. + +#[macro_use] +extern crate log; +extern crate env_logger; + +#[macro_use] +extern crate clap; +extern crate ordered_float; +extern crate thrift; +extern crate thrift_test; + +use ordered_float::OrderedFloat; +use std::collections::{BTreeMap, BTreeSet}; +use std::thread; +use std::time::Duration; + +use thrift::protocol::{TBinaryInputProtocolFactory, TBinaryOutputProtocolFactory, + TCompactInputProtocolFactory, TCompactOutputProtocolFactory, + TInputProtocolFactory, TOutputProtocolFactory}; +use thrift::server::{TMultiplexedProcessor, TServer}; +use thrift::transport::{TBufferedReadTransportFactory, TBufferedWriteTransportFactory, + TFramedReadTransportFactory, TFramedWriteTransportFactory, + TReadTransportFactory, TWriteTransportFactory}; +use thrift_test::*; + +fn main() { + env_logger::init().expect("logger setup failed"); + + debug!("initialized logger - running cross-test server"); + + match run() { + Ok(()) => info!("cross-test server succeeded"), + Err(e) => { + info!("cross-test server failed with error {:?}", e); + std::process::exit(1); + } + } +} + +fn run() -> thrift::Result<()> { + + // unsupported options: + // --domain-socket + // --named-pipe + // --ssl + let matches = clap_app!(rust_test_client => + (version: "1.0") + (author: "Apache Thrift Developers <dev@thrift.apache.org>") + (about: "Rust Thrift test server") + (@arg port: --port +takes_value "port on which the test server listens") + (@arg transport: --transport +takes_value "transport implementation to use (\"buffered\", \"framed\")") + (@arg protocol: --protocol +takes_value "protocol implementation to use (\"binary\", \"compact\")") + (@arg server_type: --server_type +takes_value "type of server instantiated (\"simple\", \"thread-pool\")") + (@arg workers: -n --workers +takes_value "number of thread-pool workers (\"4\")") + ) + .get_matches(); + + let port = value_t!(matches, "port", u16).unwrap_or(9090); + let transport = matches.value_of("transport").unwrap_or("buffered"); + let protocol = matches.value_of("protocol").unwrap_or("binary"); + let server_type = matches.value_of("server_type").unwrap_or("thread-pool"); + let workers = value_t!(matches, "workers", usize).unwrap_or(4); + let listen_address = format!("127.0.0.1:{}", port); + + info!("binding to {}", listen_address); + + let (i_transport_factory, o_transport_factory): (Box<TReadTransportFactory>, + Box<TWriteTransportFactory>) = + match &*transport { + "buffered" => { + (Box::new(TBufferedReadTransportFactory::new()), + Box::new(TBufferedWriteTransportFactory::new())) + } + "framed" => { + (Box::new(TFramedReadTransportFactory::new()), + Box::new(TFramedWriteTransportFactory::new())) + } + unknown => { + return Err(format!("unsupported transport type {}", unknown).into()); + } + }; + + let (i_protocol_factory, o_protocol_factory): (Box<TInputProtocolFactory>, + Box<TOutputProtocolFactory>) = + match &*protocol { + "binary" | "multi" | "multi:binary" => { + (Box::new(TBinaryInputProtocolFactory::new()), + Box::new(TBinaryOutputProtocolFactory::new())) + } + "compact" | "multic" | "multi:compact" => { + (Box::new(TCompactInputProtocolFactory::new()), + Box::new(TCompactOutputProtocolFactory::new())) + } + unknown => { + return Err(format!("unsupported transport type {}", unknown).into()); + } + }; + + let test_processor = ThriftTestSyncProcessor::new(ThriftTestSyncHandlerImpl {}); + + match &*server_type { + "simple" | "thread-pool" => { + if protocol == "multi" || protocol == "multic" { + let second_service_processor = SecondServiceSyncProcessor::new(SecondServiceSyncHandlerImpl {},); + + let mut multiplexed_processor = TMultiplexedProcessor::new(); + multiplexed_processor + .register("ThriftTest", Box::new(test_processor), true)?; + multiplexed_processor + .register("SecondService", Box::new(second_service_processor), false)?; + + let mut server = TServer::new( + i_transport_factory, + i_protocol_factory, + o_transport_factory, + o_protocol_factory, + multiplexed_processor, + workers, + ); + + server.listen(&listen_address) + } else { + let mut server = TServer::new( + i_transport_factory, + i_protocol_factory, + o_transport_factory, + o_protocol_factory, + test_processor, + workers, + ); + + server.listen(&listen_address) + } + } + unknown => Err(format!("unsupported server type {}", unknown).into()), + } +} + +struct ThriftTestSyncHandlerImpl; +impl ThriftTestSyncHandler for ThriftTestSyncHandlerImpl { + fn handle_test_void(&self) -> thrift::Result<()> { + info!("testVoid()"); + Ok(()) + } + + fn handle_test_string(&self, thing: String) -> thrift::Result<String> { + info!("testString({})", &thing); + Ok(thing) + } + + fn handle_test_bool(&self, thing: bool) -> thrift::Result<bool> { + info!("testBool({})", thing); + Ok(thing) + } + + fn handle_test_byte(&self, thing: i8) -> thrift::Result<i8> { + info!("testByte({})", thing); + Ok(thing) + } + + fn handle_test_i32(&self, thing: i32) -> thrift::Result<i32> { + info!("testi32({})", thing); + Ok(thing) + } + + fn handle_test_i64(&self, thing: i64) -> thrift::Result<i64> { + info!("testi64({})", thing); + Ok(thing) + } + + fn handle_test_double(&self, thing: OrderedFloat<f64>) -> thrift::Result<OrderedFloat<f64>> { + info!("testDouble({})", thing); + Ok(thing) + } + + fn handle_test_binary(&self, thing: Vec<u8>) -> thrift::Result<Vec<u8>> { + info!("testBinary({:?})", thing); + Ok(thing) + } + + fn handle_test_struct(&self, thing: Xtruct) -> thrift::Result<Xtruct> { + info!("testStruct({:?})", thing); + Ok(thing) + } + + fn handle_test_nest(&self, thing: Xtruct2) -> thrift::Result<Xtruct2> { + info!("testNest({:?})", thing); + Ok(thing) + } + + fn handle_test_map(&self, thing: BTreeMap<i32, i32>) -> thrift::Result<BTreeMap<i32, i32>> { + info!("testMap({:?})", thing); + Ok(thing) + } + + fn handle_test_string_map( + &self, + thing: BTreeMap<String, String>, + ) -> thrift::Result<BTreeMap<String, String>> { + info!("testStringMap({:?})", thing); + Ok(thing) + } + + fn handle_test_set(&self, thing: BTreeSet<i32>) -> thrift::Result<BTreeSet<i32>> { + info!("testSet({:?})", thing); + Ok(thing) + } + + fn handle_test_list(&self, thing: Vec<i32>) -> thrift::Result<Vec<i32>> { + info!("testList({:?})", thing); + Ok(thing) + } + + fn handle_test_enum(&self, thing: Numberz) -> thrift::Result<Numberz> { + info!("testEnum({:?})", thing); + Ok(thing) + } + + fn handle_test_typedef(&self, thing: UserId) -> thrift::Result<UserId> { + info!("testTypedef({})", thing); + Ok(thing) + } + + /// @return map<i32,map<i32,i32>> - returns a dictionary with these values: + /// {-4 => {-4 => -4, -3 => -3, -2 => -2, -1 => -1, }, 4 => {1 => 1, 2 => + /// 2, 3 => 3, 4 => 4, }, } + fn handle_test_map_map(&self, hello: i32) -> thrift::Result<BTreeMap<i32, BTreeMap<i32, i32>>> { + info!("testMapMap({})", hello); + + let mut inner_map_0: BTreeMap<i32, i32> = BTreeMap::new(); + for i in -4..(0 as i32) { + inner_map_0.insert(i, i); + } + + let mut inner_map_1: BTreeMap<i32, i32> = BTreeMap::new(); + for i in 1..5 { + inner_map_1.insert(i, i); + } + + let mut ret_map: BTreeMap<i32, BTreeMap<i32, i32>> = BTreeMap::new(); + ret_map.insert(-4, inner_map_0); + ret_map.insert(4, inner_map_1); + + Ok(ret_map) + } + + /// Creates a the returned map with these values and prints it out: + /// { 1 => { 2 => argument, + /// 3 => argument, + /// }, + /// 2 => { 6 => <empty Insanity struct>, }, + /// } + /// return map<UserId, map<Numberz,Insanity>> - a map with the above values + fn handle_test_insanity( + &self, + argument: Insanity, + ) -> thrift::Result<BTreeMap<UserId, BTreeMap<Numberz, Insanity>>> { + info!("testInsanity({:?})", argument); + let mut map_0: BTreeMap<Numberz, Insanity> = BTreeMap::new(); + map_0.insert(Numberz::Two, argument.clone()); + map_0.insert(Numberz::Three, argument.clone()); + + let mut map_1: BTreeMap<Numberz, Insanity> = BTreeMap::new(); + let insanity = Insanity { + user_map: None, + xtructs: None, + }; + map_1.insert(Numberz::Six, insanity); + + let mut ret: BTreeMap<UserId, BTreeMap<Numberz, Insanity>> = BTreeMap::new(); + ret.insert(1, map_0); + ret.insert(2, map_1); + + Ok(ret) + } + + /// returns an Xtruct with: + /// string_thing = "Hello2", byte_thing = arg0, i32_thing = arg1 and + /// i64_thing = arg2 + fn handle_test_multi( + &self, + arg0: i8, + arg1: i32, + arg2: i64, + _: BTreeMap<i16, String>, + _: Numberz, + _: UserId, + ) -> thrift::Result<Xtruct> { + let x_ret = Xtruct { + string_thing: Some("Hello2".to_owned()), + byte_thing: Some(arg0), + i32_thing: Some(arg1), + i64_thing: Some(arg2), + }; + + Ok(x_ret) + } + + /// if arg == "Xception" throw Xception with errorCode = 1001 and message = + /// arg + /// else if arg == "TException" throw TException + /// else do not throw anything + fn handle_test_exception(&self, arg: String) -> thrift::Result<()> { + info!("testException({})", arg); + + match &*arg { + "Xception" => { + Err( + (Xception { + error_code: Some(1001), + message: Some(arg), + }) + .into(), + ) + } + "TException" => Err("this is a random error".into()), + _ => Ok(()), + } + } + + /// if arg0 == "Xception": + /// throw Xception with errorCode = 1001 and message = "This is an + /// Xception" + /// else if arg0 == "Xception2": + /// throw Xception2 with errorCode = 2002 and struct_thing.string_thing = + /// "This is an Xception2" + // else: + // do not throw anything and return Xtruct with string_thing = arg1 + fn handle_test_multi_exception(&self, arg0: String, arg1: String) -> thrift::Result<Xtruct> { + match &*arg0 { + "Xception" => { + Err( + (Xception { + error_code: Some(1001), + message: Some("This is an Xception".to_owned()), + }) + .into(), + ) + } + "Xception2" => { + Err( + (Xception2 { + error_code: Some(2002), + struct_thing: Some( + Xtruct { + string_thing: Some("This is an Xception2".to_owned()), + byte_thing: None, + i32_thing: None, + i64_thing: None, + }, + ), + }) + .into(), + ) + } + _ => { + Ok( + Xtruct { + string_thing: Some(arg1), + byte_thing: None, + i32_thing: None, + i64_thing: None, + }, + ) + } + } + } + + fn handle_test_oneway(&self, seconds_to_sleep: i32) -> thrift::Result<()> { + thread::sleep(Duration::from_secs(seconds_to_sleep as u64)); + Ok(()) + } +} + +struct SecondServiceSyncHandlerImpl; +impl SecondServiceSyncHandler for SecondServiceSyncHandlerImpl { + fn handle_secondtest_string(&self, thing: String) -> thrift::Result<String> { + info!("(second)testString({})", &thing); + let ret = format!("testString(\"{}\")", &thing); + Ok(ret) + } +} diff --git a/src/jaegertracing/thrift/test/rs/src/lib.rs b/src/jaegertracing/thrift/test/rs/src/lib.rs new file mode 100644 index 000000000..479bf9051 --- /dev/null +++ b/src/jaegertracing/thrift/test/rs/src/lib.rs @@ -0,0 +1,23 @@ +// 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. + +extern crate ordered_float; +extern crate thrift; +extern crate try_from; + +mod thrift_test; +pub use thrift_test::*; diff --git a/src/jaegertracing/thrift/test/test.py b/src/jaegertracing/thrift/test/test.py new file mode 100755 index 000000000..f59256a26 --- /dev/null +++ b/src/jaegertracing/thrift/test/test.py @@ -0,0 +1,192 @@ +#!/usr/bin/env python3 +# +# 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. +# + +# +# Apache Thrift - integration (cross) test suite +# +# tests different server-client, protocol and transport combinations +# +# This script requires python 3.x due to the improvements in +# subprocess management that are needed for reliability. +# + +from __future__ import print_function +from itertools import chain +import json +import logging +import multiprocessing +import argparse +import os +import sys + +import crossrunner +from crossrunner.compat import path_join + +# 3.3 introduced subprocess timeouts on waiting for child +req_version = (3, 3) +cur_version = sys.version_info +assert (cur_version >= req_version), "Python 3.3 or later is required for proper operation." + + +ROOT_DIR = os.path.dirname(os.path.realpath(os.path.dirname(__file__))) +TEST_DIR_RELATIVE = 'test' +TEST_DIR = path_join(ROOT_DIR, TEST_DIR_RELATIVE) +FEATURE_DIR_RELATIVE = path_join(TEST_DIR_RELATIVE, 'features') +CONFIG_FILE = 'tests.json' + + +def run_cross_tests(server_match, client_match, jobs, skip_known_failures, only_known_failures, retry_count, regex): + logger = multiprocessing.get_logger() + logger.debug('Collecting tests') + with open(path_join(TEST_DIR, CONFIG_FILE), 'r') as fp: + j = json.load(fp) + tests = crossrunner.collect_cross_tests(j, server_match, client_match, regex) + if not tests: + print('No test found that matches the criteria', file=sys.stderr) + print(' servers: %s' % server_match, file=sys.stderr) + print(' clients: %s' % client_match, file=sys.stderr) + return False + if only_known_failures: + logger.debug('Only running known failures') + known = crossrunner.load_known_failures(TEST_DIR) + tests = list(filter(lambda t: crossrunner.test_name(**t) in known, tests)) + if skip_known_failures: + logger.debug('Skipping known failures') + known = crossrunner.load_known_failures(TEST_DIR) + tests = list(filter(lambda t: crossrunner.test_name(**t) not in known, tests)) + + dispatcher = crossrunner.TestDispatcher(TEST_DIR, ROOT_DIR, TEST_DIR_RELATIVE, jobs) + logger.debug('Executing %d tests' % len(tests)) + try: + for r in [dispatcher.dispatch(test, retry_count) for test in tests]: + r.wait() + logger.debug('Waiting for completion') + return dispatcher.wait() + except (KeyboardInterrupt, SystemExit): + logger.debug('Interrupted, shutting down') + dispatcher.terminate() + return False + + +def run_feature_tests(server_match, feature_match, jobs, skip_known_failures, only_known_failures, retry_count, regex): + basedir = path_join(ROOT_DIR, FEATURE_DIR_RELATIVE) + logger = multiprocessing.get_logger() + logger.debug('Collecting tests') + with open(path_join(TEST_DIR, CONFIG_FILE), 'r') as fp: + j = json.load(fp) + with open(path_join(basedir, CONFIG_FILE), 'r') as fp: + j2 = json.load(fp) + tests = crossrunner.collect_feature_tests(j, j2, server_match, feature_match, regex) + if not tests: + print('No test found that matches the criteria', file=sys.stderr) + print(' servers: %s' % server_match, file=sys.stderr) + print(' features: %s' % feature_match, file=sys.stderr) + return False + if only_known_failures: + logger.debug('Only running known failures') + known = crossrunner.load_known_failures(basedir) + tests = list(filter(lambda t: crossrunner.test_name(**t) in known, tests)) + if skip_known_failures: + logger.debug('Skipping known failures') + known = crossrunner.load_known_failures(basedir) + tests = list(filter(lambda t: crossrunner.test_name(**t) not in known, tests)) + + dispatcher = crossrunner.TestDispatcher(TEST_DIR, ROOT_DIR, FEATURE_DIR_RELATIVE, jobs) + logger.debug('Executing %d tests' % len(tests)) + try: + for r in [dispatcher.dispatch(test, retry_count) for test in tests]: + r.wait() + logger.debug('Waiting for completion') + return dispatcher.wait() + except (KeyboardInterrupt, SystemExit): + logger.debug('Interrupted, shutting down') + dispatcher.terminate() + return False + + +def default_concurrenty(): + try: + return int(os.environ.get('THRIFT_CROSSTEST_CONCURRENCY')) + except (TypeError, ValueError): + # Since much time is spent sleeping, use many threads + return int(multiprocessing.cpu_count() * 1.25) + 1 + + +def main(argv): + parser = argparse.ArgumentParser() + parser.add_argument('--server', default='', nargs='*', + help='list of servers to test') + parser.add_argument('--client', default='', nargs='*', + help='list of clients to test') + parser.add_argument('-F', '--features', nargs='*', default=None, + help='run server feature tests instead of cross language tests') + parser.add_argument('-R', '--regex', help='test name pattern to run') + parser.add_argument('-o', '--only-known_failures', action='store_true', dest='only_known_failures', + help='only execute tests that are known to fail') + parser.add_argument('-s', '--skip-known-failures', action='store_true', dest='skip_known_failures', + help='do not execute tests that are known to fail') + parser.add_argument('-r', '--retry-count', type=int, + default=0, help='maximum retry on failure') + parser.add_argument('-j', '--jobs', type=int, + default=default_concurrenty(), + help='number of concurrent test executions') + + g = parser.add_argument_group(title='Advanced') + g.add_argument('-v', '--verbose', action='store_const', + dest='log_level', const=logging.DEBUG, default=logging.WARNING, + help='show debug output for test runner') + g.add_argument('-P', '--print-expected-failures', choices=['merge', 'overwrite'], + dest='print_failures', + help="generate expected failures based on last result and print to stdout") + g.add_argument('-U', '--update-expected-failures', choices=['merge', 'overwrite'], + dest='update_failures', + help="generate expected failures based on last result and save to default file location") + options = parser.parse_args(argv) + + logger = multiprocessing.log_to_stderr() + logger.setLevel(options.log_level) + + if options.features is not None and options.client: + print('Cannot specify both --features and --client ', file=sys.stderr) + return 1 + + # Allow multiple args separated with ',' for backward compatibility + server_match = list(chain(*[x.split(',') for x in options.server])) + client_match = list(chain(*[x.split(',') for x in options.client])) + + if options.update_failures or options.print_failures: + dire = path_join(ROOT_DIR, FEATURE_DIR_RELATIVE) if options.features is not None else TEST_DIR + res = crossrunner.generate_known_failures( + dire, options.update_failures == 'overwrite', + options.update_failures, options.print_failures) + elif options.features is not None: + features = options.features or ['.*'] + res = run_feature_tests(server_match, features, options.jobs, + options.skip_known_failures, options.only_known_failures, + options.retry_count, options.regex) + else: + res = run_cross_tests(server_match, client_match, options.jobs, + options.skip_known_failures, options.only_known_failures, + options.retry_count, options.regex) + return 0 if res else 1 + + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:])) diff --git a/src/jaegertracing/thrift/test/tests.json b/src/jaegertracing/thrift/test/tests.json new file mode 100644 index 000000000..78d4c0e9b --- /dev/null +++ b/src/jaegertracing/thrift/test/tests.json @@ -0,0 +1,758 @@ +[ + { + "name": "c_glib", + "platforms": [ + "Linux" + ], + "server": { + "command": [ + "test_server", + "--lt-debug" + ], + "protocols": [ + "binary:multi", + "compact:multic" + ] + }, + "client": { + "command": [ + "test_client", + "--lt-debug" + ], + "protocols": [ + "multi:binary", + "multic:compact" + ], + "sockets": [ + "ip-ssl" + ] + }, + "transports": [ + "buffered", + "framed" + ], + "sockets": [ + "ip", + "domain" + ], + "protocols": [ + "binary", + "compact", + "multi", + "multic" + ], + "workdir": "c_glib" + }, + { + "name": "cl", + "server": { + "command": ["TestServer"], + "workdir": "cl", + "protocols": ["binary", "multi"], + "transports": ["buffered", "framed"], + "sockets": ["ip"] + }, + "client": { + "command": ["TestClient"], + "workdir": "cl", + "protocols": ["binary", "multi"], + "transports": ["buffered", "framed"], + "sockets": ["ip"] + } + }, + { + "name": "d", + "server": { + "command": [ + "thrift_test_server", + "--trace" + ] + }, + "client": { + "command": [ + "thrift_test_client" + ] + }, + "transports": [ + "http", + "buffered", + "framed" + ], + "sockets": [ + "ip", + "ip-ssl" + ], + "protocols": [ + "binary", + "compact", + "json" + ], + "workdir": "../lib/d/test" + }, + { + "name": "go", + "server": { + "command": [ + "testserver", + "--certPath=../../keys" + ] + }, + "client": { + "timeout": 6, + "command": [ + "testclient" + ] + }, + "transports": [ + "buffered", + "framed", + "http", + "zlib" + ], + "sockets": [ + "ip", + "ip-ssl" + ], + "protocols": [ + "binary", + "compact", + "json", + "header" + ], + "workdir": "go/bin" + }, + { + "name": "java", + "join_args": false, + "server": { + "delay": 15, + "command": [ + "build/runserver" + ], + "protocols": [ + "binary:multi", + "compact:multic", + "json:multij" + ] + }, + "client": { + "timeout": 13, + "command": [ + "build/runclient" + ], + "transports": [ + "http" + ], + "protocols": [ + "multi:binary", + "multic:compact", + "multij:json" + ] + }, + "transports": [ + "buffered", + "framed", + "framed:fastframed" + ], + "sockets": [ + "ip", + "ip-ssl" + ], + "protocols": [ + "binary", + "compact", + "json", + "multi", + "multic", + "multij" + ], + "workdir": "../lib/java" + }, + { + "name": "nodejs", + "env": { + "NODE_PATH": "../lib" + }, + "server": { + "command": [ + "node", + "server.js", + "--type=tcp" + ] + }, + "client": { + "timeout": 6, + "command": [ + "node", + "client.js", + "--type=tcp" + ] + }, + "transports": [ + "buffered", + "framed", + "http" + ], + "sockets": [ + "ip", + "ip-ssl", + "domain" + ], + "protocols": [ + "compact", + "binary", + "json", + "header" + ], + "workdir": "../lib/nodejs/test" + }, + { + "name": "hs", + "server": { + "command": [ + "TestServer" + ] + }, + "client": { + "timeout": 6, + "transports": [ + "http" + ], + "command": [ + "TestClient" + ] + }, + "transports": [ + "buffered", + "framed" + ], + "sockets": [ + "ip" + ], + "protocols": [ + "header", + "compact", + "binary", + "json" + ], + "workdir": "hs" + }, + { + "name": "py", + "server": { + "extra_args": ["TSimpleServer"], + "command": [ + "TestServer.py", + "--verbose", + "--genpydir=gen-py" + ] + }, + "client": { + "timeout": 10, + "command": [ + "TestClient.py", + "--verbose", + "--host=localhost", + "--genpydir=gen-py" + ] + }, + "transports": [ + "buffered", + "framed", + "http", + "zlib" + ], + "sockets": [ + "ip", + "ip-ssl" + ], + "protocols": [ + "binary", + "binary:accel", + "compact", + "compact:accelc", + "header", + "json", + "multi", + "multi:multia", + "multia", + "multiac", + "multic", + "multic:multiac", + "multih", + "multij" + ], + "workdir": "py" + }, + { + "comment": "Using 'python3' executable to test py2 and 3 at once", + "name": "py3", + "server": { + "extra_args": ["TSimpleServer"], + "command": [ + "python3", + "TestServer.py", + "--verbose", + "--genpydir=gen-py" + ] + }, + "client": { + "timeout": 10, + "command": [ + "python3", + "TestClient.py", + "--host=localhost", + "--genpydir=gen-py" + ] + }, + "transports": [ + "buffered", + "framed", + "http", + "zlib" + ], + "sockets": [ + "ip", + "ip-ssl" + ], + "protocols": [ + "binary", + "binary:accel", + "compact", + "compact:accelc", + "header", + "json", + "multi", + "multi:multia", + "multia", + "multiac", + "multic", + "multic:multiac", + "multih", + "multij" + ], + "workdir": "py" + }, + { + "name": "cpp", + "server": { + "command": [ + "TestServer" + ], + "protocols": [ + "binary:multi", + "compact:multic", + "header:multih", + "json:multij" + ] + }, + "client": { + "timeout": 8, + "command": [ + "TestClient" + ], + "protocols": [ + "multi:binary", + "multic:compact", + "multih:header", + "multij:json" + ] + }, + "transports": [ + "buffered", + "http", + "framed", + "zlib" + ], + "sockets": [ + "ip", + "ip-ssl", + "domain" + ], + "protocols": [ + "compact", + "binary", + "json", + "header", + "multi", + "multic", + "multih", + "multij" + ], + "workdir": "cpp" + }, + { + "name": "rb", + "server": { + "command": [ + "ruby", + "../integration/TestServer.rb" + ] + }, + "client": { + "timeout": 10, + "command": [ + "ruby", + "../integration/TestClient.rb", + "--" + ] + }, + "transports": [ + "buffered", + "framed" + ], + "sockets": [ + "domain", + "ip", + "ip-ssl" + ], + "protocols": [ + "binary", + "binary:accel", + "compact", + "json" + ], + "workdir": "rb/gen-rb" + }, + { + "name": "csharp", + "env": { + "MONO_PATH": "../../lib/csharp/" + }, + "transports": [ + "buffered", + "framed" + ], + "sockets": [ + "ip", + "ip-ssl" + ], + "protocols": [ + "binary", + "compact", + "json" + ], + "server": { + "command": [ + "mono", + "TestClientServer.exe", + "server" + ] + }, + "client": { + "timeout": 9, + "command": [ + "mono", + "TestClientServer.exe", + "client" + ], + "protocols": [ + "multi", + "multic", + "multi:binary", + "multic:compact" + ] + }, + "workdir": "csharp" + }, + { + "name": "netcore", + "transports": [ + "buffered", + "framed" + ], + "sockets": [ + "ip", + "ip-ssl" + ], + "protocols": [ + "binary", + "compact", + "json" + ], + "server": { + "command": [ + "dotnet", + "run", + "--no-build", + "--project=Server/Server.csproj", + "server" + ] + }, + "client": { + "timeout": 10, + "command": [ + "dotnet", + "run", + "--no-build", + "--project=Client/Client.csproj", + "client" + ] + }, + "workdir": "netcore" + }, + { + "name": "perl", + "transports": [ + "buffered", + "framed" + ], + "sockets": [ + "ip", + "ip-ssl", + "domain" + ], + "protocols": [ + "binary", + "multi" + ], + "client": { + "command": [ + "perl", + "-Igen-perl/", + "-I../../lib/perl/lib/", + "TestClient.pl", + "--ca=../keys/CA.pem", + "--cert=../keys/client.crt", + "--key=../keys/client.key" + ], + "protocols": [ + "multi:binary" + ] + }, + "server": { + "command": [ + "perl", + "-Igen-perl/", + "-I../../lib/perl/lib/", + "TestServer.pl", + "--cert=../keys/server.crt", + "--key=../keys/server.key" + ], + "protocols": [ + "binary:multi" + ] + }, + "workdir": "perl" + }, + { + "name": "php", + "client": { + "timeout": 6, + "transports": [ + "buffered", + "framed" + ], + "sockets": [ + "ip" + ], + "protocols": [ + "binary", + "binary:accel", + "compact", + "json" + ], + "command": [ + "php", + "-dextension_dir=php_ext_dir", + "--php-ini=test_php.ini", + "--no-php-ini", + "-ddisplay_errors=stderr", + "-dlog_errors=0", + "-derror_reporting=E_ALL", + "TestClient.php" + ] + }, + "workdir": "php" + }, + { + "name": "dart", + "client": { + "timeout": 30, + "transports": [ + "buffered", + "framed", + "http" + ], + "sockets": [ + "ip" + ], + "protocols": [ + "binary", + "compact", + "json" + ], + "command": [ + "dart", + "--enable-asserts", + "test_client/bin/main.dart", + "--verbose" + ] + }, + "workdir": "dart" + }, + { + "name": "erl", + "transports": [ + "buffered", + "framed" + ], + "sockets": [ + "ip", + "ip-ssl" + ], + "protocols": [ + "binary", + "compact" + ], + "client": { + "command": [ + "erl", + "+K", + "true", + "-noshell", + "-pa", + "../../lib/erl/_build/default/lib/thrift/ebin/", + "-pa", + "./_build/default/lib/thrift_test/ebin", + "-s", + "test_client", + "-s", + "init", + "stop", + "-extra" + ] + }, + "server": { + "command": [ + "erl", + "+K", + "true", + "-noshell", + "-pa", + "../../lib/erl/_build/default/lib/thrift/ebin/", + "-pa", + "./_build/default/lib/thrift_test/ebin", + "-s", + "test_thrift_server", + "-extra" + ] + }, + "workdir": "erl" + }, + { + "name": "js", + "transports": [ + "http" + ], + "sockets": [ + "ip" + ], + "protocols": [ + "json" + ], + "client": { + "command": [ + "phantomjs", + "test/phantom-client.js" + ] + }, + "workdir": "../lib/js" + }, + { + "name": "lua", + "TODO": "Add dll to LUA_CPATH", + "env": { + "LUA_PATH": ";;gen-lua/?.lua;../../lib/lua/?.lua", + "LUA_CPATH": ";;../../lib/lua/.libs/?.so" + }, + "client": { + "timeout": 5, + "transports": [ + "buffered", + "framed", + "http" + ], + "sockets": [ + "ip" + ], + "protocols": [ + "binary", + "compact", + "json" + ], + "command": [ + "lua", + "test_basic_client.lua" + ] + }, + "workdir": "lua" + }, + { + "name": "rs", + "env": { + "RUST_BACKTRACE": "1", + "RUST_LOG": "info" + }, + "server": { + "command": [ + "test_server" + ], + "protocols": [ + "binary:multi", + "compact:multic" + ] + }, + "client": { + "timeout": 6, + "command": [ + "test_client" + ], + "protocols": [ + "multi:binary", + "multic:compact" + ] + }, + "sockets": [ + "ip" + ], + "transports": [ + "buffered", + "framed" + ], + "protocols": [ + "binary", + "compact", + "multi", + "multic" + ], + "workdir": "rs/bin" + }, + { + "name": "nodets", + "env": { + "NODE_PATH": "../lib" + }, + "server": { + "command": [ + "runServer.sh" + ] + }, + "client": { + "timeout": 6, + "command": [ + "runClient.sh" + ] + }, + "protocols": [ + "binary" + ], + "sockets": [ + "ip" + ], + "transports": [ + "buffered" + ], + "workdir": "../lib/nodets/test" + } +] diff --git a/src/jaegertracing/thrift/test/threads/Makefile b/src/jaegertracing/thrift/test/threads/Makefile new file mode 100644 index 000000000..df7239691 --- /dev/null +++ b/src/jaegertracing/thrift/test/threads/Makefile @@ -0,0 +1,63 @@ +# +# 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. +# + +# Default target is everything + +ifndef thrift_home +thrift_home=../../ +endif #thrift_home + +target: all + +ifndef boost_home +boost_home=/usr/local/include/boost-1_33_1 +endif #boost_home +target: all + +include_paths = $(thrift_home)/lib/cpp/src \ + $(boost_home) + +include_flags = $(patsubst %,-I%, $(include_paths)) + +# Tools +ifndef THRIFT +THRIFT = ../../compiler/cpp/thrift +endif # THRIFT + +CC = g++ +LD = g++ + +# Compiler flags +LFL = -L$(thrift_home)/lib/cpp/.libs -lthrift +CCFL = -Wall -O3 -g -I./gen-cpp $(include_flags) +CFL = $(CCFL) $(LFL) + +all: server client + +stubs: ThreadsTest.thrift + $(THRIFT) --gen cpp --gen py ThreadsTest.thrift + +server: stubs + $(CC) -o ThreadsServer $(CFL) ThreadsServer.cpp ./gen-cpp/ThreadsTest.cpp ./gen-cpp/ThreadsTest_types.cpp + +client: stubs + $(CC) -o ThreadsClient $(CFL) ThreadsClient.cpp ./gen-cpp/ThreadsTest.cpp ./gen-cpp/ThreadsTest_types.cpp + +clean: + $(RM) -r *.o ThreadsServer ThreadsClient gen-cpp gen-py diff --git a/src/jaegertracing/thrift/test/threads/ThreadsClient.cpp b/src/jaegertracing/thrift/test/threads/ThreadsClient.cpp new file mode 100644 index 000000000..e8bd79e69 --- /dev/null +++ b/src/jaegertracing/thrift/test/threads/ThreadsClient.cpp @@ -0,0 +1,69 @@ +/* + * 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. + */ + +// This autogenerated skeleton file illustrates how to build a server. +// You should copy it to another filename to avoid overwriting it. + +#include "ThreadsTest.h" +#include <thrift/protocol/TBinaryProtocol.h> +#include <thrift/server/TThreadPoolServer.h> +#include <thrift/transport/TSocket.h> +#include <thrift/transport/TTransportUtils.h> +#include <thrift/concurrency/Monitor.h> +#include <thrift/concurrency/ThreadManager.h> +#include <thrift/concurrency/ThreadFactory.h> +#if _WIN32 + #include <thrift/windows/TWinsockSingleton.h> +#endif + +using boost::shared_ptr; +using namespace apache::thrift; +using namespace apache::thrift::protocol; +using namespace apache::thrift::transport; +using namespace apache::thrift::server; +using namespace apache::thrift::concurrency; + +int main(int argc, char **argv) { +#if _WIN32 + transport::TWinsockSingleton::create(); +#endif + int port = 9090; + std::string host = "localhost"; + + shared_ptr<TTransport> transport(new TSocket(host, port)); + shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport)); + + transport->open(); + + ThreadsTestClient client(protocol); + int val; + val = client.threadOne(5); + fprintf(stderr, "%d\n", val); + val = client.stop(); + fprintf(stderr, "%d\n", val); + val = client.threadTwo(5); + fprintf(stderr, "%d\n", val); + + transport->close(); + + fprintf(stderr, "done.\n"); + + return 0; +} + diff --git a/src/jaegertracing/thrift/test/threads/ThreadsServer.cpp b/src/jaegertracing/thrift/test/threads/ThreadsServer.cpp new file mode 100644 index 000000000..3811b60c5 --- /dev/null +++ b/src/jaegertracing/thrift/test/threads/ThreadsServer.cpp @@ -0,0 +1,148 @@ +/* + * 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. + */ + +// This autogenerated skeleton file illustrates how to build a server. +// You should copy it to another filename to avoid overwriting it. + +#include "ThreadsTest.h" +#include <thrift/protocol/TBinaryProtocol.h> +#include <thrift/server/TThreadPoolServer.h> +#include <thrift/server/TThreadedServer.h> +#include <thrift/transport/TServerSocket.h> +#include <thrift/transport/TTransportUtils.h> +#include <thrift/concurrency/Monitor.h> +#include <thrift/concurrency/ThreadManager.h> +#include <thrift/concurrency/ThreadFactory.h> +#if _WIN32 + #include <thrift/windows/TWinsockSingleton.h> +#endif + +using boost::shared_ptr; +using namespace apache::thrift; +using namespace apache::thrift::protocol; +using namespace apache::thrift::transport; +using namespace apache::thrift::server; +using namespace apache::thrift::concurrency; + + +class ThreadsTestHandler : virtual public ThreadsTestIf { + public: + ThreadsTestHandler() { + // Your initialization goes here + } + + int32_t threadOne(const int32_t sleep) { + // Your implementation goes here + printf("threadOne\n"); + go2sleep(1, sleep); + return 1; + } + + int32_t threadTwo(const int32_t sleep) { + // Your implementation goes here + printf("threadTwo\n"); + go2sleep(2, sleep); + return 1; + } + + int32_t threadThree(const int32_t sleep) { + // Your implementation goes here + printf("threadThree\n"); + go2sleep(3, sleep); + return 1; + } + + int32_t threadFour(const int32_t sleep) { + // Your implementation goes here + printf("threadFour\n"); + go2sleep(4, sleep); + return 1; + } + + int32_t stop() { + printf("stop\n"); + server_->stop(); + return 1; + } + + void setServer(boost::shared_ptr<TServer> server) { + server_ = server; + } + +protected: + void go2sleep(int thread, int seconds) { + Monitor m; + Synchronized s(m); + for (int i = 0; i < seconds; ++i) { + fprintf(stderr, "Thread %d: sleep %d\n", thread, i); + try { + m.wait(1000); + } catch(const TimedOutException&) { + } + } + fprintf(stderr, "THREAD %d DONE\n", thread); + } + +private: + boost::shared_ptr<TServer> server_; + +}; + +int main(int argc, char **argv) { +#if _WIN32 + transport::TWinsockSingleton::create(); +#endif + int port = 9090; + shared_ptr<ThreadsTestHandler> handler(new ThreadsTestHandler()); + shared_ptr<TProcessor> processor(new ThreadsTestProcessor(handler)); + shared_ptr<TServerTransport> serverTransport(new TServerSocket(port)); + shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory()); + shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory()); + + /* + shared_ptr<ThreadManager> threadManager = + ThreadManager::newSimpleThreadManager(10); + shared_ptr<ThreadFactory> threadFactory = + shared_ptr<ThreadFactory>(new ThreadFactory()); + threadManager->threadFactory(threadFactory); + threadManager->start(); + + shared_ptr<TServer> server = + shared_ptr<TServer>(new TThreadPoolServer(processor, + serverTransport, + transportFactory, + protocolFactory, + threadManager)); + */ + + shared_ptr<TServer> server = + shared_ptr<TServer>(new TThreadedServer(processor, + serverTransport, + transportFactory, + protocolFactory)); + + handler->setServer(server); + + server->serve(); + + fprintf(stderr, "done.\n"); + + return 0; +} + diff --git a/src/jaegertracing/thrift/test/threads/ThreadsTest.thrift b/src/jaegertracing/thrift/test/threads/ThreadsTest.thrift new file mode 100644 index 000000000..caa934605 --- /dev/null +++ b/src/jaegertracing/thrift/test/threads/ThreadsTest.thrift @@ -0,0 +1,28 @@ +/* + * 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. + */ + +service ThreadsTest { + i32 threadOne(1: i32 sleep=15), + i32 threadTwo(2: i32 sleep=15), + i32 threadThree(3: i32 sleep=15), + i32 threadFour(4: i32 sleep=15) + + i32 stop(); + +} diff --git a/src/jaegertracing/thrift/test/valgrind.suppress b/src/jaegertracing/thrift/test/valgrind.suppress new file mode 100644 index 000000000..de17cb8d8 --- /dev/null +++ b/src/jaegertracing/thrift/test/valgrind.suppress @@ -0,0 +1,53 @@ +{ + boost/get_once_per_thread_epoch/ignore + Memcheck:Leak + match-leak-kinds: reachable + fun:malloc + fun:_ZN5boost6detail25get_once_per_thread_epochEv +} +{ + boostthreads/once/ignore + Helgrind:Race + fun:_ZN5boost13thread_detail17enter_once_regionERNS_9once_flagE + fun:_ZN5boost6detail23get_current_thread_dataEv + fun:_ZN5boost6detail20interruption_checkerC1EP15pthread_mutex_tP14pthread_cond_t + fun:_ZN5boost22condition_variable_any4waitINS_11unique_lockINS_11timed_mutexEEEEEvRT_ + fun:_ZN6apache6thrift11concurrency7Monitor4Impl11waitForeverEv + fun:_ZN6apache6thrift11concurrency7Monitor4Impl19waitForTimeRelativeEl + fun:_ZN6apache6thrift11concurrency7Monitor4Impl4waitEl + fun:_ZNK6apache6thrift11concurrency7Monitor4waitEl + fun:_ZN6apache6thrift11concurrency11BoostThread5startEv + fun:_ZN6apache6thrift11concurrency4test18ThreadFactoryTests12reapNThreadsEii + fun:main +} +{ + pthread/creation-tls/ignore + Helgrind:Race + fun:mempcpy + fun:_dl_allocate_tls_init + fun:get_cached_stack + fun:allocate_stack + fun:pthread_create@@GLIBC_2.2* + obj:/usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so + fun:_ZN6apache6thrift11concurrency13PthreadThread5startEv + fun:_ZN6apache6thrift11concurrency4test18ThreadFactoryTests12reapNThreadsEii + fun:main +} +{ + boost-thread/creation-tls/ignore + Helgrind:Race + fun:mempcpy + fun:_dl_allocate_tls_init + fun:get_cached_stack + fun:allocate_stack + fun:pthread_create@@GLIBC_2.2.5 + obj:/usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so + fun:_ZN5boost6thread21start_thread_noexceptEv + fun:_ZN5boost6thread12start_threadEv + fun:_ZN5boost6threadC1ISt5_BindIFPFPvS3_ES3_EEEEOT_ + fun:_ZN6apache6thrift11concurrency11BoostThread5startEv + fun:_ZN6apache6thrift11concurrency4test18ThreadFactoryTests12reapNThreadsEii + fun:main +} + + |