From ec41bfc1e00619818b25b35fad10ecae004ed7e1 Mon Sep 17 00:00:00 2001 From: Derek Xu Date: Tue, 14 Nov 2023 13:10:15 -0500 Subject: [PATCH 1/8] Populate package:http_profile --- pkgs/http_profile/lib/http_profile.dart | 308 +++++++++++++++++++++++- 1 file changed, 301 insertions(+), 7 deletions(-) diff --git a/pkgs/http_profile/lib/http_profile.dart b/pkgs/http_profile/lib/http_profile.dart index ea27665fb1..98fc2fcf2b 100644 --- a/pkgs/http_profile/lib/http_profile.dart +++ b/pkgs/http_profile/lib/http_profile.dart @@ -2,8 +2,208 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +import 'dart:async' show StreamController, StreamSink; +import 'dart:developer' show addHttpClientProfilingData, Timeline; import 'dart:io'; +/// Describes an event related to an HTTP request. +final class HttpProfileRequestEvent { + final int _timestamp; + final String _name; + + /// [timestamp] should be the time at which the event occurred, as a + /// microsecond value on the monotonic clock used by the [Timeline]. + HttpProfileRequestEvent({required int timestamp, required String name}) + : _timestamp = timestamp, + _name = name; + + Map _toJson() => { + 'timestamp': _timestamp, + 'event': _name, + }; +} + +/// Describes proxy authentication details associated with an HTTP request. +final class HttpProfileProxyData { + final String? _host; + final String? _username; + final bool? _isDirect; + final int? _port; + + HttpProfileProxyData( + {String? host, String? username, bool? isDirect, int? port}) + : _host = host, + _username = username, + _isDirect = isDirect, + _port = port; + + Map _toJson() => { + if (_host != null) 'host': _host, + if (_username != null) 'username': _username, + if (_isDirect != null) 'isDirect': _isDirect, + if (_port != null) 'port': _port, + }; +} + +/// Describes details about an HTTP request. +final class HttpProfileRequestData { + final Map _data; + + final void Function() _updated; + + /// The elements of [connectionInfo] can either be [String]s or [int]s. + set connectionInfo(Map value) { + _data['connectionInfo'] = value; + _updated(); + } + + /// The content length of the request, in bytes. + set contentLength(int value) { + _data['contentLength'] = value; + _updated(); + } + + /// The cookies presented to the server (in the 'cookie' header). + set cookies(List value) { + _data['cookies'] = value; + _updated(); + } + + /// The error associated with the failed request. + set error(String value) { + _data['error'] = value; + _updated(); + } + + /// Whether redirects were followed automatically. + set followRedirects(bool value) { + _data['followRedirects'] = value; + _updated(); + } + + set headers(Map> value) { + _data['headers'] = value; + _updated(); + } + + /// If [followRedirects] is true, this is the maximum number of redirects that + /// were followed. + set maxRedirects(int value) { + _data['maxRedirects'] = value; + _updated(); + } + + /// The requested persistent connection state. + set persistentConnection(bool value) { + _data['persistentConnection'] = value; + _updated(); + } + + /// Proxy authentication details for the request. + set proxyDetails(HttpProfileProxyData value) { + _data['proxyDetails'] = value._toJson(); + _updated(); + } + + HttpProfileRequestData._( + Map this._data, void Function() this._updated); +} + +/// Describes details about a response to an HTTP request. +final class HttpProfileResponseData { + final Map _data; + + final void Function() _updated; + + /// Records a redirect that the connection went through. The elements of + /// [redirect] can either be [String]s or [int]s. + void addRedirect(Map redirect) { + _data['redirects'].add(redirect); + _updated(); + } + + /// The cookies set by the server (from the 'set-cookie' header). + set cookies(List value) { + _data['cookies'] = value; + _updated(); + } + + /// The elements of [connectionInfo] can either be [String]s or [int]s. + set connectionInfo(Map value) { + _data['connectionInfo'] = value; + _updated(); + } + + set headers(Map> value) { + _data['headers'] = value; + _updated(); + } + + // The compression state of the response. + // + // This specifies whether the response bytes were compressed when they were + // received across the wire and whether callers will receive compressed or + // uncompressed bytes when they listen to the response body byte stream. + set compressionState(String value) { + _data['compressionState'] = value; + _updated(); + } + + set reasonPhrase(String value) { + _data['reasonPhrase'] = value; + _updated(); + } + + /// Whether the status code was one of the normal redirect codes. + set isRedirect(bool value) { + _data['isRedirect'] = value; + _updated(); + } + + /// The persistent connection state returned by the server. + set persistentConnection(bool value) { + _data['persistentConnection'] = value; + _updated(); + } + + /// The content length of the response body, in bytes. + set contentLength(int value) { + _data['contentLength'] = value; + _updated(); + } + + set statusCode(int value) { + _data['statusCode'] = value; + _updated(); + } + + /// The time at which the initial response was received, as a microsecond + /// value on the monotonic clock used by the [Timeline]. + set startTime(int value) { + _data['startTime'] = value; + _updated(); + } + + /// The time at which the response was completed, as a microsecond value on + /// the monotonic clock used by the [Timeline]. Note that DevTools will not + /// consider the request to be complete until [endTime] is non-null. + set endTime(int value) { + _data['endTime'] = value; + _updated(); + } + + /// The error associated with the failed request. + set error(String value) { + _data['error'] = value; + _updated(); + } + + HttpProfileResponseData._( + Map this._data, void Function() this._updated) { + _data['redirects'] = >[]; + } +} + /// A record of debugging information about an HTTP request. final class HttpClientRequestProfile { /// Whether HTTP profiling is enabled or not. @@ -14,20 +214,114 @@ final class HttpClientRequestProfile { static set profilingEnabled(bool enabled) => HttpClient.enableTimelineLogging = enabled; - String? requestMethod; - String? requestUri; + final _data = {}; + + /// The ID of the isolate the request was issued from. + String? get isolateId => _data['isolateId'] as String?; + set isolateId(String? value) { + _data['isolateId'] = value; + _updated(); + } + + /// The HTTP request method associated with the request. + String? get requestMethod => _data['requestMethod'] as String?; + set requestMethod(String? value) { + _data['requestMethod'] = value; + _updated(); + } + + /// The URI to which the request was sent. + String? get requestUri => _data['requestUri'] as String?; + set requestUri(String? value) { + _data['requestUri'] = value; + _updated(); + } + + /// Records an event related to the request. + /// + /// Usage example: + /// + /// ```dart + /// profile.addEvent(HttpProfileRequestEvent(Timeline.now, "Connection Established"); + /// profile.addEvent(HttpProfileRequestEvent(Timeline.now, "Remote Disconnected"); + /// ``` + void addEvent(HttpProfileRequestEvent event) { + _data['events'].add(event._toJson()); + _updated(); + } + + /// The time at which the request was initiated, as a microsecond value on the + /// monotonic clock used by the [Timeline]. + int? get requestStartTimestamp => _data['requestStartTimestamp'] as int?; + set requestStartTimestamp(int? value) { + _data['requestStartTimestamp'] = value; + _updated(); + } + + /// The time at which the request was completed, as a microsecond value on the + /// monotonic clock used by the [Timeline]. Note that DevTools will not + /// consider the request to be complete until [requestEndTimestamp] is + /// non-null. + int? get requestEndTimestamp => _data['requestEndTimestamp'] as int?; + set requestEndTimestamp(int? value) { + _data['requestEndTimestamp'] = value; + _updated(); + } - HttpClientRequestProfile._(); + /// Details about the request. + late final HttpProfileRequestData requestData; + + final StreamController> _requestBody = + StreamController>(); + + /// The body of the request. + StreamSink> get requestBodySink { + _updated(); + return _requestBody.sink; + } + + /// Details about the response. + late final HttpProfileResponseData responseData; + + final StreamController> _responseBody = + StreamController>(); + + /// The body of the response. + StreamSink> get responseBodySink { + _updated(); + return _responseBody.sink; + } + + void _updated() => _data['_lastUpdateTime'] = Timeline.now; + + HttpClientRequestProfile._() { + _data['events'] = >[]; + _data['requestData'] = {}; + requestData = HttpProfileRequestData._( + _data['requestData'] as Map, _updated); + _data['responseData'] = {}; + responseData = HttpProfileResponseData._( + _data['responseData'] as Map, _updated); + _data['_requestBodyStream'] = _requestBody.stream; + _data['_responseBodyStream'] = _responseBody.stream; + // This entry is needed to support the updatedSince parameter of + // ext.dart.io.getHttpProfile. + _data['_lastUpdateTime'] = 0; + } - /// If HTTP profiling is enabled, returns - /// a [HttpClientRequestProfile] otherwise returns `null`. + /// If HTTP profiling is enabled, returns an [HttpClientRequestProfile], + /// otherwise returns `null`. static HttpClientRequestProfile? profile() { - // Always return `null` in product mode so that the - // profiling code can be tree shaken away. + // Always return `null` in product mode so that the profiling code can be + // tree shaken away. if (const bool.fromEnvironment('dart.vm.product') || !profilingEnabled) { return null; } final requestProfile = HttpClientRequestProfile._(); + // This entry is needed to support the id parameter of + // ext.dart.io.getHttpProfileRequest. + requestProfile._data['id'] = + 'from_package/${addHttpClientProfilingData(requestProfile._data)}'; return requestProfile; } } From b5f549012e0b118d015a1cf3259cf5e58a9c0812 Mon Sep 17 00:00:00 2001 From: Derek Xu Date: Mon, 4 Dec 2023 17:18:07 -0500 Subject: [PATCH 2/8] Address comments --- pkgs/http_profile/lib/http_profile.dart | 144 +++++++++++++++--------- 1 file changed, 93 insertions(+), 51 deletions(-) diff --git a/pkgs/http_profile/lib/http_profile.dart b/pkgs/http_profile/lib/http_profile.dart index 98fc2fcf2b..dd1795cc56 100644 --- a/pkgs/http_profile/lib/http_profile.dart +++ b/pkgs/http_profile/lib/http_profile.dart @@ -11,10 +11,8 @@ final class HttpProfileRequestEvent { final int _timestamp; final String _name; - /// [timestamp] should be the time at which the event occurred, as a - /// microsecond value on the monotonic clock used by the [Timeline]. - HttpProfileRequestEvent({required int timestamp, required String name}) - : _timestamp = timestamp, + HttpProfileRequestEvent({required DateTime timestamp, required String name}) + : _timestamp = timestamp.microsecondsSinceEpoch, _name = name; Map _toJson() => { @@ -30,9 +28,12 @@ final class HttpProfileProxyData { final bool? _isDirect; final int? _port; - HttpProfileProxyData( - {String? host, String? username, bool? isDirect, int? port}) - : _host = host, + HttpProfileProxyData({ + String? host, + String? username, + bool? isDirect, + int? port, + }) : _host = host, _username = username, _isDirect = isDirect, _port = port; @@ -45,15 +46,48 @@ final class HttpProfileProxyData { }; } +/// Describes a redirect that an HTTP connection went through. +class HttpProfileRedirectData { + int _statusCode; + String _method; + String _location; + + HttpProfileRedirectData({ + required int statusCode, + required String method, + required String location, + }) : _statusCode = statusCode, + _method = method, + _location = location; + + Map _toJson() => { + 'statusCode': _statusCode, + 'method': _method, + 'location': _location, + }; +} + /// Describes details about an HTTP request. final class HttpProfileRequestData { final Map _data; final void Function() _updated; - /// The elements of [connectionInfo] can either be [String]s or [int]s. + /// Information about the networking connection used in the HTTP request. + /// + /// This information is meant to be used for debugging. + /// + /// It can contain any arbitrary data as long as the values are of type + /// [String] or [int]. For example: + /// { 'localPort': 1285, 'remotePort': 443, 'connectionPoolId': '21x23' } set connectionInfo(Map value) { - _data['connectionInfo'] = value; + for (final v in value.values) { + if (!(v is String || v is int)) { + throw ArgumentError( + "The values in connectionInfo must be of type String or int."); + } + } + _data['connectionInfo'] = {...value}; _updated(); } @@ -64,30 +98,29 @@ final class HttpProfileRequestData { } /// The cookies presented to the server (in the 'cookie' header). - set cookies(List value) { - _data['cookies'] = value; + set cookies(List value) { + _data['cookies'] = [for (final cookie in value) cookie.toString()]; _updated(); } - /// The error associated with the failed request. + /// The error associated with a failed request. set error(String value) { _data['error'] = value; _updated(); } - /// Whether redirects were followed automatically. + /// Whether automatic redirect following was enabled for the request. set followRedirects(bool value) { _data['followRedirects'] = value; _updated(); } set headers(Map> value) { - _data['headers'] = value; + _data['headers'] = {...value}; _updated(); } - /// If [followRedirects] is true, this is the maximum number of redirects that - /// were followed. + /// The maximum number of redirects allowed during the request. set maxRedirects(int value) { _data['maxRedirects'] = value; _updated(); @@ -105,8 +138,10 @@ final class HttpProfileRequestData { _updated(); } - HttpProfileRequestData._( - Map this._data, void Function() this._updated); + const HttpProfileRequestData._( + Map this._data, + void Function() this._updated, + ); } /// Describes details about a response to an HTTP request. @@ -115,27 +150,38 @@ final class HttpProfileResponseData { final void Function() _updated; - /// Records a redirect that the connection went through. The elements of - /// [redirect] can either be [String]s or [int]s. - void addRedirect(Map redirect) { - _data['redirects'].add(redirect); + /// Records a redirect that the connection went through. + void addRedirect(HttpProfileRedirectData redirect) { + _data['redirects'].add(redirect._toJson()); _updated(); } /// The cookies set by the server (from the 'set-cookie' header). - set cookies(List value) { - _data['cookies'] = value; + set cookies(List value) { + _data['cookies'] = [for (final cookie in value) cookie.toString()]; _updated(); } - /// The elements of [connectionInfo] can either be [String]s or [int]s. + /// Information about the networking connection used in the HTTP response. + /// + /// This information is meant to be used for debugging. + /// + /// It can contain any arbitrary data as long as the values are of type + /// [String] or [int]. For example: + /// { 'localPort': 1285, 'remotePort': 443, 'connectionPoolId': '21x23' } set connectionInfo(Map value) { - _data['connectionInfo'] = value; + for (final v in value.values) { + if (!(v is String || v is int)) { + throw ArgumentError( + "The values in connectionInfo must be of type String or int."); + } + } + _data['connectionInfo'] = {...value}; _updated(); } set headers(Map> value) { - _data['headers'] = value; + _data['headers'] = {...value}; _updated(); } @@ -144,8 +190,8 @@ final class HttpProfileResponseData { // This specifies whether the response bytes were compressed when they were // received across the wire and whether callers will receive compressed or // uncompressed bytes when they listen to the response body byte stream. - set compressionState(String value) { - _data['compressionState'] = value; + set compressionState(HttpClientResponseCompressionState value) { + _data['compressionState'] = value.name; _updated(); } @@ -177,29 +223,29 @@ final class HttpProfileResponseData { _updated(); } - /// The time at which the initial response was received, as a microsecond - /// value on the monotonic clock used by the [Timeline]. - set startTime(int value) { - _data['startTime'] = value; + /// The time at which the initial response was received. + set startTime(DateTime value) { + _data['startTime'] = value.microsecondsSinceEpoch; _updated(); } - /// The time at which the response was completed, as a microsecond value on - /// the monotonic clock used by the [Timeline]. Note that DevTools will not + /// The time at which the response was completed. Note that DevTools will not /// consider the request to be complete until [endTime] is non-null. - set endTime(int value) { - _data['endTime'] = value; + set endTime(DateTime value) { + _data['endTime'] = value.microsecondsSinceEpoch; _updated(); } - /// The error associated with the failed request. + /// The error associated with a failed request. set error(String value) { _data['error'] = value; _updated(); } HttpProfileResponseData._( - Map this._data, void Function() this._updated) { + Map this._data, + void Function() this._updated, + ) { _data['redirects'] = >[]; } } @@ -242,29 +288,25 @@ final class HttpClientRequestProfile { /// Usage example: /// /// ```dart - /// profile.addEvent(HttpProfileRequestEvent(Timeline.now, "Connection Established"); - /// profile.addEvent(HttpProfileRequestEvent(Timeline.now, "Remote Disconnected"); + /// profile.addEvent(HttpProfileRequestEvent(DateTime.now(), "Connection Established"); + /// profile.addEvent(HttpProfileRequestEvent(DateTime.now(), "Remote Disconnected"); /// ``` void addEvent(HttpProfileRequestEvent event) { _data['events'].add(event._toJson()); _updated(); } - /// The time at which the request was initiated, as a microsecond value on the - /// monotonic clock used by the [Timeline]. - int? get requestStartTimestamp => _data['requestStartTimestamp'] as int?; - set requestStartTimestamp(int? value) { - _data['requestStartTimestamp'] = value; + /// The time at which the request was initiated. + set requestStartTimestamp(DateTime value) { + _data['requestStartTimestamp'] = value.microsecondsSinceEpoch; _updated(); } - /// The time at which the request was completed, as a microsecond value on the - /// monotonic clock used by the [Timeline]. Note that DevTools will not + /// The time at which the request was completed. Note that DevTools will not /// consider the request to be complete until [requestEndTimestamp] is /// non-null. - int? get requestEndTimestamp => _data['requestEndTimestamp'] as int?; - set requestEndTimestamp(int? value) { - _data['requestEndTimestamp'] = value; + set requestEndTimestamp(DateTime value) { + _data['requestEndTimestamp'] = value.microsecondsSinceEpoch; _updated(); } From 746ef59162c6750f1540f2ea7ba8316d09dad994 Mon Sep 17 00:00:00 2001 From: Derek Xu Date: Tue, 5 Dec 2023 11:25:42 -0500 Subject: [PATCH 3/8] Add examples showing how to use the `cookies` setters --- pkgs/http_profile/lib/http_profile.dart | 26 +++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/pkgs/http_profile/lib/http_profile.dart b/pkgs/http_profile/lib/http_profile.dart index dd1795cc56..f3adc2a91f 100644 --- a/pkgs/http_profile/lib/http_profile.dart +++ b/pkgs/http_profile/lib/http_profile.dart @@ -98,8 +98,17 @@ final class HttpProfileRequestData { } /// The cookies presented to the server (in the 'cookie' header). - set cookies(List value) { - _data['cookies'] = [for (final cookie in value) cookie.toString()]; + /// + /// Usage example: + /// + /// ```dart + /// profile.requestData.cookies = [ + /// 'sessionId=abc123', + /// 'csrftoken=def456', + /// ]; + /// ``` + set cookies(List value) { + _data['cookies'] = [...value]; _updated(); } @@ -157,8 +166,17 @@ final class HttpProfileResponseData { } /// The cookies set by the server (from the 'set-cookie' header). - set cookies(List value) { - _data['cookies'] = [for (final cookie in value) cookie.toString()]; + /// + /// Usage example: + /// + /// ```dart + /// profile.responseData.cookies = [ + /// 'sessionId=abc123', + /// 'id=def456; Max-Age=2592000; Domain=example.com', + /// ]; + /// ``` + set cookies(List value) { + _data['cookies'] = [...value]; _updated(); } From f95902be6b13c4eacc7f86a8afb907bbfe17a4ca Mon Sep 17 00:00:00 2001 From: Derek Xu Date: Tue, 12 Dec 2023 14:19:16 -0500 Subject: [PATCH 4/8] Update --- pkgs/http_profile/lib/http_profile.dart | 64 ++++++++++++------------- 1 file changed, 30 insertions(+), 34 deletions(-) diff --git a/pkgs/http_profile/lib/http_profile.dart b/pkgs/http_profile/lib/http_profile.dart index f3adc2a91f..a980d02e7f 100644 --- a/pkgs/http_profile/lib/http_profile.dart +++ b/pkgs/http_profile/lib/http_profile.dart @@ -3,8 +3,9 @@ // BSD-style license that can be found in the LICENSE file. import 'dart:async' show StreamController, StreamSink; -import 'dart:developer' show addHttpClientProfilingData, Timeline; -import 'dart:io'; +import 'dart:developer' show addHttpClientProfilingData, Service, Timeline; +import 'dart:io' show HttpClient, HttpClientResponseCompressionState; +import 'dart:isolate' show Isolate; /// Describes an event related to an HTTP request. final class HttpProfileRequestEvent { @@ -280,27 +281,6 @@ final class HttpClientRequestProfile { final _data = {}; - /// The ID of the isolate the request was issued from. - String? get isolateId => _data['isolateId'] as String?; - set isolateId(String? value) { - _data['isolateId'] = value; - _updated(); - } - - /// The HTTP request method associated with the request. - String? get requestMethod => _data['requestMethod'] as String?; - set requestMethod(String? value) { - _data['requestMethod'] = value; - _updated(); - } - - /// The URI to which the request was sent. - String? get requestUri => _data['requestUri'] as String?; - set requestUri(String? value) { - _data['requestUri'] = value; - _updated(); - } - /// Records an event related to the request. /// /// Usage example: @@ -314,12 +294,6 @@ final class HttpClientRequestProfile { _updated(); } - /// The time at which the request was initiated. - set requestStartTimestamp(DateTime value) { - _data['requestStartTimestamp'] = value.microsecondsSinceEpoch; - _updated(); - } - /// The time at which the request was completed. Note that DevTools will not /// consider the request to be complete until [requestEndTimestamp] is /// non-null. @@ -354,7 +328,16 @@ final class HttpClientRequestProfile { void _updated() => _data['_lastUpdateTime'] = Timeline.now; - HttpClientRequestProfile._() { + HttpClientRequestProfile._({ + required DateTime requestStartTimestamp, + required String requestMethod, + required String requestUri, + }) { + _data['isolateId'] = Service.getIsolateId(Isolate.current)!; + _data['requestStartTimestamp'] = + requestStartTimestamp.microsecondsSinceEpoch; + _data['requestMethod'] = requestMethod; + _data['requestUri'] = requestUri; _data['events'] = >[]; _data['requestData'] = {}; requestData = HttpProfileRequestData._( @@ -366,22 +349,35 @@ final class HttpClientRequestProfile { _data['_responseBodyStream'] = _responseBody.stream; // This entry is needed to support the updatedSince parameter of // ext.dart.io.getHttpProfile. - _data['_lastUpdateTime'] = 0; + _data['_lastUpdateTime'] = Timeline.now; } /// If HTTP profiling is enabled, returns an [HttpClientRequestProfile], /// otherwise returns `null`. - static HttpClientRequestProfile? profile() { + static HttpClientRequestProfile? profile({ + /// The time at which the request was initiated. + required DateTime requestStartTimestamp, + + /// The HTTP request method associated with the request. + required String requestMethod, + + /// The URI to which the request was sent. + required String requestUri, + }) { // Always return `null` in product mode so that the profiling code can be // tree shaken away. if (const bool.fromEnvironment('dart.vm.product') || !profilingEnabled) { return null; } - final requestProfile = HttpClientRequestProfile._(); + final requestProfile = HttpClientRequestProfile._( + requestStartTimestamp: requestStartTimestamp, + requestMethod: requestMethod, + requestUri: requestUri, + ); // This entry is needed to support the id parameter of // ext.dart.io.getHttpProfileRequest. requestProfile._data['id'] = - 'from_package/${addHttpClientProfilingData(requestProfile._data)}'; + addHttpClientProfilingData(requestProfile._data); return requestProfile; } } From b076d976872da2b8a6ceaac13636c6e3ff5105de Mon Sep 17 00:00:00 2001 From: Derek Xu Date: Thu, 14 Dec 2023 17:38:40 -0500 Subject: [PATCH 5/8] Add unit tests --- .../test/populating_profiles_test.dart | 386 ++++++++++++++++++ .../test/profiling_enabled_test.dart | 18 +- 2 files changed, 402 insertions(+), 2 deletions(-) create mode 100644 pkgs/http_profile/test/populating_profiles_test.dart diff --git a/pkgs/http_profile/test/populating_profiles_test.dart b/pkgs/http_profile/test/populating_profiles_test.dart new file mode 100644 index 0000000000..1b5b547134 --- /dev/null +++ b/pkgs/http_profile/test/populating_profiles_test.dart @@ -0,0 +1,386 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; +import 'dart:developer' show getHttpClientProfilingData, Service; +import 'dart:io'; +import 'dart:isolate' show Isolate; + +import 'package:http_profile/http_profile.dart'; +import 'package:test/test.dart'; + +void main() { + late HttpClientRequestProfile profile; + late Map backingMap; + + setUp(() { + HttpClientRequestProfile.profilingEnabled = true; + + profile = HttpClientRequestProfile.profile( + requestStartTimestamp: DateTime.parse('2024-03-21'), + requestMethod: 'GET', + requestUri: 'https://www.example.com', + )!; + + final profileBackingMaps = getHttpClientProfilingData(); + expect(profileBackingMaps.length, isPositive); + backingMap = profileBackingMaps.lastOrNull!; + }); + + test( + 'mandatory fields are populated when an HttpClientRequestProfile is ' + 'constructed', () async { + expect(backingMap['id'], isNotNull); + expect(backingMap['isolateId'], Service.getIsolateId(Isolate.current)!); + expect( + backingMap['requestStartTimestamp'], + DateTime.parse('2024-03-21').microsecondsSinceEpoch, + ); + expect(backingMap['requestMethod'], 'GET'); + expect(backingMap['requestUri'], 'https://www.example.com'); + }); + + test('calling HttpClientRequestProfile.addEvent', () async { + final events = backingMap['events'] as List>; + expect(events, isEmpty); + + profile.addEvent(HttpProfileRequestEvent( + timestamp: DateTime.parse('2024-03-22'), + name: 'an event', + )); + + expect(events.length, 1); + final event = events.last; + expect( + event['timestamp'], + DateTime.parse('2024-03-22').microsecondsSinceEpoch, + ); + expect(event['event'], 'an event'); + }); + + test('populating HttpClientRequestProfile.requestEndTimestamp', () async { + expect(backingMap['requestEndTimestamp'], isNull); + + profile.requestEndTimestamp = DateTime.parse('2024-03-23'); + + expect( + backingMap['requestEndTimestamp'], + DateTime.parse('2024-03-23').microsecondsSinceEpoch, + ); + }); + + test('populating HttpClientRequestProfile.requestData.connectionInfo', + () async { + final requestData = backingMap['requestData'] as Map; + expect(requestData['connectionInfo'], isNull); + + profile.requestData.connectionInfo = { + 'localPort': 1285, + 'remotePort': 443, + 'connectionPoolId': '21x23' + }; + + final connectionInfo = + requestData['connectionInfo'] as Map; + expect(connectionInfo['localPort'], 1285); + expect(connectionInfo['remotePort'], 443); + expect(connectionInfo['connectionPoolId'], '21x23'); + }); + + test('populating HttpClientRequestProfile.requestData.contentLength', + () async { + final requestData = backingMap['requestData'] as Map; + expect(requestData['contentLength'], isNull); + + profile.requestData.contentLength = 1200; + + expect(requestData['contentLength'], 1200); + }); + + test('populating HttpClientRequestProfile.requestData.cookies', () async { + final requestData = backingMap['requestData'] as Map; + expect(requestData['cookies'], isNull); + + profile.requestData.cookies = [ + 'sessionId=abc123', + 'csrftoken=def456', + ]; + + final cookies = requestData['cookies'] as List; + expect(cookies.length, 2); + expect(cookies[0], 'sessionId=abc123'); + expect(cookies[1], 'csrftoken=def456'); + }); + + test('populating HttpClientRequestProfile.requestData.error', () async { + final requestData = backingMap['requestData'] as Map; + expect(requestData['error'], isNull); + + profile.requestData.error = 'failed'; + + expect(requestData['error'], 'failed'); + }); + + test('populating HttpClientRequestProfile.requestData.followRedirects', + () async { + final requestData = backingMap['requestData'] as Map; + expect(requestData['followRedirects'], isNull); + + profile.requestData.followRedirects = true; + + expect(requestData['followRedirects'], true); + }); + + test('populating HttpClientRequestProfile.requestData.headers', () async { + final requestData = backingMap['requestData'] as Map; + expect(requestData['headers'], isNull); + + profile.requestData.headers = { + 'content-length': ['0'], + }; + + final headers = requestData['headers'] as Map>; + expect(headers['content-length']!.length, 1); + expect(headers['content-length']![0], '0'); + }); + + test('populating HttpClientRequestProfile.requestData.maxRedirects', + () async { + final requestData = backingMap['requestData'] as Map; + expect(requestData['maxRedirects'], isNull); + + profile.requestData.maxRedirects = 5; + + expect(requestData['maxRedirects'], 5); + }); + + test('populating HttpClientRequestProfile.requestData.persistentConnection', + () async { + final requestData = backingMap['requestData'] as Map; + expect(requestData['persistentConnection'], isNull); + + profile.requestData.persistentConnection = true; + + expect(requestData['persistentConnection'], true); + }); + + test('populating HttpClientRequestProfile.requestData.proxyDetails', + () async { + final requestData = backingMap['requestData'] as Map; + expect(requestData['proxyDetails'], isNull); + + profile.requestData.proxyDetails = HttpProfileProxyData( + host: 'https://www.example.com', + username: 'abc123', + isDirect: true, + port: 4321, + ); + + final proxyDetails = requestData['proxyDetails'] as Map; + expect( + proxyDetails['host'], + 'https://www.example.com', + ); + expect(proxyDetails['username'], 'abc123'); + expect(proxyDetails['isDirect'], true); + expect(proxyDetails['port'], 4321); + }); + + test('calling HttpClientRequestProfile.responseData.addRedirect', () async { + final responseData = backingMap['responseData'] as Map; + final redirects = responseData['redirects'] as List>; + expect(redirects, isEmpty); + + profile.responseData.addRedirect(HttpProfileRedirectData( + statusCode: 301, + method: 'GET', + location: 'https://images.example.com/1', + )); + + expect(redirects.length, 1); + final redirect = redirects.last; + expect(redirect['statusCode'], 301); + expect(redirect['method'], 'GET'); + expect(redirect['location'], 'https://images.example.com/1'); + }); + + test('populating HttpClientRequestProfile.responseData.cookies', () async { + final responseData = backingMap['responseData'] as Map; + expect(responseData['cookies'], isNull); + + profile.responseData.cookies = [ + 'sessionId=abc123', + 'id=def456; Max-Age=2592000; Domain=example.com', + ]; + + final cookies = responseData['cookies'] as List; + expect(cookies.length, 2); + expect(cookies[0], 'sessionId=abc123'); + expect(cookies[1], 'id=def456; Max-Age=2592000; Domain=example.com'); + }); + + test('populating HttpClientRequestProfile.responseData.connectionInfo', + () async { + final responseData = backingMap['responseData'] as Map; + expect(responseData['connectionInfo'], isNull); + + profile.responseData.connectionInfo = { + 'localPort': 1285, + 'remotePort': 443, + 'connectionPoolId': '21x23' + }; + + final connectionInfo = + responseData['connectionInfo'] as Map; + expect(connectionInfo['localPort'], 1285); + expect(connectionInfo['remotePort'], 443); + expect(connectionInfo['connectionPoolId'], '21x23'); + }); + + test('populating HttpClientRequestProfile.responseData.headers', () async { + final responseData = backingMap['responseData'] as Map; + expect(responseData['headers'], isNull); + + profile.responseData.headers = { + 'connection': ['keep-alive'], + 'cache-control': ['max-age=43200'], + 'content-type': ['application/json', 'charset=utf-8'], + }; + + final headers = responseData['headers'] as Map>; + expect(headers['connection']!.length, 1); + expect(headers['connection']![0], 'keep-alive'); + expect(headers['cache-control']!.length, 1); + expect(headers['cache-control']![0], 'max-age=43200'); + expect(headers['content-type']!.length, 2); + expect(headers['content-type']![0], 'application/json'); + expect(headers['content-type']![1], 'charset=utf-8'); + }); + + test('populating HttpClientRequestProfile.responseData.compressionState', + () async { + final responseData = backingMap['responseData'] as Map; + expect(responseData['compressionState'], isNull); + + profile.responseData.compressionState = + HttpClientResponseCompressionState.decompressed; + + expect(responseData['compressionState'], 'decompressed'); + }); + + test('populating HttpClientRequestProfile.responseData.reasonPhrase', + () async { + final responseData = backingMap['responseData'] as Map; + expect(responseData['reasonPhrase'], isNull); + + profile.responseData.reasonPhrase = 'OK'; + + expect(responseData['reasonPhrase'], 'OK'); + }); + + test('populating HttpClientRequestProfile.responseData.isRedirect', () async { + final responseData = backingMap['responseData'] as Map; + expect(responseData['isRedirect'], isNull); + + profile.responseData.isRedirect = true; + + expect(responseData['isRedirect'], true); + }); + + test('populating HttpClientRequestProfile.responseData.persistentConnection', + () async { + final responseData = backingMap['responseData'] as Map; + expect(responseData['persistentConnection'], isNull); + + profile.responseData.persistentConnection = true; + + expect(responseData['persistentConnection'], true); + }); + + test('populating HttpClientRequestProfile.responseData.contentLength', + () async { + final responseData = backingMap['responseData'] as Map; + expect(responseData['contentLength'], isNull); + + profile.responseData.contentLength = 1200; + + expect(responseData['contentLength'], 1200); + }); + + test('populating HttpClientRequestProfile.responseData.statusCode', () async { + final responseData = backingMap['responseData'] as Map; + expect(responseData['statusCode'], isNull); + + profile.responseData.statusCode = 200; + + expect(responseData['statusCode'], 200); + }); + + test('populating HttpClientRequestProfile.responseData.startTime', () async { + final responseData = backingMap['responseData'] as Map; + expect(responseData['startTime'], isNull); + + profile.responseData.startTime = DateTime.parse('2024-03-21'); + + expect( + responseData['startTime'], + DateTime.parse('2024-03-21').microsecondsSinceEpoch, + ); + }); + + test('populating HttpClientRequestProfile.responseData.endTime', () async { + final responseData = backingMap['responseData'] as Map; + expect(responseData['endTime'], isNull); + + profile.responseData.endTime = DateTime.parse('2024-03-23'); + + expect( + responseData['endTime'], + DateTime.parse('2024-03-23').microsecondsSinceEpoch, + ); + }); + + test('populating HttpClientRequestProfile.responseData.error', () async { + final responseData = backingMap['responseData'] as Map; + expect(responseData['error'], isNull); + + profile.responseData.error = 'failed'; + + expect(responseData['error'], 'failed'); + }); + + test('using HttpClientRequestProfile.requestBodySink', () async { + final requestBodyStream = + backingMap['_requestBodyStream'] as Stream>; + + profile.requestBodySink.add([1, 2, 3]); + + await Future.wait([ + Future.sync( + () async => expect( + await requestBodyStream.expand((i) => i).toList(), + [1, 2, 3], + ), + ), + profile.requestBodySink.close(), + ]); + }); + + test('using HttpClientRequestProfile.responseBodySink', () async { + final requestBodyStream = + backingMap['_responseBodyStream'] as Stream>; + + profile.responseBodySink.add([1, 2, 3]); + + await Future.wait([ + Future.sync( + () async => expect( + await requestBodyStream.expand((i) => i).toList(), + [1, 2, 3], + ), + ), + profile.responseBodySink.close(), + ]); + }); +} diff --git a/pkgs/http_profile/test/profiling_enabled_test.dart b/pkgs/http_profile/test/profiling_enabled_test.dart index 6336da6ee4..3062c79719 100644 --- a/pkgs/http_profile/test/profiling_enabled_test.dart +++ b/pkgs/http_profile/test/profiling_enabled_test.dart @@ -11,12 +11,26 @@ void main() { test('profiling enabled', () async { HttpClientRequestProfile.profilingEnabled = true; expect(HttpClient.enableTimelineLogging, true); - expect(HttpClientRequestProfile.profile(), isNotNull); + expect( + HttpClientRequestProfile.profile( + requestStartTimestamp: DateTime.parse('2024-03-21'), + requestMethod: 'GET', + requestUri: 'https://www.example.com', + ), + isNotNull, + ); }); test('profiling disabled', () async { HttpClientRequestProfile.profilingEnabled = false; expect(HttpClient.enableTimelineLogging, false); - expect(HttpClientRequestProfile.profile(), isNull); + expect( + HttpClientRequestProfile.profile( + requestStartTimestamp: DateTime.parse('2024-03-21'), + requestMethod: 'GET', + requestUri: 'https://www.example.com', + ), + isNull, + ); }); } From 45655fe16672be55dc9c72723e115ea1137cd4ea Mon Sep 17 00:00:00 2001 From: Derek Xu Date: Thu, 15 Feb 2024 16:26:32 -0500 Subject: [PATCH 6/8] Address lints --- pkgs/http_profile/lib/http_profile.dart | 34 ++++++++++++------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/pkgs/http_profile/lib/http_profile.dart b/pkgs/http_profile/lib/http_profile.dart index a980d02e7f..fdf7349b9c 100644 --- a/pkgs/http_profile/lib/http_profile.dart +++ b/pkgs/http_profile/lib/http_profile.dart @@ -49,9 +49,9 @@ final class HttpProfileProxyData { /// Describes a redirect that an HTTP connection went through. class HttpProfileRedirectData { - int _statusCode; - String _method; - String _location; + final int _statusCode; + final String _method; + final String _location; HttpProfileRedirectData({ required int statusCode, @@ -85,7 +85,8 @@ final class HttpProfileRequestData { for (final v in value.values) { if (!(v is String || v is int)) { throw ArgumentError( - "The values in connectionInfo must be of type String or int."); + 'The values in connectionInfo must be of type String or int.', + ); } } _data['connectionInfo'] = {...value}; @@ -149,8 +150,8 @@ final class HttpProfileRequestData { } const HttpProfileRequestData._( - Map this._data, - void Function() this._updated, + this._data, + this._updated, ); } @@ -162,7 +163,7 @@ final class HttpProfileResponseData { /// Records a redirect that the connection went through. void addRedirect(HttpProfileRedirectData redirect) { - _data['redirects'].add(redirect._toJson()); + (_data['redirects'] as List>).add(redirect._toJson()); _updated(); } @@ -192,7 +193,8 @@ final class HttpProfileResponseData { for (final v in value.values) { if (!(v is String || v is int)) { throw ArgumentError( - "The values in connectionInfo must be of type String or int."); + 'The values in connectionInfo must be of type String or int.', + ); } } _data['connectionInfo'] = {...value}; @@ -262,8 +264,8 @@ final class HttpProfileResponseData { } HttpProfileResponseData._( - Map this._data, - void Function() this._updated, + this._data, + this._updated, ) { _data['redirects'] = >[]; } @@ -290,7 +292,7 @@ final class HttpClientRequestProfile { /// profile.addEvent(HttpProfileRequestEvent(DateTime.now(), "Remote Disconnected"); /// ``` void addEvent(HttpProfileRequestEvent event) { - _data['events'].add(event._toJson()); + (_data['events'] as List>).add(event._toJson()); _updated(); } @@ -326,7 +328,8 @@ final class HttpClientRequestProfile { return _responseBody.sink; } - void _updated() => _data['_lastUpdateTime'] = Timeline.now; + void _updated() => + _data['_lastUpdateTime'] = DateTime.now().microsecondsSinceEpoch; HttpClientRequestProfile._({ required DateTime requestStartTimestamp, @@ -349,7 +352,7 @@ final class HttpClientRequestProfile { _data['_responseBodyStream'] = _responseBody.stream; // This entry is needed to support the updatedSince parameter of // ext.dart.io.getHttpProfile. - _data['_lastUpdateTime'] = Timeline.now; + _data['_lastUpdateTime'] = DateTime.now().microsecondsSinceEpoch; } /// If HTTP profiling is enabled, returns an [HttpClientRequestProfile], @@ -374,10 +377,7 @@ final class HttpClientRequestProfile { requestMethod: requestMethod, requestUri: requestUri, ); - // This entry is needed to support the id parameter of - // ext.dart.io.getHttpProfileRequest. - requestProfile._data['id'] = - addHttpClientProfilingData(requestProfile._data); + addHttpClientProfilingData(requestProfile._data); return requestProfile; } } From af40a789e6fab6e22693a91f645a5a7dec3bb5d0 Mon Sep 17 00:00:00 2001 From: Derek Xu Date: Thu, 15 Feb 2024 16:34:22 -0500 Subject: [PATCH 7/8] Update SDK constraint in pubspec.yaml --- .github/workflows/dart.yml | 158 +++++++++++++-------------------- pkgs/http_profile/pubspec.yaml | 3 +- 2 files changed, 64 insertions(+), 97 deletions(-) diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index 22c1e5205c..f57d2c5755 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -40,36 +40,6 @@ jobs: - name: mono_repo self validate run: dart pub global run mono_repo generate --validate job_002: - name: "analyze_and_format; linux; Dart 3.0.0; PKG: pkgs/http_profile; `dart analyze --fatal-infos`" - runs-on: ubuntu-latest - steps: - - name: Cache Pub hosted dependencies - uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 - with: - path: "~/.pub-cache/hosted" - key: "os:ubuntu-latest;pub-cache-hosted;sdk:3.0.0;packages:pkgs/http_profile;commands:analyze_1" - restore-keys: | - os:ubuntu-latest;pub-cache-hosted;sdk:3.0.0;packages:pkgs/http_profile - os:ubuntu-latest;pub-cache-hosted;sdk:3.0.0 - os:ubuntu-latest;pub-cache-hosted - os:ubuntu-latest - - name: Setup Dart SDK - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 - with: - sdk: "3.0.0" - - id: checkout - name: Checkout repository - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - id: pkgs_http_profile_pub_upgrade - name: pkgs/http_profile; dart pub upgrade - run: dart pub upgrade - if: "always() && steps.checkout.conclusion == 'success'" - working-directory: pkgs/http_profile - - name: "pkgs/http_profile; dart analyze --fatal-infos" - run: dart analyze --fatal-infos - if: "always() && steps.pkgs_http_profile_pub_upgrade.conclusion == 'success'" - working-directory: pkgs/http_profile - job_003: name: "analyze_and_format; linux; Dart 3.2.0; PKG: pkgs/http_client_conformance_tests; `dart analyze --fatal-infos`" runs-on: ubuntu-latest steps: @@ -99,68 +69,68 @@ jobs: run: dart analyze --fatal-infos if: "always() && steps.pkgs_http_client_conformance_tests_pub_upgrade.conclusion == 'success'" working-directory: pkgs/http_client_conformance_tests - job_004: - name: "analyze_and_format; linux; Dart 3.2.6; PKG: pkgs/web_socket; `dart analyze --fatal-infos`" + job_003: + name: "analyze_and_format; linux; Dart 3.3.0; PKG: pkgs/http; `dart analyze --fatal-infos`" runs-on: ubuntu-latest steps: - name: Cache Pub hosted dependencies uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 with: path: "~/.pub-cache/hosted" - key: "os:ubuntu-latest;pub-cache-hosted;sdk:3.2.6;packages:pkgs/web_socket;commands:analyze_1" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:3.3.0;packages:pkgs/http;commands:analyze_1" restore-keys: | - os:ubuntu-latest;pub-cache-hosted;sdk:3.2.6;packages:pkgs/web_socket - os:ubuntu-latest;pub-cache-hosted;sdk:3.2.6 + os:ubuntu-latest;pub-cache-hosted;sdk:3.3.0;packages:pkgs/http + os:ubuntu-latest;pub-cache-hosted;sdk:3.3.0 os:ubuntu-latest;pub-cache-hosted os:ubuntu-latest - name: Setup Dart SDK uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: - sdk: "3.2.6" + sdk: "3.3.0" - id: checkout name: Checkout repository uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - id: pkgs_web_socket_pub_upgrade - name: pkgs/web_socket; dart pub upgrade + - id: pkgs_http_pub_upgrade + name: pkgs/http; dart pub upgrade run: dart pub upgrade if: "always() && steps.checkout.conclusion == 'success'" - working-directory: pkgs/web_socket - - name: "pkgs/web_socket; dart analyze --fatal-infos" + working-directory: pkgs/http + - name: "pkgs/http; dart analyze --fatal-infos" run: dart analyze --fatal-infos - if: "always() && steps.pkgs_web_socket_pub_upgrade.conclusion == 'success'" - working-directory: pkgs/web_socket - job_005: - name: "analyze_and_format; linux; Dart 3.3.0; PKG: pkgs/http; `dart analyze --fatal-infos`" + if: "always() && steps.pkgs_http_pub_upgrade.conclusion == 'success'" + working-directory: pkgs/http + job_004: + name: "analyze_and_format; linux; Dart 3.4.0-149.0.dev; PKG: pkgs/http_profile; `dart analyze --fatal-infos`" runs-on: ubuntu-latest steps: - name: Cache Pub hosted dependencies uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 with: path: "~/.pub-cache/hosted" - key: "os:ubuntu-latest;pub-cache-hosted;sdk:3.3.0;packages:pkgs/http;commands:analyze_1" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:3.4.0-149.0.dev;packages:pkgs/http_profile;commands:analyze_1" restore-keys: | - os:ubuntu-latest;pub-cache-hosted;sdk:3.3.0;packages:pkgs/http - os:ubuntu-latest;pub-cache-hosted;sdk:3.3.0 + os:ubuntu-latest;pub-cache-hosted;sdk:3.4.0-149.0.dev;packages:pkgs/http_profile + os:ubuntu-latest;pub-cache-hosted;sdk:3.4.0-149.0.dev os:ubuntu-latest;pub-cache-hosted os:ubuntu-latest - name: Setup Dart SDK uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: - sdk: "3.3.0" + sdk: "3.4.0-149.0.dev" - id: checkout name: Checkout repository uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - id: pkgs_http_pub_upgrade - name: pkgs/http; dart pub upgrade + - id: pkgs_http_profile_pub_upgrade + name: pkgs/http_profile; dart pub upgrade run: dart pub upgrade if: "always() && steps.checkout.conclusion == 'success'" - working-directory: pkgs/http - - name: "pkgs/http; dart analyze --fatal-infos" + working-directory: pkgs/http_profile + - name: "pkgs/http_profile; dart analyze --fatal-infos" run: dart analyze --fatal-infos - if: "always() && steps.pkgs_http_pub_upgrade.conclusion == 'success'" - working-directory: pkgs/http - job_006: - name: "analyze_and_format; linux; Dart dev; PKGS: pkgs/http, pkgs/http_client_conformance_tests, pkgs/http_profile, pkgs/web_socket; `dart analyze --fatal-infos`" + if: "always() && steps.pkgs_http_profile_pub_upgrade.conclusion == 'success'" + working-directory: pkgs/http_profile + job_005: + name: "analyze_and_format; linux; Dart dev; PKGS: pkgs/http, pkgs/http_client_conformance_tests, pkgs/http_profile; `dart analyze --fatal-infos`" runs-on: ubuntu-latest steps: - name: Cache Pub hosted dependencies @@ -333,36 +303,36 @@ jobs: run: flutter analyze --fatal-infos if: "always() && steps.pkgs_flutter_http_example_pub_upgrade.conclusion == 'success'" working-directory: pkgs/flutter_http_example - job_010: - name: "unit_test; linux; Dart 3.0.0; PKG: pkgs/http_profile; `dart test --platform vm`" + job_009: + name: "unit_test; linux; Dart 3.3.0; PKG: pkgs/http; `dart run --define=no_default_http_client=true test/no_default_http_client_test.dart`" runs-on: ubuntu-latest steps: - name: Cache Pub hosted dependencies uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 with: path: "~/.pub-cache/hosted" - key: "os:ubuntu-latest;pub-cache-hosted;sdk:3.0.0;packages:pkgs/http_profile;commands:test_2" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:3.3.0;packages:pkgs/http;commands:command_1" restore-keys: | - os:ubuntu-latest;pub-cache-hosted;sdk:3.0.0;packages:pkgs/http_profile - os:ubuntu-latest;pub-cache-hosted;sdk:3.0.0 + os:ubuntu-latest;pub-cache-hosted;sdk:3.3.0;packages:pkgs/http + os:ubuntu-latest;pub-cache-hosted;sdk:3.3.0 os:ubuntu-latest;pub-cache-hosted os:ubuntu-latest - name: Setup Dart SDK uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: - sdk: "3.0.0" + sdk: "3.3.0" - id: checkout name: Checkout repository uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - id: pkgs_http_profile_pub_upgrade - name: pkgs/http_profile; dart pub upgrade + - id: pkgs_http_pub_upgrade + name: pkgs/http; dart pub upgrade run: dart pub upgrade if: "always() && steps.checkout.conclusion == 'success'" - working-directory: pkgs/http_profile - - name: "pkgs/http_profile; dart test --platform vm" - run: dart test --platform vm - if: "always() && steps.pkgs_http_profile_pub_upgrade.conclusion == 'success'" - working-directory: pkgs/http_profile + working-directory: pkgs/http + - name: "pkgs/http; dart run --define=no_default_http_client=true test/no_default_http_client_test.dart" + run: "dart run --define=no_default_http_client=true test/no_default_http_client_test.dart" + if: "always() && steps.pkgs_http_pub_upgrade.conclusion == 'success'" + working-directory: pkgs/http needs: - job_001 - job_002 @@ -372,16 +342,15 @@ jobs: - job_006 - job_007 - job_008 - - job_009 - job_011: - name: "unit_test; linux; Dart 3.3.0; PKG: pkgs/http; `dart run --define=no_default_http_client=true test/no_default_http_client_test.dart`" + job_010: + name: "unit_test; linux; Dart 3.3.0; PKG: pkgs/http; `dart test --platform chrome`" runs-on: ubuntu-latest steps: - name: Cache Pub hosted dependencies uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 with: path: "~/.pub-cache/hosted" - key: "os:ubuntu-latest;pub-cache-hosted;sdk:3.3.0;packages:pkgs/http;commands:command_1" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:3.3.0;packages:pkgs/http;commands:test_3" restore-keys: | os:ubuntu-latest;pub-cache-hosted;sdk:3.3.0;packages:pkgs/http os:ubuntu-latest;pub-cache-hosted;sdk:3.3.0 @@ -399,8 +368,8 @@ jobs: run: dart pub upgrade if: "always() && steps.checkout.conclusion == 'success'" working-directory: pkgs/http - - name: "pkgs/http; dart run --define=no_default_http_client=true test/no_default_http_client_test.dart" - run: "dart run --define=no_default_http_client=true test/no_default_http_client_test.dart" + - name: "pkgs/http; dart test --platform chrome" + run: dart test --platform chrome if: "always() && steps.pkgs_http_pub_upgrade.conclusion == 'success'" working-directory: pkgs/http needs: @@ -412,16 +381,15 @@ jobs: - job_006 - job_007 - job_008 - - job_009 - job_012: - name: "unit_test; linux; Dart 3.3.0; PKG: pkgs/http; `dart test --platform chrome`" + job_011: + name: "unit_test; linux; Dart 3.3.0; PKG: pkgs/http; `dart test --platform vm`" runs-on: ubuntu-latest steps: - name: Cache Pub hosted dependencies uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 with: path: "~/.pub-cache/hosted" - key: "os:ubuntu-latest;pub-cache-hosted;sdk:3.3.0;packages:pkgs/http;commands:test_3" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:3.3.0;packages:pkgs/http;commands:test_2" restore-keys: | os:ubuntu-latest;pub-cache-hosted;sdk:3.3.0;packages:pkgs/http os:ubuntu-latest;pub-cache-hosted;sdk:3.3.0 @@ -439,8 +407,8 @@ jobs: run: dart pub upgrade if: "always() && steps.checkout.conclusion == 'success'" working-directory: pkgs/http - - name: "pkgs/http; dart test --platform chrome" - run: dart test --platform chrome + - name: "pkgs/http; dart test --platform vm" + run: dart test --platform vm if: "always() && steps.pkgs_http_pub_upgrade.conclusion == 'success'" working-directory: pkgs/http needs: @@ -452,37 +420,36 @@ jobs: - job_006 - job_007 - job_008 - - job_009 - job_013: - name: "unit_test; linux; Dart 3.3.0; PKG: pkgs/http; `dart test --platform vm`" + job_012: + name: "unit_test; linux; Dart 3.4.0-149.0.dev; PKG: pkgs/http_profile; `dart test --platform vm`" runs-on: ubuntu-latest steps: - name: Cache Pub hosted dependencies uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 with: path: "~/.pub-cache/hosted" - key: "os:ubuntu-latest;pub-cache-hosted;sdk:3.3.0;packages:pkgs/http;commands:test_2" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:3.4.0-149.0.dev;packages:pkgs/http_profile;commands:test_2" restore-keys: | - os:ubuntu-latest;pub-cache-hosted;sdk:3.3.0;packages:pkgs/http - os:ubuntu-latest;pub-cache-hosted;sdk:3.3.0 + os:ubuntu-latest;pub-cache-hosted;sdk:3.4.0-149.0.dev;packages:pkgs/http_profile + os:ubuntu-latest;pub-cache-hosted;sdk:3.4.0-149.0.dev os:ubuntu-latest;pub-cache-hosted os:ubuntu-latest - name: Setup Dart SDK uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: - sdk: "3.3.0" + sdk: "3.4.0-149.0.dev" - id: checkout name: Checkout repository uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - id: pkgs_http_pub_upgrade - name: pkgs/http; dart pub upgrade + - id: pkgs_http_profile_pub_upgrade + name: pkgs/http_profile; dart pub upgrade run: dart pub upgrade if: "always() && steps.checkout.conclusion == 'success'" - working-directory: pkgs/http - - name: "pkgs/http; dart test --platform vm" + working-directory: pkgs/http_profile + - name: "pkgs/http_profile; dart test --platform vm" run: dart test --platform vm - if: "always() && steps.pkgs_http_pub_upgrade.conclusion == 'success'" - working-directory: pkgs/http + if: "always() && steps.pkgs_http_profile_pub_upgrade.conclusion == 'success'" + working-directory: pkgs/http_profile needs: - job_001 - job_002 @@ -492,8 +459,7 @@ jobs: - job_006 - job_007 - job_008 - - job_009 - job_014: + job_013: name: "unit_test; linux; Dart dev; PKG: pkgs/http; `dart run --define=no_default_http_client=true test/no_default_http_client_test.dart`" runs-on: ubuntu-latest steps: diff --git a/pkgs/http_profile/pubspec.yaml b/pkgs/http_profile/pubspec.yaml index 1b5891e2c1..160917d455 100644 --- a/pkgs/http_profile/pubspec.yaml +++ b/pkgs/http_profile/pubspec.yaml @@ -7,7 +7,8 @@ repository: https://github.com/dart-lang/http/tree/master/pkgs/http_profile publish_to: none environment: - sdk: ^3.0.0 + # TODO(derekxu16): Change the following constraint to ^3.4.0 before publishing this package. + sdk: ^3.4.0-149.0.dev dependencies: test: ^1.24.9 From 653e5daba58a8934ddbb17f204c7dad0ad95482f Mon Sep 17 00:00:00 2001 From: Derek Xu Date: Tue, 20 Feb 2024 10:56:43 -0500 Subject: [PATCH 8/8] Fix analysis issues --- .github/workflows/dart.yml | 70 ++++++++++++++----- pkgs/http_profile/lib/http_profile.dart | 16 ++++- pkgs/http_profile/pubspec.yaml | 2 +- .../test/populating_profiles_test.dart | 2 +- 4 files changed, 67 insertions(+), 23 deletions(-) diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index f57d2c5755..400bdd10df 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -70,6 +70,36 @@ jobs: if: "always() && steps.pkgs_http_client_conformance_tests_pub_upgrade.conclusion == 'success'" working-directory: pkgs/http_client_conformance_tests job_003: + name: "analyze_and_format; linux; Dart 3.2.6; PKG: pkgs/web_socket; `dart analyze --fatal-infos`" + runs-on: ubuntu-latest + steps: + - name: Cache Pub hosted dependencies + uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 + with: + path: "~/.pub-cache/hosted" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:3.2.6;packages:pkgs/web_socket;commands:analyze_1" + restore-keys: | + os:ubuntu-latest;pub-cache-hosted;sdk:3.2.6;packages:pkgs/web_socket + os:ubuntu-latest;pub-cache-hosted;sdk:3.2.6 + os:ubuntu-latest;pub-cache-hosted + os:ubuntu-latest + - name: Setup Dart SDK + uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 + with: + sdk: "3.2.6" + - id: checkout + name: Checkout repository + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - id: pkgs_web_socket_pub_upgrade + name: pkgs/web_socket; dart pub upgrade + run: dart pub upgrade + if: "always() && steps.checkout.conclusion == 'success'" + working-directory: pkgs/web_socket + - name: "pkgs/web_socket; dart analyze --fatal-infos" + run: dart analyze --fatal-infos + if: "always() && steps.pkgs_web_socket_pub_upgrade.conclusion == 'success'" + working-directory: pkgs/web_socket + job_004: name: "analyze_and_format; linux; Dart 3.3.0; PKG: pkgs/http; `dart analyze --fatal-infos`" runs-on: ubuntu-latest steps: @@ -99,24 +129,24 @@ jobs: run: dart analyze --fatal-infos if: "always() && steps.pkgs_http_pub_upgrade.conclusion == 'success'" working-directory: pkgs/http - job_004: - name: "analyze_and_format; linux; Dart 3.4.0-149.0.dev; PKG: pkgs/http_profile; `dart analyze --fatal-infos`" + job_005: + name: "analyze_and_format; linux; Dart 3.4.0-154.0.dev; PKG: pkgs/http_profile; `dart analyze --fatal-infos`" runs-on: ubuntu-latest steps: - name: Cache Pub hosted dependencies uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 with: path: "~/.pub-cache/hosted" - key: "os:ubuntu-latest;pub-cache-hosted;sdk:3.4.0-149.0.dev;packages:pkgs/http_profile;commands:analyze_1" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:3.4.0-154.0.dev;packages:pkgs/http_profile;commands:analyze_1" restore-keys: | - os:ubuntu-latest;pub-cache-hosted;sdk:3.4.0-149.0.dev;packages:pkgs/http_profile - os:ubuntu-latest;pub-cache-hosted;sdk:3.4.0-149.0.dev + os:ubuntu-latest;pub-cache-hosted;sdk:3.4.0-154.0.dev;packages:pkgs/http_profile + os:ubuntu-latest;pub-cache-hosted;sdk:3.4.0-154.0.dev os:ubuntu-latest;pub-cache-hosted os:ubuntu-latest - name: Setup Dart SDK uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: - sdk: "3.4.0-149.0.dev" + sdk: "3.4.0-154.0.dev" - id: checkout name: Checkout repository uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 @@ -129,8 +159,8 @@ jobs: run: dart analyze --fatal-infos if: "always() && steps.pkgs_http_profile_pub_upgrade.conclusion == 'success'" working-directory: pkgs/http_profile - job_005: - name: "analyze_and_format; linux; Dart dev; PKGS: pkgs/http, pkgs/http_client_conformance_tests, pkgs/http_profile; `dart analyze --fatal-infos`" + job_006: + name: "analyze_and_format; linux; Dart dev; PKGS: pkgs/http, pkgs/http_client_conformance_tests, pkgs/http_profile, pkgs/web_socket; `dart analyze --fatal-infos`" runs-on: ubuntu-latest steps: - name: Cache Pub hosted dependencies @@ -303,7 +333,7 @@ jobs: run: flutter analyze --fatal-infos if: "always() && steps.pkgs_flutter_http_example_pub_upgrade.conclusion == 'success'" working-directory: pkgs/flutter_http_example - job_009: + job_010: name: "unit_test; linux; Dart 3.3.0; PKG: pkgs/http; `dart run --define=no_default_http_client=true test/no_default_http_client_test.dart`" runs-on: ubuntu-latest steps: @@ -342,7 +372,8 @@ jobs: - job_006 - job_007 - job_008 - job_010: + - job_009 + job_011: name: "unit_test; linux; Dart 3.3.0; PKG: pkgs/http; `dart test --platform chrome`" runs-on: ubuntu-latest steps: @@ -381,7 +412,8 @@ jobs: - job_006 - job_007 - job_008 - job_011: + - job_009 + job_012: name: "unit_test; linux; Dart 3.3.0; PKG: pkgs/http; `dart test --platform vm`" runs-on: ubuntu-latest steps: @@ -420,24 +452,25 @@ jobs: - job_006 - job_007 - job_008 - job_012: - name: "unit_test; linux; Dart 3.4.0-149.0.dev; PKG: pkgs/http_profile; `dart test --platform vm`" + - job_009 + job_013: + name: "unit_test; linux; Dart 3.4.0-154.0.dev; PKG: pkgs/http_profile; `dart test --platform vm`" runs-on: ubuntu-latest steps: - name: Cache Pub hosted dependencies uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 with: path: "~/.pub-cache/hosted" - key: "os:ubuntu-latest;pub-cache-hosted;sdk:3.4.0-149.0.dev;packages:pkgs/http_profile;commands:test_2" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:3.4.0-154.0.dev;packages:pkgs/http_profile;commands:test_2" restore-keys: | - os:ubuntu-latest;pub-cache-hosted;sdk:3.4.0-149.0.dev;packages:pkgs/http_profile - os:ubuntu-latest;pub-cache-hosted;sdk:3.4.0-149.0.dev + os:ubuntu-latest;pub-cache-hosted;sdk:3.4.0-154.0.dev;packages:pkgs/http_profile + os:ubuntu-latest;pub-cache-hosted;sdk:3.4.0-154.0.dev os:ubuntu-latest;pub-cache-hosted os:ubuntu-latest - name: Setup Dart SDK uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: - sdk: "3.4.0-149.0.dev" + sdk: "3.4.0-154.0.dev" - id: checkout name: Checkout repository uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 @@ -459,7 +492,8 @@ jobs: - job_006 - job_007 - job_008 - job_013: + - job_009 + job_014: name: "unit_test; linux; Dart dev; PKG: pkgs/http; `dart run --define=no_default_http_client=true test/no_default_http_client_test.dart`" runs-on: ubuntu-latest steps: diff --git a/pkgs/http_profile/lib/http_profile.dart b/pkgs/http_profile/lib/http_profile.dart index fdf7349b9c..b0b7a87677 100644 --- a/pkgs/http_profile/lib/http_profile.dart +++ b/pkgs/http_profile/lib/http_profile.dart @@ -3,7 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'dart:async' show StreamController, StreamSink; -import 'dart:developer' show addHttpClientProfilingData, Service, Timeline; +import 'dart:developer' show Service, addHttpClientProfilingData; import 'dart:io' show HttpClient, HttpClientResponseCompressionState; import 'dart:isolate' show Isolate; @@ -288,8 +288,18 @@ final class HttpClientRequestProfile { /// Usage example: /// /// ```dart - /// profile.addEvent(HttpProfileRequestEvent(DateTime.now(), "Connection Established"); - /// profile.addEvent(HttpProfileRequestEvent(DateTime.now(), "Remote Disconnected"); + /// profile.addEvent( + /// HttpProfileRequestEvent( + /// timestamp: DateTime.now(), + /// name: "Connection Established", + /// ), + /// ); + /// profile.addEvent( + /// HttpProfileRequestEvent( + /// timestamp: DateTime.now(), + /// name: "Remote Disconnected", + /// ), + /// ); /// ``` void addEvent(HttpProfileRequestEvent event) { (_data['events'] as List>).add(event._toJson()); diff --git a/pkgs/http_profile/pubspec.yaml b/pkgs/http_profile/pubspec.yaml index 160917d455..93b55f296c 100644 --- a/pkgs/http_profile/pubspec.yaml +++ b/pkgs/http_profile/pubspec.yaml @@ -8,7 +8,7 @@ publish_to: none environment: # TODO(derekxu16): Change the following constraint to ^3.4.0 before publishing this package. - sdk: ^3.4.0-149.0.dev + sdk: ^3.4.0-154.0.dev dependencies: test: ^1.24.9 diff --git a/pkgs/http_profile/test/populating_profiles_test.dart b/pkgs/http_profile/test/populating_profiles_test.dart index 1b5b547134..a1cbbb4b30 100644 --- a/pkgs/http_profile/test/populating_profiles_test.dart +++ b/pkgs/http_profile/test/populating_profiles_test.dart @@ -3,7 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'dart:async'; -import 'dart:developer' show getHttpClientProfilingData, Service; +import 'dart:developer' show Service, getHttpClientProfilingData; import 'dart:io'; import 'dart:isolate' show Isolate;