Test on oldest supported SDK, enable and fix many lints
diff --git a/.travis.yml b/.travis.yml
index 9d8258c..cae5503 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,16 +1,13 @@
language: dart
-# By default, builds are run in containers.
-# https://docs.travis-ci.com/user/getting-started/#Selecting-infrastructure-(optional)
-# Set `sudo: true` to disable containers if you need to use sudo in your scripts.
-# sudo: true
-
dart:
+- 2.0.0
- dev
-# See https://docs.travis-ci.com/user/languages/dart/ for details.
+
dart_task:
- dartfmt
- dartanalyzer
+
# TODO: reinstate tests once https://github.com/dart-lang/http_retry/issues/6 is fixed
# - test: --platform vm
# xvfb: false
diff --git a/analysis_options.yaml b/analysis_options.yaml
new file mode 100644
index 0000000..815f325
--- /dev/null
+++ b/analysis_options.yaml
@@ -0,0 +1,99 @@
+include: package:pedantic/analysis_options.yaml
+analyzer:
+ strong-mode:
+ implicit-casts: false
+ errors:
+ dead_code: error
+ override_on_non_overriding_method: error
+ unused_element: error
+ unused_import: error
+ unused_local_variable: error
+linter:
+ rules:
+ - always_declare_return_types
+ - annotate_overrides
+ - avoid_bool_literals_in_conditional_expressions
+ - avoid_classes_with_only_static_members
+ - avoid_empty_else
+ - avoid_function_literals_in_foreach_calls
+ - avoid_init_to_null
+ - avoid_null_checks_in_equality_operators
+ - avoid_relative_lib_imports
+ - avoid_renaming_method_parameters
+ - avoid_return_types_on_setters
+ - avoid_returning_null
+ - avoid_returning_null_for_future
+ - avoid_returning_null_for_void
+ - avoid_returning_this
+ - avoid_shadowing_type_parameters
+ - avoid_single_cascade_in_expression_statements
+ - avoid_types_as_parameter_names
+ - avoid_unused_constructor_parameters
+ - await_only_futures
+ - camel_case_types
+ - cancel_subscriptions
+ #- cascade_invocations
+ - comment_references
+ - constant_identifier_names
+ - control_flow_in_finally
+ - directives_ordering
+ - empty_catches
+ - empty_constructor_bodies
+ - empty_statements
+ - file_names
+ - hash_and_equals
+ - implementation_imports
+ - invariant_booleans
+ - iterable_contains_unrelated_type
+ - join_return_with_assignment
+ - library_names
+ - library_prefixes
+ - list_remove_unrelated_type
+ - literal_only_boolean_expressions
+ - no_adjacent_strings_in_list
+ - no_duplicate_case_values
+ - non_constant_identifier_names
+ - null_closures
+ - omit_local_variable_types
+ - only_throw_errors
+ - overridden_fields
+ - package_api_docs
+ - package_names
+ - package_prefixed_library_names
+ - prefer_adjacent_string_concatenation
+ - prefer_collection_literals
+ - prefer_conditional_assignment
+ - prefer_const_constructors
+ - prefer_contains
+ - prefer_equal_for_default_values
+ - prefer_final_fields
+ #- prefer_final_locals
+ - prefer_generic_function_type_aliases
+ - prefer_initializing_formals
+ - prefer_interpolation_to_compose_strings
+ - prefer_is_empty
+ - prefer_is_not_empty
+ - prefer_null_aware_operators
+ #- prefer_single_quotes
+ - prefer_typing_uninitialized_variables
+ - recursive_getters
+ - slash_for_doc_comments
+ - test_types_in_equals
+ - throw_in_finally
+ - type_init_formals
+ - unawaited_futures
+ - unnecessary_await_in_return
+ - unnecessary_brace_in_string_interps
+ - unnecessary_const
+ - unnecessary_getters_setters
+ - unnecessary_lambdas
+ - unnecessary_new
+ - unnecessary_null_aware_assignments
+ - unnecessary_parenthesis
+ - unnecessary_statements
+ - unnecessary_this
+ - unrelated_type_equality_checks
+ #- use_function_type_syntax_for_parameters
+ - use_rethrow_when_possible
+ - valid_regexps
+ - void_checks
diff --git a/lib/http_retry.dart b/lib/http_retry.dart
index e1b08fd..5bb3695 100644
--- a/lib/http_retry.dart
+++ b/lib/http_retry.dart
@@ -7,6 +7,7 @@
import 'package:async/async.dart';
import 'package:http/http.dart';
+import 'package:pedantic/pedantic.dart';
/// An HTTP client wrapper that automatically retries failing requests.
class RetryClient extends BaseClient {
@@ -28,7 +29,7 @@
/// The callback to call to indicate that a request is being retried.
final void Function(BaseRequest, BaseResponse, int) _onRetry;
- /// Creates a client wrapping [inner] that retries HTTP requests.
+ /// Creates a client wrapping [_inner] that retries HTTP requests.
///
/// This retries a failing request [retries] times (3 by default). Note that
/// `n` retries means that the request will be sent at most `n + 1` times.
@@ -58,7 +59,7 @@
_whenError = whenError ?? ((_, __) => false),
_delay = delay ??
((retryCount) =>
- new Duration(milliseconds: 500) * math.pow(1.5, retryCount)),
+ Duration(milliseconds: 500) * math.pow(1.5, retryCount)),
_onRetry = onRetry {
RangeError.checkNotNegative(_retries, "retries");
}
@@ -87,11 +88,12 @@
whenError: whenError,
onRetry: onRetry);
+ @override
Future<StreamedResponse> send(BaseRequest request) async {
- var splitter = new StreamSplitter(request.finalize());
+ var splitter = StreamSplitter(request.finalize());
var i = 0;
- while (true) {
+ for (;;) {
StreamedResponse response;
try {
response = await _inner.send(_copyRequest(request, splitter.split()));
@@ -104,10 +106,10 @@
// Make sure the response stream is listened to so that we don't leave
// dangling connections.
- response.stream.listen((_) {}).cancel()?.catchError((_) {});
+ unawaited(response.stream.listen((_) {}).cancel()?.catchError((_) {}));
}
- await new Future.delayed(_delay(i));
+ await Future.delayed(_delay(i));
if (_onRetry != null) _onRetry(request, response, i);
i++;
}
@@ -115,7 +117,7 @@
/// Returns a copy of [original] with the given [body].
StreamedRequest _copyRequest(BaseRequest original, Stream<List<int>> body) {
- var request = new StreamedRequest(original.method, original.url);
+ var request = StreamedRequest(original.method, original.url);
request.contentLength = original.contentLength;
request.followRedirects = original.followRedirects;
request.headers.addAll(original.headers);
@@ -130,5 +132,6 @@
return request;
}
+ @override
void close() => _inner.close();
}
diff --git a/pubspec.yaml b/pubspec.yaml
index 74168c4..85743ad 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -11,6 +11,7 @@
dependencies:
async: ^2.0.7
http: '>=0.11.0 <0.13.0'
+ pedantic: ^1.0.0
dev_dependencies:
fake_async: ^1.0.0
diff --git a/test/http_retry_test.dart b/test/http_retry_test.dart
index dc7bc19..b51ed1f 100644
--- a/test/http_retry_test.dart
+++ b/test/http_retry_test.dart
@@ -5,32 +5,29 @@
import 'package:fake_async/fake_async.dart';
import 'package:http/http.dart';
import 'package:http/testing.dart';
-import 'package:test/test.dart';
-
import 'package:http_retry/http_retry.dart';
+import 'package:test/test.dart';
void main() {
group("doesn't retry when", () {
test("a request has a non-503 error code", () async {
- var client = new RetryClient(new MockClient(
- expectAsync1((_) async => new Response("", 502), count: 1)));
+ var client = RetryClient(
+ MockClient(expectAsync1((_) async => Response("", 502), count: 1)));
var response = await client.get("http://example.org");
expect(response.statusCode, equals(502));
});
test("a request doesn't match when()", () async {
- var client = new RetryClient(
- new MockClient(
- expectAsync1((_) async => new Response("", 503), count: 1)),
+ var client = RetryClient(
+ MockClient(expectAsync1((_) async => Response("", 503), count: 1)),
when: (_) => false);
var response = await client.get("http://example.org");
expect(response.statusCode, equals(503));
});
test("retries is 0", () async {
- var client = new RetryClient(
- new MockClient(
- expectAsync1((_) async => new Response("", 503), count: 1)),
+ var client = RetryClient(
+ MockClient(expectAsync1((_) async => Response("", 503), count: 1)),
retries: 0);
var response = await client.get("http://example.org");
expect(response.statusCode, equals(503));
@@ -39,10 +36,10 @@
test("retries on a 503 by default", () async {
var count = 0;
- var client = new RetryClient(
- new MockClient(expectAsync1((request) async {
+ var client = RetryClient(
+ MockClient(expectAsync1((request) async {
count++;
- return count < 2 ? new Response("", 503) : new Response("", 200);
+ return count < 2 ? Response("", 503) : Response("", 200);
}, count: 2)),
delay: (_) => Duration.zero);
@@ -52,10 +49,10 @@
test("retries on any request where when() returns true", () async {
var count = 0;
- var client = new RetryClient(
- new MockClient(expectAsync1((request) async {
+ var client = RetryClient(
+ MockClient(expectAsync1((request) async {
count++;
- return new Response("", 503,
+ return Response("", 503,
headers: {"retry": count < 2 ? "true" : "false"});
}, count: 2)),
when: (response) => response.headers["retry"] == "true",
@@ -68,13 +65,14 @@
test("retries on any request where whenError() returns true", () async {
var count = 0;
- var client = new RetryClient(
- new MockClient(expectAsync1((request) async {
+ var client = RetryClient(
+ MockClient(expectAsync1((request) async {
count++;
- if (count < 2) throw "oh no";
- return new Response("", 200);
+ if (count < 2) throw StateError("oh no");
+ return Response("", 200);
}, count: 2)),
- whenError: (error, _) => error == "oh no",
+ whenError: (error, _) =>
+ error is StateError && error.message == "oh no",
delay: (_) => Duration.zero);
var response = await client.get("http://example.org");
@@ -82,27 +80,26 @@
});
test("doesn't retry a request where whenError() returns false", () async {
- var client = new RetryClient(
- new MockClient(expectAsync1((request) async => throw "oh no")),
+ var client = RetryClient(
+ MockClient(expectAsync1((request) async => throw StateError("oh no"))),
whenError: (error, _) => error == "oh yeah",
delay: (_) => Duration.zero);
- expect(client.get("http://example.org"), throwsA("oh no"));
+ expect(client.get("http://example.org"),
+ throwsA(isStateError.having((e) => e.message, 'message', "oh no")));
});
test("retries three times by default", () async {
- var client = new RetryClient(
- new MockClient(
- expectAsync1((_) async => new Response("", 503), count: 4)),
+ var client = RetryClient(
+ MockClient(expectAsync1((_) async => Response("", 503), count: 4)),
delay: (_) => Duration.zero);
var response = await client.get("http://example.org");
expect(response.statusCode, equals(503));
});
test("retries the given number of times", () async {
- var client = new RetryClient(
- new MockClient(
- expectAsync1((_) async => new Response("", 503), count: 13)),
+ var client = RetryClient(
+ MockClient(expectAsync1((_) async => Response("", 503), count: 13)),
retries: 12,
delay: (_) => Duration.zero);
var response = await client.get("http://example.org");
@@ -110,87 +107,82 @@
});
test("waits 1.5x as long each time by default", () {
- new FakeAsync().run((fake) {
+ FakeAsync().run((fake) {
var count = 0;
- var client = new RetryClient(new MockClient(expectAsync1((_) async {
+ var client = RetryClient(MockClient(expectAsync1((_) async {
count++;
if (count == 1) {
expect(fake.elapsed, equals(Duration.zero));
} else if (count == 2) {
- expect(fake.elapsed, equals(new Duration(milliseconds: 500)));
+ expect(fake.elapsed, equals(Duration(milliseconds: 500)));
} else if (count == 3) {
- expect(fake.elapsed, equals(new Duration(milliseconds: 1250)));
+ expect(fake.elapsed, equals(Duration(milliseconds: 1250)));
} else if (count == 4) {
- expect(fake.elapsed, equals(new Duration(milliseconds: 2375)));
+ expect(fake.elapsed, equals(Duration(milliseconds: 2375)));
}
- return new Response("", 503);
+ return Response("", 503);
}, count: 4)));
expect(client.get("http://example.org"), completes);
- fake.elapse(new Duration(minutes: 10));
+ fake.elapse(Duration(minutes: 10));
});
});
test("waits according to the delay parameter", () {
- new FakeAsync().run((fake) {
+ FakeAsync().run((fake) {
var count = 0;
- var client = new RetryClient(
- new MockClient(expectAsync1((_) async {
+ var client = RetryClient(
+ MockClient(expectAsync1((_) async {
count++;
if (count == 1) {
expect(fake.elapsed, equals(Duration.zero));
} else if (count == 2) {
expect(fake.elapsed, equals(Duration.zero));
} else if (count == 3) {
- expect(fake.elapsed, equals(new Duration(seconds: 1)));
+ expect(fake.elapsed, equals(Duration(seconds: 1)));
} else if (count == 4) {
- expect(fake.elapsed, equals(new Duration(seconds: 3)));
+ expect(fake.elapsed, equals(Duration(seconds: 3)));
}
- return new Response("", 503);
+ return Response("", 503);
}, count: 4)),
- delay: (requestCount) => new Duration(seconds: requestCount));
+ delay: (requestCount) => Duration(seconds: requestCount));
expect(client.get("http://example.org"), completes);
- fake.elapse(new Duration(minutes: 10));
+ fake.elapse(Duration(minutes: 10));
});
});
test("waits according to the delay list", () {
- new FakeAsync().run((fake) {
+ FakeAsync().run((fake) {
var count = 0;
- var client = new RetryClient.withDelays(
- new MockClient(expectAsync1((_) async {
+ var client = RetryClient.withDelays(
+ MockClient(expectAsync1((_) async {
count++;
if (count == 1) {
expect(fake.elapsed, equals(Duration.zero));
} else if (count == 2) {
- expect(fake.elapsed, equals(new Duration(seconds: 1)));
+ expect(fake.elapsed, equals(Duration(seconds: 1)));
} else if (count == 3) {
- expect(fake.elapsed, equals(new Duration(seconds: 61)));
+ expect(fake.elapsed, equals(Duration(seconds: 61)));
} else if (count == 4) {
- expect(fake.elapsed, equals(new Duration(seconds: 73)));
+ expect(fake.elapsed, equals(Duration(seconds: 73)));
}
- return new Response("", 503);
+ return Response("", 503);
}, count: 4)),
- [
- new Duration(seconds: 1),
- new Duration(minutes: 1),
- new Duration(seconds: 12)
- ]);
+ [Duration(seconds: 1), Duration(minutes: 1), Duration(seconds: 12)]);
expect(client.get("http://example.org"), completes);
- fake.elapse(new Duration(minutes: 10));
+ fake.elapse(Duration(minutes: 10));
});
});
test("calls onRetry for each retry", () async {
var count = 0;
- var client = new RetryClient(
- new MockClient(
- expectAsync1((_) async => new Response("", 503), count: 3)),
+ var client = RetryClient(
+ MockClient(expectAsync1((_) async => Response("", 503), count: 3)),
retries: 2,
delay: (_) => Duration.zero,
onRetry: expectAsync3((request, response, retryCount) {
@@ -204,8 +196,8 @@
});
test("copies all request attributes for each attempt", () async {
- var client = new RetryClient.withDelays(
- new MockClient(expectAsync1((request) async {
+ var client = RetryClient.withDelays(
+ MockClient(expectAsync1((request) async {
expect(request.contentLength, equals(5));
expect(request.followRedirects, isFalse);
expect(request.headers, containsPair("foo", "bar"));
@@ -214,11 +206,11 @@
expect(request.persistentConnection, isFalse);
expect(request.url, equals(Uri.parse("http://example.org")));
expect(request.body, equals("hello"));
- return new Response("", 503);
+ return Response("", 503);
}, count: 2)),
[Duration.zero]);
- var request = new Request("POST", Uri.parse("http://example.org"));
+ var request = Request("POST", Uri.parse("http://example.org"));
request.body = "hello";
request.followRedirects = false;
request.headers["foo"] = "bar";