fix message codecs for the Web (#36549)
This commit is contained in:
parent
5ecda9e1b5
commit
ecd89fb7ad
@ -338,6 +338,14 @@ class StandardMessageCodec implements MessageCodec<dynamic> {
|
||||
buffer.putUint8(_valueNull);
|
||||
} else if (value is bool) {
|
||||
buffer.putUint8(value ? _valueTrue : _valueFalse);
|
||||
} else if (value is double) { // Double precedes int because in JS everything is a double.
|
||||
// Therefore in JS, both `is int` and `is double` always
|
||||
// return `true`. If we check int first, we'll end up treating
|
||||
// all numbers as ints and attempt the int32/int64 conversion,
|
||||
// which is wrong. This precedence rule is irrelevant when
|
||||
// decoding because we use tags to detect the type of value.
|
||||
buffer.putUint8(_valueFloat64);
|
||||
buffer.putFloat64(value);
|
||||
} else if (value is int) {
|
||||
if (-0x7fffffff - 1 <= value && value <= 0x7fffffff) {
|
||||
buffer.putUint8(_valueInt32);
|
||||
@ -346,9 +354,6 @@ class StandardMessageCodec implements MessageCodec<dynamic> {
|
||||
buffer.putUint8(_valueInt64);
|
||||
buffer.putInt64(value);
|
||||
}
|
||||
} else if (value is double) {
|
||||
buffer.putUint8(_valueFloat64);
|
||||
buffer.putFloat64(value);
|
||||
} else if (value is String) {
|
||||
buffer.putUint8(_valueString);
|
||||
final List<int> bytes = utf8.encoder.convert(value);
|
||||
|
@ -2,28 +2,31 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
@TestOn('!chrome')
|
||||
// This files contains message codec tests that are supported both on the Web
|
||||
// and in the VM. For VM-only tests see message_codecs_vm_test.dart.
|
||||
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import '../flutter_test_alternative.dart';
|
||||
import 'message_codecs_testing.dart';
|
||||
|
||||
void main() {
|
||||
group('Binary codec', () {
|
||||
const MessageCodec<ByteData> binary = BinaryCodec();
|
||||
test('should encode and decode simple messages', () {
|
||||
_checkEncodeDecode<ByteData>(binary, null);
|
||||
_checkEncodeDecode<ByteData>(binary, ByteData(0));
|
||||
_checkEncodeDecode<ByteData>(binary, ByteData(4)..setInt32(0, -7));
|
||||
checkEncodeDecode<ByteData>(binary, null);
|
||||
checkEncodeDecode<ByteData>(binary, ByteData(0));
|
||||
checkEncodeDecode<ByteData>(binary, ByteData(4)..setInt32(0, -7));
|
||||
});
|
||||
});
|
||||
group('String codec', () {
|
||||
const MessageCodec<String> string = StringCodec();
|
||||
test('should encode and decode simple messages', () {
|
||||
_checkEncodeDecode<String>(string, null);
|
||||
_checkEncodeDecode<String>(string, '');
|
||||
_checkEncodeDecode<String>(string, 'hello');
|
||||
_checkEncodeDecode<String>(string, 'special chars >\u263A\u{1F602}<');
|
||||
checkEncodeDecode<String>(string, null);
|
||||
checkEncodeDecode<String>(string, '');
|
||||
checkEncodeDecode<String>(string, 'hello');
|
||||
checkEncodeDecode<String>(string, 'special chars >\u263A\u{1F602}<');
|
||||
});
|
||||
test('ByteData with offset', () {
|
||||
const MessageCodec<String> string = StringCodec();
|
||||
@ -42,19 +45,17 @@ void main() {
|
||||
group('JSON message codec', () {
|
||||
const MessageCodec<dynamic> json = JSONMessageCodec();
|
||||
test('should encode and decode simple messages', () {
|
||||
_checkEncodeDecode<dynamic>(json, null);
|
||||
_checkEncodeDecode<dynamic>(json, true);
|
||||
_checkEncodeDecode<dynamic>(json, false);
|
||||
_checkEncodeDecode<dynamic>(json, 7);
|
||||
_checkEncodeDecode<dynamic>(json, -7);
|
||||
_checkEncodeDecode<dynamic>(json, 98742923489);
|
||||
_checkEncodeDecode<dynamic>(json, -98742923489);
|
||||
_checkEncodeDecode<dynamic>(json, 9223372036854775807);
|
||||
_checkEncodeDecode<dynamic>(json, -9223372036854775807);
|
||||
_checkEncodeDecode<dynamic>(json, 3.14);
|
||||
_checkEncodeDecode<dynamic>(json, '');
|
||||
_checkEncodeDecode<dynamic>(json, 'hello');
|
||||
_checkEncodeDecode<dynamic>(json, 'special chars >\u263A\u{1F602}<');
|
||||
checkEncodeDecode<dynamic>(json, null);
|
||||
checkEncodeDecode<dynamic>(json, true);
|
||||
checkEncodeDecode<dynamic>(json, false);
|
||||
checkEncodeDecode<dynamic>(json, 7);
|
||||
checkEncodeDecode<dynamic>(json, -7);
|
||||
checkEncodeDecode<dynamic>(json, 98742923489);
|
||||
checkEncodeDecode<dynamic>(json, -98742923489);
|
||||
checkEncodeDecode<dynamic>(json, 3.14);
|
||||
checkEncodeDecode<dynamic>(json, '');
|
||||
checkEncodeDecode<dynamic>(json, 'hello');
|
||||
checkEncodeDecode<dynamic>(json, 'special chars >\u263A\u{1F602}<');
|
||||
});
|
||||
test('should encode and decode composite message', () {
|
||||
final List<dynamic> message = <dynamic>[
|
||||
@ -63,7 +64,6 @@ void main() {
|
||||
false,
|
||||
-707,
|
||||
-7000000007,
|
||||
-7000000000000000007,
|
||||
-3.14,
|
||||
'',
|
||||
'hello',
|
||||
@ -71,91 +71,47 @@ void main() {
|
||||
<dynamic, dynamic>{'a': 'nested', 'b': <dynamic, dynamic>{}},
|
||||
'world',
|
||||
];
|
||||
_checkEncodeDecode<dynamic>(json, message);
|
||||
checkEncodeDecode<dynamic>(json, message);
|
||||
});
|
||||
});
|
||||
group('Standard message codec', () {
|
||||
const MessageCodec<dynamic> standard = StandardMessageCodec();
|
||||
test('should encode integers correctly at boundary cases', () {
|
||||
_checkEncoding<dynamic>(
|
||||
standard,
|
||||
-0x7fffffff - 1,
|
||||
<int>[3, 0x00, 0x00, 0x00, 0x80],
|
||||
);
|
||||
_checkEncoding<dynamic>(
|
||||
standard,
|
||||
-0x7fffffff - 2,
|
||||
<int>[4, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff],
|
||||
);
|
||||
_checkEncoding<dynamic>(
|
||||
standard,
|
||||
0x7fffffff,
|
||||
<int>[3, 0xff, 0xff, 0xff, 0x7f],
|
||||
);
|
||||
_checkEncoding<dynamic>(
|
||||
standard,
|
||||
0x7fffffff + 1,
|
||||
<int>[4, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00],
|
||||
);
|
||||
_checkEncoding<dynamic>(
|
||||
standard,
|
||||
-0x7fffffffffffffff - 1,
|
||||
<int>[4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80],
|
||||
);
|
||||
_checkEncoding<dynamic>(
|
||||
standard,
|
||||
-0x7fffffffffffffff - 2,
|
||||
<int>[4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f],
|
||||
);
|
||||
_checkEncoding<dynamic>(
|
||||
standard,
|
||||
0x7fffffffffffffff,
|
||||
<int>[4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f],
|
||||
);
|
||||
_checkEncoding<dynamic>(
|
||||
standard,
|
||||
0x7fffffffffffffff + 1,
|
||||
<int>[4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80],
|
||||
);
|
||||
});
|
||||
test('should encode sizes correctly at boundary cases', () {
|
||||
_checkEncoding<dynamic>(
|
||||
checkEncoding<dynamic>(
|
||||
standard,
|
||||
Uint8List(253),
|
||||
<int>[8, 253, ...List<int>.filled(253, 0)],
|
||||
);
|
||||
_checkEncoding<dynamic>(
|
||||
checkEncoding<dynamic>(
|
||||
standard,
|
||||
Uint8List(254),
|
||||
<int>[8, 254, 254, 0, ...List<int>.filled(254, 0)],
|
||||
);
|
||||
_checkEncoding<dynamic>(
|
||||
checkEncoding<dynamic>(
|
||||
standard,
|
||||
Uint8List(0xffff),
|
||||
<int>[8, 254, 0xff, 0xff, ...List<int>.filled(0xffff, 0)],
|
||||
);
|
||||
_checkEncoding<dynamic>(
|
||||
checkEncoding<dynamic>(
|
||||
standard,
|
||||
Uint8List(0xffff + 1),
|
||||
<int>[8, 255, 0, 0, 1, 0, ...List<int>.filled(0xffff + 1, 0)],
|
||||
);
|
||||
});
|
||||
test('should encode and decode simple messages', () {
|
||||
_checkEncodeDecode<dynamic>(standard, null);
|
||||
_checkEncodeDecode<dynamic>(standard, true);
|
||||
_checkEncodeDecode<dynamic>(standard, false);
|
||||
_checkEncodeDecode<dynamic>(standard, 7);
|
||||
_checkEncodeDecode<dynamic>(standard, -7);
|
||||
_checkEncodeDecode<dynamic>(standard, 98742923489);
|
||||
_checkEncodeDecode<dynamic>(standard, -98742923489);
|
||||
_checkEncodeDecode<dynamic>(standard, 9223372036854775807);
|
||||
_checkEncodeDecode<dynamic>(standard, -9223372036854775807);
|
||||
_checkEncodeDecode<dynamic>(standard, 3.14);
|
||||
_checkEncodeDecode<dynamic>(standard, double.infinity);
|
||||
_checkEncodeDecode<dynamic>(standard, double.nan);
|
||||
_checkEncodeDecode<dynamic>(standard, '');
|
||||
_checkEncodeDecode<dynamic>(standard, 'hello');
|
||||
_checkEncodeDecode<dynamic>(standard, 'special chars >\u263A\u{1F602}<');
|
||||
checkEncodeDecode<dynamic>(standard, null);
|
||||
checkEncodeDecode<dynamic>(standard, true);
|
||||
checkEncodeDecode<dynamic>(standard, false);
|
||||
checkEncodeDecode<dynamic>(standard, 7);
|
||||
checkEncodeDecode<dynamic>(standard, -7);
|
||||
checkEncodeDecode<dynamic>(standard, 98742923489);
|
||||
checkEncodeDecode<dynamic>(standard, -98742923489);
|
||||
checkEncodeDecode<dynamic>(standard, 3.14);
|
||||
checkEncodeDecode<dynamic>(standard, double.infinity);
|
||||
checkEncodeDecode<dynamic>(standard, double.nan);
|
||||
checkEncodeDecode<dynamic>(standard, '');
|
||||
checkEncodeDecode<dynamic>(standard, 'hello');
|
||||
checkEncodeDecode<dynamic>(standard, 'special chars >\u263A\u{1F602}<');
|
||||
});
|
||||
test('should encode and decode composite message', () {
|
||||
final List<dynamic> message = <dynamic>[
|
||||
@ -164,15 +120,12 @@ void main() {
|
||||
false,
|
||||
-707,
|
||||
-7000000007,
|
||||
-7000000000000000007,
|
||||
-3.14,
|
||||
'',
|
||||
'hello',
|
||||
Uint8List.fromList(<int>[0xBA, 0x5E, 0xBA, 0x11]),
|
||||
Int32List.fromList(<int>[-0x7fffffff - 1, 0, 0x7fffffff]),
|
||||
null, // ensures the offset of the following list is unaligned.
|
||||
Int64List.fromList(
|
||||
<int>[-0x7fffffffffffffff - 1, 0, 0x7fffffffffffffff]),
|
||||
null, // ensures the offset of the following list is unaligned.
|
||||
Float64List.fromList(<double>[
|
||||
double.negativeInfinity,
|
||||
@ -189,10 +142,10 @@ void main() {
|
||||
<dynamic, dynamic>{'a': 'nested', null: <dynamic, dynamic>{}},
|
||||
'world',
|
||||
];
|
||||
_checkEncodeDecode<dynamic>(standard, message);
|
||||
checkEncodeDecode<dynamic>(standard, message);
|
||||
});
|
||||
test('should align doubles to 8 bytes', () {
|
||||
_checkEncoding<dynamic>(
|
||||
checkEncoding<dynamic>(
|
||||
standard,
|
||||
1.0,
|
||||
<int>[6, 0, 0, 0, 0, 0, 0, 0,
|
||||
@ -201,76 +154,3 @@ void main() {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void _checkEncoding<T>(MessageCodec<T> codec, T message, List<int> expectedBytes) {
|
||||
final ByteData encoded = codec.encodeMessage(message);
|
||||
expect(
|
||||
encoded.buffer.asUint8List(0, encoded.lengthInBytes),
|
||||
orderedEquals(expectedBytes),
|
||||
);
|
||||
}
|
||||
|
||||
void _checkEncodeDecode<T>(MessageCodec<T> codec, T message) {
|
||||
final ByteData encoded = codec.encodeMessage(message);
|
||||
final T decoded = codec.decodeMessage(encoded);
|
||||
if (message == null) {
|
||||
expect(encoded, isNull);
|
||||
expect(decoded, isNull);
|
||||
} else {
|
||||
expect(_deepEquals(message, decoded), isTrue);
|
||||
final ByteData encodedAgain = codec.encodeMessage(decoded);
|
||||
expect(
|
||||
encodedAgain.buffer.asUint8List(),
|
||||
orderedEquals(encoded.buffer.asUint8List()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
bool _deepEquals(dynamic valueA, dynamic valueB) {
|
||||
if (valueA is TypedData)
|
||||
return valueB is TypedData && _deepEqualsTypedData(valueA, valueB);
|
||||
if (valueA is List)
|
||||
return valueB is List && _deepEqualsList(valueA, valueB);
|
||||
if (valueA is Map)
|
||||
return valueB is Map && _deepEqualsMap(valueA, valueB);
|
||||
if (valueA is double && valueA.isNaN)
|
||||
return valueB is double && valueB.isNaN;
|
||||
return valueA == valueB;
|
||||
}
|
||||
|
||||
bool _deepEqualsTypedData(TypedData valueA, TypedData valueB) {
|
||||
if (valueA is ByteData) {
|
||||
return valueB is ByteData
|
||||
&& _deepEqualsList(
|
||||
valueA.buffer.asUint8List(), valueB.buffer.asUint8List());
|
||||
}
|
||||
if (valueA is Uint8List)
|
||||
return valueB is Uint8List && _deepEqualsList(valueA, valueB);
|
||||
if (valueA is Int32List)
|
||||
return valueB is Int32List && _deepEqualsList(valueA, valueB);
|
||||
if (valueA is Int64List)
|
||||
return valueB is Int64List && _deepEqualsList(valueA, valueB);
|
||||
if (valueA is Float64List)
|
||||
return valueB is Float64List && _deepEqualsList(valueA, valueB);
|
||||
throw 'Unexpected typed data: $valueA';
|
||||
}
|
||||
|
||||
bool _deepEqualsList(List<dynamic> valueA, List<dynamic> valueB) {
|
||||
if (valueA.length != valueB.length)
|
||||
return false;
|
||||
for (int i = 0; i < valueA.length; i++) {
|
||||
if (!_deepEquals(valueA[i], valueB[i]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _deepEqualsMap(Map<dynamic, dynamic> valueA, Map<dynamic, dynamic> valueB) {
|
||||
if (valueA.length != valueB.length)
|
||||
return false;
|
||||
for (final dynamic key in valueA.keys) {
|
||||
if (!valueB.containsKey(key) || !_deepEquals(valueA[key], valueB[key]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
81
packages/flutter/test/services/message_codecs_testing.dart
Normal file
81
packages/flutter/test/services/message_codecs_testing.dart
Normal file
@ -0,0 +1,81 @@
|
||||
// Copyright 2019 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import '../flutter_test_alternative.dart';
|
||||
|
||||
void checkEncoding<T>(MessageCodec<T> codec, T message, List<int> expectedBytes) {
|
||||
final ByteData encoded = codec.encodeMessage(message);
|
||||
expect(
|
||||
encoded.buffer.asUint8List(0, encoded.lengthInBytes),
|
||||
orderedEquals(expectedBytes),
|
||||
);
|
||||
}
|
||||
|
||||
void checkEncodeDecode<T>(MessageCodec<T> codec, T message) {
|
||||
final ByteData encoded = codec.encodeMessage(message);
|
||||
final T decoded = codec.decodeMessage(encoded);
|
||||
if (message == null) {
|
||||
expect(encoded, isNull);
|
||||
expect(decoded, isNull);
|
||||
} else {
|
||||
expect(deepEquals(message, decoded), isTrue);
|
||||
final ByteData encodedAgain = codec.encodeMessage(decoded);
|
||||
expect(
|
||||
encodedAgain.buffer.asUint8List(),
|
||||
orderedEquals(encoded.buffer.asUint8List()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
bool deepEquals(dynamic valueA, dynamic valueB) {
|
||||
if (valueA is TypedData)
|
||||
return valueB is TypedData && deepEqualsTypedData(valueA, valueB);
|
||||
if (valueA is List)
|
||||
return valueB is List && deepEqualsList(valueA, valueB);
|
||||
if (valueA is Map)
|
||||
return valueB is Map && deepEqualsMap(valueA, valueB);
|
||||
if (valueA is double && valueA.isNaN)
|
||||
return valueB is double && valueB.isNaN;
|
||||
return valueA == valueB;
|
||||
}
|
||||
|
||||
bool deepEqualsTypedData(TypedData valueA, TypedData valueB) {
|
||||
if (valueA is ByteData) {
|
||||
return valueB is ByteData
|
||||
&& deepEqualsList(
|
||||
valueA.buffer.asUint8List(), valueB.buffer.asUint8List());
|
||||
}
|
||||
if (valueA is Uint8List)
|
||||
return valueB is Uint8List && deepEqualsList(valueA, valueB);
|
||||
if (valueA is Int32List)
|
||||
return valueB is Int32List && deepEqualsList(valueA, valueB);
|
||||
if (valueA is Int64List)
|
||||
return valueB is Int64List && deepEqualsList(valueA, valueB);
|
||||
if (valueA is Float64List)
|
||||
return valueB is Float64List && deepEqualsList(valueA, valueB);
|
||||
throw 'Unexpected typed data: $valueA';
|
||||
}
|
||||
|
||||
bool deepEqualsList(List<dynamic> valueA, List<dynamic> valueB) {
|
||||
if (valueA.length != valueB.length)
|
||||
return false;
|
||||
for (int i = 0; i < valueA.length; i++) {
|
||||
if (!deepEquals(valueA[i], valueB[i]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool deepEqualsMap(Map<dynamic, dynamic> valueA, Map<dynamic, dynamic> valueB) {
|
||||
if (valueA.length != valueB.length)
|
||||
return false;
|
||||
for (final dynamic key in valueA.keys) {
|
||||
if (!valueB.containsKey(key) || !deepEquals(valueA[key], valueB[key]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
84
packages/flutter/test/services/message_codecs_vm_test.dart
Normal file
84
packages/flutter/test/services/message_codecs_vm_test.dart
Normal file
@ -0,0 +1,84 @@
|
||||
// Copyright 2019 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// This file contains tests that are only supported by the Dart VM. For
|
||||
// example, on the Web there's no way to express large integers.
|
||||
@TestOn('!chrome')
|
||||
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import '../flutter_test_alternative.dart';
|
||||
import 'message_codecs_testing.dart';
|
||||
|
||||
void main() {
|
||||
group('JSON message codec', () {
|
||||
const MessageCodec<dynamic> json = JSONMessageCodec();
|
||||
test('should encode and decode big numbers', () {
|
||||
checkEncodeDecode<dynamic>(json, 9223372036854775807);
|
||||
checkEncodeDecode<dynamic>(json, -9223372036854775807);
|
||||
});
|
||||
test('should encode and decode list with a big number', () {
|
||||
final List<dynamic> message = <dynamic>[-7000000000000000007];
|
||||
checkEncodeDecode<dynamic>(json, message);
|
||||
});
|
||||
});
|
||||
group('Standard message codec', () {
|
||||
const MessageCodec<dynamic> standard = StandardMessageCodec();
|
||||
test('should encode integers correctly at boundary cases', () {
|
||||
checkEncoding<dynamic>(
|
||||
standard,
|
||||
-0x7fffffff - 1,
|
||||
<int>[3, 0x00, 0x00, 0x00, 0x80],
|
||||
);
|
||||
checkEncoding<dynamic>(
|
||||
standard,
|
||||
-0x7fffffff - 2,
|
||||
<int>[4, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff],
|
||||
);
|
||||
checkEncoding<dynamic>(
|
||||
standard,
|
||||
0x7fffffff,
|
||||
<int>[3, 0xff, 0xff, 0xff, 0x7f],
|
||||
);
|
||||
checkEncoding<dynamic>(
|
||||
standard,
|
||||
0x7fffffff + 1,
|
||||
<int>[4, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00],
|
||||
);
|
||||
checkEncoding<dynamic>(
|
||||
standard,
|
||||
-0x7fffffffffffffff - 1,
|
||||
<int>[4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80],
|
||||
);
|
||||
checkEncoding<dynamic>(
|
||||
standard,
|
||||
-0x7fffffffffffffff - 2,
|
||||
<int>[4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f],
|
||||
);
|
||||
checkEncoding<dynamic>(
|
||||
standard,
|
||||
0x7fffffffffffffff,
|
||||
<int>[4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f],
|
||||
);
|
||||
checkEncoding<dynamic>(
|
||||
standard,
|
||||
0x7fffffffffffffff + 1,
|
||||
<int>[4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80],
|
||||
);
|
||||
});
|
||||
test('should encode and decode big numbers', () {
|
||||
checkEncodeDecode<dynamic>(standard, 9223372036854775807);
|
||||
checkEncodeDecode<dynamic>(standard, -9223372036854775807);
|
||||
});
|
||||
test('should encode and decode a list containing big numbers', () {
|
||||
final List<dynamic> message = <dynamic>[
|
||||
-7000000000000000007,
|
||||
Int64List.fromList(
|
||||
<int>[-0x7fffffffffffffff - 1, 0, 0x7fffffffffffffff]),
|
||||
];
|
||||
checkEncodeDecode<dynamic>(standard, message);
|
||||
});
|
||||
});
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user