[metric_center] Migrate code to null safety (#439)

This commit is contained in:
Casey Hillers
2021-08-17 10:47:08 -07:00
committed by GitHub
parent e438ad5c32
commit 7b0b8e3381
12 changed files with 389 additions and 61 deletions

View File

@ -1,3 +1,7 @@
# 1.0.0
- Null safety support
# 0.1.1
- Update packages to null safe

View File

@ -16,11 +16,11 @@ class MetricPoint extends Equatable {
/// Creates a new data point.
MetricPoint(
this.value,
Map<String, String> tags,
Map<String, String?> tags,
) : _tags = SplayTreeMap<String, String>.from(tags);
/// Can store integer values.
final double value;
final double? value;
/// Test name, unit, timestamp, configs, git revision, ..., in sorted order.
UnmodifiableMapView<String, String> get tags =>
@ -43,7 +43,7 @@ class MetricPoint extends Equatable {
final SplayTreeMap<String, String> _tags;
@override
List<Object> get props => <Object>[value, tags];
List<Object?> get props => <Object?>[value, tags];
}
/// Interface to write [MetricPoint].

View File

@ -82,7 +82,7 @@ class GcsLock {
await _api.objects.delete(_bucketName, lockFileName);
}
StorageApi _api;
late StorageApi _api;
final String _bucketName;
final AuthClient _client;

View File

@ -50,21 +50,21 @@ void _parseAnItem(
};
for (final String subResult in item.keys) {
if (!_kNonNumericalValueSubResults.contains(subResult)) {
num rawValue;
num? rawValue;
try {
rawValue = item[subResult] as num;
rawValue = item[subResult] as num?;
} catch (e) {
print(
'$subResult: ${item[subResult]} (${item[subResult].runtimeType}) is not a number');
rethrow;
}
final double value =
rawValue is int ? rawValue.toDouble() : rawValue as double;
final double? value =
rawValue is int ? rawValue.toDouble() : rawValue as double?;
points.add(
MetricPoint(
value,
<String, String>{kNameKey: name, kSubResultKey: subResult}
<String, String?>{kNameKey: name, kSubResultKey: subResult}
..addAll(context)
..addAll(
subResult.endsWith('time') ? timeUnitMap : <String, String>{}),

View File

@ -48,15 +48,15 @@ import 'gcs_lock.dart';
/// ```
class SkiaPerfPoint extends MetricPoint {
SkiaPerfPoint._(this.githubRepo, this.gitHash, this.testName, this.subResult,
double value, this._options, this.jsonUrl)
double? value, this._options, this.jsonUrl)
: assert(_options[kGithubRepoKey] == null),
assert(_options[kGitRevisionKey] == null),
assert(_options[kNameKey] == null),
super(
value,
<String, String>{}
<String, String?>{}
..addAll(_options)
..addAll(<String, String>{
..addAll(<String, String?>{
kGithubRepoKey: githubRepo,
kGitRevisionKey: gitHash,
kNameKey: testName,
@ -78,9 +78,9 @@ class SkiaPerfPoint extends MetricPoint {
/// Skia perf will use the git revision's date instead of this date tag in
/// the time axis.
factory SkiaPerfPoint.fromPoint(MetricPoint p) {
final String githubRepo = p.tags[kGithubRepoKey];
final String gitHash = p.tags[kGitRevisionKey];
final String name = p.tags[kNameKey];
final String? githubRepo = p.tags[kGithubRepoKey];
final String? gitHash = p.tags[kGitRevisionKey];
final String? name = p.tags[kNameKey];
if (githubRepo == null || gitHash == null || name == null) {
throw '$kGithubRepoKey, $kGitRevisionKey, $kNameKey must be set in'
@ -113,7 +113,7 @@ class SkiaPerfPoint extends MetricPoint {
final String githubRepo;
/// SHA such as 'ad20d368ffa09559754e4b2b5c12951341ca3b2d'
final String gitHash;
final String? gitHash;
/// For Flutter devicelab, this is the task name (e.g.,
/// 'flutter_gallery__transition_perf'); for Google benchmark, this is the
@ -138,7 +138,7 @@ class SkiaPerfPoint extends MetricPoint {
/// The url to the Skia perf json file in the Google Cloud Storage bucket.
///
/// This can be null if the point has been stored in the bucket yet.
final String jsonUrl;
final String? jsonUrl;
Map<String, dynamic> _toSubResultJson() {
return <String, dynamic>{
@ -260,7 +260,7 @@ class SkiaPerfGcsAdaptor {
}
Future<List<SkiaPerfPoint>> _readPointsWithoutRetry(String objectName) async {
ObjectInfo info;
ObjectInfo? info;
try {
info = await _gcsBucket.info(objectName);
@ -282,10 +282,10 @@ class SkiaPerfGcsAdaptor {
final String firstGcsNameComponent = objectName.split('/')[0];
_populateGcsNameToGithubRepoMapIfNeeded();
final String githubRepo = _gcsNameToGithubRepo[firstGcsNameComponent];
final String githubRepo = _gcsNameToGithubRepo[firstGcsNameComponent]!;
assert(githubRepo != null);
final String gitHash = decodedJson[kSkiaPerfGitHashKey] as String;
final String? gitHash = decodedJson[kSkiaPerfGitHashKey] as String?;
final Map<String, dynamic> results =
decodedJson[kSkiaPerfResultsKey] as Map<String, dynamic>;
for (final String name in results.keys) {
@ -298,7 +298,7 @@ class SkiaPerfGcsAdaptor {
gitHash,
name,
subResult,
subResultMap[subResult] as double,
subResultMap[subResult] as double?,
(subResultMap[kSkiaPerfOptionsKey] as Map<String, dynamic>)
.cast<String, String>(),
info.downloadLink.toString(),
@ -317,9 +317,9 @@ class SkiaPerfGcsAdaptor {
/// json files in the future to scale up the system if too many writes are
/// competing for the same json file.
static Future<String> computeObjectName(
String githubRepo, String revision, DateTime commitTime) async {
String githubRepo, String? revision, DateTime commitTime) async {
assert(_githubRepoToGcsName[githubRepo] != null);
final String topComponent = _githubRepoToGcsName[githubRepo];
final String? topComponent = _githubRepoToGcsName[githubRepo];
// [commitTime] is not guranteed to be UTC. Ensure it is so all results
// pushed to GCS are the same timezone.
final DateTime commitUtcTime = commitTime.toUtc();
@ -334,12 +334,12 @@ class SkiaPerfGcsAdaptor {
kFlutterFrameworkRepo: 'flutter-flutter',
kFlutterEngineRepo: 'flutter-engine',
};
static final Map<String, String> _gcsNameToGithubRepo = <String, String>{};
static final Map<String?, String> _gcsNameToGithubRepo = <String?, String>{};
static void _populateGcsNameToGithubRepoMapIfNeeded() {
if (_gcsNameToGithubRepo.isEmpty) {
for (final String repo in _githubRepoToGcsName.keys) {
final String gcsName = _githubRepoToGcsName[repo];
final String? gcsName = _githubRepoToGcsName[repo];
assert(_gcsNameToGithubRepo[gcsName] == null);
_gcsNameToGithubRepo[gcsName] = repo;
}
@ -396,43 +396,43 @@ class SkiaPerfDestination extends MetricDestination {
// 1st, create a map based on git repo, git revision, and point id. Git repo
// and git revision are the top level components of the Skia perf GCS object
// name.
final Map<String, Map<String, Map<String, SkiaPerfPoint>>> pointMap =
final Map<String, Map<String?, Map<String, SkiaPerfPoint>>> pointMap =
<String, Map<String, Map<String, SkiaPerfPoint>>>{};
for (final SkiaPerfPoint p
in points.map((MetricPoint x) => SkiaPerfPoint.fromPoint(x))) {
if (p != null) {
pointMap[p.githubRepo] ??= <String, Map<String, SkiaPerfPoint>>{};
pointMap[p.githubRepo][p.gitHash] ??= <String, SkiaPerfPoint>{};
pointMap[p.githubRepo][p.gitHash][p.id] = p;
pointMap[p.githubRepo]![p.gitHash] ??= <String, SkiaPerfPoint>{};
pointMap[p.githubRepo]![p.gitHash]![p.id] = p;
}
}
// 2nd, read existing points from the gcs object and update with new ones.
for (final String repo in pointMap.keys) {
for (final String revision in pointMap[repo].keys) {
for (final String? revision in pointMap[repo]!.keys) {
final String objectName = await SkiaPerfGcsAdaptor.computeObjectName(
repo, revision, commitTime);
final Map<String, SkiaPerfPoint> newPoints = pointMap[repo][revision];
final Map<String, SkiaPerfPoint>? newPoints = pointMap[repo]![revision];
// If too many bots are writing the metrics of a git revision into this
// single json file (with name `objectName`), the contention on the lock
// might be too high. In that case, break the json file into multiple
// json files according to bot names or task names. Skia perf read all
// json files in the directory so one can use arbitrary names for those
// sharded json file names.
_lock.protectedRun('$objectName.lock', () async {
_lock!.protectedRun('$objectName.lock', () async {
final List<SkiaPerfPoint> oldPoints =
await _gcs.readPoints(objectName);
for (final SkiaPerfPoint p in oldPoints) {
if (newPoints[p.id] == null) {
if (newPoints![p.id] == null) {
newPoints[p.id] = p;
}
}
await _gcs.writePoints(objectName, newPoints.values.toList());
await _gcs.writePoints(objectName, newPoints!.values.toList());
});
}
}
}
final SkiaPerfGcsAdaptor _gcs;
final GcsLock _lock;
late final GcsLock? _lock;
}

View File

@ -1,23 +1,24 @@
name: metrics_center
version: 0.1.1
version: 1.0.0
description:
Support multiple performance metrics sources/formats and destinations.
repository: https://github.com/flutter/packages/tree/master/packages/metrics_center
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+metrics_center%22
environment:
sdk: '>=2.10.0 <3.0.0'
sdk: '>=2.12.0 <3.0.0'
dependencies:
crypto: ^3.0.0
equatable: ^1.2.5
gcloud: ^0.8.0
crypto: ^3.0.1
equatable: ^2.0.3
gcloud: ^0.8.2
googleapis: ^3.0.0
googleapis_auth: ^1.0.0
googleapis_auth: ^1.1.0
http: ^0.13.3
dev_dependencies:
build_runner: ^2.1.1
fake_async: ^1.2.0
mockito: ^5.0.0
pedantic: ^1.10.0
test: ^1.17.0
mockito: ^5.0.14
pedantic: ^1.11.1
test: ^1.17.11

View File

@ -38,11 +38,11 @@ void main() {
expect(detailedPoint.tags[kUnitKey], equals('ns'));
});
final Map<String, dynamic> credentialsJson = getTestGcpCredentialsJson();
final Map<String, dynamic>? credentialsJson = getTestGcpCredentialsJson();
test('FlutterDestination integration test with update.', () async {
final FlutterDestination dst =
await FlutterDestination.makeFromCredentialsJson(credentialsJson,
await FlutterDestination.makeFromCredentialsJson(credentialsJson!,
isTesting: true);
dst.update(<FlutterEngineMetricPoint>[simplePoint],
DateTime.fromMillisecondsSinceEpoch(123));

View File

@ -10,9 +10,11 @@ import 'package:googleapis/storage/v1.dart';
import 'package:googleapis_auth/auth_io.dart';
import 'package:metrics_center/src/constants.dart';
import 'package:metrics_center/src/gcs_lock.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'common.dart';
import 'gcs_lock_test.mocks.dart';
import 'utility.dart';
enum TestPhase {
@ -20,11 +22,10 @@ enum TestPhase {
run2,
}
class MockClient extends Mock implements AuthClient {}
@GenerateMocks(<Type>[AuthClient])
void main() {
const Duration kDelayStep = Duration(milliseconds: 10);
final Map<String, dynamic> credentialsJson = getTestGcpCredentialsJson();
final Map<String, dynamic>? credentialsJson = getTestGcpCredentialsJson();
test('GcsLock prints warnings for long waits', () {
// Capture print to verify error messages.
@ -34,7 +35,7 @@ void main() {
Zone.current.fork(specification: spec).run<void>(() {
fakeAsync((FakeAsync fakeAsync) {
final MockClient mockClient = MockClient();
final MockAuthClient mockClient = MockAuthClient();
final GcsLock lock = GcsLock(mockClient, 'mockBucket');
when(mockClient.send(any)).thenThrow(DetailedApiRequestError(412, ''));
final Future<void> runFinished =

View File

@ -0,0 +1,117 @@
// Mocks generated by Mockito 5.0.14 from annotations
// in metrics_center/test/gcs_lock_test.dart.
// Do not manually edit this file.
import 'dart:async' as _i5;
import 'dart:convert' as _i6;
import 'dart:typed_data' as _i7;
import 'package:googleapis_auth/src/access_credentials.dart' as _i2;
import 'package:googleapis_auth/src/auth_client.dart' as _i4;
import 'package:http/http.dart' as _i3;
import 'package:mockito/mockito.dart' as _i1;
// ignore_for_file: always_specify_types
// ignore_for_file: avoid_redundant_argument_values
// ignore_for_file: avoid_setters_without_getters
// ignore_for_file: camel_case_types
// ignore_for_file: comment_references
// ignore_for_file: implementation_imports
// ignore_for_file: invalid_use_of_visible_for_testing_member
// ignore_for_file: prefer_const_constructors
// ignore_for_file: unnecessary_overrides
// ignore_for_file: unnecessary_parenthesis
class _FakeAccessCredentials_0 extends _i1.Fake
implements _i2.AccessCredentials {}
class _FakeResponse_1 extends _i1.Fake implements _i3.Response {}
class _FakeStreamedResponse_2 extends _i1.Fake implements _i3.StreamedResponse {
}
/// A class which mocks [AuthClient].
///
/// See the documentation for Mockito's code generation for more information.
class MockAuthClient extends _i1.Mock implements _i4.AuthClient {
MockAuthClient() {
_i1.throwOnMissingStub(this);
}
@override
_i2.AccessCredentials get credentials =>
(super.noSuchMethod(Invocation.getter(#credentials),
returnValue: _FakeAccessCredentials_0()) as _i2.AccessCredentials);
@override
String toString() => super.toString();
@override
_i5.Future<_i3.Response> head(Uri? url, {Map<String, String>? headers}) =>
(super.noSuchMethod(Invocation.method(#head, [url], {#headers: headers}),
returnValue: Future<_i3.Response>.value(_FakeResponse_1()))
as _i5.Future<_i3.Response>);
@override
_i5.Future<_i3.Response> get(Uri? url, {Map<String, String>? headers}) =>
(super.noSuchMethod(Invocation.method(#get, [url], {#headers: headers}),
returnValue: Future<_i3.Response>.value(_FakeResponse_1()))
as _i5.Future<_i3.Response>);
@override
_i5.Future<_i3.Response> post(Uri? url,
{Map<String, String>? headers,
Object? body,
_i6.Encoding? encoding}) =>
(super.noSuchMethod(
Invocation.method(#post, [url],
{#headers: headers, #body: body, #encoding: encoding}),
returnValue: Future<_i3.Response>.value(_FakeResponse_1()))
as _i5.Future<_i3.Response>);
@override
_i5.Future<_i3.Response> put(Uri? url,
{Map<String, String>? headers,
Object? body,
_i6.Encoding? encoding}) =>
(super.noSuchMethod(
Invocation.method(#put, [url],
{#headers: headers, #body: body, #encoding: encoding}),
returnValue: Future<_i3.Response>.value(_FakeResponse_1()))
as _i5.Future<_i3.Response>);
@override
_i5.Future<_i3.Response> patch(Uri? url,
{Map<String, String>? headers,
Object? body,
_i6.Encoding? encoding}) =>
(super.noSuchMethod(
Invocation.method(#patch, [url],
{#headers: headers, #body: body, #encoding: encoding}),
returnValue: Future<_i3.Response>.value(_FakeResponse_1()))
as _i5.Future<_i3.Response>);
@override
_i5.Future<_i3.Response> delete(Uri? url,
{Map<String, String>? headers,
Object? body,
_i6.Encoding? encoding}) =>
(super.noSuchMethod(
Invocation.method(#delete, [url],
{#headers: headers, #body: body, #encoding: encoding}),
returnValue: Future<_i3.Response>.value(_FakeResponse_1()))
as _i5.Future<_i3.Response>);
@override
_i5.Future<String> read(Uri? url, {Map<String, String>? headers}) =>
(super.noSuchMethod(Invocation.method(#read, [url], {#headers: headers}),
returnValue: Future<String>.value('')) as _i5.Future<String>);
@override
_i5.Future<_i7.Uint8List> readBytes(Uri? url,
{Map<String, String>? headers}) =>
(super.noSuchMethod(
Invocation.method(#readBytes, [url], {#headers: headers}),
returnValue: Future<_i7.Uint8List>.value(_i7.Uint8List(0)))
as _i5.Future<_i7.Uint8List>);
@override
_i5.Future<_i3.StreamedResponse> send(_i3.BaseRequest? request) =>
(super.noSuchMethod(Invocation.method(#send, [request]),
returnValue:
Future<_i3.StreamedResponse>.value(_FakeStreamedResponse_2()))
as _i5.Future<_i3.StreamedResponse>);
@override
void close() => super.noSuchMethod(Invocation.method(#close, []),
returnValueForMissingStub: null);
}

View File

@ -12,15 +12,13 @@ import 'package:googleapis_auth/auth_io.dart';
import 'package:metrics_center/metrics_center.dart';
import 'package:metrics_center/src/constants.dart';
import 'package:metrics_center/src/gcs_lock.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'common.dart';
import 'skiaperf_test.mocks.dart';
import 'utility.dart';
class MockBucket extends Mock implements Bucket {}
class MockObjectInfo extends Mock implements ObjectInfo {}
class MockGcsLock implements GcsLock {
@override
Future<void> protectedRun(
@ -46,6 +44,7 @@ class MockSkiaPerfGcsAdaptor implements SkiaPerfGcsAdaptor {
<String, List<SkiaPerfPoint>>{};
}
@GenerateMocks(<Type>[Bucket, ObjectInfo])
Future<void> main() async {
const double kValue1 = 1.0;
const double kValue2 = 2.0;
@ -353,6 +352,8 @@ Future<void> main() async {
];
final String skiaPerfJson =
jsonEncode(SkiaPerfPoint.toSkiaPerfJson(writePoints));
when(testBucket.writeBytes(testObjectName, utf8.encode(skiaPerfJson)))
.thenAnswer((_) async => FakeObjectInfo());
await skiaPerfGcs.writePoints(testObjectName, writePoints);
verify(testBucket.writeBytes(testObjectName, utf8.encode(skiaPerfJson)));
@ -392,9 +393,9 @@ Future<void> main() async {
});
// The following is for integration tests.
Bucket testBucket;
GcsLock testLock;
final Map<String, dynamic> credentialsJson = getTestGcpCredentialsJson();
Bucket? testBucket;
GcsLock? testLock;
final Map<String, dynamic>? credentialsJson = getTestGcpCredentialsJson();
if (credentialsJson != null) {
final ServiceAccountCredentials credentials =
ServiceAccountCredentials.fromJson(credentialsJson);
@ -412,7 +413,7 @@ Future<void> main() async {
}
Future<void> skiaPerfGcsAdapterIntegrationTest() async {
final SkiaPerfGcsAdaptor skiaPerfGcs = SkiaPerfGcsAdaptor(testBucket);
final SkiaPerfGcsAdaptor skiaPerfGcs = SkiaPerfGcsAdaptor(testBucket!);
final String testObjectName = await SkiaPerfGcsAdaptor.computeObjectName(
kFlutterFrameworkRepo,
@ -443,7 +444,7 @@ Future<void> main() async {
}
Future<void> skiaPerfGcsIntegrationTestWithEnginePoints() async {
final SkiaPerfGcsAdaptor skiaPerfGcs = SkiaPerfGcsAdaptor(testBucket);
final SkiaPerfGcsAdaptor skiaPerfGcs = SkiaPerfGcsAdaptor(testBucket!);
final String testObjectName = await SkiaPerfGcsAdaptor.computeObjectName(
kFlutterEngineRepo,
@ -569,7 +570,7 @@ Future<void> main() async {
Future<void> skiaPerfDestinationIntegrationTest() async {
final SkiaPerfDestination destination =
SkiaPerfDestination(SkiaPerfGcsAdaptor(testBucket), testLock);
SkiaPerfDestination(SkiaPerfGcsAdaptor(testBucket!), testLock);
await destination.update(<MetricPoint>[cocoonPointRev1Metric1],
DateTime.fromMillisecondsSinceEpoch(123));
}
@ -580,3 +581,32 @@ Future<void> main() async {
skip: testBucket == null,
);
}
class FakeObjectInfo extends ObjectInfo {
@override
int get crc32CChecksum => throw UnimplementedError();
@override
Uri get downloadLink => throw UnimplementedError();
@override
String get etag => throw UnimplementedError();
@override
ObjectGeneration get generation => throw UnimplementedError();
@override
int get length => throw UnimplementedError();
@override
List<int> get md5Hash => throw UnimplementedError();
@override
ObjectMetadata get metadata => throw UnimplementedError();
@override
String get name => throw UnimplementedError();
@override
DateTime get updated => throw UnimplementedError();
}

View File

@ -0,0 +1,175 @@
// Mocks generated by Mockito 5.0.14 from annotations
// in metrics_center/test/skiaperf_test.dart.
// Do not manually edit this file.
import 'dart:async' as _i2;
import 'package:gcloud/common.dart' as _i4;
import 'package:gcloud/storage.dart' as _i3;
import 'package:mockito/mockito.dart' as _i1;
// ignore_for_file: always_specify_types
// ignore_for_file: avoid_redundant_argument_values
// ignore_for_file: avoid_setters_without_getters
// ignore_for_file: camel_case_types
// ignore_for_file: comment_references
// ignore_for_file: implementation_imports
// ignore_for_file: invalid_use_of_visible_for_testing_member
// ignore_for_file: prefer_const_constructors
// ignore_for_file: unnecessary_overrides
// ignore_for_file: unnecessary_parenthesis
class _FakeStreamSink_0<S> extends _i1.Fake implements _i2.StreamSink<S> {}
class _FakeObjectInfo_1 extends _i1.Fake implements _i3.ObjectInfo {}
class _FakePage_2<T> extends _i1.Fake implements _i4.Page<T> {}
class _FakeDateTime_3 extends _i1.Fake implements DateTime {}
class _FakeUri_4 extends _i1.Fake implements Uri {}
class _FakeObjectGeneration_5 extends _i1.Fake implements _i3.ObjectGeneration {
}
class _FakeObjectMetadata_6 extends _i1.Fake implements _i3.ObjectMetadata {}
/// A class which mocks [Bucket].
///
/// See the documentation for Mockito's code generation for more information.
class MockBucket extends _i1.Mock implements _i3.Bucket {
MockBucket() {
_i1.throwOnMissingStub(this);
}
@override
String get bucketName =>
(super.noSuchMethod(Invocation.getter(#bucketName), returnValue: '')
as String);
@override
String absoluteObjectName(String? objectName) =>
(super.noSuchMethod(Invocation.method(#absoluteObjectName, [objectName]),
returnValue: '') as String);
@override
_i2.StreamSink<List<int>> write(String? objectName,
{int? length,
_i3.ObjectMetadata? metadata,
_i3.Acl? acl,
_i3.PredefinedAcl? predefinedAcl,
String? contentType}) =>
(super.noSuchMethod(
Invocation.method(#write, [
objectName
], {
#length: length,
#metadata: metadata,
#acl: acl,
#predefinedAcl: predefinedAcl,
#contentType: contentType
}),
returnValue: _FakeStreamSink_0<List<int>>())
as _i2.StreamSink<List<int>>);
@override
_i2.Future<_i3.ObjectInfo> writeBytes(String? name, List<int>? bytes,
{_i3.ObjectMetadata? metadata,
_i3.Acl? acl,
_i3.PredefinedAcl? predefinedAcl,
String? contentType}) =>
(super.noSuchMethod(
Invocation.method(#writeBytes, [
name,
bytes
], {
#metadata: metadata,
#acl: acl,
#predefinedAcl: predefinedAcl,
#contentType: contentType
}),
returnValue: Future<_i3.ObjectInfo>.value(_FakeObjectInfo_1()))
as _i2.Future<_i3.ObjectInfo>);
@override
_i2.Stream<List<int>> read(String? objectName, {int? offset, int? length}) =>
(super.noSuchMethod(
Invocation.method(
#read, [objectName], {#offset: offset, #length: length}),
returnValue: Stream<List<int>>.empty()) as _i2.Stream<List<int>>);
@override
_i2.Future<_i3.ObjectInfo> info(String? name) =>
(super.noSuchMethod(Invocation.method(#info, [name]),
returnValue: Future<_i3.ObjectInfo>.value(_FakeObjectInfo_1()))
as _i2.Future<_i3.ObjectInfo>);
@override
_i2.Future<dynamic> delete(String? name) =>
(super.noSuchMethod(Invocation.method(#delete, [name]),
returnValue: Future<dynamic>.value()) as _i2.Future<dynamic>);
@override
_i2.Future<dynamic> updateMetadata(
String? objectName, _i3.ObjectMetadata? metadata) =>
(super.noSuchMethod(
Invocation.method(#updateMetadata, [objectName, metadata]),
returnValue: Future<dynamic>.value()) as _i2.Future<dynamic>);
@override
_i2.Stream<_i3.BucketEntry> list({String? prefix, String? delimiter}) =>
(super.noSuchMethod(
Invocation.method(
#list, [], {#prefix: prefix, #delimiter: delimiter}),
returnValue: Stream<_i3.BucketEntry>.empty())
as _i2.Stream<_i3.BucketEntry>);
@override
_i2.Future<_i4.Page<_i3.BucketEntry>> page(
{String? prefix, String? delimiter, int? pageSize = 50}) =>
(super.noSuchMethod(
Invocation.method(#page, [], {
#prefix: prefix,
#delimiter: delimiter,
#pageSize: pageSize
}),
returnValue: Future<_i4.Page<_i3.BucketEntry>>.value(
_FakePage_2<_i3.BucketEntry>()))
as _i2.Future<_i4.Page<_i3.BucketEntry>>);
@override
String toString() => super.toString();
}
/// A class which mocks [ObjectInfo].
///
/// See the documentation for Mockito's code generation for more information.
class MockObjectInfo extends _i1.Mock implements _i3.ObjectInfo {
MockObjectInfo() {
_i1.throwOnMissingStub(this);
}
@override
String get name =>
(super.noSuchMethod(Invocation.getter(#name), returnValue: '') as String);
@override
int get length =>
(super.noSuchMethod(Invocation.getter(#length), returnValue: 0) as int);
@override
DateTime get updated => (super.noSuchMethod(Invocation.getter(#updated),
returnValue: _FakeDateTime_3()) as DateTime);
@override
String get etag =>
(super.noSuchMethod(Invocation.getter(#etag), returnValue: '') as String);
@override
List<int> get md5Hash =>
(super.noSuchMethod(Invocation.getter(#md5Hash), returnValue: <int>[])
as List<int>);
@override
int get crc32CChecksum =>
(super.noSuchMethod(Invocation.getter(#crc32CChecksum), returnValue: 0)
as int);
@override
Uri get downloadLink => (super.noSuchMethod(Invocation.getter(#downloadLink),
returnValue: _FakeUri_4()) as Uri);
@override
_i3.ObjectGeneration get generation =>
(super.noSuchMethod(Invocation.getter(#generation),
returnValue: _FakeObjectGeneration_5()) as _i3.ObjectGeneration);
@override
_i3.ObjectMetadata get metadata =>
(super.noSuchMethod(Invocation.getter(#metadata),
returnValue: _FakeObjectMetadata_6()) as _i3.ObjectMetadata);
@override
String toString() => super.toString();
}

View File

@ -13,11 +13,11 @@ void expectSetMatch<T>(Iterable<T> actual, Iterable<T> expected) {
}
// May return null if the credentials file doesn't exist.
Map<String, dynamic> getTestGcpCredentialsJson() {
Map<String, dynamic>? getTestGcpCredentialsJson() {
final File f = File('secret/test_gcp_credentials.json');
if (!f.existsSync()) {
return null;
}
return jsonDecode(File('secret/test_gcp_credentials.json').readAsStringSync())
as Map<String, dynamic>;
as Map<String, dynamic>?;
}