| #!/usr/bin/env dart |
| // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| import 'package:fixnum/fixnum.dart'; |
| import 'package:protobuf/protobuf.dart'; |
| import 'package:test/test.dart'; |
| |
| import '../out/protos/foo.pb.dart' as foo; |
| import '../out/protos/google/protobuf/unittest.pb.dart'; |
| import '../out/protos/map_enum_value.pb.dart'; |
| import 'test_util.dart'; |
| |
| void main() { |
| final testAllJsonTypes = '{"1":101,"2":"102","3":103,"4":"104",' |
| '"5":105,"6":"106","7":107,"8":"108","9":109,"10":"110","11":111.0,' |
| '"12":112.0,"13":true,"14":"115","15":"MTE2","16":{"17":117},' |
| '"18":{"1":118},"19":{"1":119},"20":{"1":120},"21":3,"22":6,"23":9,' |
| '"24":"124","25":"125","31":[201,301],"32":["202","302"],' |
| '"33":[203,303],"34":["204","304"],"35":[205,305],"36":["206","306"],' |
| '"37":[207,307],"38":["208","308"],"39":[209,309],"40":["210","310"],' |
| '"41":[211.0,311.0],"42":[212.0,312.0],"43":[true,false],' |
| '"44":["215","315"],"45":["MjE2","MzE2"],"46":[{"47":217},{"47":317}],' |
| '"48":[{"1":218},{"1":318}],"49":[{"1":219},{"1":319}],' |
| '"50":[{"1":220},{"1":320}],"51":[2,3],"52":[5,6],"53":[8,9],' |
| '"54":["224","324"],"55":["225","325"],"61":401,"62":"402","63":403,' |
| '"64":"404","65":405,"66":"406","67":407,"68":"408","69":409,' |
| '"70":"410","71":411.0,"72":412.0,"73":false,"74":"415","75":"NDE2",' |
| '"81":1,"82":4,"83":7,"84":"424","85":"425"}'; |
| |
| // Checks that message once serialized to JSON |
| // matches TEST_ALL_TYPES_JSON massaged with [:.replaceAll(from, to):]. |
| Matcher expectedJson(String from, String to) { |
| var expectedJson = testAllJsonTypes.replaceAll(from, to); |
| return predicate( |
| (GeneratedMessage message) => message.writeToJson() == expectedJson, |
| 'Incorrect output'); |
| } |
| |
| test('testUnsignedOutput', () { |
| var message = TestAllTypes(); |
| // These values selected because: |
| // (1) large enough to set the sign bit |
| // (2) don't set all of the first 10 bits under the sign bit |
| // (3) are near each other |
| message.optionalUint64 = Int64.parseHex('f0000000ffff0000'); |
| message.optionalFixed64 = Int64.parseHex('f0000000ffff0001'); |
| |
| var expectedJsonValue = |
| '{"4":"17293822573397606400","8":"17293822573397606401"}'; |
| expect(message.writeToJson(), expectedJsonValue); |
| }); |
| |
| test('testOutput', () { |
| expect(getAllSet().writeToJson(), testAllJsonTypes); |
| |
| // Test empty list. |
| expect(getAllSet()..repeatedBool.clear(), |
| expectedJson('"43":[true,false],', '')); |
| |
| // Test negative number. |
| expect(getAllSet()..optionalInt32 = -1234567, |
| expectedJson(':101,', ':-1234567,')); |
| |
| // All 64-bit numbers are quoted. |
| expect(getAllSet()..optionalInt64 = make64(0, 0x200000), |
| expectedJson(':"102",', ':"9007199254740992",')); |
| expect(getAllSet()..optionalInt64 = make64(1, 0x200000), |
| expectedJson(':"102",', ':"9007199254740993",')); |
| expect(getAllSet()..optionalInt64 = -make64(0, 0x200000), |
| expectedJson(':"102",', ':"-9007199254740992",')); |
| expect(getAllSet()..optionalInt64 = -make64(1, 0x200000), |
| expectedJson(':"102",', ':"-9007199254740993",')); |
| |
| // Quotes, backslashes, and control characters in strings are quoted. |
| expect(getAllSet()..optionalString = 'a\u0000b\u0001cd\\e"fg', |
| expectedJson(':"115",', ':"a\\u0000b\\u0001cd\\\\e\\"fg",')); |
| }); |
| |
| test('testBase64Encode', () { |
| expect(getAllSet()..optionalBytes = 'Hello, world'.codeUnits, |
| expectedJson(':"MTE2",', ':"SGVsbG8sIHdvcmxk",')); |
| |
| expect(getAllSet()..optionalBytes = 'Hello, world!'.codeUnits, |
| expectedJson(':"MTE2",', ':"SGVsbG8sIHdvcmxkIQ==",')); |
| |
| expect(getAllSet()..optionalBytes = 'Hello, world!!'.codeUnits, |
| expectedJson(':"MTE2",', ':"SGVsbG8sIHdvcmxkISE=",')); |
| |
| // An empty list should not appear in the output. |
| expect(getAllSet()..optionalBytes = [], expectedJson('"15":"MTE2",', '')); |
| |
| expect(getAllSet()..optionalBytes = 'a'.codeUnits, |
| expectedJson(':"MTE2",', ':"YQ==",')); |
| }); |
| |
| test('testBase64Decode', () { |
| String optionalBytes(String from, String to) { |
| var json = testAllJsonTypes.replaceAll(from, to); |
| return String.fromCharCodes(TestAllTypes.fromJson(json).optionalBytes); |
| } |
| |
| expect(optionalBytes(':"MTE2",', ':"SGVsbG8sIHdvcmxk",'), 'Hello, world'); |
| |
| expect( |
| optionalBytes(':"MTE2",', ':"SGVsbG8sIHdvcmxkIQ==",'), 'Hello, world!'); |
| |
| expect(optionalBytes(':"MTE2",', ':"SGVsbG8sIHdvcmxkISE=",'), |
| 'Hello, world!!'); |
| |
| // Remove optionalBytes tag, reads back as empty list, hence empty string. |
| expect(optionalBytes('"15":"MTE2",', ''), isEmpty); |
| |
| // Keep optionalBytes tag, set data to empty string, get back empty list. |
| expect(optionalBytes(':"MTE2",', ':"",'), isEmpty); |
| |
| expect(optionalBytes(':"MTE2",', ':"YQ==",'), 'a'); |
| }); |
| |
| test('testParseUnsigned', () { |
| var parsed = TestAllTypes.fromJson( |
| '{"4":"17293822573397606400","8":"17293822573397606401"}'); |
| var expected = TestAllTypes(); |
| expected.optionalUint64 = Int64.parseHex('f0000000ffff0000'); |
| expected.optionalFixed64 = Int64.parseHex('f0000000ffff0001'); |
| |
| expect(parsed, expected); |
| }); |
| |
| test('testParseUnsignedLegacy', () { |
| var parsed = TestAllTypes.fromJson( |
| '{"4":"-1152921500311945216","8":"-1152921500311945215"}'); |
| var expected = TestAllTypes(); |
| expected.optionalUint64 = Int64.parseHex('f0000000ffff0000'); |
| expected.optionalFixed64 = Int64.parseHex('f0000000ffff0001'); |
| |
| expect(parsed, expected); |
| }); |
| |
| test('testFixed32IntNegative', () { |
| var message = foo.Inner.fromJson('{"5": -1}'); |
| expect(message.count, 4294967295); |
| message = foo.Inner.fromJson('{"5": -2080294357}'); |
| expect(message.count, 2214672939); |
| }); |
| |
| test('testParse', () { |
| expect(TestAllTypes.fromJson(testAllJsonTypes), getAllSet()); |
| }); |
| |
| test('testExtensionsOutput', () { |
| expect(getAllExtensionsSet().writeToJson(), testAllJsonTypes); |
| }); |
| |
| test('testExtensionsParse', () { |
| var registry = getExtensionRegistry(); |
| expect(TestAllExtensions.fromJson(testAllJsonTypes, registry), |
| getAllExtensionsSet()); |
| }); |
| |
| test('testUnknownEnumValueInOptionalField', () { |
| // optional NestedEnum optional_nested_enum = 21; |
| var message = TestAllTypes.fromJson('{"21": 4}'); |
| // 4 is an unknown value. |
| expect(message.optionalNestedEnum, equals(TestAllTypes_NestedEnum.FOO)); |
| }); |
| |
| test('testUnknownEnumValueInRepeatedField', () { |
| // repeated NestedEnum repeated_nested_enum = 51; |
| var message = TestAllTypes.fromJson('{"51": [4]}'); |
| // 4 is an unknown value, which should default to the enum's default value. |
| expect(message.repeatedNestedEnum, equals([TestAllTypes_NestedEnum.FOO])); |
| |
| // 1 (FOO) and 2 (BAR) are known values. All unknowns should fill in to |
| // the default enum value (FOO). |
| message = TestAllTypes.fromJson('{"51": [1, 4, 2, 4, 1, 4]}'); |
| expect( |
| message.repeatedNestedEnum, |
| equals([ |
| TestAllTypes_NestedEnum.FOO, |
| TestAllTypes_NestedEnum.FOO, |
| TestAllTypes_NestedEnum.BAR, |
| TestAllTypes_NestedEnum.FOO, |
| TestAllTypes_NestedEnum.FOO, |
| TestAllTypes_NestedEnum.FOO |
| ])); |
| }); |
| |
| test('testUnknownEnumValueInMapField', () { |
| final key = 'new_field'; |
| // Only 0 and 1 are known enum values. |
| final message = MapEnumValue()..mergeFromJson('{"1":[{"1":"$key","2":2}]}'); |
| expect(message.values[key], equals(MapEnumValue_NestedEnum.UNKNOWN)); |
| }); |
| } |