mirror of https://github.com/grpc/grpc-dart.git
Enable and fix pedantic v1.9 lints (#445)
Co-authored-by: Vyacheslav Egorov <vegorov@google.com>
This commit is contained in:
parent
cbec527ba7
commit
32fbc03c63
|
|
@ -28,18 +28,17 @@ jobs:
|
||||||
run: dart pub get
|
run: dart pub get
|
||||||
- name: Check formatting
|
- name: Check formatting
|
||||||
run: dart format --output=none --set-exit-if-changed .
|
run: dart format --output=none --set-exit-if-changed .
|
||||||
- name: Analyze code (lib and test)
|
|
||||||
run: dart analyze --fatal-infos .
|
|
||||||
- name: Analyze code (introp and examples)
|
- name: Analyze code (introp and examples)
|
||||||
run: |
|
run: |
|
||||||
for example in interop example/*/; do
|
for example in interop example/*/; do
|
||||||
pushd $example
|
pushd $example
|
||||||
echo [Analyzing $example]
|
echo [Getting dependencies in $example]
|
||||||
dart pub get
|
dart pub get
|
||||||
dart analyze --fatal-infos .
|
|
||||||
popd
|
popd
|
||||||
done
|
done
|
||||||
shell: bash
|
shell: bash
|
||||||
|
- name: Analyze code
|
||||||
|
run: dart analyze --fatal-infos .
|
||||||
|
|
||||||
# Run tests on a matrix consisting of three dimensions:
|
# Run tests on a matrix consisting of three dimensions:
|
||||||
# 1. OS: mac, windows, linux
|
# 1. OS: mac, windows, linux
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,56 @@
|
||||||
# Lint rules and documentation, see http://dart-lang.github.io/linter/lints
|
# Lint rules and documentation, see http://dart-lang.github.io/linter/lints
|
||||||
analyzer:
|
|
||||||
exclude:
|
|
||||||
- example/**
|
|
||||||
- interop/**
|
|
||||||
linter:
|
linter:
|
||||||
rules:
|
rules:
|
||||||
|
- always_declare_return_types
|
||||||
|
- always_require_non_null_named_parameters
|
||||||
|
- annotate_overrides
|
||||||
|
- avoid_empty_else
|
||||||
- avoid_init_to_null
|
- avoid_init_to_null
|
||||||
|
- avoid_null_checks_in_equality_operators
|
||||||
|
- avoid_relative_lib_imports
|
||||||
|
- avoid_return_types_on_setters
|
||||||
|
- avoid_shadowing_type_parameters
|
||||||
|
- avoid_types_as_parameter_names
|
||||||
|
- camel_case_extensions
|
||||||
- cancel_subscriptions
|
- cancel_subscriptions
|
||||||
- close_sinks
|
- close_sinks
|
||||||
|
- curly_braces_in_flow_control_structures
|
||||||
- directives_ordering
|
- directives_ordering
|
||||||
|
- empty_catches
|
||||||
|
- empty_constructor_bodies
|
||||||
- hash_and_equals
|
- hash_and_equals
|
||||||
- iterable_contains_unrelated_type
|
- iterable_contains_unrelated_type
|
||||||
|
- library_names
|
||||||
|
- library_prefixes
|
||||||
- list_remove_unrelated_type
|
- list_remove_unrelated_type
|
||||||
|
- no_duplicate_case_values
|
||||||
|
- null_closures
|
||||||
|
- omit_local_variable_types
|
||||||
|
- prefer_adjacent_string_concatenation
|
||||||
|
- prefer_collection_literals
|
||||||
|
- prefer_conditional_assignment
|
||||||
|
- prefer_contains
|
||||||
|
- prefer_equal_for_default_values
|
||||||
- prefer_final_fields
|
- prefer_final_fields
|
||||||
- prefer_final_locals
|
- prefer_final_locals
|
||||||
|
- prefer_for_elements_to_map_fromIterable
|
||||||
|
- prefer_generic_function_type_aliases
|
||||||
|
- prefer_if_null_operators
|
||||||
|
- prefer_is_empty
|
||||||
- prefer_is_not_empty
|
- prefer_is_not_empty
|
||||||
|
- prefer_iterable_whereType
|
||||||
|
- prefer_single_quotes
|
||||||
|
- prefer_spread_collections
|
||||||
|
- recursive_getters
|
||||||
|
- slash_for_doc_comments
|
||||||
- test_types_in_equals
|
- test_types_in_equals
|
||||||
|
- type_init_formals
|
||||||
|
- unnecessary_const
|
||||||
|
- unnecessary_new
|
||||||
|
- unnecessary_null_in_if_null_operators
|
||||||
|
- unnecessary_this
|
||||||
- unrelated_type_equality_checks
|
- unrelated_type_equality_checks
|
||||||
|
- use_function_type_syntax_for_parameters
|
||||||
|
- use_rethrow_when_possible
|
||||||
- valid_regexps
|
- valid_regexps
|
||||||
- prefer_collection_literals
|
|
||||||
|
|
|
||||||
|
|
@ -33,11 +33,11 @@ class EchoApp {
|
||||||
}
|
}
|
||||||
|
|
||||||
void _addLeftMessage(String message) {
|
void _addLeftMessage(String message) {
|
||||||
_addMessage(message, "label-primary pull-left");
|
_addMessage(message, 'label-primary pull-left');
|
||||||
}
|
}
|
||||||
|
|
||||||
void _addRightMessage(String message) {
|
void _addRightMessage(String message) {
|
||||||
_addMessage(message, "label-default pull-right");
|
_addMessage(message, 'label-default pull-right');
|
||||||
}
|
}
|
||||||
|
|
||||||
void _addMessage(String message, String cssClass) {
|
void _addMessage(String message, String cssClass) {
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,6 @@
|
||||||
|
|
||||||
import 'package:metadata/src/client.dart';
|
import 'package:metadata/src/client.dart';
|
||||||
|
|
||||||
main(List<String> args) {
|
void main(List<String> args) {
|
||||||
Client().main(args);
|
Client().main(args);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,6 @@
|
||||||
|
|
||||||
import 'package:metadata/src/server.dart';
|
import 'package:metadata/src/server.dart';
|
||||||
|
|
||||||
main(List<String> args) {
|
void main(List<String> args) {
|
||||||
Server().main(args);
|
Server().main(args);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,7 @@ class Client {
|
||||||
/// after receiving more than 5 responses.
|
/// after receiving more than 5 responses.
|
||||||
Future<void> runFibonacciCancel() async {
|
Future<void> runFibonacciCancel() async {
|
||||||
final call = stub.fibonacci(Empty());
|
final call = stub.fibonacci(Empty());
|
||||||
int count = 0;
|
var count = 0;
|
||||||
try {
|
try {
|
||||||
await for (var number in call) {
|
await for (var number in call) {
|
||||||
count++;
|
count++;
|
||||||
|
|
@ -135,7 +135,7 @@ class Client {
|
||||||
Future<void> runFibonacciTimeout() async {
|
Future<void> runFibonacciTimeout() async {
|
||||||
final call = stub.fibonacci(Empty(),
|
final call = stub.fibonacci(Empty(),
|
||||||
options: CallOptions(timeout: Duration(seconds: 2)));
|
options: CallOptions(timeout: Duration(seconds: 2)));
|
||||||
int count = 0;
|
var count = 0;
|
||||||
try {
|
try {
|
||||||
await for (var number in call) {
|
await for (var number in call) {
|
||||||
count++;
|
count++;
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ class MetadataService extends MetadataServiceBase {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Stream<Number> addOne(grpc.ServiceCall call, Stream<Number> request) async* {
|
Stream<Number> addOne(grpc.ServiceCall call, Stream<Number> request) async* {
|
||||||
int lastNumber = -1;
|
var lastNumber = -1;
|
||||||
try {
|
try {
|
||||||
await for (var number in request) {
|
await for (var number in request) {
|
||||||
lastNumber = number.value;
|
lastNumber = number.value;
|
||||||
|
|
@ -56,9 +56,10 @@ class MetadataService extends MetadataServiceBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Streams a Fibonacci number every 500ms until the call is canceled.
|
/// Streams a Fibonacci number every 500ms until the call is canceled.
|
||||||
|
@override
|
||||||
Stream<Number> fibonacci(grpc.ServiceCall call, Empty request) async* {
|
Stream<Number> fibonacci(grpc.ServiceCall call, Empty request) async* {
|
||||||
int previous = 0;
|
var previous = 0;
|
||||||
int current = 1;
|
var current = 1;
|
||||||
try {
|
try {
|
||||||
while (true) {
|
while (true) {
|
||||||
await Future.delayed(Duration(milliseconds: 500));
|
await Future.delayed(Duration(milliseconds: 500));
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,6 @@
|
||||||
|
|
||||||
import 'package:route_guide/src/client.dart';
|
import 'package:route_guide/src/client.dart';
|
||||||
|
|
||||||
main(List<String> args) async {
|
Future<void> main(List<String> args) async {
|
||||||
await Client().main(args);
|
await Client().main(args);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,6 @@
|
||||||
|
|
||||||
import 'package:route_guide/src/server.dart';
|
import 'package:route_guide/src/server.dart';
|
||||||
|
|
||||||
main(List<String> args) async {
|
Future<void> main(List<String> args) async {
|
||||||
await Server().main(args);
|
await Server().main(args);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@ class Client {
|
||||||
Stream<Point> generateRoute(int count) async* {
|
Stream<Point> generateRoute(int count) async* {
|
||||||
final random = Random();
|
final random = Random();
|
||||||
|
|
||||||
for (int i = 0; i < count; i++) {
|
for (var i = 0; i < count; i++) {
|
||||||
final point = featuresDb[random.nextInt(featuresDb.length)].location;
|
final point = featuresDb[random.nextInt(featuresDb.length)].location;
|
||||||
print(
|
print(
|
||||||
'Visiting point ${point.latitude / coordFactor}, ${point.longitude / coordFactor}');
|
'Visiting point ${point.latitude / coordFactor}, ${point.longitude / coordFactor}');
|
||||||
|
|
|
||||||
|
|
@ -75,9 +75,9 @@ class RouteGuideService extends RouteGuideServiceBase {
|
||||||
@override
|
@override
|
||||||
Future<RouteSummary> recordRoute(
|
Future<RouteSummary> recordRoute(
|
||||||
grpc.ServiceCall call, Stream<Point> request) async {
|
grpc.ServiceCall call, Stream<Point> request) async {
|
||||||
int pointCount = 0;
|
var pointCount = 0;
|
||||||
int featureCount = 0;
|
var featureCount = 0;
|
||||||
double distance = 0.0;
|
var distance = 0.0;
|
||||||
Point previous;
|
Point previous;
|
||||||
final timer = Stopwatch();
|
final timer = Stopwatch();
|
||||||
|
|
||||||
|
|
@ -110,7 +110,9 @@ class RouteGuideService extends RouteGuideServiceBase {
|
||||||
grpc.ServiceCall call, Stream<RouteNote> request) async* {
|
grpc.ServiceCall call, Stream<RouteNote> request) async* {
|
||||||
await for (var note in request) {
|
await for (var note in request) {
|
||||||
final notes = routeNotes.putIfAbsent(note.location, () => <RouteNote>[]);
|
final notes = routeNotes.putIfAbsent(note.location, () => <RouteNote>[]);
|
||||||
for (var note in notes) yield note;
|
for (var note in notes) {
|
||||||
|
yield note;
|
||||||
|
}
|
||||||
notes.add(note);
|
notes.add(note);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ class Tester {
|
||||||
return File(serviceAccountKeyFile).readAsStringSync();
|
return File(serviceAccountKeyFile).readAsStringSync();
|
||||||
}
|
}
|
||||||
|
|
||||||
void set serverPort(String value) {
|
set serverPort(String value) {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
_serverPort = null;
|
_serverPort = null;
|
||||||
return;
|
return;
|
||||||
|
|
@ -63,11 +63,11 @@ class Tester {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void set useTls(String value) {
|
set useTls(String value) {
|
||||||
_useTls = value != 'false';
|
_useTls = value != 'false';
|
||||||
}
|
}
|
||||||
|
|
||||||
void set useTestCA(String value) {
|
set useTestCA(String value) {
|
||||||
_useTestCA = value == 'true';
|
_useTestCA = value == 'true';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -613,7 +613,7 @@ class Tester {
|
||||||
final call = client.fullDuplexCall(requests.stream);
|
final call = client.fullDuplexCall(requests.stream);
|
||||||
requests.close();
|
requests.close();
|
||||||
final responses = await call.toList();
|
final responses = await call.toList();
|
||||||
if (responses.length != 0) {
|
if (responses.isNotEmpty) {
|
||||||
throw 'Received too many responses. ${responses.length} != 0';
|
throw 'Received too many responses. ${responses.length} != 0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,7 @@ abstract class BaseAuthenticator {
|
||||||
abstract class HttpBasedAuthenticator extends BaseAuthenticator {
|
abstract class HttpBasedAuthenticator extends BaseAuthenticator {
|
||||||
Future<void>? _call;
|
Future<void>? _call;
|
||||||
|
|
||||||
|
@override
|
||||||
Future<void> obtainAccessCredentials(String uri) {
|
Future<void> obtainAccessCredentials(String uri) {
|
||||||
if (_call == null) {
|
if (_call == null) {
|
||||||
final authClient = http.Client();
|
final authClient = http.Client();
|
||||||
|
|
@ -94,6 +95,7 @@ class JwtServiceAccountAuthenticator extends BaseAuthenticator {
|
||||||
|
|
||||||
String? get projectId => _projectId;
|
String? get projectId => _projectId;
|
||||||
|
|
||||||
|
@override
|
||||||
Future<void> obtainAccessCredentials(String uri) async {
|
Future<void> obtainAccessCredentials(String uri) async {
|
||||||
_accessToken = _jwtTokenFor(_serviceAccountCredentials, _keyId, uri);
|
_accessToken = _jwtTokenFor(_serviceAccountCredentials, _keyId, uri);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import 'package:http/http.dart' as http;
|
||||||
import 'auth.dart';
|
import 'auth.dart';
|
||||||
|
|
||||||
class ComputeEngineAuthenticator extends HttpBasedAuthenticator {
|
class ComputeEngineAuthenticator extends HttpBasedAuthenticator {
|
||||||
|
@override
|
||||||
Future<auth.AccessCredentials> obtainCredentialsWithClient(
|
Future<auth.AccessCredentials> obtainCredentialsWithClient(
|
||||||
http.Client client, String uri) =>
|
http.Client client, String uri) =>
|
||||||
auth.obtainAccessCredentialsViaMetadataServer(client);
|
auth.obtainAccessCredentialsViaMetadataServer(client);
|
||||||
|
|
@ -30,6 +31,7 @@ class ServiceAccountAuthenticator extends HttpBasedAuthenticator {
|
||||||
|
|
||||||
String? get projectId => _projectId;
|
String? get projectId => _projectId;
|
||||||
|
|
||||||
|
@override
|
||||||
Future<auth.AccessCredentials> obtainCredentialsWithClient(
|
Future<auth.AccessCredentials> obtainCredentialsWithClient(
|
||||||
http.Client client, String uri) =>
|
http.Client client, String uri) =>
|
||||||
auth.obtainAccessCredentialsViaServiceAccount(
|
auth.obtainAccessCredentialsViaServiceAccount(
|
||||||
|
|
@ -47,6 +49,7 @@ class _CredentialsRefreshingAuthenticator extends HttpBasedAuthenticator {
|
||||||
this._quotaProject,
|
this._quotaProject,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
Future<void> authenticate(Map<String, String> metadata, String uri) async {
|
Future<void> authenticate(Map<String, String> metadata, String uri) async {
|
||||||
await super.authenticate(metadata, uri);
|
await super.authenticate(metadata, uri);
|
||||||
if (_quotaProject != null) {
|
if (_quotaProject != null) {
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ class RS256Signer {
|
||||||
// NIST sha-256 OID (2 16 840 1 101 3 4 2 1)
|
// NIST sha-256 OID (2 16 840 1 101 3 4 2 1)
|
||||||
// See a reference for the encoding here:
|
// See a reference for the encoding here:
|
||||||
// http://msdn.microsoft.com/en-us/library/bb540809%28v=vs.85%29.aspx
|
// http://msdn.microsoft.com/en-us/library/bb540809%28v=vs.85%29.aspx
|
||||||
static const _RSA_SHA256_ALGORITHM_IDENTIFIER = const [
|
static const _RSA_SHA256_ALGORITHM_IDENTIFIER = [
|
||||||
0x06,
|
0x06,
|
||||||
0x09,
|
0x09,
|
||||||
0x60,
|
0x60,
|
||||||
|
|
@ -52,7 +52,7 @@ class RS256Signer {
|
||||||
final digest = _digestInfo(sha256.convert(bytes).bytes);
|
final digest = _digestInfo(sha256.convert(bytes).bytes);
|
||||||
final modulusLen = (_rsaKey.bitLength + 7) ~/ 8;
|
final modulusLen = (_rsaKey.bitLength + 7) ~/ 8;
|
||||||
|
|
||||||
final block = new Uint8List(modulusLen);
|
final block = Uint8List(modulusLen);
|
||||||
final padLength = block.length - digest.length - 3;
|
final padLength = block.length - digest.length - 3;
|
||||||
block[0] = 0x00;
|
block[0] = 0x00;
|
||||||
block[1] = 0x01;
|
block[1] = 0x01;
|
||||||
|
|
@ -68,7 +68,7 @@ class RS256Signer {
|
||||||
// digest OCTET STRING
|
// digest OCTET STRING
|
||||||
// }
|
// }
|
||||||
var offset = 0;
|
var offset = 0;
|
||||||
final digestInfo = new Uint8List(
|
final digestInfo = Uint8List(
|
||||||
2 + 2 + _RSA_SHA256_ALGORITHM_IDENTIFIER.length + 2 + 2 + hash.length);
|
2 + 2 + _RSA_SHA256_ALGORITHM_IDENTIFIER.length + 2 + 2 + hash.length);
|
||||||
{
|
{
|
||||||
// DigestInfo
|
// DigestInfo
|
||||||
|
|
@ -100,14 +100,14 @@ class ASN1Parser {
|
||||||
|
|
||||||
static ASN1Object parse(Uint8List bytes) {
|
static ASN1Object parse(Uint8List bytes) {
|
||||||
Never invalidFormat(String msg) {
|
Never invalidFormat(String msg) {
|
||||||
throw new ArgumentError("Invalid DER encoding: $msg");
|
throw ArgumentError('Invalid DER encoding: $msg');
|
||||||
}
|
}
|
||||||
|
|
||||||
final data = new ByteData.view(bytes.buffer);
|
final data = ByteData.view(bytes.buffer);
|
||||||
int offset = 0;
|
var offset = 0;
|
||||||
final end = bytes.length;
|
final end = bytes.length;
|
||||||
|
|
||||||
checkNBytesAvailable(int n) {
|
void checkNBytesAvailable(int n) {
|
||||||
if ((offset + n) > end) {
|
if ((offset + n) > end) {
|
||||||
invalidFormat('Tried to read more bytes than available.');
|
invalidFormat('Tried to read more bytes than available.');
|
||||||
}
|
}
|
||||||
|
|
@ -134,10 +134,10 @@ class ASN1Parser {
|
||||||
// Long length encoding form:
|
// Long length encoding form:
|
||||||
// This byte has in bits 0..6 the number of bytes following which encode
|
// This byte has in bits 0..6 the number of bytes following which encode
|
||||||
// the length.
|
// the length.
|
||||||
int countLengthBytes = lengthByte & 0x7f;
|
var countLengthBytes = lengthByte & 0x7f;
|
||||||
checkNBytesAvailable(countLengthBytes);
|
checkNBytesAvailable(countLengthBytes);
|
||||||
|
|
||||||
int length = 0;
|
var length = 0;
|
||||||
while (countLengthBytes > 0) {
|
while (countLengthBytes > 0) {
|
||||||
length = (length << 8) | data.getUint8(offset++);
|
length = (length << 8) | data.getUint8(offset++);
|
||||||
countLengthBytes--;
|
countLengthBytes--;
|
||||||
|
|
@ -159,16 +159,16 @@ class ASN1Parser {
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case INTEGER_TAG:
|
case INTEGER_TAG:
|
||||||
final size = readEncodedLength();
|
final size = readEncodedLength();
|
||||||
return new ASN1Integer(RSAAlgorithm.bytes2BigInt(readBytes(size)));
|
return ASN1Integer(RSAAlgorithm.bytes2BigInt(readBytes(size)));
|
||||||
case OCTET_STRING_TAG:
|
case OCTET_STRING_TAG:
|
||||||
final size = readEncodedLength();
|
final size = readEncodedLength();
|
||||||
return new ASN1OctetString(readBytes(size));
|
return ASN1OctetString(readBytes(size));
|
||||||
case NULL_TAG:
|
case NULL_TAG:
|
||||||
readNullBytes();
|
readNullBytes();
|
||||||
return new ASN1Null();
|
return ASN1Null();
|
||||||
case OBJECT_ID_TAG:
|
case OBJECT_ID_TAG:
|
||||||
final size = readEncodedLength();
|
final size = readEncodedLength();
|
||||||
return new ASN1ObjectIdentifier(readBytes(size));
|
return ASN1ObjectIdentifier(readBytes(size));
|
||||||
case SEQUENCE_TAG:
|
case SEQUENCE_TAG:
|
||||||
final lengthInBytes = readEncodedLength();
|
final lengthInBytes = readEncodedLength();
|
||||||
if ((offset + lengthInBytes) > end) {
|
if ((offset + lengthInBytes) > end) {
|
||||||
|
|
@ -180,7 +180,7 @@ class ASN1Parser {
|
||||||
while (offset < endOfSequence) {
|
while (offset < endOfSequence) {
|
||||||
objects.add(decodeObject());
|
objects.add(decodeObject());
|
||||||
}
|
}
|
||||||
return new ASN1Sequence(objects);
|
return ASN1Sequence(objects);
|
||||||
default:
|
default:
|
||||||
invalidFormat(
|
invalidFormat(
|
||||||
'Unexpected tag $tag at offset ${offset - 1} (end: $end).');
|
'Unexpected tag $tag at offset ${offset - 1} (end: $end).');
|
||||||
|
|
@ -189,7 +189,7 @@ class ASN1Parser {
|
||||||
|
|
||||||
final obj = decodeObject();
|
final obj = decodeObject();
|
||||||
if (offset != bytes.length) {
|
if (offset != bytes.length) {
|
||||||
throw new ArgumentError('More bytes than expected in ASN1 encoding.');
|
throw ArgumentError('More bytes than expected in ASN1 encoding.');
|
||||||
}
|
}
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
@ -300,17 +300,17 @@ abstract class RSAAlgorithm {
|
||||||
static BigInt bytes2BigInt(List<int> bytes) {
|
static BigInt bytes2BigInt(List<int> bytes) {
|
||||||
var number = BigInt.zero;
|
var number = BigInt.zero;
|
||||||
for (var i = 0; i < bytes.length; i++) {
|
for (var i = 0; i < bytes.length; i++) {
|
||||||
number = (number << 8) | new BigInt.from(bytes[i]);
|
number = (number << 8) | BigInt.from(bytes[i]);
|
||||||
}
|
}
|
||||||
return number;
|
return number;
|
||||||
}
|
}
|
||||||
|
|
||||||
static List<int> integer2Bytes(BigInt integer, int intendedLength) {
|
static List<int> integer2Bytes(BigInt integer, int intendedLength) {
|
||||||
if (integer < BigInt.one) {
|
if (integer < BigInt.one) {
|
||||||
throw new ArgumentError('Only positive integers are supported.');
|
throw ArgumentError('Only positive integers are supported.');
|
||||||
}
|
}
|
||||||
final bytes = new Uint8List(intendedLength);
|
final bytes = Uint8List(intendedLength);
|
||||||
for (int i = bytes.length - 1; i >= 0; i--) {
|
for (var i = bytes.length - 1; i >= 0; i--) {
|
||||||
bytes[i] = (integer & _bigIntFF).toInt();
|
bytes[i] = (integer & _bigIntFF).toInt();
|
||||||
integer >>= 8;
|
integer >>= 8;
|
||||||
}
|
}
|
||||||
|
|
@ -318,4 +318,4 @@ abstract class RSAAlgorithm {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final _bigIntFF = new BigInt.from(0xff);
|
final _bigIntFF = BigInt.from(0xff);
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ const _statusDetailsHeader = 'grpc-status-details-bin';
|
||||||
/// by previous metadata providers) and the [uri] that is being called, and is
|
/// by previous metadata providers) and the [uri] that is being called, and is
|
||||||
/// expected to modify the map before returning or before completing the
|
/// expected to modify the map before returning or before completing the
|
||||||
/// returned [Future].
|
/// returned [Future].
|
||||||
typedef FutureOr<void> MetadataProvider(
|
typedef MetadataProvider = FutureOr<void> Function(
|
||||||
Map<String, String> metadata, String uri);
|
Map<String, String> metadata, String uri);
|
||||||
|
|
||||||
/// Runtime options for an RPC.
|
/// Runtime options for an RPC.
|
||||||
|
|
|
||||||
|
|
@ -45,8 +45,7 @@ regenerate these stubs using protobuf compiler plugin version 19.2.0 or newer.
|
||||||
|
|
||||||
ResponseFuture<R> $createUnaryCall<Q, R>(ClientMethod<Q, R> method, Q request,
|
ResponseFuture<R> $createUnaryCall<Q, R>(ClientMethod<Q, R> method, Q request,
|
||||||
{CallOptions? options}) {
|
{CallOptions? options}) {
|
||||||
ClientUnaryInvoker<Q, R> invoker = (method, request, options) =>
|
var invoker = (method, request, options) => ResponseFuture<R>(
|
||||||
ResponseFuture<R>(
|
|
||||||
_channel.createCall<Q, R>(method, Stream.value(request), options));
|
_channel.createCall<Q, R>(method, Stream.value(request), options));
|
||||||
|
|
||||||
for (final interceptor in _interceptors.reversed) {
|
for (final interceptor in _interceptors.reversed) {
|
||||||
|
|
@ -61,7 +60,7 @@ regenerate these stubs using protobuf compiler plugin version 19.2.0 or newer.
|
||||||
ResponseStream<R> $createStreamingCall<Q, R>(
|
ResponseStream<R> $createStreamingCall<Q, R>(
|
||||||
ClientMethod<Q, R> method, Stream<Q> requests,
|
ClientMethod<Q, R> method, Stream<Q> requests,
|
||||||
{CallOptions? options}) {
|
{CallOptions? options}) {
|
||||||
ClientStreamingInvoker<Q, R> invoker = (method, request, options) =>
|
var invoker = (method, request, options) =>
|
||||||
ResponseStream<R>(_channel.createCall<Q, R>(method, requests, options));
|
ResponseStream<R>(_channel.createCall<Q, R>(method, requests, options));
|
||||||
|
|
||||||
for (final interceptor in _interceptors.reversed) {
|
for (final interceptor in _interceptors.reversed) {
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ abstract class Response {
|
||||||
/// A gRPC response producing a single value.
|
/// A gRPC response producing a single value.
|
||||||
class ResponseFuture<R> extends DelegatingFuture<R>
|
class ResponseFuture<R> extends DelegatingFuture<R>
|
||||||
with _ResponseMixin<dynamic, R> {
|
with _ResponseMixin<dynamic, R> {
|
||||||
|
@override
|
||||||
final ClientCall<dynamic, R> _call;
|
final ClientCall<dynamic, R> _call;
|
||||||
|
|
||||||
static R _ensureOnlyOneResponse<R>(R? previous, R element) {
|
static R _ensureOnlyOneResponse<R>(R? previous, R element) {
|
||||||
|
|
@ -67,11 +68,13 @@ class ResponseFuture<R> extends DelegatingFuture<R>
|
||||||
/// A gRPC response producing a stream of values.
|
/// A gRPC response producing a stream of values.
|
||||||
class ResponseStream<R> extends DelegatingStream<R>
|
class ResponseStream<R> extends DelegatingStream<R>
|
||||||
with _ResponseMixin<dynamic, R> {
|
with _ResponseMixin<dynamic, R> {
|
||||||
|
@override
|
||||||
final ClientCall<dynamic, R> _call;
|
final ClientCall<dynamic, R> _call;
|
||||||
|
|
||||||
ResponseStream(this._call) : super(_call.response);
|
ResponseStream(this._call) : super(_call.response);
|
||||||
|
|
||||||
ResponseFuture<R> get single => ResponseFuture(this._call);
|
@override
|
||||||
|
ResponseFuture<R> get single => ResponseFuture(_call);
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class _ResponseMixin<Q, R> implements Response {
|
abstract class _ResponseMixin<Q, R> implements Response {
|
||||||
|
|
|
||||||
|
|
@ -66,13 +66,15 @@ class Http2ClientConnection implements connection.ClientConnection {
|
||||||
|
|
||||||
ChannelCredentials get credentials => options.credentials;
|
ChannelCredentials get credentials => options.credentials;
|
||||||
|
|
||||||
|
@override
|
||||||
String get authority => _transportConnector.authority;
|
String get authority => _transportConnector.authority;
|
||||||
|
|
||||||
|
@override
|
||||||
String get scheme => options.credentials.isSecure ? 'https' : 'http';
|
String get scheme => options.credentials.isSecure ? 'https' : 'http';
|
||||||
|
|
||||||
ConnectionState get state => _state;
|
ConnectionState get state => _state;
|
||||||
|
|
||||||
static const _estimatedRoundTripTime = const Duration(milliseconds: 20);
|
static const _estimatedRoundTripTime = Duration(milliseconds: 20);
|
||||||
|
|
||||||
Future<ClientTransportConnection> connectTransport() async {
|
Future<ClientTransportConnection> connectTransport() async {
|
||||||
final connection = await _transportConnector.connect();
|
final connection = await _transportConnector.connect();
|
||||||
|
|
@ -81,7 +83,7 @@ class Http2ClientConnection implements connection.ClientConnection {
|
||||||
// Give the settings settings-frame a bit of time to arrive.
|
// Give the settings settings-frame a bit of time to arrive.
|
||||||
// TODO(sigurdm): This is a hack. The http2 package should expose a way of
|
// TODO(sigurdm): This is a hack. The http2 package should expose a way of
|
||||||
// waiting for the settings frame to arrive.
|
// waiting for the settings frame to arrive.
|
||||||
await new Future.delayed(_estimatedRoundTripTime);
|
await Future.delayed(_estimatedRoundTripTime);
|
||||||
|
|
||||||
if (_state == ConnectionState.shutdown) {
|
if (_state == ConnectionState.shutdown) {
|
||||||
_transportConnector.shutdown();
|
_transportConnector.shutdown();
|
||||||
|
|
@ -119,8 +121,8 @@ class Http2ClientConnection implements connection.ClientConnection {
|
||||||
///
|
///
|
||||||
/// Assumes [_transportConnection] is not `null`.
|
/// Assumes [_transportConnection] is not `null`.
|
||||||
void _refreshConnectionIfUnhealthy() {
|
void _refreshConnectionIfUnhealthy() {
|
||||||
final bool isHealthy = _transportConnection!.isOpen;
|
final isHealthy = _transportConnection!.isOpen;
|
||||||
final bool shouldRefresh =
|
final shouldRefresh =
|
||||||
_connectionLifeTimer.elapsed > options.connectionTimeout;
|
_connectionLifeTimer.elapsed > options.connectionTimeout;
|
||||||
if (shouldRefresh) {
|
if (shouldRefresh) {
|
||||||
_transportConnection!.finish();
|
_transportConnection!.finish();
|
||||||
|
|
@ -130,6 +132,7 @@ class Http2ClientConnection implements connection.ClientConnection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
void dispatchCall(ClientCall call) {
|
void dispatchCall(ClientCall call) {
|
||||||
if (_transportConnection != null) {
|
if (_transportConnection != null) {
|
||||||
_refreshConnectionIfUnhealthy();
|
_refreshConnectionIfUnhealthy();
|
||||||
|
|
@ -149,6 +152,7 @@ class Http2ClientConnection implements connection.ClientConnection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
GrpcTransportStream makeRequest(String path, Duration? timeout,
|
GrpcTransportStream makeRequest(String path, Duration? timeout,
|
||||||
Map<String, String> metadata, ErrorHandler onRequestFailure,
|
Map<String, String> metadata, ErrorHandler onRequestFailure,
|
||||||
{CallOptions? callOptions}) {
|
{CallOptions? callOptions}) {
|
||||||
|
|
@ -188,12 +192,14 @@ class Http2ClientConnection implements connection.ClientConnection {
|
||||||
_failCall(call, 'Connection shutting down.');
|
_failCall(call, 'Connection shutting down.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
Future<void> shutdown() async {
|
Future<void> shutdown() async {
|
||||||
if (_state == ConnectionState.shutdown) return null;
|
if (_state == ConnectionState.shutdown) return null;
|
||||||
_setShutdownState();
|
_setShutdownState();
|
||||||
await _transportConnection?.finish();
|
await _transportConnection?.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
Future<void> terminate() async {
|
Future<void> terminate() async {
|
||||||
_setShutdownState();
|
_setShutdownState();
|
||||||
await _transportConnection?.terminate();
|
await _transportConnection?.terminate();
|
||||||
|
|
@ -353,7 +359,7 @@ class _SocketTransportConnector implements ClientTransportConnector {
|
||||||
final host =
|
final host =
|
||||||
_host is String ? _host as String : (_host as InternetAddress).host;
|
_host is String ? _host as String : (_host as InternetAddress).host;
|
||||||
return _options.credentials.authority ??
|
return _options.credentials.authority ??
|
||||||
(_port == 443 ? host : "$host:$_port");
|
(_port == 443 ? host : '$host:$_port');
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ const defaultIdleTimeout = Duration(minutes: 5);
|
||||||
const defaultConnectionTimeOut = Duration(minutes: 50);
|
const defaultConnectionTimeOut = Duration(minutes: 50);
|
||||||
const defaultUserAgent = 'dart-grpc/2.0.0';
|
const defaultUserAgent = 'dart-grpc/2.0.0';
|
||||||
|
|
||||||
typedef Duration BackoffStrategy(Duration? lastBackoff);
|
typedef BackoffStrategy = Duration Function(Duration? lastBackoff);
|
||||||
|
|
||||||
// Backoff algorithm from https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md
|
// Backoff algorithm from https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md
|
||||||
const _initialBackoff = Duration(seconds: 1);
|
const _initialBackoff = Duration(seconds: 1);
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,8 @@ import '../../shared/security.dart';
|
||||||
/// returns `true`, the bad certificate is allowed, and the TLS handshake can
|
/// returns `true`, the bad certificate is allowed, and the TLS handshake can
|
||||||
/// continue. If the handler returns `false`, the TLS handshake fails, and the
|
/// continue. If the handler returns `false`, the TLS handshake fails, and the
|
||||||
/// connection is aborted.
|
/// connection is aborted.
|
||||||
typedef bool BadCertificateHandler(X509Certificate certificate, String host);
|
typedef BadCertificateHandler = bool Function(
|
||||||
|
X509Certificate certificate, String host);
|
||||||
|
|
||||||
/// Bad certificate handler that disables all certificate checks.
|
/// Bad certificate handler that disables all certificate checks.
|
||||||
/// DO NOT USE IN PRODUCTION!
|
/// DO NOT USE IN PRODUCTION!
|
||||||
|
|
@ -60,7 +61,7 @@ class ChannelCredentials {
|
||||||
..setTrustedCertificatesBytes(_certificateBytes!,
|
..setTrustedCertificatesBytes(_certificateBytes!,
|
||||||
password: _certificatePassword);
|
password: _certificatePassword);
|
||||||
}
|
}
|
||||||
final context = new SecurityContext(withTrustedRoots: true);
|
final context = SecurityContext(withTrustedRoots: true);
|
||||||
context.setAlpnProtocols(supportedAlpnProtocols, false);
|
context.setAlpnProtocols(supportedAlpnProtocols, false);
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,10 +25,12 @@ import 'transport.dart';
|
||||||
|
|
||||||
class Http2TransportStream extends GrpcTransportStream {
|
class Http2TransportStream extends GrpcTransportStream {
|
||||||
final TransportStream _transportStream;
|
final TransportStream _transportStream;
|
||||||
|
@override
|
||||||
final Stream<GrpcMessage> incomingMessages;
|
final Stream<GrpcMessage> incomingMessages;
|
||||||
final StreamController<List<int>> _outgoingMessages = StreamController();
|
final StreamController<List<int>> _outgoingMessages = StreamController();
|
||||||
final ErrorHandler _onError;
|
final ErrorHandler _onError;
|
||||||
|
|
||||||
|
@override
|
||||||
StreamSink<List<int>> get outgoingMessages => _outgoingMessages.sink;
|
StreamSink<List<int>> get outgoingMessages => _outgoingMessages.sink;
|
||||||
|
|
||||||
Http2TransportStream(
|
Http2TransportStream(
|
||||||
|
|
|
||||||
|
|
@ -17,12 +17,13 @@ import 'dart:async';
|
||||||
|
|
||||||
import '../../shared/message.dart';
|
import '../../shared/message.dart';
|
||||||
|
|
||||||
typedef void SocketClosedHandler();
|
typedef SocketClosedHandler = void Function();
|
||||||
typedef void ActiveStateHandler(bool isActive);
|
typedef ActiveStateHandler = void Function(bool isActive);
|
||||||
typedef void ErrorHandler(error, StackTrace stackTrace);
|
typedef ErrorHandler = void Function(Object, StackTrace);
|
||||||
|
|
||||||
abstract class GrpcTransportStream {
|
abstract class GrpcTransportStream {
|
||||||
Stream<GrpcMessage> get incomingMessages;
|
Stream<GrpcMessage> get incomingMessages;
|
||||||
|
|
||||||
StreamSink<List<int>> get outgoingMessages;
|
StreamSink<List<int>> get outgoingMessages;
|
||||||
|
|
||||||
Future<void> terminate();
|
Future<void> terminate();
|
||||||
|
|
|
||||||
|
|
@ -166,7 +166,9 @@ class XhrClientConnection extends ClientConnection {
|
||||||
|
|
||||||
XhrClientConnection(this.uri);
|
XhrClientConnection(this.uri);
|
||||||
|
|
||||||
|
@override
|
||||||
String get authority => uri.authority;
|
String get authority => uri.authority;
|
||||||
|
@override
|
||||||
String get scheme => uri.scheme;
|
String get scheme => uri.scheme;
|
||||||
|
|
||||||
void _initializeRequest(HttpRequest request, Map<String, String> metadata) {
|
void _initializeRequest(HttpRequest request, Map<String, String> metadata) {
|
||||||
|
|
@ -198,7 +200,7 @@ class XhrClientConnection extends ClientConnection {
|
||||||
requestUri = cors.moveHttpHeadersToQueryParam(metadata, requestUri);
|
requestUri = cors.moveHttpHeadersToQueryParam(metadata, requestUri);
|
||||||
}
|
}
|
||||||
|
|
||||||
final HttpRequest request = createHttpRequest();
|
final request = createHttpRequest();
|
||||||
request.open('POST', requestUri.toString());
|
request.open('POST', requestUri.toString());
|
||||||
if (callOptions is WebCallOptions && callOptions.withCredentials == true) {
|
if (callOptions is WebCallOptions && callOptions.withCredentials == true) {
|
||||||
request.withCredentials = true;
|
request.withCredentials = true;
|
||||||
|
|
@ -206,7 +208,7 @@ class XhrClientConnection extends ClientConnection {
|
||||||
// Must set headers after calling open().
|
// Must set headers after calling open().
|
||||||
_initializeRequest(request, metadata);
|
_initializeRequest(request, metadata);
|
||||||
|
|
||||||
final XhrTransportStream transportStream =
|
final transportStream =
|
||||||
XhrTransportStream(request, onError: onError, onDone: _removeStream);
|
XhrTransportStream(request, onError: onError, onDone: _removeStream);
|
||||||
_requests.add(transportStream);
|
_requests.add(transportStream);
|
||||||
return transportStream;
|
return transportStream;
|
||||||
|
|
|
||||||
|
|
@ -66,16 +66,22 @@ class ServerHandler_ extends ServiceCall {
|
||||||
this._codecRegistry,
|
this._codecRegistry,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
DateTime? get deadline => _deadline;
|
DateTime? get deadline => _deadline;
|
||||||
|
|
||||||
|
@override
|
||||||
bool get isCanceled => _isCanceled;
|
bool get isCanceled => _isCanceled;
|
||||||
|
|
||||||
|
@override
|
||||||
bool get isTimedOut => _isTimedOut;
|
bool get isTimedOut => _isTimedOut;
|
||||||
|
|
||||||
|
@override
|
||||||
Map<String, String>? get clientMetadata => _clientMetadata;
|
Map<String, String>? get clientMetadata => _clientMetadata;
|
||||||
|
|
||||||
|
@override
|
||||||
Map<String, String>? get headers => _customHeaders;
|
Map<String, String>? get headers => _customHeaders;
|
||||||
|
|
||||||
|
@override
|
||||||
Map<String, String>? get trailers => _customTrailers;
|
Map<String, String>? get trailers => _customTrailers;
|
||||||
|
|
||||||
void handle() {
|
void handle() {
|
||||||
|
|
@ -162,7 +168,7 @@ class ServerHandler_ extends ServiceCall {
|
||||||
Future<GrpcError?> _applyInterceptors() async {
|
Future<GrpcError?> _applyInterceptors() async {
|
||||||
try {
|
try {
|
||||||
for (final interceptor in _interceptors) {
|
for (final interceptor in _interceptors) {
|
||||||
final error = await interceptor(this, this._descriptor);
|
final error = await interceptor(this, _descriptor);
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
@ -293,6 +299,7 @@ class ServerHandler_ extends ServiceCall {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
void sendHeaders() {
|
void sendHeaders() {
|
||||||
if (_headersSent) throw GrpcError.internal('Headers already sent');
|
if (_headersSent) throw GrpcError.internal('Headers already sent');
|
||||||
|
|
||||||
|
|
@ -316,6 +323,7 @@ class ServerHandler_ extends ServiceCall {
|
||||||
_headersSent = true;
|
_headersSent = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
void sendTrailers({int? status = 0, String? message}) {
|
void sendTrailers({int? status = 0, String? message}) {
|
||||||
_timeoutTimer?.cancel();
|
_timeoutTimer?.cancel();
|
||||||
|
|
||||||
|
|
@ -336,7 +344,7 @@ class ServerHandler_ extends ServiceCall {
|
||||||
outgoingTrailersMap['grpc-status'] = status.toString();
|
outgoingTrailersMap['grpc-status'] = status.toString();
|
||||||
if (message != null) {
|
if (message != null) {
|
||||||
outgoingTrailersMap['grpc-message'] =
|
outgoingTrailersMap['grpc-message'] =
|
||||||
Uri.encodeFull(message).replaceAll("%20", " ");
|
Uri.encodeFull(message).replaceAll('%20', ' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
final outgoingTrailers = <Header>[];
|
final outgoingTrailers = <Header>[];
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,7 @@ class ServerTlsCredentials extends ServerCredentials {
|
||||||
this.privateKey,
|
this.privateKey,
|
||||||
this.privateKeyPassword});
|
this.privateKeyPassword});
|
||||||
|
|
||||||
|
@override
|
||||||
SecurityContext get securityContext {
|
SecurityContext get securityContext {
|
||||||
final context = createSecurityContext(true);
|
final context = createSecurityContext(true);
|
||||||
if (privateKey != null) {
|
if (privateKey != null) {
|
||||||
|
|
@ -152,6 +153,7 @@ class Server extends ConnectionServer {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
Service? lookupService(String service) => _services[service];
|
Service? lookupService(String service) => _services[service];
|
||||||
|
|
||||||
/// Starts the [Server] with the given options.
|
/// Starts the [Server] with the given options.
|
||||||
|
|
@ -162,9 +164,9 @@ class Server extends ConnectionServer {
|
||||||
int? port,
|
int? port,
|
||||||
ServerCredentials? security,
|
ServerCredentials? security,
|
||||||
ServerSettings? http2ServerSettings,
|
ServerSettings? http2ServerSettings,
|
||||||
int backlog: 0,
|
int backlog = 0,
|
||||||
bool v6Only: false,
|
bool v6Only = false,
|
||||||
bool shared: false}) async {
|
bool shared = false}) async {
|
||||||
// TODO(dart-lang/grpc-dart#9): Handle HTTP/1.1 upgrade to h2c, if allowed.
|
// TODO(dart-lang/grpc-dart#9): Handle HTTP/1.1 upgrade to h2c, if allowed.
|
||||||
Stream<Socket>? server;
|
Stream<Socket>? server;
|
||||||
final securityContext = security?.securityContext;
|
final securityContext = security?.securityContext;
|
||||||
|
|
@ -198,6 +200,7 @@ class Server extends ConnectionServer {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
@visibleForTesting
|
@visibleForTesting
|
||||||
ServerHandler_ serveStream_(ServerTransportStream stream) {
|
ServerHandler_ serveStream_(ServerTransportStream stream) {
|
||||||
return ServerHandler_(lookupService, stream, _interceptors, _codecRegistry)
|
return ServerHandler_(lookupService, stream, _interceptors, _codecRegistry)
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ class ServiceMethod<Q, R> {
|
||||||
return future;
|
return future;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _awaitAndCatch<Q>(Future<Q> f) async {
|
void _awaitAndCatch(Future<Q> f) async {
|
||||||
try {
|
try {
|
||||||
await f;
|
await f;
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ class GzipCodec implements Codec {
|
||||||
const GzipCodec();
|
const GzipCodec();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
final encodingName = "gzip";
|
final encodingName = 'gzip';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<int> compress(List<int> data) {
|
List<int> compress(List<int> data) {
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
|
|
||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
|
|
||||||
typedef TimelineTask TimelineTaskFactory(
|
typedef TimelineTaskFactory = TimelineTask Function(
|
||||||
{String? filterKey, TimelineTask? parent});
|
{String? filterKey, TimelineTask? parent});
|
||||||
|
|
||||||
TimelineTaskFactory timelineTaskFactory = _defaultTimelineTaskFactory;
|
TimelineTaskFactory timelineTaskFactory = _defaultTimelineTaskFactory;
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ class TestClient extends grpc.Client {
|
||||||
}
|
}
|
||||||
|
|
||||||
class TestService extends grpc.Service {
|
class TestService extends grpc.Service {
|
||||||
|
@override
|
||||||
String get $name => 'test.TestService';
|
String get $name => 'test.TestService';
|
||||||
|
|
||||||
TestService() {
|
TestService() {
|
||||||
|
|
@ -47,11 +48,11 @@ class FixedConnectionClientChannel extends ClientChannelBase {
|
||||||
ClientConnection createConnection() => clientConnection;
|
ClientConnection createConnection() => clientConnection;
|
||||||
}
|
}
|
||||||
|
|
||||||
main() async {
|
Future<void> main() async {
|
||||||
testTcpAndUds('client reconnects after the connection gets old',
|
testTcpAndUds('client reconnects after the connection gets old',
|
||||||
(address) async {
|
(address) async {
|
||||||
// client reconnect after a short delay.
|
// client reconnect after a short delay.
|
||||||
final grpc.Server server = grpc.Server([TestService()]);
|
final server = grpc.Server([TestService()]);
|
||||||
await server.serve(address: address, port: 0);
|
await server.serve(address: address, port: 0);
|
||||||
|
|
||||||
final channel = FixedConnectionClientChannel(Http2ClientConnection(
|
final channel = FixedConnectionClientChannel(Http2ClientConnection(
|
||||||
|
|
@ -76,7 +77,7 @@ main() async {
|
||||||
|
|
||||||
testTcpAndUds('client reconnects when stream limit is used', (address) async {
|
testTcpAndUds('client reconnects when stream limit is used', (address) async {
|
||||||
// client reconnect after setting stream limit.
|
// client reconnect after setting stream limit.
|
||||||
final grpc.Server server = grpc.Server([TestService()]);
|
final server = grpc.Server([TestService()]);
|
||||||
await server.serve(
|
await server.serve(
|
||||||
address: address,
|
address: address,
|
||||||
port: 0,
|
port: 0,
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ void main() {
|
||||||
test('WebCallOptions mergeWith CallOptions returns WebCallOptions', () {
|
test('WebCallOptions mergeWith CallOptions returns WebCallOptions', () {
|
||||||
final options =
|
final options =
|
||||||
WebCallOptions(bypassCorsPreflight: true, withCredentials: true);
|
WebCallOptions(bypassCorsPreflight: true, withCredentials: true);
|
||||||
final metadata = {"test": "42"};
|
final metadata = {'test': '42'};
|
||||||
final mergedOptions =
|
final mergedOptions =
|
||||||
options.mergedWith(CallOptions(metadata: metadata)) as WebCallOptions;
|
options.mergedWith(CallOptions(metadata: metadata)) as WebCallOptions;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ class InterceptorInvocation {
|
||||||
|
|
||||||
InterceptorInvocation(this.id, this.unary, this.streaming);
|
InterceptorInvocation(this.id, this.unary, this.streaming);
|
||||||
|
|
||||||
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return '{id: ${id}, unary: ${unary}, streaming: ${streaming}}';
|
return '{id: ${id}, unary: ${unary}, streaming: ${streaming}}';
|
||||||
}
|
}
|
||||||
|
|
@ -48,7 +49,7 @@ class FakeInterceptor implements ClientInterceptor {
|
||||||
|
|
||||||
CallOptions _inject(CallOptions options) {
|
CallOptions _inject(CallOptions options) {
|
||||||
return options.mergedWith(CallOptions(metadata: {
|
return options.mergedWith(CallOptions(metadata: {
|
||||||
"x-interceptor": _invocations.map((i) => i.toString()).join(', '),
|
'x-interceptor': _invocations.map((i) => i.toString()).join(', '),
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -57,7 +58,7 @@ class FakeInterceptor implements ClientInterceptor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
main() {
|
void main() {
|
||||||
test('single unary interceptor', () async {
|
test('single unary interceptor', () async {
|
||||||
final harness = ClientHarness()
|
final harness = ClientHarness()
|
||||||
..interceptors = [FakeInterceptor(1)]
|
..interceptors = [FakeInterceptor(1)]
|
||||||
|
|
@ -81,7 +82,7 @@ main() {
|
||||||
expectedResult: responseValue,
|
expectedResult: responseValue,
|
||||||
expectedPath: '/Test/Unary',
|
expectedPath: '/Test/Unary',
|
||||||
expectedCustomHeaders: {
|
expectedCustomHeaders: {
|
||||||
"x-interceptor": "{id: 1, unary: 1, streaming: 0}"
|
'x-interceptor': '{id: 1, unary: 1, streaming: 0}'
|
||||||
},
|
},
|
||||||
serverHandlers: [handleRequest],
|
serverHandlers: [handleRequest],
|
||||||
);
|
);
|
||||||
|
|
@ -113,8 +114,8 @@ main() {
|
||||||
expectedResult: responseValue,
|
expectedResult: responseValue,
|
||||||
expectedPath: '/Test/Unary',
|
expectedPath: '/Test/Unary',
|
||||||
expectedCustomHeaders: {
|
expectedCustomHeaders: {
|
||||||
"x-interceptor":
|
'x-interceptor':
|
||||||
"{id: 1, unary: 1, streaming: 0}, {id: 2, unary: 1, streaming: 0}"
|
'{id: 1, unary: 1, streaming: 0}, {id: 2, unary: 1, streaming: 0}'
|
||||||
},
|
},
|
||||||
serverHandlers: [handleRequest],
|
serverHandlers: [handleRequest],
|
||||||
);
|
);
|
||||||
|
|
@ -154,7 +155,7 @@ main() {
|
||||||
expectedResult: responses,
|
expectedResult: responses,
|
||||||
expectedPath: '/Test/Bidirectional',
|
expectedPath: '/Test/Bidirectional',
|
||||||
expectedCustomHeaders: {
|
expectedCustomHeaders: {
|
||||||
"x-interceptor": "{id: 1, unary: 0, streaming: 1}"
|
'x-interceptor': '{id: 1, unary: 0, streaming: 1}'
|
||||||
},
|
},
|
||||||
serverHandlers: [handleRequest, handleRequest, handleRequest],
|
serverHandlers: [handleRequest, handleRequest, handleRequest],
|
||||||
doneHandler: handleDone,
|
doneHandler: handleDone,
|
||||||
|
|
@ -195,8 +196,8 @@ main() {
|
||||||
expectedResult: responses,
|
expectedResult: responses,
|
||||||
expectedPath: '/Test/Bidirectional',
|
expectedPath: '/Test/Bidirectional',
|
||||||
expectedCustomHeaders: {
|
expectedCustomHeaders: {
|
||||||
"x-interceptor":
|
'x-interceptor':
|
||||||
"{id: 1, unary: 0, streaming: 1}, {id: 2, unary: 0, streaming: 1}"
|
'{id: 1, unary: 0, streaming: 1}, {id: 2, unary: 0, streaming: 1}'
|
||||||
},
|
},
|
||||||
serverHandlers: [handleRequest, handleRequest, handleRequest],
|
serverHandlers: [handleRequest, handleRequest, handleRequest],
|
||||||
doneHandler: handleDone,
|
doneHandler: handleDone,
|
||||||
|
|
|
||||||
|
|
@ -330,7 +330,7 @@ void main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
harness.client = TestClient(harness.channel, decode: (bytes) {
|
harness.client = TestClient(harness.channel, decode: (bytes) {
|
||||||
throw "error decoding";
|
throw 'error decoding';
|
||||||
});
|
});
|
||||||
|
|
||||||
await harness.runFailureTest(
|
await harness.runFailureTest(
|
||||||
|
|
@ -439,9 +439,9 @@ void main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Default reconnect backoff backs off', () {
|
test('Default reconnect backoff backs off', () {
|
||||||
Duration lastBackoff = defaultBackoffStrategy(null);
|
var lastBackoff = defaultBackoffStrategy(null);
|
||||||
expect(lastBackoff, const Duration(seconds: 1));
|
expect(lastBackoff, const Duration(seconds: 1));
|
||||||
for (int i = 0; i < 12; i++) {
|
for (var i = 0; i < 12; i++) {
|
||||||
final minNext = lastBackoff * (1.6 - 0.2);
|
final minNext = lastBackoff * (1.6 - 0.2);
|
||||||
final maxNext = lastBackoff * (1.6 + 0.2);
|
final maxNext = lastBackoff * (1.6 + 0.2);
|
||||||
lastBackoff = defaultBackoffStrategy(lastBackoff);
|
lastBackoff = defaultBackoffStrategy(lastBackoff);
|
||||||
|
|
|
||||||
|
|
@ -280,7 +280,7 @@ void main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
harness.client = TestClient(harness.channel, decode: (bytes) {
|
harness.client = TestClient(harness.channel, decode: (bytes) {
|
||||||
throw "error decoding";
|
throw 'error decoding';
|
||||||
});
|
});
|
||||||
|
|
||||||
await harness.runFailureTest(
|
await harness.runFailureTest(
|
||||||
|
|
@ -389,9 +389,9 @@ void main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Default reconnect backoff backs off', () {
|
test('Default reconnect backoff backs off', () {
|
||||||
Duration lastBackoff = defaultBackoffStrategy(null);
|
var lastBackoff = defaultBackoffStrategy(null);
|
||||||
expect(lastBackoff, const Duration(seconds: 1));
|
expect(lastBackoff, const Duration(seconds: 1));
|
||||||
for (int i = 0; i < 12; i++) {
|
for (var i = 0; i < 12; i++) {
|
||||||
final minNext = lastBackoff * (1.6 - 0.2);
|
final minNext = lastBackoff * (1.6 - 0.2);
|
||||||
final maxNext = lastBackoff * (1.6 + 0.2);
|
final maxNext = lastBackoff * (1.6 + 0.2);
|
||||||
lastBackoff = defaultBackoffStrategy(lastBackoff);
|
lastBackoff = defaultBackoffStrategy(lastBackoff);
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,7 @@ class MockHttpRequest extends Mock implements HttpRequest {
|
||||||
@override
|
@override
|
||||||
final int status;
|
final int status;
|
||||||
|
|
||||||
|
@override
|
||||||
int get readyState => super.noSuchMethod(Invocation.getter(#readyState), -1);
|
int get readyState => super.noSuchMethod(Invocation.getter(#readyState), -1);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -69,7 +70,7 @@ class MockXhrClientConnection extends XhrClientConnection {
|
||||||
final int _statusCode;
|
final int _statusCode;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
createHttpRequest() {
|
HttpRequest createHttpRequest() {
|
||||||
final request = MockHttpRequest(code: _statusCode);
|
final request = MockHttpRequest(code: _statusCode);
|
||||||
latestRequest = request;
|
latestRequest = request;
|
||||||
return request;
|
return request;
|
||||||
|
|
@ -360,9 +361,9 @@ void main() {
|
||||||
final errorReceived = Completer<void>();
|
final errorReceived = Completer<void>();
|
||||||
connection.makeRequest('test_path', Duration(seconds: 10), {}, (e, _) {
|
connection.makeRequest('test_path', Duration(seconds: 10), {}, (e, _) {
|
||||||
errorReceived.complete();
|
errorReceived.complete();
|
||||||
errors.add(e);
|
errors.add(e as GrpcError);
|
||||||
});
|
});
|
||||||
const errorDetails = "error details";
|
const errorDetails = 'error details';
|
||||||
when(connection.latestRequest.getResponseHeader('Content-Type'))
|
when(connection.latestRequest.getResponseHeader('Content-Type'))
|
||||||
.thenReturn('application/grpc+proto');
|
.thenReturn('application/grpc+proto');
|
||||||
when(connection.latestRequest.responseHeaders).thenReturn({});
|
when(connection.latestRequest.responseHeaders).thenReturn({});
|
||||||
|
|
|
||||||
|
|
@ -289,7 +289,7 @@ void main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
final Interceptor interceptor = (call, method) {
|
final Interceptor interceptor = (call, method) {
|
||||||
if (method.name == "Unary") {
|
if (method.name == 'Unary') {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return GrpcError.unauthenticated('Request is unauthenticated');
|
return GrpcError.unauthenticated('Request is unauthenticated');
|
||||||
|
|
@ -311,7 +311,7 @@ void main() {
|
||||||
|
|
||||||
group('returns error if interceptor blocks request', () {
|
group('returns error if interceptor blocks request', () {
|
||||||
final Interceptor interceptor = (call, method) {
|
final Interceptor interceptor = (call, method) {
|
||||||
if (method.name == "Unary") {
|
if (method.name == 'Unary') {
|
||||||
return GrpcError.unauthenticated('Request is unauthenticated');
|
return GrpcError.unauthenticated('Request is unauthenticated');
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,9 @@ import 'package:grpc/src/client/transport/web_streams.dart';
|
||||||
import 'package:grpc/src/shared/message.dart';
|
import 'package:grpc/src/shared/message.dart';
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
main() {
|
void main() {
|
||||||
test("decoding an empty repeated", () async {
|
test('decoding an empty repeated', () async {
|
||||||
final GrpcData data = await GrpcWebDecoder()
|
final data = await GrpcWebDecoder()
|
||||||
.bind(Stream.fromIterable([
|
.bind(Stream.fromIterable([
|
||||||
Uint8List.fromList([0, 0, 0, 0, 0]).buffer
|
Uint8List.fromList([0, 0, 0, 0, 0]).buffer
|
||||||
]))
|
]))
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,7 @@ static_resources:
|
||||||
port_value: %TARGET_PORT%
|
port_value: %TARGET_PORT%
|
||||||
''';
|
''';
|
||||||
|
|
||||||
hybridMain(StreamChannel channel) async {
|
Future<void> hybridMain(StreamChannel channel) async {
|
||||||
// Envoy output will be collected and dumped to stdout if envoy exits
|
// Envoy output will be collected and dumped to stdout if envoy exits
|
||||||
// with an error. Otherwise if verbose is specified it will be dumped
|
// with an error. Otherwise if verbose is specified it will be dumped
|
||||||
// to stdout unconditionally.
|
// to stdout unconditionally.
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ void main() {
|
||||||
|
|
||||||
// Verify that terminate does not cause an exception when terminating
|
// Verify that terminate does not cause an exception when terminating
|
||||||
// channel with multiple active requests.
|
// channel with multiple active requests.
|
||||||
test("terminate works", () async {
|
test('terminate works', () async {
|
||||||
final channel = GrpcWebClientChannel.xhr(server.uri);
|
final channel = GrpcWebClientChannel.xhr(server.uri);
|
||||||
final service = EchoServiceClient(channel);
|
final service = EchoServiceClient(channel);
|
||||||
|
|
||||||
|
|
@ -96,7 +96,7 @@ void main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Verify that stream cancellation does not cause an exception
|
// Verify that stream cancellation does not cause an exception
|
||||||
test("stream cancellation works", () async {
|
test('stream cancellation works', () async {
|
||||||
final channel = GrpcWebClientChannel.xhr(server.uri);
|
final channel = GrpcWebClientChannel.xhr(server.uri);
|
||||||
final service = EchoServiceClient(channel);
|
final service = EchoServiceClient(channel);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ class TestClient extends Client {
|
||||||
}
|
}
|
||||||
|
|
||||||
class TestService extends Service {
|
class TestService extends Service {
|
||||||
|
@override
|
||||||
String get $name => 'test.TestService';
|
String get $name => 'test.TestService';
|
||||||
|
|
||||||
TestService() {
|
TestService() {
|
||||||
|
|
@ -43,6 +44,7 @@ class TestService extends Service {
|
||||||
}
|
}
|
||||||
|
|
||||||
class TestServiceWithOnMetadataException extends TestService {
|
class TestServiceWithOnMetadataException extends TestService {
|
||||||
|
@override
|
||||||
void $onMetadata(ServiceCall context) {
|
void $onMetadata(ServiceCall context) {
|
||||||
throw Exception('business exception');
|
throw Exception('business exception');
|
||||||
}
|
}
|
||||||
|
|
@ -58,10 +60,10 @@ class FixedConnectionClientChannel extends ClientChannelBase {
|
||||||
ClientConnection createConnection() => clientConnection;
|
ClientConnection createConnection() => clientConnection;
|
||||||
}
|
}
|
||||||
|
|
||||||
main() async {
|
Future<void> main() async {
|
||||||
testTcpAndUds('round trip insecure connection', (address) async {
|
testTcpAndUds('round trip insecure connection', (address) async {
|
||||||
// round trip test of insecure connection.
|
// round trip test of insecure connection.
|
||||||
final Server server = Server([TestService()]);
|
final server = Server([TestService()]);
|
||||||
await server.serve(address: address, port: 0);
|
await server.serve(address: address, port: 0);
|
||||||
|
|
||||||
final channel = FixedConnectionClientChannel(Http2ClientConnection(
|
final channel = FixedConnectionClientChannel(Http2ClientConnection(
|
||||||
|
|
@ -77,7 +79,7 @@ main() async {
|
||||||
|
|
||||||
testTcpAndUds('round trip with outgoing and incoming compression',
|
testTcpAndUds('round trip with outgoing and incoming compression',
|
||||||
(address) async {
|
(address) async {
|
||||||
final Server server = Server(
|
final server = Server(
|
||||||
[TestService()], const [], CodecRegistry(codecs: const [GzipCodec()]));
|
[TestService()], const [], CodecRegistry(codecs: const [GzipCodec()]));
|
||||||
await server.serve(address: address, port: 0);
|
await server.serve(address: address, port: 0);
|
||||||
|
|
||||||
|
|
@ -101,7 +103,7 @@ main() async {
|
||||||
|
|
||||||
testTcpAndUds('round trip secure connection', (address) async {
|
testTcpAndUds('round trip secure connection', (address) async {
|
||||||
// round trip test of secure connection.
|
// round trip test of secure connection.
|
||||||
final Server server = Server([TestService()]);
|
final server = Server([TestService()]);
|
||||||
await server.serve(
|
await server.serve(
|
||||||
address: address,
|
address: address,
|
||||||
port: 0,
|
port: 0,
|
||||||
|
|
@ -124,7 +126,7 @@ main() async {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('exception in onMetadataException', () async {
|
test('exception in onMetadataException', () async {
|
||||||
final Server server = Server([TestServiceWithOnMetadataException()]);
|
final server = Server([TestServiceWithOnMetadataException()]);
|
||||||
await server.serve(address: 'localhost', port: 0);
|
await server.serve(address: 'localhost', port: 0);
|
||||||
|
|
||||||
final channel = FixedConnectionClientChannel(Http2ClientConnection(
|
final channel = FixedConnectionClientChannel(Http2ClientConnection(
|
||||||
|
|
@ -140,7 +142,7 @@ main() async {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('cancellation of streaming subscription propagates properly', () async {
|
test('cancellation of streaming subscription propagates properly', () async {
|
||||||
final Server server = Server([TestService()]);
|
final server = Server([TestService()]);
|
||||||
await server.serve(address: 'localhost', port: 0);
|
await server.serve(address: 'localhost', port: 0);
|
||||||
|
|
||||||
final channel = FixedConnectionClientChannel(Http2ClientConnection(
|
final channel = FixedConnectionClientChannel(Http2ClientConnection(
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ class TestClient extends grpc.Client {
|
||||||
}
|
}
|
||||||
|
|
||||||
class TestService extends grpc.Service {
|
class TestService extends grpc.Service {
|
||||||
|
@override
|
||||||
String get $name => 'test.TestService';
|
String get $name => 'test.TestService';
|
||||||
final void Function() finallyCallback;
|
final void Function() finallyCallback;
|
||||||
|
|
||||||
|
|
@ -31,7 +32,7 @@ class TestService extends grpc.Service {
|
||||||
|
|
||||||
Stream<int> infiniteStream(
|
Stream<int> infiniteStream(
|
||||||
grpc.ServiceCall call, Future<int> request) async* {
|
grpc.ServiceCall call, Future<int> request) async* {
|
||||||
int count = await request;
|
var count = await request;
|
||||||
try {
|
try {
|
||||||
while (true) {
|
while (true) {
|
||||||
count++;
|
count++;
|
||||||
|
|
@ -70,9 +71,9 @@ void client(clientData) async {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
main() async {
|
Future<void> main() async {
|
||||||
testTcpAndUds(
|
testTcpAndUds(
|
||||||
"the client interrupting the connection does not crash the server",
|
'the client interrupting the connection does not crash the server',
|
||||||
(address) async {
|
(address) async {
|
||||||
// interrrupt the connect of client, the server does not crash.
|
// interrrupt the connect of client, the server does not crash.
|
||||||
late grpc.Server server;
|
late grpc.Server server;
|
||||||
|
|
|
||||||
|
|
@ -169,7 +169,7 @@ void main() {
|
||||||
|
|
||||||
test('Server returns encoded error for unary call', () async {
|
test('Server returns encoded error for unary call', () async {
|
||||||
Future<int> methodHandler(ServiceCall call, Future<int> request) async {
|
Future<int> methodHandler(ServiceCall call, Future<int> request) async {
|
||||||
throw GrpcError.unknown("エラー");
|
throw GrpcError.unknown('エラー');
|
||||||
}
|
}
|
||||||
|
|
||||||
harness
|
harness
|
||||||
|
|
@ -303,7 +303,7 @@ void main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
final Interceptor interceptor = (call, method) {
|
final Interceptor interceptor = (call, method) {
|
||||||
if (method.name == "Unary") {
|
if (method.name == 'Unary') {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return GrpcError.unauthenticated('Request is unauthenticated');
|
return GrpcError.unauthenticated('Request is unauthenticated');
|
||||||
|
|
@ -325,7 +325,7 @@ void main() {
|
||||||
|
|
||||||
group('returns error if interceptor blocks request', () {
|
group('returns error if interceptor blocks request', () {
|
||||||
final Interceptor interceptor = (call, method) {
|
final Interceptor interceptor = (call, method) {
|
||||||
if (method.name == "Unary") {
|
if (method.name == 'Unary') {
|
||||||
return GrpcError.unauthenticated('Request is unauthenticated');
|
return GrpcError.unauthenticated('Request is unauthenticated');
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
|
||||||
|
|
@ -62,16 +62,23 @@ class FakeClientTransportConnection extends Http2ClientConnection {
|
||||||
Duration testBackoff(Duration? lastBackoff) => const Duration(milliseconds: 1);
|
Duration testBackoff(Duration? lastBackoff) => const Duration(milliseconds: 1);
|
||||||
|
|
||||||
class FakeChannelOptions implements ChannelOptions {
|
class FakeChannelOptions implements ChannelOptions {
|
||||||
|
@override
|
||||||
ChannelCredentials credentials = const ChannelCredentials.secure();
|
ChannelCredentials credentials = const ChannelCredentials.secure();
|
||||||
|
@override
|
||||||
Duration idleTimeout = const Duration(seconds: 1);
|
Duration idleTimeout = const Duration(seconds: 1);
|
||||||
|
@override
|
||||||
Duration connectionTimeout = const Duration(seconds: 10);
|
Duration connectionTimeout = const Duration(seconds: 10);
|
||||||
|
@override
|
||||||
String userAgent = 'dart-grpc/1.0.0 test';
|
String userAgent = 'dart-grpc/1.0.0 test';
|
||||||
|
@override
|
||||||
BackoffStrategy backoffStrategy = testBackoff;
|
BackoffStrategy backoffStrategy = testBackoff;
|
||||||
|
@override
|
||||||
CodecRegistry codecRegistry = CodecRegistry.empty();
|
CodecRegistry codecRegistry = CodecRegistry.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
class FakeChannel extends ClientChannel {
|
class FakeChannel extends ClientChannel {
|
||||||
final Http2ClientConnection connection;
|
final Http2ClientConnection connection;
|
||||||
|
@override
|
||||||
final FakeChannelOptions options;
|
final FakeChannelOptions options;
|
||||||
|
|
||||||
FakeChannel(String host, this.connection, this.options)
|
FakeChannel(String host, this.connection, this.options)
|
||||||
|
|
@ -83,6 +90,7 @@ class FakeChannel extends ClientChannel {
|
||||||
|
|
||||||
class FakeClientConnectorChannel extends ClientTransportConnectorChannel {
|
class FakeClientConnectorChannel extends ClientTransportConnectorChannel {
|
||||||
final Http2ClientConnection connection;
|
final Http2ClientConnection connection;
|
||||||
|
@override
|
||||||
final FakeChannelOptions options;
|
final FakeChannelOptions options;
|
||||||
|
|
||||||
FakeClientConnectorChannel(
|
FakeClientConnectorChannel(
|
||||||
|
|
@ -106,7 +114,7 @@ class TestClient extends Client {
|
||||||
TestClient(base.ClientChannel channel,
|
TestClient(base.ClientChannel channel,
|
||||||
{CallOptions? options,
|
{CallOptions? options,
|
||||||
Iterable<ClientInterceptor>? interceptors,
|
Iterable<ClientInterceptor>? interceptors,
|
||||||
this.decode: mockDecode})
|
this.decode = mockDecode})
|
||||||
: super(channel, options: options, interceptors: interceptors) {
|
: super(channel, options: options, interceptors: interceptors) {
|
||||||
_$unary = ClientMethod<int, int>('/Test/Unary', mockEncode, decode);
|
_$unary = ClientMethod<int, int>('/Test/Unary', mockEncode, decode);
|
||||||
_$clientStreaming =
|
_$clientStreaming =
|
||||||
|
|
@ -255,7 +263,7 @@ abstract class _Harness {
|
||||||
List<MessageHandler> serverHandlers = const [],
|
List<MessageHandler> serverHandlers = const [],
|
||||||
void Function()? doneHandler,
|
void Function()? doneHandler,
|
||||||
bool expectDone = true}) async {
|
bool expectDone = true}) async {
|
||||||
int serverHandlerIndex = 0;
|
var serverHandlerIndex = 0;
|
||||||
void handleServerMessage(StreamMessage message) {
|
void handleServerMessage(StreamMessage message) {
|
||||||
serverHandlers[serverHandlerIndex++](message);
|
serverHandlers[serverHandlerIndex++](message);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,9 @@ class TestInterceptor {
|
||||||
}
|
}
|
||||||
|
|
||||||
class TestServerStream extends ServerTransportStream {
|
class TestServerStream extends ServerTransportStream {
|
||||||
|
@override
|
||||||
final Stream<StreamMessage> incomingMessages;
|
final Stream<StreamMessage> incomingMessages;
|
||||||
|
@override
|
||||||
final StreamSink<StreamMessage> outgoingMessages;
|
final StreamSink<StreamMessage> outgoingMessages;
|
||||||
|
|
||||||
TestServerStream(this.incomingMessages, this.outgoingMessages);
|
TestServerStream(this.incomingMessages, this.outgoingMessages);
|
||||||
|
|
@ -106,7 +108,7 @@ class TestServerStream extends ServerTransportStream {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
set onTerminated(void value(int x)) {}
|
set onTerminated(void Function(int x) value) {}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool get canPush => true;
|
bool get canPush => true;
|
||||||
|
|
@ -162,7 +164,7 @@ abstract class _Harness {
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupTest(List<MessageHandler> handlers) {
|
void setupTest(List<MessageHandler> handlers) {
|
||||||
int handlerIndex = 0;
|
var handlerIndex = 0;
|
||||||
void handleMessages(StreamMessage message) {
|
void handleMessages(StreamMessage message) {
|
||||||
handlers[handlerIndex++](message);
|
handlers[handlerIndex++](message);
|
||||||
}
|
}
|
||||||
|
|
@ -204,7 +206,7 @@ abstract class _Harness {
|
||||||
validateResponseHeaders(header.metadata);
|
validateResponseHeaders(header.metadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
int responseIndex = 0;
|
var responseIndex = 0;
|
||||||
void handleResponse(StreamMessage message) {
|
void handleResponse(StreamMessage message) {
|
||||||
final response = validateDataMessage(message);
|
final response = validateDataMessage(message);
|
||||||
expect(mockDecode(response.data), expectedResponses[responseIndex++]);
|
expect(mockDecode(response.data), expectedResponses[responseIndex++]);
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,7 @@ List<int> mockEncode(int value) => List.filled(value, 0);
|
||||||
int mockDecode(List<int> value) => value.length;
|
int mockDecode(List<int> value) => value.length;
|
||||||
|
|
||||||
Map<String, String> headersToMap(List<Header> headers) =>
|
Map<String, String> headersToMap(List<Header> headers) =>
|
||||||
Map.fromIterable(headers,
|
{for (var h in headers) ascii.decode(h.name): ascii.decode(h.value)};
|
||||||
key: (h) => ascii.decode(h.name), value: (h) => ascii.decode(h.value));
|
|
||||||
|
|
||||||
void validateRequestHeaders(Map<String, String> headers,
|
void validateRequestHeaders(Map<String, String> headers,
|
||||||
{String? path,
|
{String? path,
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ class TestClient extends Client {
|
||||||
}
|
}
|
||||||
|
|
||||||
class TestService extends Service {
|
class TestService extends Service {
|
||||||
|
@override
|
||||||
String get $name => 'test.TestService';
|
String get $name => 'test.TestService';
|
||||||
|
|
||||||
TestService() {
|
TestService() {
|
||||||
|
|
@ -84,6 +85,7 @@ class FakeTimelineTask extends Fake implements TimelineTask {
|
||||||
|
|
||||||
bool get isComplete => _startFinishCount == 0;
|
bool get isComplete => _startFinishCount == 0;
|
||||||
|
|
||||||
|
@override
|
||||||
void start(String name, {Map? arguments}) {
|
void start(String name, {Map? arguments}) {
|
||||||
events.add({
|
events.add({
|
||||||
'id': id,
|
'id': id,
|
||||||
|
|
@ -98,6 +100,7 @@ class FakeTimelineTask extends Fake implements TimelineTask {
|
||||||
++_startFinishCount;
|
++_startFinishCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
void instant(String name, {Map? arguments}) {
|
void instant(String name, {Map? arguments}) {
|
||||||
events.add({
|
events.add({
|
||||||
'id': id,
|
'id': id,
|
||||||
|
|
@ -110,6 +113,7 @@ class FakeTimelineTask extends Fake implements TimelineTask {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
void finish({Map? arguments}) {
|
void finish({Map? arguments}) {
|
||||||
events.add({
|
events.add({
|
||||||
'id': id,
|
'id': id,
|
||||||
|
|
@ -128,8 +132,8 @@ TimelineTask fakeTimelineTaskFactory(
|
||||||
{String? filterKey, TimelineTask? parent}) =>
|
{String? filterKey, TimelineTask? parent}) =>
|
||||||
FakeTimelineTask(filterKey: filterKey, parent: parent);
|
FakeTimelineTask(filterKey: filterKey, parent: parent);
|
||||||
|
|
||||||
testee() async {
|
Future<void> testee() async {
|
||||||
final Server server = Server([TestService()]);
|
final server = Server([TestService()]);
|
||||||
await server.serve(address: 'localhost', port: 0);
|
await server.serve(address: 'localhost', port: 0);
|
||||||
isTimelineLoggingEnabled = true;
|
isTimelineLoggingEnabled = true;
|
||||||
timelineTaskFactory = fakeTimelineTaskFactory;
|
timelineTaskFactory = fakeTimelineTaskFactory;
|
||||||
|
|
@ -171,7 +175,7 @@ void checkWriteEvent(List<Map> events) {
|
||||||
void checkReceiveEvent(List<Map> events) {
|
void checkReceiveEvent(List<Map> events) {
|
||||||
events = events.where((e) => e['name'] == 'Data received').toList();
|
events = events.where((e) => e['name'] == 'Data received').toList();
|
||||||
expect(events.length, equals(3));
|
expect(events.length, equals(3));
|
||||||
int sum = 0;
|
var sum = 0;
|
||||||
for (final e in events) {
|
for (final e in events) {
|
||||||
expect(e['id'], 1);
|
expect(e['id'], 1);
|
||||||
// 3 elements are 1, 2 and 3.
|
// 3 elements are 1, 2 and 3.
|
||||||
|
|
@ -200,7 +204,7 @@ void checkFinishEvent(List<Map> events) {
|
||||||
expect(e.length, 2);
|
expect(e.length, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
main([args = const <String>[]]) {
|
void main([args = const <String>[]]) {
|
||||||
test('Test gRPC timeline logging', () async {
|
test('Test gRPC timeline logging', () async {
|
||||||
await testee();
|
await testee();
|
||||||
for (final task in FakeTimelineTask.tasks) {
|
for (final task in FakeTimelineTask.tasks) {
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ void main() {
|
||||||
test('Calls time out if deadline is exceeded', () async {
|
test('Calls time out if deadline is exceeded', () async {
|
||||||
void handleRequest(StreamMessage message) {
|
void handleRequest(StreamMessage message) {
|
||||||
validateDataMessage(message);
|
validateDataMessage(message);
|
||||||
final Future delay = Future.delayed(Duration(milliseconds: 2));
|
final delay = Future.delayed(Duration(milliseconds: 2));
|
||||||
expect(delay, completes);
|
expect(delay, completes);
|
||||||
delay.then((_) {
|
delay.then((_) {
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue