Migrate GitHub Actions (#86)

diff --git a/.github/workflows/test-package.yml b/.github/workflows/test-package.yml
new file mode 100644
index 0000000..16cf1cf
--- /dev/null
+++ b/.github/workflows/test-package.yml
@@ -0,0 +1,86 @@
+name: Dart CI
+
+on:
+  # Run on PRs and pushes to the default branch.
+  push:
+    branches: [ master ]
+  pull_request:
+    branches: [ master ]
+  schedule:
+    - cron: "0 0 * * 0"
+
+env:
+  PUB_ENVIRONMENT: bot.github
+
+jobs:
+  # Check code formatting and static analysis on a single OS (linux)
+  # against Dart dev.
+  analyze:
+    runs-on: ubuntu-latest
+    strategy:
+      fail-fast: false
+      matrix:
+        sdk: [dev]
+    steps:
+      - uses: actions/checkout@v2
+      - uses: dart-lang/setup-dart@v0.3
+        with:
+          sdk: ${{ matrix.sdk }}
+      - id: install
+        name: Install dependencies
+        run: dart pub get
+      - name: Check formatting
+        run: dart format --output=none --set-exit-if-changed .
+        if: always() && steps.install.outcome == 'success'
+      - name: Analyze code
+        run: dart analyze --fatal-infos
+        if: always() && steps.install.outcome == 'success'
+
+  # Run tests on a matrix consisting of two dimensions:
+  # 1. OS: ubuntu-latest, (macos-latest, windows-latest)
+  # 2. release channel: dev
+  test:
+    needs: analyze
+    runs-on: ${{ matrix.os }}
+    strategy:
+      fail-fast: false
+      matrix:
+        # Add macos-latest and/or windows-latest if relevant for this package.
+        os: [ubuntu-latest]
+        sdk: [dev]
+    steps:
+      - uses: actions/checkout@v2
+      - uses: dart-lang/setup-dart@v0.3
+        with:
+          sdk: ${{ matrix.sdk }}
+      - id: install
+        name: Install dependencies
+        run: dart pub get
+      - name: Run VM tests
+        run: dart test --platform vm
+        if: always() && steps.install.outcome == 'success'
+
+  # Run tests on a matrix consisting of two dimensions:
+  # 1. OS: ubuntu-latest, (macos-latest, windows-latest)
+  # 2. release channel: 2.8.4
+  test-legacy-sdk:
+    needs: analyze
+    runs-on: ${{ matrix.os }}
+    strategy:
+      fail-fast: false
+      matrix:
+        # Add macos-latest and/or windows-latest if relevant for this package.
+        os: [ubuntu-latest]
+        sdk: [2.8.4]
+    steps:
+      - uses: actions/checkout@v2
+      - uses: dart-lang/setup-dart@v0.3
+        with:
+          sdk: ${{ matrix.sdk }}
+      - id: install
+        name: Install dependencies
+        run: pub get
+      - name: Run VM tests
+        run: pub run test --platform vm
+        if: always() && steps.install.outcome == 'success'
+  
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 100aac5..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,29 +0,0 @@
-language: dart
-
-before_script:
-  # Add an IPv6 config - see the corresponding Travis issue
-  # https://github.com/travis-ci/travis-ci/issues/8361
-  - if [ "${TRAVIS_OS_NAME}" == "linux" ]; then
-      sudo sh -c 'echo 0 > /proc/sys/net/ipv6/conf/all/disable_ipv6';
-    fi
-
-dart:
-  - 2.8.4
-  - dev
-
-dart_task:
-  - test
-  - dartanalyzer: --fatal-infos --fatal-warnings .
-
-matrix:
-  include:
-  - dart: dev
-    dart_task: dartfmt
-
-# Only building master means that we don't run two builds for each pull request.
-branches:
-  only: [master]
-
-cache:
-  directories:
-    - $HOME/.pub-cache
diff --git a/README.md b/README.md
index 55ad5fe..5808dd8 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
 # http_io
 
-[![Build Status](https://travis-ci.org/dart-lang/http_io.svg?branch=master)](https://travis-ci.org/dart-lang/http_io)
+[![Build Status](https://github.com/dart-lang/http_io/workflows/Dart%20CI/badge.svg)](https://github.com/dart-lang/http_io/actions?query=workflow%3A"Dart+CI"+branch%3Amaster)
 
 The HTTP APIs in `dart:io` are pure Dart code not relying on native runtime
 calls. To enable faster development and bug fixes, these APIs are moving out of
diff --git a/lib/src/crypto.dart b/lib/src/crypto.dart
index 2b73395..3368100 100644
--- a/lib/src/crypto.dart
+++ b/lib/src/crypto.dart
@@ -75,7 +75,7 @@
     if (addLineSeparator) {
       outputLen += ((outputLen - 1) ~/ LINE_LENGTH) << 1;
     }
-    List<int> out = List<int>(outputLen);
+    List<int> out = List<int>.filled(outputLen, null);
 
     // Encode 24 bit chunks.
     int j = 0, i = 0, c = 0;
@@ -119,7 +119,7 @@
       [bool ignoreInvalidCharacters = true]) {
     int len = input.length;
     if (len == 0) {
-      return List<int>(0);
+      return const <int>[];
     }
 
     // Count '\r', '\n' and illegal characters, For illegal characters,
@@ -148,7 +148,7 @@
       if (currentCodeUnit == PAD) padLength++;
     }
     int outputLen = (((len - extrasLen) * 6) >> 3) - padLength;
-    List<int> out = List<int>(outputLen);
+    List<int> out = List<int>.filled(outputLen, null);
 
     for (int i = 0, o = 0; o < outputLen;) {
       // Accumulate 4 valid 6 bit Base 64 characters into an int.
@@ -192,8 +192,8 @@
   HashBase(
       this._chunkSizeInWords, this._digestSizeInWords, this._bigEndianWords)
       : _pendingData = [] {
-    _currentChunk = List(_chunkSizeInWords);
-    _h = List(_digestSizeInWords);
+    _currentChunk = List.filled(_chunkSizeInWords, null);
+    _h = List.filled(_digestSizeInWords, null);
   }
 
   // Update the hasher with more data.
@@ -269,7 +269,7 @@
 
   // Convert a 32-bit word to four bytes.
   List<int> _wordToBytes(int word) {
-    List<int> bytes = List(_BYTES_PER_WORD);
+    List<int> bytes = List.filled(_BYTES_PER_WORD, null);
     bytes[0] = (word >> (_bigEndianWords ? 24 : 0)) & _MASK_8;
     bytes[1] = (word >> (_bigEndianWords ? 16 : 8)) & _MASK_8;
     bytes[2] = (word >> (_bigEndianWords ? 8 : 16)) & _MASK_8;
diff --git a/lib/src/http_headers_impl.dart b/lib/src/http_headers_impl.dart
index 71891a8..b0e8242 100644
--- a/lib/src/http_headers_impl.dart
+++ b/lib/src/http_headers_impl.dart
@@ -112,7 +112,7 @@
   }
 
   void noFolding(String name) {
-    _noFoldingHeaders ??= List<String>();
+    _noFoldingHeaders ??= <String>[];
     _noFoldingHeaders.add(name);
   }
 
@@ -432,7 +432,7 @@
   void _addValue(String name, Object value) {
     List<String> values = headers[name];
     if (values == null) {
-      values = List<String>();
+      values = <String>[];
       headers[name] = values;
     }
     if (value is DateTime) {
@@ -446,7 +446,7 @@
 
   void _set(String name, String value) {
     assert(name == _validateField(name));
-    List<String> values = List<String>();
+    List<String> values = <String>[];
     headers[name] = values;
     values.add(value);
   }
@@ -522,7 +522,7 @@
 
   List<Cookie> parseCookies() {
     // Parse a Cookie header value according to the rules in RFC 6265.
-    var cookies = List<Cookie>();
+    var cookies = <Cookie>[];
     void parseCookieString(String s) {
       int index = 0;
 
diff --git a/lib/src/http_impl.dart b/lib/src/http_impl.dart
index d12e801..4f74002 100644
--- a/lib/src/http_impl.dart
+++ b/lib/src/http_impl.dart
@@ -240,7 +240,7 @@
 
   List<Cookie> get cookies {
     if (_cookies != null) return _cookies;
-    _cookies = List<Cookie>();
+    _cookies = <Cookie>[];
     List<String> values = headers[HttpHeaders.SET_COOKIE];
     if (values != null) {
       values.forEach((value) {
@@ -727,7 +727,7 @@
   bool get _isConnectionClosed => _httpRequest._httpConnection._isClosing;
 
   List<Cookie> get cookies {
-    _cookies ??= List<Cookie>();
+    _cookies ??= <Cookie>[];
     return _cookies;
   }
 
@@ -936,7 +936,7 @@
     implements HttpClientRequest {
   final String method;
   final Uri uri;
-  final List<Cookie> cookies = List<Cookie>();
+  final List<Cookie> cookies = <Cookie>[];
 
   // The HttpClient this request belongs to.
   final _HttpClient _httpClient;
@@ -2597,7 +2597,7 @@
   static const String PROXY_PREFIX = "PROXY ";
   static const String DIRECT_PREFIX = "DIRECT";
 
-  _ProxyConfiguration(String configuration) : proxies = List<_Proxy>() {
+  _ProxyConfiguration(String configuration) : proxies = <_Proxy>[] {
     if (configuration == null) {
       throw HttpException("Invalid proxy configuration $configuration");
     }
diff --git a/lib/src/http_parser.dart b/lib/src/http_parser.dart
index 2b5914e..56d711d 100644
--- a/lib/src/http_parser.dart
+++ b/lib/src/http_parser.dart
@@ -541,9 +541,7 @@
 
         case _State.RESPONSE_LINE_ENDING:
           _expect(byte, CharCode.LF);
-          // TODO(kevmoo): file a linter bug on this!
-          // ignore: unnecessary_statements
-          _messageType == _MessageType.RESPONSE;
+          _messageType = _MessageType.RESPONSE;
           if (_statusCode < 100 || _statusCode > 599) {
             throw HttpException("Invalid response status code");
           } else {
@@ -883,7 +881,7 @@
   }
 
   static List<String> _tokenizeFieldValue(String headerValue) {
-    List<String> tokens = List<String>();
+    List<String> tokens = <String>[];
     int start = 0;
     int index = 0;
     while (index < headerValue.length) {
diff --git a/test/http_read_test.dart b/test/http_read_test.dart
index 7941a7e..e347e3b 100644
--- a/test/http_read_test.dart
+++ b/test/http_read_test.dart
@@ -187,7 +187,7 @@
         return request.close();
       }).then((response) {
         expect(HttpStatus.OK, equals(response.statusCode));
-        List<int> body = List<int>();
+        List<int> body = <int>[];
         response.listen(body.addAll, onDone: () {
           expect(data, equals(String.fromCharCodes(body)));
           count++;
diff --git a/test/http_reuse_server_port_test.dart b/test/http_reuse_server_port_test.dart
index 0e78bb9..a27d215 100644
--- a/test/http_reuse_server_port_test.dart
+++ b/test/http_reuse_server_port_test.dart
@@ -43,7 +43,7 @@
   final completer = Completer<Null>();
   runServer(0, 10, true).then((int port) {
     // Stress test the port reusing it 10 times.
-    Future.forEach(List(10), (_) {
+    Future.forEach(Iterable.generate(10), (_) {
       return runServer(port, 10, true);
     }).then((_) {
       completer.complete();
@@ -56,7 +56,7 @@
   final completer = Completer<Null>();
   runServer(0, 10, false).then((int port) {
     // Stress test the port reusing it 10 times.
-    Future.forEach(List(10), (_) {
+    Future.forEach(Iterable.generate(10), (_) {
       return runServer(port, 10, false);
     }).then((_) {
       completer.complete();
diff --git a/test/http_server_early_client_close_test.dart b/test/http_server_early_client_close_test.dart
index cc2d4c9..c533684 100644
--- a/test/http_server_early_client_close_test.dart
+++ b/test/http_server_early_client_close_test.dart
@@ -70,7 +70,7 @@
 }
 
 Future<Null> testEarlyClose1() async {
-  List<EarlyCloseTest> tests = List<EarlyCloseTest>();
+  List<EarlyCloseTest> tests = <EarlyCloseTest>[];
   void add(Object data, [String exception, bool expectRequest = false]) {
     tests.add(EarlyCloseTest(data, exception, expectRequest));
   }
diff --git a/test/http_server_response_test.dart b/test/http_server_response_test.dart
index 34999d0..d5676a7 100644
--- a/test/http_server_response_test.dart
+++ b/test/http_server_response_test.dart
@@ -51,7 +51,7 @@
 }
 
 Future<List> testResponseDone() {
-  final completers = List<Future<Null>>();
+  final completers = <Future<Null>>[];
   final completer = Completer<Null>();
   testServerRequest((server, request) {
     request.response.close();
@@ -93,7 +93,7 @@
 Future<List> testResponseAddStream() {
   File file = scriptSource;
   int bytes = file.lengthSync();
-  final completers = List<Future<Null>>();
+  final completers = <Future<Null>>[];
   final completer = Completer<Null>();
   testServerRequest((server, request) {
     request.response.addStream(file.openRead()).then((response) {
@@ -197,7 +197,7 @@
 
 Future<List> testResponseAddClosed() {
   File file = scriptSource;
-  final completers = List<Future<Null>>();
+  final completers = <Future<Null>>[];
 
   final completer = Completer<Null>();
   testServerRequest((server, request) {
@@ -249,7 +249,7 @@
 }
 
 Future<List> testBadResponseAdd() {
-  final completers = List<Future<Null>>();
+  final completers = <Future<Null>>[];
   final completer = Completer<Null>();
   testServerRequest((server, request) {
     request.response.contentLength = 0;
@@ -292,7 +292,7 @@
 }
 
 Future<List> testBadResponseClose() {
-  final completers = List<Future<Null>>();
+  final completers = <Future<Null>>[];
   final completer = Completer<Null>();
   testServerRequest((server, request) {
     request.response.contentLength = 5;