| // 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:convert' show utf8; |
| import 'dart:typed_data' show Uint8List; |
| |
| import 'package:test/test.dart'; |
| import 'package:thrift/thrift.dart'; |
| |
| void main() { |
| final message = TMessage('my message', TMessageType.ONEWAY, 123); |
| |
| TProtocol protocol; |
| |
| Primitive getPrimitive(int tType) { |
| switch (tType) { |
| case TType.BOOL: |
| return Primitive(protocol.readBool, protocol.writeBool, false); |
| |
| case TType.BYTE: |
| return Primitive(protocol.readByte, protocol.writeByte, 0); |
| |
| case TType.I16: |
| return Primitive(protocol.readI16, protocol.writeI16, 0); |
| |
| case TType.I32: |
| return Primitive(protocol.readI32, protocol.writeI32, 0); |
| |
| case TType.I64: |
| return Primitive(protocol.readI64, protocol.writeI64, 0); |
| |
| case TType.DOUBLE: |
| return Primitive(protocol.readDouble, protocol.writeDouble, 0); |
| |
| case TType.STRING: |
| return Primitive(protocol.readString, protocol.writeString, ''); |
| |
| default: |
| throw 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 = 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 = 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 = 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 = 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 = 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 = Uint8List.fromList(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(TStruct()); |
| protocol.writeFieldBegin(TField('success', TType.MAP, 0)); |
| protocol.writeMapBegin(TMap(TType.I32, TType.MAP, 2)); |
| |
| protocol.writeI32(1); // key |
| protocol.writeMapBegin(TMap(TType.I32, TType.I32, 1)); |
| protocol.writeI32(10); // key |
| protocol.writeI32(20); // value |
| protocol.writeMapEnd(); |
| |
| protocol.writeI32(2); // key |
| protocol.writeMapBegin(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(TMap(TType.I32, TType.LIST, 2)); |
| |
| protocol.writeI32(1); // key |
| protocol.writeListBegin(TList(TType.MAP, 1)); |
| protocol.writeMapBegin(TMap(TType.I32, TType.I32, 1)); |
| protocol.writeI32(10); // key |
| protocol.writeI32(20); // value |
| protocol.writeMapEnd(); |
| protocol.writeListEnd(); |
| |
| protocol.writeI32(2); // key |
| protocol.writeListBegin(TList(TType.MAP, 1)); |
| protocol.writeMapBegin(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 = TJsonProtocol(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 = TBufferedTransport(); |
| transport.writeAll(buffer); |
| |
| var protocol = 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 = TBinaryProtocol(TBufferedTransport()); |
| protocol.writeMessageBegin(message); |
| }); |
| |
| group('shared tests', sharedTests); |
| }); |
| |
| group('compact', () { |
| setUp(() { |
| protocol = TCompactProtocol(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); |
| } |