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/lib/dart/test | |
parent | Initial commit. (diff) | |
download | ceph-upstream.tar.xz ceph-upstream.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 'src/jaegertracing/thrift/lib/dart/test')
8 files changed, 1604 insertions, 0 deletions
diff --git a/src/jaegertracing/thrift/lib/dart/test/protocol/t_protocol_test.dart b/src/jaegertracing/thrift/lib/dart/test/protocol/t_protocol_test.dart new file mode 100644 index 000000000..dc63dbb71 --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/test/protocol/t_protocol_test.dart @@ -0,0 +1,406 @@ +// 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. + +library thrift.test.transport.t_json_protocol_test; + +import 'dart:async'; +import 'dart:typed_data' show Uint8List; + +import 'package:dart2_constant/convert.dart' show utf8; +import 'package:test/test.dart'; +import 'package:thrift/thrift.dart'; + +void main() { + final message = new TMessage('my message', TMessageType.ONEWAY, 123); + + TProtocol protocol; + + Primitive getPrimitive(int tType) { + switch (tType) { + case TType.BOOL: + return new Primitive(protocol.readBool, protocol.writeBool, false); + + case TType.BYTE: + return new Primitive(protocol.readByte, protocol.writeByte, 0); + + case TType.I16: + return new Primitive(protocol.readI16, protocol.writeI16, 0); + + case TType.I32: + return new Primitive(protocol.readI32, protocol.writeI32, 0); + + case TType.I64: + return new Primitive(protocol.readI64, protocol.writeI64, 0); + + case TType.DOUBLE: + return new Primitive(protocol.readDouble, protocol.writeDouble, 0); + + case TType.STRING: + return new Primitive(protocol.readString, protocol.writeString, ''); + + default: + throw new UnsupportedError("Unsupported TType $tType"); + } + } + + Future primitiveTest(Primitive primitive, input) async { + primitive.write(input); + protocol.writeMessageEnd(); + + await protocol.transport.flush(); + + protocol.readMessageBegin(); + var output = primitive.read(); + + expect(output, input); + } + + Future primitiveNullTest(Primitive primitive) async { + primitive.write(null); + protocol.writeMessageEnd(); + + await protocol.transport.flush(); + + protocol.readMessageBegin(); + var output = primitive.read(); + + expect(output, primitive.defaultValue); + } + + var sharedTests = () { + test('Test message', () async { + protocol.writeMessageEnd(); + + await protocol.transport.flush(); + + var subject = protocol.readMessageBegin(); + + expect(subject.name, message.name); + expect(subject.type, message.type); + expect(subject.seqid, message.seqid); + }); + + test('Test struct', () async { + var input = new TStruct(); + + protocol.writeStructBegin(input); + protocol.writeStructEnd(); + protocol.writeMessageEnd(); + + await protocol.transport.flush(); + + protocol.readMessageBegin(); + var output = protocol.readStructBegin(); + + // name is not serialized, see C# version for reference + expect(output, isNotNull); + }); + + test('Test field', () async { + var input = new TField('my field', TType.MAP, 123); + + protocol.writeFieldBegin(input); + protocol.writeFieldEnd(); + protocol.writeMessageEnd(); + + await protocol.transport.flush(); + + protocol.readMessageBegin(); + var output = protocol.readFieldBegin(); + + // name is not serialized, see C# version for reference + expect(output.type, input.type); + expect(output.id, input.id); + }); + + test('Test map', () async { + var input = new TMap(TType.STRING, TType.STRUCT, 123); + + protocol.writeMapBegin(input); + protocol.writeMapEnd(); + protocol.writeMessageEnd(); + + await protocol.transport.flush(); + + protocol.readMessageBegin(); + var output = protocol.readMapBegin(); + + expect(output.keyType, input.keyType); + expect(output.valueType, input.valueType); + expect(output.length, input.length); + }); + + test('Test list', () async { + var input = new TList(TType.STRING, 123); + + protocol.writeListBegin(input); + protocol.writeListEnd(); + protocol.writeMessageEnd(); + + await protocol.transport.flush(); + + protocol.readMessageBegin(); + var output = protocol.readListBegin(); + + expect(output.elementType, input.elementType); + expect(output.length, input.length); + }); + + test('Test set', () async { + var input = new TSet(TType.STRING, 123); + + protocol.writeSetBegin(input); + protocol.writeSetEnd(); + protocol.writeMessageEnd(); + + await protocol.transport.flush(); + + protocol.readMessageBegin(); + var output = protocol.readListBegin(); + + expect(output.elementType, input.elementType); + expect(output.length, input.length); + }); + + test('Test bool', () async { + await primitiveTest(getPrimitive(TType.BOOL), true); + }); + + test('Test bool null', () async { + await primitiveNullTest(getPrimitive(TType.BOOL)); + }); + + test('Test byte', () async { + await primitiveTest(getPrimitive(TType.BYTE), 64); + }); + + test('Test byte null', () async { + await primitiveNullTest(getPrimitive(TType.BYTE)); + }); + + test('Test I16', () async { + await primitiveTest(getPrimitive(TType.I16), 32767); + }); + + test('Test I16 null', () async { + await primitiveNullTest(getPrimitive(TType.I16)); + }); + + test('Test I32', () async { + await primitiveTest(getPrimitive(TType.I32), 2147483647); + }); + + test('Test I32 null', () async { + await primitiveNullTest(getPrimitive(TType.I32)); + }); + + test('Test I64', () async { + await primitiveTest(getPrimitive(TType.I64), 9223372036854775807); + }); + + test('Test I64 null', () async { + await primitiveNullTest(getPrimitive(TType.I64)); + }); + + test('Test double', () async { + await primitiveTest(getPrimitive(TType.DOUBLE), 3.1415926); + }); + + test('Test double null', () async { + await primitiveNullTest(getPrimitive(TType.DOUBLE)); + }); + + test('Test string', () async { + var input = 'There are only two hard things in computer science: ' + 'cache invalidation, naming things, and off-by-one errors.'; + await primitiveTest(getPrimitive(TType.STRING), input); + }); + + test('Test string null', () async { + await primitiveNullTest(getPrimitive(TType.STRING)); + }); + + test('Test binary', () async { + var input = new Uint8List.fromList(new List.filled(100, 123)); + + protocol.writeBinary(input); + protocol.writeMessageEnd(); + + await protocol.transport.flush(); + + protocol.readMessageBegin(); + var output = protocol.readBinary(); + + expect(output.length, input.length); + expect(output.every((i) => i == 123), isTrue); + }); + + test('Test complex struct', () async { + // {1: {10: 20}, 2: {30: 40}} + protocol.writeStructBegin(new TStruct()); + protocol.writeFieldBegin(new TField('success', TType.MAP, 0)); + protocol.writeMapBegin(new TMap(TType.I32, TType.MAP, 2)); + + protocol.writeI32(1); // key + protocol.writeMapBegin(new TMap(TType.I32, TType.I32, 1)); + protocol.writeI32(10); // key + protocol.writeI32(20); // value + protocol.writeMapEnd(); + + protocol.writeI32(2); // key + protocol.writeMapBegin(new TMap(TType.I32, TType.I32, 1)); + protocol.writeI32(30); // key + protocol.writeI32(40); // value + protocol.writeMapEnd(); + + protocol.writeMapEnd(); + protocol.writeFieldEnd(); + protocol.writeFieldStop(); + protocol.writeStructEnd(); + protocol.writeMessageEnd(); + + await protocol.transport.flush(); + + protocol.readMessageBegin(); + protocol.readStructBegin(); + expect(protocol.readFieldBegin().type, TType.MAP); + expect(protocol.readMapBegin().length, 2); + + expect(protocol.readI32(), 1); // key + expect(protocol.readMapBegin().length, 1); + expect(protocol.readI32(), 10); // key + expect(protocol.readI32(), 20); // value + protocol.readMapEnd(); + + expect(protocol.readI32(), 2); // key + expect(protocol.readMapBegin().length, 1); + expect(protocol.readI32(), 30); // key + expect(protocol.readI32(), 40); // value + protocol.readMapEnd(); + + protocol.readMapEnd(); + protocol.readFieldEnd(); + protocol.readStructEnd(); + protocol.readMessageEnd(); + }); + + test('Test nested maps and lists', () async { + // {1: [{10: 20}], 2: [{30: 40}]} + protocol.writeMapBegin(new TMap(TType.I32, TType.LIST, 2)); + + protocol.writeI32(1); // key + protocol.writeListBegin(new TList(TType.MAP, 1)); + protocol.writeMapBegin(new TMap(TType.I32, TType.I32, 1)); + protocol.writeI32(10); // key + protocol.writeI32(20); // value + protocol.writeMapEnd(); + protocol.writeListEnd(); + + protocol.writeI32(2); // key + protocol.writeListBegin(new TList(TType.MAP, 1)); + protocol.writeMapBegin(new TMap(TType.I32, TType.I32, 1)); + protocol.writeI32(30); // key + protocol.writeI32(40); // value + protocol.writeMapEnd(); + protocol.writeListEnd(); + + protocol.writeMapEnd(); + protocol.writeMessageEnd(); + + await protocol.transport.flush(); + + protocol.readMessageBegin(); + expect(protocol.readMapBegin().length, 2); + + expect(protocol.readI32(), 1); // key + expect(protocol.readListBegin().length, 1); + expect(protocol.readMapBegin().length, 1); + expect(protocol.readI32(), 10); // key + expect(protocol.readI32(), 20); // value + protocol.readMapEnd(); + protocol.readListEnd(); + + expect(protocol.readI32(), 2); // key + expect(protocol.readListBegin().length, 1); + expect(protocol.readMapBegin().length, 1); + expect(protocol.readI32(), 30); // key + expect(protocol.readI32(), 40); // value + protocol.readMapEnd(); + protocol.readListEnd(); + + protocol.readMapEnd(); + protocol.readMessageEnd(); + }); + }; + + group('JSON', () { + setUp(() { + protocol = new TJsonProtocol(new TBufferedTransport()); + protocol.writeMessageBegin(message); + }); + + test('Test escaped unicode', () async { + /* + KOR_KAI + UTF-8: 0xE0 0xB8 0x81 + UTF-16: 0x0E01 + G clef: + UTF-8: 0xF0 0x9D 0x84 0x9E + UTF-16: 0xD834 0xDD1E + */ + var buffer = utf8.encode(r'"\u0001\u0e01 \ud834\udd1e"'); + var transport = new TBufferedTransport(); + transport.writeAll(buffer); + + var protocol = new TJsonProtocol(transport); + + await protocol.transport.flush(); + + var subject = protocol.readString(); + expect(subject, + utf8.decode([0x01, 0xE0, 0xB8, 0x81, 0x20, 0xF0, 0x9D, 0x84, 0x9E])); + }); + + group('shared tests', sharedTests); + }); + + group('binary', () { + setUp(() { + protocol = new TBinaryProtocol(new TBufferedTransport()); + protocol.writeMessageBegin(message); + }); + + group('shared tests', sharedTests); + }); + + group('compact', () { + setUp(() { + protocol = new TCompactProtocol(new TBufferedTransport()); + protocol.writeMessageBegin(message); + }); + + group('shared tests', sharedTests); + }); +} + +class Primitive { + final Function read; + final Function write; + final defaultValue; + + Primitive(this.read, this.write, this.defaultValue); +} diff --git a/src/jaegertracing/thrift/lib/dart/test/serializer/serializer_test.dart b/src/jaegertracing/thrift/lib/dart/test/serializer/serializer_test.dart new file mode 100644 index 000000000..2f76503c4 --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/test/serializer/serializer_test.dart @@ -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. + */ + +library thrift.test.serializer.serializer_test; + +import 'package:test/test.dart'; +import 'package:thrift/thrift.dart'; +import 'serializer_test_data.dart'; + +void main() { + var serializer = () { + TDeserializer deserializer; + TSerializer serializer; + TestTObject testTObject; + + setUp(() { + serializer = new TSerializer(); + deserializer = new TDeserializer(); + + testTObject = new TestTObject(); + testTObject.b = true; + testTObject.s = "TEST"; + testTObject.d = 15.25; + testTObject.i = 10; + + var testList = new List<String>(); + testList.add("TEST 1"); + testList.add("TEST 2"); + + testTObject.l = testList; + }); + + assertNewObjectEqualsTObject(TestTObject newObject) { + expect(newObject.l, equals(testTObject.l)); + expect(newObject.b, equals(testTObject.b)); + expect(newObject.i, equals(testTObject.i)); + expect(newObject.d, equals(testTObject.d)); + expect(newObject.s, equals(testTObject.s)); + } + + runWriteStringTest() { + var s = serializer.writeString(testTObject); + + var newObject = new TestTObject(); + deserializer.readString(newObject, s); + + assertNewObjectEqualsTObject(newObject); + }; + + runWriteTest() { + var s = serializer.write(testTObject); + + var newObject = new TestTObject(); + deserializer.read(newObject, s); + + assertNewObjectEqualsTObject(newObject); + }; + + test('JSON Protocol String', () { + serializer.protocol = new TJsonProtocol(serializer.transport); + deserializer.protocol = new TJsonProtocol(deserializer.transport); + + runWriteStringTest(); + }); + + test('JSON Protocol', () { + serializer.protocol = new TJsonProtocol(serializer.transport); + deserializer.protocol = new TJsonProtocol(deserializer.transport); + + runWriteTest(); + }); + + test('Binary Protocol String', () { + serializer.protocol = new TBinaryProtocol(serializer.transport); + deserializer.protocol = new TBinaryProtocol(deserializer.transport); + + runWriteStringTest(); + }); + + test('Binary Protocol', () { + serializer.protocol = new TBinaryProtocol(serializer.transport); + deserializer.protocol = new TBinaryProtocol(deserializer.transport); + + runWriteTest(); + }); + + test('Compact Protocol String', () { + serializer.protocol = new TCompactProtocol(serializer.transport); + deserializer.protocol = new TCompactProtocol(deserializer.transport); + + runWriteStringTest(); + }); + + test('Compact Protocol', () { + serializer.protocol = new TCompactProtocol(serializer.transport); + deserializer.protocol = new TCompactProtocol(deserializer.transport); + + runWriteTest(); + }); + }; + + group('Serializer', serializer); +} diff --git a/src/jaegertracing/thrift/lib/dart/test/serializer/serializer_test_data.dart b/src/jaegertracing/thrift/lib/dart/test/serializer/serializer_test_data.dart new file mode 100644 index 000000000..3586f08fc --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/test/serializer/serializer_test_data.dart @@ -0,0 +1,342 @@ +/* + * 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. + */ + +library thrift.test.serializer.serializer_test; + +import 'package:thrift/thrift.dart'; + +/// TestTObject is a simple test struct +class TestTObject implements TBase { + static final TStruct _STRUCT_DESC = new TStruct("TestTObject"); + static final TField _I_FIELD_DESC = new TField("i", TType.I32, 1); + static final TField _D_FIELD_DESC = new TField("d", TType.DOUBLE, 2); + static final TField _S_FIELD_DESC = new TField("s", TType.STRING, 3); + static final TField _L_FIELD_DESC = new TField("l", TType.LIST, 4); + static final TField _B_FIELD_DESC = new TField("b", TType.BOOL, 5); + + int _i; + static const int I = 1; + double _d; + static const int D = 2; + String _s; + static const int S = 3; + List<String> _l; + static const int L = 4; + bool _b; + static const int B = 5; + + bool __isset_i = false; + bool __isset_d = false; + bool __isset_b = false; + + TestTObject() { + } + + // i + int get i => this._i; + + set i(int i) { + this._i = i; + this.__isset_i = true; + } + + bool isSetI() => this.__isset_i; + + unsetI() { + this.__isset_i = false; + } + + // d + double get d => this._d; + + set d(double d) { + this._d = d; + this.__isset_d = true; + } + + bool isSetD() => this.__isset_d; + + unsetD() { + this.__isset_d = false; + } + + // s + String get s => this._s; + + set s(String s) { + this._s = s; + } + + bool isSetS() => this.s != null; + + unsetS() { + this.s = null; + } + + // l + List<String> get l => this._l; + + set l(List<String> l) { + this._l = l; + } + + bool isSetL() => this.l != null; + + unsetL() { + this.l = null; + } + + // b + bool get b => this._b; + + set b(bool b) { + this._b = b; + this.__isset_b = true; + } + + bool isSetB() => this.__isset_b; + + unsetB() { + this.__isset_b = false; + } + + getFieldValue(int fieldID) { + switch (fieldID) { + case I: + return this.i; + case D: + return this.d; + case S: + return this.s; + case L: + return this.l; + case B: + return this.b; + default: + throw new ArgumentError("Field $fieldID doesn't exist!"); + } + } + + setFieldValue(int fieldID, Object value) { + switch (fieldID) { + case I: + if (value == null) { + unsetI(); + } else { + this.i = value; + } + break; + + case D: + if (value == null) { + unsetD(); + } else { + this.d = value; + } + break; + + case S: + if (value == null) { + unsetS(); + } else { + this.s = value; + } + break; + + case L: + if (value == null) { + unsetL(); + } else { + this.l = value as List<String>; + } + break; + + case B: + if (value == null) { + unsetB(); + } else { + this.b = value; + } + break; + + default: + throw new ArgumentError("Field $fieldID doesn't exist!"); + } + } + + // Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise + bool isSet(int fieldID) { + switch (fieldID) { + case I: + return isSetI(); + case D: + return isSetD(); + case S: + return isSetS(); + case L: + return isSetL(); + case B: + return isSetB(); + default: + throw new ArgumentError("Field $fieldID doesn't exist!"); + } + } + + read(TProtocol iprot) { + TField field; + iprot.readStructBegin(); + while (true) { + field = iprot.readFieldBegin(); + if (field.type == TType.STOP) { + break; + } + switch (field.id) { + case I: + if (field.type == TType.I32) { + this.i = iprot.readI32(); + this.__isset_i = true; + } else { + TProtocolUtil.skip(iprot, field.type); + } + break; + case D: + if (field.type == TType.DOUBLE) { + this.d = iprot.readDouble(); + this.__isset_d = true; + } else { + TProtocolUtil.skip(iprot, field.type); + } + break; + case S: + if (field.type == TType.STRING) { + this.s = iprot.readString(); + } else { + TProtocolUtil.skip(iprot, field.type); + } + break; + case L: + if (field.type == TType.LIST) { + { + TList _list74 = iprot.readListBegin(); + this.l = new List<String>(); + for (int _i75 = 0; _i75 < _list74.length; ++_i75) { + String _elem76; + _elem76 = iprot.readString(); + this.l.add(_elem76); + } + iprot.readListEnd(); + } + } else { + TProtocolUtil.skip(iprot, field.type); + } + break; + case B: + if (field.type == TType.BOOL) { + this.b = iprot.readBool(); + this.__isset_b = true; + } else { + TProtocolUtil.skip(iprot, field.type); + } + break; + default: + TProtocolUtil.skip(iprot, field.type); + break; + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + validate(); + } + + write(TProtocol oprot) { + validate(); + + oprot.writeStructBegin(_STRUCT_DESC); + oprot.writeFieldBegin(_I_FIELD_DESC); + oprot.writeI32(this.i); + oprot.writeFieldEnd(); + oprot.writeFieldBegin(_D_FIELD_DESC); + oprot.writeDouble(this.d); + oprot.writeFieldEnd(); + if (this.s != null) { + oprot.writeFieldBegin(_S_FIELD_DESC); + oprot.writeString(this.s); + oprot.writeFieldEnd(); + } + if (this.l != null) { + oprot.writeFieldBegin(_L_FIELD_DESC); + { + oprot.writeListBegin(new TList(TType.STRING, this.l.length)); + for (var elem77 in this.l) { + oprot.writeString(elem77); + } + oprot.writeListEnd(); + } + oprot.writeFieldEnd(); + } + oprot.writeFieldBegin(_B_FIELD_DESC); + oprot.writeBool(this.b); + oprot.writeFieldEnd(); + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + String toString() { + StringBuffer ret = new StringBuffer("TestTObject("); + + ret.write("i:"); + ret.write(this.i); + + ret.write(", "); + ret.write("d:"); + ret.write(this.d); + + ret.write(", "); + ret.write("s:"); + if (this.s == null) { + ret.write("null"); + } else { + ret.write(this.s); + } + + ret.write(", "); + ret.write("l:"); + if (this.l == null) { + ret.write("null"); + } else { + ret.write(this.l); + } + + ret.write(", "); + ret.write("b:"); + ret.write(this.b); + + ret.write(")"); + + return ret.toString(); + } + + validate() { + // check for required fields + // check that fields of type enum have valid values + } + +} diff --git a/src/jaegertracing/thrift/lib/dart/test/t_application_error_test.dart b/src/jaegertracing/thrift/lib/dart/test/t_application_error_test.dart new file mode 100644 index 000000000..511d8d691 --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/test/t_application_error_test.dart @@ -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. + +library thrift.test.t_application_error_test; + +import 'package:test/test.dart'; +import 'package:thrift/thrift.dart'; + +void main() { + TProtocol protocol; + + setUp(() { + protocol = new TBinaryProtocol(new TBufferedTransport()); + }); + + test('Write and read an application error', () { + var expectedType = TApplicationErrorType.INTERNAL_ERROR; + var expectedMessage = 'test error message'; + + TApplicationError error = + new TApplicationError(expectedType, expectedMessage); + error.write(protocol); + + protocol.transport.flush(); + + TApplicationError subject = TApplicationError.read(protocol); + + expect(subject, isNotNull); + expect(subject.type, expectedType); + expect(subject.message, expectedMessage); + }); +} diff --git a/src/jaegertracing/thrift/lib/dart/test/transport/t_framed_transport_test.dart b/src/jaegertracing/thrift/lib/dart/test/transport/t_framed_transport_test.dart new file mode 100644 index 000000000..7ab490539 --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/test/transport/t_framed_transport_test.dart @@ -0,0 +1,175 @@ +// 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. + +library thrift.test.transport.t_framed_transport_test; + +import 'dart:async'; +import 'dart:typed_data' show Uint8List; + +import 'package:dart2_constant/convert.dart' show utf8; +import 'package:test/test.dart'; +import 'package:thrift/thrift.dart'; + +void main() { + group('TFramedTransport partial reads', () { + final flushAwaitDuration = new Duration(seconds: 10); + + FakeReadOnlySocket socket; + TSocketTransport socketTransport; + TFramedTransport transport; + var messageAvailable; + + setUp(() { + socket = new FakeReadOnlySocket(); + socketTransport = new TClientSocketTransport(socket); + transport = new TFramedTransport(socketTransport); + messageAvailable = false; + }); + + expectNoReadableBytes() { + var readBuffer = new Uint8List(128); + var readBytes = transport.read(readBuffer, 0, readBuffer.lengthInBytes); + expect(readBytes, 0); + expect(messageAvailable, false); + } + + test('Test transport reads messages where header and body are sent separately', () async { + // buffer into which we'll read + var readBuffer = new Uint8List(10); + var readBytes; + + // registers for readable bytes + var flushFuture = transport.flush().timeout(flushAwaitDuration); + flushFuture.then((_) { + messageAvailable = true; + }); + + // write header bytes + socket.messageController.add(new Uint8List.fromList([0x00, 0x00, 0x00, 0x06])); + + // you shouldn't be able to get any bytes from the read, + // because the header has been consumed internally + expectNoReadableBytes(); + + // write first batch of body + socket.messageController.add(new Uint8List.fromList(utf8.encode("He"))); + + // you shouldn't be able to get any bytes from the read, + // because the frame has been consumed internally + expectNoReadableBytes(); + + // write second batch of body + socket.messageController.add(new Uint8List.fromList(utf8.encode("llo!"))); + + // have to wait for the flush to complete, + // because it's only then that the frame is available for reading + await flushFuture; + expect(messageAvailable, true); + + // at this point the frame is complete, so we expect the read to complete + readBytes = transport.read(readBuffer, 0, readBuffer.lengthInBytes); + expect(readBytes, 6); + expect(readBuffer.sublist(0, 6), utf8.encode("Hello!")); + }); + + test('Test transport reads messages where header is sent in pieces ' + 'and body is also sent in pieces', () async { + // buffer into which we'll read + var readBuffer = new Uint8List(10); + var readBytes; + + // registers for readable bytes + var flushFuture = transport.flush().timeout(flushAwaitDuration); + flushFuture.then((_) { + messageAvailable = true; + }); + + // write first part of header bytes + socket.messageController.add(new Uint8List.fromList([0x00, 0x00])); + + // you shouldn't be able to get any bytes from the read + expectNoReadableBytes(); + + // write second part of header bytes + socket.messageController.add(new Uint8List.fromList([0x00, 0x03])); + + // you shouldn't be able to get any bytes from the read again + // because only the header was read, and there's no frame body + readBytes = expectNoReadableBytes(); + + // write first batch of body + socket.messageController.add(new Uint8List.fromList(utf8.encode("H"))); + + // you shouldn't be able to get any bytes from the read, + // because the frame has been consumed internally + expectNoReadableBytes(); + + // write second batch of body + socket.messageController.add(new Uint8List.fromList(utf8.encode("i!"))); + + // have to wait for the flush to complete, + // because it's only then that the frame is available for reading + await flushFuture; + expect(messageAvailable, true); + + // at this point the frame is complete, so we expect the read to complete + readBytes = transport.read(readBuffer, 0, readBuffer.lengthInBytes); + expect(readBytes, 3); + expect(readBuffer.sublist(0, 3), utf8.encode("Hi!")); + }); + }); +} + + + +class FakeReadOnlySocket extends TSocket { + + StreamController<Uint8List> messageController = new StreamController<Uint8List>(sync: true); + StreamController<Object> errorController = new StreamController<Object>(); + StreamController<TSocketState> stateController = new StreamController<TSocketState>(); + + @override + Future close() { + // noop + } + + @override + bool get isClosed => false; + + @override + bool get isOpen => true; + + @override + Stream<Object> get onError => errorController.stream; + + @override + Stream<Uint8List> get onMessage => messageController.stream; + + @override + Stream<TSocketState> get onState => stateController.stream; + + @override + Future open() { + // noop + } + + @override + void send(Uint8List data) { + // noop + } +} + diff --git a/src/jaegertracing/thrift/lib/dart/test/transport/t_http_transport_test.dart b/src/jaegertracing/thrift/lib/dart/test/transport/t_http_transport_test.dart new file mode 100644 index 000000000..03ccede9a --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/test/transport/t_http_transport_test.dart @@ -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. + +library thrift.test.transport.t_socket_transport_test; + +import 'dart:async'; +import 'dart:convert' show Encoding; +import 'dart:convert' show Utf8Codec; +import 'dart:typed_data' show Uint8List; + +import 'package:dart2_constant/convert.dart' show base64; +import 'package:http/http.dart' show BaseRequest; +import 'package:http/http.dart' show Client; +import 'package:http/http.dart' show Response; +import 'package:http/http.dart' show StreamedResponse; +import 'package:test/test.dart'; +import 'package:thrift/thrift.dart'; + +void main() { + const utf8Codec = const Utf8Codec(); + + group('THttpClientTransport', () { + FakeHttpClient client; + THttpClientTransport transport; + + setUp(() { + client = new FakeHttpClient(sync: false); + var config = new THttpConfig(Uri.parse('http://localhost'), {}); + transport = new THttpClientTransport(client, config); + }); + + test('Test transport sends body', () async { + var expectedText = 'my request'; + transport.writeAll(utf8Codec.encode(expectedText)); + + expect(client.postRequest, isEmpty); + + await transport.flush(); + + expect(client.postRequest, isNotEmpty); + + var requestText = utf8Codec.decode(base64.decode(client.postRequest)); + expect(requestText, expectedText); + }); + + test('Test transport receives response', () async { + var expectedText = 'my response'; + var expectedBytes = utf8Codec.encode(expectedText); + client.postResponse = base64.encode(expectedBytes); + + transport.writeAll(utf8Codec.encode('my request')); + expect(transport.hasReadData, isFalse); + + await transport.flush(); + + expect(transport.hasReadData, isTrue); + + var buffer = new Uint8List(expectedBytes.length); + transport.readAll(buffer, 0, expectedBytes.length); + + var bufferText = utf8Codec.decode(buffer); + expect(bufferText, expectedText); + }); + }); + + group('THttpClientTransport with multiple messages', () { + FakeHttpClient client; + THttpClientTransport transport; + + setUp(() { + client = new FakeHttpClient(sync: true); + var config = new THttpConfig(Uri.parse('http://localhost'), {}); + transport = new THttpClientTransport(client, config); + }); + + test('Test read correct buffer after flush', () async { + String bufferText; + var expectedText = 'response 1'; + var expectedBytes = utf8Codec.encode(expectedText); + + // prepare a response + transport.writeAll(utf8Codec.encode('request 1')); + client.postResponse = base64.encode(expectedBytes); + + Future responseReady = transport.flush().then((_) { + var buffer = new Uint8List(expectedBytes.length); + transport.readAll(buffer, 0, expectedBytes.length); + bufferText = utf8Codec.decode(buffer); + }); + + // prepare a second response + transport.writeAll(utf8Codec.encode('request 2')); + var response2Bytes = utf8Codec.encode('response 2'); + client.postResponse = base64.encode(response2Bytes); + await transport.flush(); + + await responseReady; + expect(bufferText, expectedText); + }); + }); +} + +class FakeHttpClient implements Client { + String postResponse = ''; + String postRequest = ''; + + final bool sync; + + FakeHttpClient({this.sync: false}); + + Future<Response> post(url, + {Map<String, String> headers, body, Encoding encoding}) { + postRequest = body; + var response = new Response(postResponse, 200); + + if (sync) { + return new Future.sync(() => response); + } else { + return new Future.value(response); + } + } + + Future<Response> head(url, {Map<String, String> headers}) => + throw new UnimplementedError(); + + Future<Response> get(url, {Map<String, String> headers}) => + throw new UnimplementedError(); + + Future<Response> put(url, + {Map<String, String> headers, body, Encoding encoding}) => + throw new UnimplementedError(); + + Future<Response> patch(url, + {Map<String, String> headers, body, Encoding encoding}) => + throw new UnimplementedError(); + + Future<Response> delete(url, {Map<String, String> headers}) => + throw new UnimplementedError(); + + Future<String> read(url, {Map<String, String> headers}) => + throw new UnimplementedError(); + + Future<Uint8List> readBytes(url, {Map<String, String> headers}) => + throw new UnimplementedError(); + + Future<StreamedResponse> send(BaseRequest request) => + throw new UnimplementedError(); + + void close() => throw new UnimplementedError(); +} diff --git a/src/jaegertracing/thrift/lib/dart/test/transport/t_socket_transport_test.dart b/src/jaegertracing/thrift/lib/dart/test/transport/t_socket_transport_test.dart new file mode 100644 index 000000000..90bffbe54 --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/test/transport/t_socket_transport_test.dart @@ -0,0 +1,311 @@ +// 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. + +library thrift.test.transport.t_socket_transport_test; + +import 'dart:async'; +import 'dart:convert' show Utf8Codec; +import 'dart:typed_data' show Uint8List; + +import 'package:dart2_constant/convert.dart' show base64; +import 'package:dart2_constant/core.dart' as core; +import 'package:mockito/mockito.dart'; +import 'package:test/test.dart'; +import 'package:thrift/thrift.dart'; + +void main() { + const utf8Codec = const Utf8Codec(); + + final requestText = 'my test request'; + final requestBytes = new Uint8List.fromList(utf8Codec.encode(requestText)); + final requestBase64 = base64.encode(requestBytes); + + final responseText = 'response 1'; + final responseBytes = new Uint8List.fromList(utf8Codec.encode(responseText)); + final responseBase64 = base64.encode(responseBytes); + + final framedResponseBase64 = base64.encode(_getFramedResponse(responseBytes)); + + group('TClientSocketTransport', () { + FakeSocket socket; + TTransport transport; + + setUp(() async { + socket = new FakeSocket(sync: false); + await socket.open(); + transport = new TClientSocketTransport(socket); + await transport.open(); + transport.writeAll(requestBytes); + }); + + test('Test client sending data over transport', () async { + expect(socket.sendPayload, isNull); + + Future responseReady = transport.flush(); + + // allow microtask events to finish + await new Future.value(); + + expect(socket.sendPayload, isNotNull); + expect(socket.sendPayload, requestBytes); + + // simulate a response + socket.receiveFakeMessage(responseBase64); + + await responseReady; + var buffer = new Uint8List(responseBytes.length); + transport.readAll(buffer, 0, responseBytes.length); + var bufferText = utf8Codec.decode(buffer); + + expect(bufferText, responseText); + }); + }, timeout: new Timeout(new Duration(seconds: 1))); + + group('TClientSocketTransport with FramedTransport', () { + FakeSocket socket; + TTransport transport; + + setUp(() async { + socket = new FakeSocket(sync: true); + await socket.open(); + + transport = new TFramedTransport(new TClientSocketTransport(socket)); + await transport.open(); + transport.writeAll(requestBytes); + }); + + test('Test client sending data over framed transport', () async { + String bufferText; + + Future responseReady = transport.flush().then((_) { + var buffer = new Uint8List(responseBytes.length); + transport.readAll(buffer, 0, responseBytes.length); + bufferText = utf8Codec.decode(buffer); + }); + + // simulate a response + socket.receiveFakeMessage(framedResponseBase64); + + await responseReady; + expect(bufferText, responseText); + }); + }, timeout: new Timeout(new Duration(seconds: 1))); + + group('TAsyncClientSocketTransport', () { + FakeSocket socket; + FakeProtocolFactory protocolFactory; + TTransport transport; + + setUp(() async { + socket = new FakeSocket(sync: true); + await socket.open(); + + protocolFactory = new FakeProtocolFactory(); + protocolFactory.message = new TMessage('foo', TMessageType.CALL, 123); + transport = new TAsyncClientSocketTransport( + socket, new TMessageReader(protocolFactory), + responseTimeout: core.Duration.zero); + await transport.open(); + transport.writeAll(requestBytes); + }); + + test('Test response correlates to correct request', () async { + String bufferText; + + Future responseReady = transport.flush().then((_) { + var buffer = new Uint8List(responseBytes.length); + transport.readAll(buffer, 0, responseBytes.length); + bufferText = utf8Codec.decode(buffer); + }); + + // simulate a response + protocolFactory.message = new TMessage('foo', TMessageType.REPLY, 123); + socket.receiveFakeMessage(responseBase64); + + // simulate a second response + var response2Text = 'response 2'; + var response2Bytes = + new Uint8List.fromList(utf8Codec.encode(response2Text)); + var response2Base64 = base64.encode(response2Bytes); + protocolFactory.message = new TMessage('foo2', TMessageType.REPLY, 124); + socket.receiveFakeMessage(response2Base64); + + await responseReady; + expect(bufferText, responseText); + }); + + test('Test response timeout', () async { + Future responseReady = transport.flush(); + expect(responseReady, throwsA(new isInstanceOf<TimeoutException>())); + }); + }, timeout: new Timeout(new Duration(seconds: 1))); + + group('TAsyncClientSocketTransport with TFramedTransport', () { + FakeSocket socket; + FakeProtocolFactory protocolFactory; + TTransport transport; + + setUp(() async { + socket = new FakeSocket(sync: true); + await socket.open(); + + protocolFactory = new FakeProtocolFactory(); + protocolFactory.message = new TMessage('foo', TMessageType.CALL, 123); + var messageReader = new TMessageReader(protocolFactory, + byteOffset: TFramedTransport.headerByteCount); + + transport = new TFramedTransport(new TAsyncClientSocketTransport( + socket, messageReader, + responseTimeout: core.Duration.zero)); + await transport.open(); + transport.writeAll(requestBytes); + }); + + test('Test async client sending data over framed transport', () async { + String bufferText; + + Future responseReady = transport.flush().then((_) { + var buffer = new Uint8List(responseBytes.length); + transport.readAll(buffer, 0, responseBytes.length); + bufferText = utf8Codec.decode(buffer); + }); + + // simulate a response + protocolFactory.message = new TMessage('foo', TMessageType.REPLY, 123); + socket.receiveFakeMessage(framedResponseBase64); + + await responseReady; + expect(bufferText, responseText); + }); + }, timeout: new Timeout(new Duration(seconds: 1))); + + group('TServerTransport', () { + test('Test server transport listens to socket', () async { + var socket = new FakeSocket(); + await socket.open(); + expect(socket.isOpen, isTrue); + + var transport = new TServerSocketTransport(socket); + expect(transport.hasReadData, isFalse); + + socket.receiveFakeMessage(requestBase64); + + // allow microtask events to finish + await new Future.value(); + + expect(transport.hasReadData, isTrue); + + var buffer = new Uint8List(requestBytes.length); + transport.readAll(buffer, 0, requestBytes.length); + + var bufferText = utf8Codec.decode(buffer); + expect(bufferText, requestText); + }); + + test('Test server sending data over transport', () async { + var socket = new FakeSocket(); + await socket.open(); + + var transport = new TServerSocketTransport(socket); + + transport.writeAll(responseBytes); + expect(socket.sendPayload, isNull); + + transport.flush(); + + // allow microtask events to finish + await new Future.value(); + + expect(socket.sendPayload, isNotNull); + expect(socket.sendPayload, responseBytes); + }); + }, timeout: new Timeout(new Duration(seconds: 1))); +} + +class FakeSocket extends TSocket { + final StreamController<TSocketState> _onStateController; + Stream<TSocketState> get onState => _onStateController.stream; + + final StreamController<Object> _onErrorController; + Stream<Object> get onError => _onErrorController.stream; + + final StreamController<Uint8List> _onMessageController; + Stream<Uint8List> get onMessage => _onMessageController.stream; + + FakeSocket({bool sync: false}) + : _onStateController = new StreamController.broadcast(sync: sync), + _onErrorController = new StreamController.broadcast(sync: sync), + _onMessageController = new StreamController.broadcast(sync: sync); + + bool _isOpen; + + bool get isOpen => _isOpen; + + bool get isClosed => !isOpen; + + Future open() async { + _isOpen = true; + _onStateController.add(TSocketState.OPEN); + } + + Future close() async { + _isOpen = false; + _onStateController.add(TSocketState.CLOSED); + } + + Uint8List _sendPayload; + Uint8List get sendPayload => _sendPayload; + + void send(Uint8List data) { + if (!isOpen) throw new StateError('The socket is not open'); + + _sendPayload = data; + } + + void receiveFakeMessage(String base64text) { + if (!isOpen) throw new StateError('The socket is not open'); + + var message = new Uint8List.fromList(base64.decode(base64text)); + _onMessageController.add(message); + } +} + +class FakeProtocolFactory implements TProtocolFactory { + FakeProtocolFactory(); + + TMessage message; + + getProtocol(TTransport transport) => new FakeProtocol(message); +} + +class FakeProtocol extends Mock implements TProtocol { + FakeProtocol(this._message); + + TMessage _message; + + readMessageBegin() => _message; +} + +Uint8List _getFramedResponse(Uint8List responseBytes) { + var byteOffset = TFramedTransport.headerByteCount; + var response = new Uint8List(byteOffset + responseBytes.length); + + response.buffer.asByteData().setInt32(0, responseBytes.length); + response.setAll(byteOffset, responseBytes); + + return response; +} diff --git a/src/jaegertracing/thrift/lib/dart/test/transport/t_transport_test.dart b/src/jaegertracing/thrift/lib/dart/test/transport/t_transport_test.dart new file mode 100644 index 000000000..0bb381ac8 --- /dev/null +++ b/src/jaegertracing/thrift/lib/dart/test/transport/t_transport_test.dart @@ -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. + +library thrift.test.transport.t_socket_transport_test; + +import 'package:test/test.dart'; +import 'package:thrift/thrift.dart'; + +/// Common transport tests +void main() { + group('TTransportFactory', () { + test('transport is returned from base factory', () async { + TTransport result; + TTransport transport = null; + + var factory = new TTransportFactory(); + + result = await factory.getTransport(transport); + expect(result, isNull); + + transport = new TBufferedTransport(); + result = await factory.getTransport(transport); + + expect(result, transport); + }); + }); +} |