Unverified Commit 060adf09 authored by Christopher Fujino's avatar Christopher Fujino Committed by GitHub

[flutter_tools] Migrate commands.shard/hermetic/doctor_test to null-safety and...

[flutter_tools] Migrate commands.shard/hermetic/doctor_test to null-safety and make hermetic (#107670)
parent bccbcd7d
......@@ -320,12 +320,12 @@ class Doctor {
Future<bool> diagnose({
bool androidLicenses = false,
bool verbose = true,
bool showColor = true,
AndroidLicenseValidator? androidLicenseValidator,
bool showPii = true,
List<ValidatorTask>? startedValidatorTasks,
bool sendEvent = true,
}) async {
final bool showColor = globals.terminal.supportsColor;
if (androidLicenses && androidLicenseValidator != null) {
return androidLicenseValidator.runLicenseManager();
}
......@@ -644,7 +644,7 @@ class DoctorText {
Future<String> _runDiagnosis(bool showPii) async {
try {
await _doctor.diagnose(showColor: false, startedValidatorTasks: _validatorTasks, showPii: showPii, sendEvent: _sendDoctorEvent);
await _doctor.diagnose(startedValidatorTasks: _validatorTasks, showPii: showPii, sendEvent: _sendDoctorEvent);
// Do not send the doctor event a second time.
_sendDoctorEvent = false;
final String text = _logger.statusText;
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
// TODO(gspencergoog): Remove this tag once this test's state leaks/test
// dependencies have been fixed.
// https://github.com/flutter/flutter/issues/85160
......@@ -42,9 +40,9 @@ import '../../src/fakes.dart';
import '../../src/test_flutter_command_runner.dart';
void main() {
FakeFlutterVersion flutterVersion;
BufferLogger logger;
FakeProcessManager fakeProcessManager;
late FakeFlutterVersion flutterVersion;
late BufferLogger logger;
late FakeProcessManager fakeProcessManager;
setUp(() {
flutterVersion = FakeFlutterVersion();
......@@ -187,12 +185,13 @@ void main() {
'• No issues found!\n'
));
}, overrides: <Type, Generator>{
AnsiTerminal: () => FakeTerminal(),
DoctorValidatorsProvider: () => FakeDoctorValidatorsProvider(),
});
});
group('doctor usage params', () {
TestUsage testUsage;
late TestUsage testUsage;
setUp(() {
testUsage = TestUsage();
......@@ -328,6 +327,8 @@ void main() {
'\n'
'• No issues found!\n'
));
}, overrides: <Type, Generator>{
AnsiTerminal: () => FakeTerminal(),
});
testUsingContext('validate non-verbose output format for run with crash', () async {
......@@ -345,6 +346,8 @@ void main() {
'\n'
'! Doctor found issues in 1 category.\n'
));
}, overrides: <Type, Generator>{
AnsiTerminal: () => FakeTerminal(),
});
testUsingContext('validate verbose output format contains trace for run with crash', () async {
......@@ -361,6 +364,8 @@ void main() {
});
expect(logger.statusText, contains('Stuck validator that never completes exceeded maximum allowed duration of '));
}, overrides: <Type, Generator>{
AnsiTerminal: () => FakeTerminal(),
});
testUsingContext('validate non-verbose output format for run with an async crash', () async {
......@@ -387,6 +392,8 @@ void main() {
'\n'
'! Doctor found issues in 1 category.\n'
));
}, overrides: <Type, Generator>{
AnsiTerminal: () => FakeTerminal(),
});
......@@ -399,6 +406,8 @@ void main() {
'\n'
'! Doctor found issues in 1 category.\n'
));
}, overrides: <Type, Generator>{
AnsiTerminal: () => FakeTerminal(),
});
testUsingContext('validate non-verbose output format for a passing run', () async {
......@@ -415,6 +424,8 @@ void main() {
'\n'
'! Doctor found issues in 2 categories.\n'
));
}, overrides: <Type, Generator>{
AnsiTerminal: () => FakeTerminal(),
});
testUsingContext('validate non-verbose output format', () async {
......@@ -436,6 +447,8 @@ void main() {
'\n'
'! Doctor found issues in 4 categories.\n'
));
}, overrides: <Type, Generator>{
AnsiTerminal: () => FakeTerminal(),
});
testUsingContext('validate verbose output format', () async {
......@@ -466,6 +479,8 @@ void main() {
'\n'
'! Doctor found issues in 4 categories.\n'
));
}, overrides: <Type, Generator>{
AnsiTerminal: () => FakeTerminal(),
});
testUsingContext('validate PII can be hidden', () async {
......@@ -485,12 +500,14 @@ void main() {
'\n'
'• No issues found!\n'
));
}, overrides: <Type, Generator>{
AnsiTerminal: () => FakeTerminal(),
});
});
group('doctor diagnosis wrapper', () {
TestUsage testUsage;
BufferLogger logger;
late TestUsage testUsage;
late BufferLogger logger;
setUp(() {
testUsage = TestUsage();
......@@ -527,6 +544,7 @@ void main() {
),
]);
}, overrides: <Type, Generator>{
AnsiTerminal: () => FakeTerminal(),
Usage: () => testUsage,
});
......@@ -572,6 +590,8 @@ void main() {
'! Doctor found issues in 4\n'
' categories.\n'
));
}, overrides: <Type, Generator>{
AnsiTerminal: () => FakeTerminal(),
});
testUsingContext('validate verbose output wrapping', () async {
......@@ -616,6 +636,8 @@ void main() {
'! Doctor found issues in 4\n'
' categories.\n'
));
}, overrides: <Type, Generator>{
AnsiTerminal: () => FakeTerminal(),
});
group('doctor with grouped validators', () {
......@@ -632,6 +654,8 @@ void main() {
'\n'
'! Doctor found issues in 1 category.\n'
));
}, overrides: <Type, Generator>{
AnsiTerminal: () => FakeTerminal(),
});
testUsingContext('validate merging assigns statusInfo and title', () async {
......@@ -644,6 +668,8 @@ void main() {
'\n'
'• No issues found!\n'
));
}, overrides: <Type, Generator>{
AnsiTerminal: () => FakeTerminal(),
});
});
......@@ -655,46 +681,64 @@ void main() {
testUsingContext('validate installed + installed = installed', () async {
expect(await FakeSmallGroupDoctor(logger, installed, installed).diagnose(), isTrue);
expect(logger.statusText, startsWith('[✓]'));
}, overrides: <Type, Generator>{
AnsiTerminal: () => FakeTerminal(),
});
testUsingContext('validate installed + partial = partial', () async {
expect(await FakeSmallGroupDoctor(logger, installed, partial).diagnose(), isTrue);
expect(logger.statusText, startsWith('[!]'));
}, overrides: <Type, Generator>{
AnsiTerminal: () => FakeTerminal(),
});
testUsingContext('validate installed + missing = partial', () async {
expect(await FakeSmallGroupDoctor(logger, installed, missing).diagnose(), isTrue);
expect(logger.statusText, startsWith('[!]'));
}, overrides: <Type, Generator>{
AnsiTerminal: () => FakeTerminal(),
});
testUsingContext('validate partial + installed = partial', () async {
expect(await FakeSmallGroupDoctor(logger, partial, installed).diagnose(), isTrue);
expect(logger.statusText, startsWith('[!]'));
}, overrides: <Type, Generator>{
AnsiTerminal: () => FakeTerminal(),
});
testUsingContext('validate partial + partial = partial', () async {
expect(await FakeSmallGroupDoctor(logger, partial, partial).diagnose(), isTrue);
expect(logger.statusText, startsWith('[!]'));
}, overrides: <Type, Generator>{
AnsiTerminal: () => FakeTerminal(),
});
testUsingContext('validate partial + missing = partial', () async {
expect(await FakeSmallGroupDoctor(logger, partial, missing).diagnose(), isTrue);
expect(logger.statusText, startsWith('[!]'));
}, overrides: <Type, Generator>{
AnsiTerminal: () => FakeTerminal(),
});
testUsingContext('validate missing + installed = partial', () async {
expect(await FakeSmallGroupDoctor(logger, missing, installed).diagnose(), isTrue);
expect(logger.statusText, startsWith('[!]'));
}, overrides: <Type, Generator>{
AnsiTerminal: () => FakeTerminal(),
});
testUsingContext('validate missing + partial = partial', () async {
expect(await FakeSmallGroupDoctor(logger, missing, partial).diagnose(), isTrue);
expect(logger.statusText, startsWith('[!]'));
}, overrides: <Type, Generator>{
AnsiTerminal: () => FakeTerminal(),
});
testUsingContext('validate missing + missing = missing', () async {
expect(await FakeSmallGroupDoctor(logger, missing, missing).diagnose(), isFalse);
expect(logger.statusText, startsWith('[✗]'));
}, overrides: <Type, Generator>{
AnsiTerminal: () => FakeTerminal(),
});
});
......@@ -747,9 +791,9 @@ class NoOpDoctor implements Doctor {
bool androidLicenses = false,
bool verbose = true,
bool showColor = true,
AndroidLicenseValidator androidLicenseValidator,
AndroidLicenseValidator? androidLicenseValidator,
bool showPii = true,
List<ValidatorTask> startedValidatorTasks,
List<ValidatorTask>? startedValidatorTasks,
bool sendEvent = true,
}) async => true;
......@@ -767,7 +811,7 @@ class NoOpDoctor implements Doctor {
}
class PassingValidator extends DoctorValidator {
PassingValidator(String name) : super(name);
PassingValidator(super.name);
@override
Future<ValidationResult> validate() async {
......@@ -875,10 +919,10 @@ class AsyncCrashingValidator extends DoctorValidator {
@override
Future<ValidationResult> validate() {
const Duration delay = Duration(seconds: 1);
final Future<ValidationResult> result = Future<ValidationResult>.delayed(delay)
.then((_) {
throw StateError('fatal error');
});
final Future<ValidationResult> result = Future<ValidationResult>.delayed(
delay,
() => throw StateError('fatal error'),
);
_time.elapse(const Duration(seconds: 1));
_time.flushMicrotasks();
return result;
......@@ -889,34 +933,27 @@ class AsyncCrashingValidator extends DoctorValidator {
class FakeDoctor extends Doctor {
FakeDoctor(Logger logger) : super(logger: logger);
List<DoctorValidator> _validators;
@override
List<DoctorValidator> get validators {
return _validators ??= <DoctorValidator>[
late final List<DoctorValidator> validators = <DoctorValidator>[
PassingValidator('Passing Validator'),
MissingValidator(),
NotAvailableValidator(),
PartialValidatorWithHintsOnly(),
PartialValidatorWithErrors(),
];
}
}
/// A doctor that should pass, but still has issues in some categories.
class FakePassingDoctor extends Doctor {
FakePassingDoctor(Logger logger) : super(logger: logger);
List<DoctorValidator> _validators;
@override
List<DoctorValidator> get validators {
return _validators ??= <DoctorValidator>[
late final List<DoctorValidator> validators = <DoctorValidator>[
PassingValidator('Passing Validator'),
PartialValidatorWithHintsOnly(),
PartialValidatorWithErrors(),
PassingValidator('Another Passing Validator'),
];
}
}
/// A doctor that should pass, but still has 1 issue to test the singular of
......@@ -924,80 +961,61 @@ class FakePassingDoctor extends Doctor {
class FakeSinglePassingDoctor extends Doctor {
FakeSinglePassingDoctor(Logger logger) : super(logger: logger);
List<DoctorValidator> _validators;
@override
List<DoctorValidator> get validators {
return _validators ??= <DoctorValidator>[
late final List<DoctorValidator> validators = <DoctorValidator>[
PartialValidatorWithHintsOnly(),
];
}
}
/// A doctor that passes and has no issues anywhere.
class FakeQuietDoctor extends Doctor {
FakeQuietDoctor(Logger logger) : super(logger: logger);
List<DoctorValidator> _validators;
@override
List<DoctorValidator> get validators {
return _validators ??= <DoctorValidator>[
late final List<DoctorValidator> validators = <DoctorValidator>[
PassingValidator('Passing Validator'),
PassingValidator('Another Passing Validator'),
PassingValidator('Validators are fun'),
PassingValidator('Four score and seven validators ago'),
];
}
}
/// A doctor that passes and contains PII that can be hidden.
class FakePiiDoctor extends Doctor {
FakePiiDoctor(Logger logger) : super(logger: logger);
List<DoctorValidator> _validators;
@override
List<DoctorValidator> get validators {
return _validators ??= <DoctorValidator>[
late final List<DoctorValidator> validators = <DoctorValidator>[
PiiValidator(),
];
}
}
/// A doctor with a validator that throws an exception.
class FakeCrashingDoctor extends Doctor {
FakeCrashingDoctor(Logger logger) : super(logger: logger);
List<DoctorValidator> _validators;
@override
List<DoctorValidator> get validators {
if (_validators == null) {
_validators = <DoctorValidator>[];
_validators.add(PassingValidator('Passing Validator'));
_validators.add(PassingValidator('Another Passing Validator'));
_validators.add(CrashingValidator());
_validators.add(PassingValidator('Validators are fun'));
_validators.add(PassingValidator('Four score and seven validators ago'));
}
return _validators;
}
late final List<DoctorValidator> validators = <DoctorValidator>[
PassingValidator('Passing Validator'),
PassingValidator('Another Passing Validator'),
CrashingValidator(),
PassingValidator('Validators are fun'),
PassingValidator('Four score and seven validators ago'),
];
}
/// A doctor with a validator that will never finish.
class FakeAsyncStuckDoctor extends Doctor {
FakeAsyncStuckDoctor(Logger logger) : super(logger: logger);
List<DoctorValidator> _validators;
@override
List<DoctorValidator> get validators {
if (_validators == null) {
_validators = <DoctorValidator>[];
_validators.add(PassingValidator('Passing Validator'));
_validators.add(PassingValidator('Another Passing Validator'));
_validators.add(StuckValidator());
_validators.add(PassingValidator('Validators are fun'));
_validators.add(PassingValidator('Four score and seven validators ago'));
}
return _validators;
}
late final List<DoctorValidator> validators = <DoctorValidator>[
PassingValidator('Passing Validator'),
PassingValidator('Another Passing Validator'),
StuckValidator(),
PassingValidator('Validators are fun'),
PassingValidator('Four score and seven validators ago'),
];
}
/// A doctor with a validator that throws an exception.
......@@ -1006,19 +1024,14 @@ class FakeAsyncCrashingDoctor extends Doctor {
final FakeAsync _time;
List<DoctorValidator> _validators;
@override
List<DoctorValidator> get validators {
if (_validators == null) {
_validators = <DoctorValidator>[];
_validators.add(PassingValidator('Passing Validator'));
_validators.add(PassingValidator('Another Passing Validator'));
_validators.add(AsyncCrashingValidator(_time));
_validators.add(PassingValidator('Validators are fun'));
_validators.add(PassingValidator('Four score and seven validators ago'));
}
return _validators;
}
late final List<DoctorValidator> validators = <DoctorValidator>[
PassingValidator('Passing Validator'),
PassingValidator('Another Passing Validator'),
AsyncCrashingValidator(_time),
PassingValidator('Validators are fun'),
PassingValidator('Four score and seven validators ago'),
];
}
/// A DoctorValidatorsProvider that overrides the default validators without
......@@ -1038,7 +1051,7 @@ class FakeDoctorValidatorsProvider implements DoctorValidatorsProvider {
}
class PassingGroupedValidator extends DoctorValidator {
PassingGroupedValidator(String name) : super(name);
PassingGroupedValidator(super.name);
@override
Future<ValidationResult> validate() async {
......@@ -1050,7 +1063,7 @@ class PassingGroupedValidator extends DoctorValidator {
}
class MissingGroupedValidator extends DoctorValidator {
MissingGroupedValidator(String name) : super(name);
MissingGroupedValidator(super.name);
@override
Future<ValidationResult> validate() async {
......@@ -1062,7 +1075,7 @@ class MissingGroupedValidator extends DoctorValidator {
}
class PartialGroupedValidator extends DoctorValidator {
PartialGroupedValidator(String name) : super(name);
PartialGroupedValidator(super.name);
@override
Future<ValidationResult> validate() async {
......@@ -1074,7 +1087,7 @@ class PartialGroupedValidator extends DoctorValidator {
}
class PassingGroupedValidatorWithStatus extends DoctorValidator {
PassingGroupedValidatorWithStatus(String name) : super(name);
PassingGroupedValidatorWithStatus(super.name);
@override
Future<ValidationResult> validate() async {
......@@ -1089,10 +1102,8 @@ class PassingGroupedValidatorWithStatus extends DoctorValidator {
class FakeGroupedDoctor extends Doctor {
FakeGroupedDoctor(Logger logger) : super(logger: logger);
List<DoctorValidator> _validators;
@override
List<DoctorValidator> get validators {
return _validators ??= <DoctorValidator>[
late final List<DoctorValidator> validators = <DoctorValidator>[
GroupedValidator(<DoctorValidator>[
PassingGroupedValidator('Category 1'),
PassingGroupedValidator('Category 1'),
......@@ -1102,39 +1113,33 @@ class FakeGroupedDoctor extends Doctor {
MissingGroupedValidator('Category 2'),
]),
];
}
}
class FakeGroupedDoctorWithStatus extends Doctor {
FakeGroupedDoctorWithStatus(Logger logger) : super(logger: logger);
List<DoctorValidator> _validators;
@override
List<DoctorValidator> get validators {
return _validators ??= <DoctorValidator>[
late final List<DoctorValidator> validators = <DoctorValidator>[
GroupedValidator(<DoctorValidator>[
PassingGroupedValidator('First validator title'),
PassingGroupedValidatorWithStatus('Second validator title'),
]),
];
}
}
/// A doctor that takes any two validators. Used to check behavior when
/// merging ValidationTypes (installed, missing, partial).
class FakeSmallGroupDoctor extends Doctor {
FakeSmallGroupDoctor(Logger logger, DoctorValidator val1, DoctorValidator val2) : super(logger: logger) {
_validators = <DoctorValidator>[GroupedValidator(<DoctorValidator>[val1, val2])];
}
List<DoctorValidator> _validators;
FakeSmallGroupDoctor(Logger logger, DoctorValidator val1, DoctorValidator val2)
: validators = <DoctorValidator>[GroupedValidator(<DoctorValidator>[val1, val2])],
super(logger: logger);
@override
List<DoctorValidator> get validators => _validators;
final List<DoctorValidator> validators;
}
class VsCodeValidatorTestTargets extends VsCodeValidator {
VsCodeValidatorTestTargets._(String installDirectory, String extensionDirectory, {String edition})
VsCodeValidatorTestTargets._(String installDirectory, String extensionDirectory, {String? edition})
: super(VsCode.fromDirectory(installDirectory, extensionDirectory, edition: edition, fileSystem: globals.fs));
static VsCodeValidatorTestTargets get installedWithExtension =>
......@@ -1190,3 +1195,8 @@ class FakeDevice extends Fake implements Device {
@override
Future<TargetPlatform> get targetPlatform => Future<TargetPlatform>.value(TargetPlatform.android);
}
class FakeTerminal extends Fake implements AnsiTerminal {
@override
final bool supportsColor = false;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment