Refactoring to use ver command instead of systeminfo (#119304)

* refactoring to use `ver` command instead of `systeminfo`

* fix tests to match new approach

* adding another valid validator using brazil locale text

* refactor tests to use generic fake class `ver` arg + showing output from `ver` if unsuccessful

* update reason text in test

* fix reason text to be hard coded
This commit is contained in:
Elias Yishak 2023-01-30 14:29:13 -05:00 committed by GitHub
parent 59d80dc876
commit 458b298f98
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 33 additions and 255 deletions

View File

@ -132,7 +132,7 @@ class _DefaultDoctorValidatorsProvider implements DoctorValidatorsProvider {
),
if (platform.isWindows)
WindowsVersionValidator(
processManager: globals.processManager,
operatingSystemUtils: globals.os,
),
if (androidWorkflow!.appliesToHostPlatform)
GroupedValidator(<DoctorValidator>[androidValidator!, androidLicenseValidator!]),

View File

@ -2,9 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:process/process.dart';
import '../base/io.dart';
import '../base/os.dart';
import '../doctor_validator.dart';
/// Flutter only supports development on Windows host machines version 10 and greater.
@ -16,49 +14,36 @@ const List<String> kUnsupportedVersions = <String>[
/// Regex pattern for identifying line from systeminfo stdout with windows version
/// (ie. 10.5.4123)
const String kWindowsOSVersionSemVerPattern =
r'^(OS )([^:]*:\s*)([0-9]+\.[0-9]+\.[0-9]+)(.*)$';
const String kWindowsOSVersionSemVerPattern = r'([0-9]+)\.([0-9]+)\.([0-9\.]+)';
/// Validator for supported Windows host machine operating system version.
class WindowsVersionValidator extends DoctorValidator {
const WindowsVersionValidator({required ProcessManager processManager})
: _processManager = processManager,
const WindowsVersionValidator({
required OperatingSystemUtils operatingSystemUtils,
}) : _operatingSystemUtils = operatingSystemUtils,
super('Windows Version');
final ProcessManager _processManager;
final OperatingSystemUtils _operatingSystemUtils;
@override
Future<ValidationResult> validate() async {
final ProcessResult result =
await _processManager.run(<String>['systeminfo']);
if (result.exitCode != 0) {
return const ValidationResult(
ValidationType.missing,
<ValidationMessage>[],
statusInfo: 'Exit status from running `systeminfo` was unsuccessful',
);
}
final String resultStdout = result.stdout as String;
final RegExp regex =
RegExp(kWindowsOSVersionSemVerPattern, multiLine: true);
final Iterable<RegExpMatch> matches = regex.allMatches(resultStdout);
final String commandResult = _operatingSystemUtils.name;
final Iterable<RegExpMatch> matches = regex.allMatches(commandResult);
// Use the string split method to extract the major version
// and check against the [kUnsupportedVersions] list
final ValidationType windowsVersionStatus;
final String statusInfo;
if (matches.length == 1 &&
!kUnsupportedVersions
.contains(matches.elementAt(0).group(3)?.split('.').elementAt(0))) {
!kUnsupportedVersions.contains(matches.elementAt(0).group(1))) {
windowsVersionStatus = ValidationType.success;
statusInfo = 'Installed version of Windows is version 10 or higher';
} else {
windowsVersionStatus = ValidationType.missing;
statusInfo =
'Unable to confirm if installed Windows version is 10 or greater';
'Unable to determine Windows version (command `ver` returned $commandResult)';
}
return ValidationResult(

View File

@ -2,138 +2,22 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter_tools/src/base/os.dart';
import 'package:flutter_tools/src/doctor_validator.dart';
import 'package:flutter_tools/src/windows/windows_version_validator.dart';
import 'package:test/fake.dart';
import '../src/common.dart';
import '../src/fake_process_manager.dart';
/// Example output from `systeminfo` from a Windows 10 host
const String validWindows10StdOut = r'''
Host Name: XXXXXXXXXXXX
OS Name: Microsoft Windows 10 Enterprise
OS Version: 10.0.19044 N/A Build 19044
OS Manufacturer: Microsoft Corporation
OS Configuration: Member Workstation
OS Build Type: Multiprocessor Free
Registered Owner: N/A
Registered Organization: N/A
Product ID: XXXXXXXXXXXX
Original Install Date: 8/4/2022, 2:51:28 PM
System Boot Time: 8/10/2022, 1:03:10 PM
System Manufacturer: Google
System Model: Google Compute Engine
System Type: x64-based PC
Processor(s): 1 Processor(s) Installed.
[01]: AMD64 Family 23 Model 49 Stepping 0 AuthenticAMD ~2250 Mhz
BIOS Version: Google Google, 6/29/2022
Windows Directory: C:\\Windows
System Directory: C:\\Windows\\system32
Boot Device: \\Device\\HarddiskVolume2
System Locale: en-us;English (United States)
Input Locale: en-us;English (United States)
Time Zone: (UTC-08:00) Pacific Time (US & Canada)
Total Physical Memory: 32,764 MB
Available Physical Memory: 17,852 MB
Virtual Memory: Max Size: 33,788 MB
Virtual Memory: Available: 18,063 MB
Virtual Memory: In Use: 15,725 MB
Page File Location(s): C:\\pagefile.sys
Domain: ad.corp.google.com
Logon Server: \\CBF-DC-8
Hotfix(s): 7 Hotfix(s) Installed.
[01]: KB5013624
[02]: KB5003791
[03]: KB5012170
[04]: KB5016616
[05]: KB5014032
[06]: KB5014671
[07]: KB5015895
Hyper-V Requirements: A hypervisor has been detected. Features required for Hyper-V will not be displayed.
''';
/// Fake [_WindowsUtils] to use for testing
class FakeValidOperatingSystemUtils extends Fake
implements OperatingSystemUtils {
FakeValidOperatingSystemUtils(
[this.name = 'Microsoft Windows [Version 11.0.22621.963]']);
const String validWindows11CnStdOut = r'''
: XXXXXXXXXXXX
OS : Microsoft Windows 11
OS : 10.0.22621 Build 22621
OS : Microsoft Corporation
OS :
OS : Multiprocessor Free
:
:
ID: XXXXXXXXXXXX
: 2022/11/9, 13:33:50
: 2022/11/30, 13:36:47
: ASUS
: System Product Name
: x64-based PC
: 1
[01]: Intel64 Family 6 Model 151 Stepping 2 GenuineIntel ~3600 Mhz
BIOS : American Megatrends Inc. 2103, 2022/9/30
Windows : C:\WINDOWS
: C:\WINDOWS\system32
: \Device\HarddiskVolume1
: zh-cn;()
: zh-cn;()
: (UTC+08:00)
: 65,277 MB
: 55,333 MB
: : 75,005 MB
: : 61,781 MB
: 使: 13,224 MB
: C:\pagefile.sys
: WORKGROUP
: \\XXXXXXXXXXXX
: 3
[01]: KB5020622
[02]: KB5019980
[03]: KB5019304
Hyper-V : Hyper-V
''';
/// Example output from `systeminfo` from version != 10
const String invalidWindowsStdOut = r'''
Host Name: XXXXXXXXXXXX
OS Name: Microsoft Windows 8.1 Enterprise
OS Version: 6.3.9600 Build 9600
OS Manufacturer: Microsoft Corporation
OS Configuration: Member Workstation
OS Build Type: Multiprocessor Free
Registered Owner: N/A
Registered Organization: N/A
Product ID: XXXXXXXXXXXX
Original Install Date: 8/4/2022, 2:51:28 PM
System Boot Time: 8/10/2022, 1:03:10 PM
System Manufacturer: Google
System Model: Google Compute Engine
System Type: x64-based PC
Processor(s): 1 Processor(s) Installed.
[01]: AMD64 Family 23 Model 49 Stepping 0 AuthenticAMD ~2250 Mhz
BIOS Version: Google Google, 6/29/2022
Windows Directory: C:\\Windows
System Directory: C:\\Windows\\system32
Boot Device: \\Device\\HarddiskVolume2
System Locale: en-us;English (United States)
Input Locale: en-us;English (United States)
Time Zone: (UTC-08:00) Pacific Time (US & Canada)
Total Physical Memory: 32,764 MB
Available Physical Memory: 17,852 MB
Virtual Memory: Max Size: 33,788 MB
Virtual Memory: Available: 18,063 MB
Virtual Memory: In Use: 15,725 MB
Page File Location(s): C:\\pagefile.sys
Domain: ad.corp.google.com
Logon Server: \\CBF-DC-8
Hotfix(s): 7 Hotfix(s) Installed.
[01]: KB5013624
[02]: KB5003791
[03]: KB5012170
[04]: KB5016616
[05]: KB5014032
[06]: KB5014671
[07]: KB5015895
Hyper-V Requirements: A hypervisor has been detected. Features required for Hyper-V will not be displayed.
''';
@override
final String name;
}
/// The expected validation result object for
/// a passing windows version test
@ -143,14 +27,6 @@ const ValidationResult validWindows10ValidationResult = ValidationResult(
statusInfo: 'Installed version of Windows is version 10 or higher',
);
/// The expected validation result object for
/// a failing exit code (!= 0)
const ValidationResult failedValidationResult = ValidationResult(
ValidationType.missing,
<ValidationMessage>[],
statusInfo: 'Exit status from running `systeminfo` was unsuccessful',
);
/// The expected validation result object for
/// a passing windows version test
const ValidationResult invalidWindowsValidationResult = ValidationResult(
@ -159,28 +35,12 @@ const ValidationResult invalidWindowsValidationResult = ValidationResult(
statusInfo: 'Unable to confirm if installed Windows version is 10 or greater',
);
/// Expected return from a nonzero exitcode when
/// running systeminfo
const ValidationResult invalidExitCodeValidationResult = ValidationResult(
ValidationType.missing,
<ValidationMessage>[],
statusInfo: 'Exit status from running `systeminfo` was unsuccessful',
);
void main() {
testWithoutContext('Successfully running windows version check on windows 10',
() async {
final WindowsVersionValidator windowsVersionValidator =
WindowsVersionValidator(
processManager: FakeProcessManager.list(
<FakeCommand>[
const FakeCommand(
command: <String>['systeminfo'],
stdout: validWindows10StdOut,
),
],
),
);
operatingSystemUtils: FakeValidOperatingSystemUtils());
final ValidationResult result = await windowsVersionValidator.validate();
@ -191,95 +51,31 @@ void main() {
});
testWithoutContext(
'Successfully running windows version check on windows 11 CN',
() async {
final WindowsVersionValidator windowsVersionValidator =
WindowsVersionValidator(
processManager: FakeProcessManager.list(
<FakeCommand>[
const FakeCommand(
command: <String>['systeminfo'],
stdout: validWindows11CnStdOut,
),
],
),
);
final ValidationResult result = await windowsVersionValidator.validate();
expect(
result.type,
validWindows10ValidationResult.type,
reason: 'The ValidationResult type should be the same (installed)',
);
expect(
result.statusInfo,
validWindows10ValidationResult.statusInfo,
reason: 'The ValidationResult statusInfo messages should be the same',
);
},
);
testWithoutContext('Failing to invoke the `systeminfo` command', () async {
'Successfully running windows version check on windows 10 for BR',
() async {
final WindowsVersionValidator windowsVersionValidator =
WindowsVersionValidator(
processManager: FakeProcessManager.list(
<FakeCommand>[
const FakeCommand(
command: <String>['systeminfo'],
stdout: validWindows10StdOut,
exitCode: 1,
),
],
),
);
operatingSystemUtils: FakeValidOperatingSystemUtils(
'Microsoft Windows [versão 10.0.22621.1105]'));
final ValidationResult result = await windowsVersionValidator.validate();
expect(result.type, failedValidationResult.type,
reason: 'The ValidationResult type should be the same (missing)');
expect(result.statusInfo, failedValidationResult.statusInfo,
expect(result.type, validWindows10ValidationResult.type,
reason: 'The ValidationResult type should be the same (installed)');
expect(result.statusInfo, validWindows10ValidationResult.statusInfo,
reason: 'The ValidationResult statusInfo messages should be the same');
});
testWithoutContext('Identifying a windows version before 10', () async {
final WindowsVersionValidator windowsVersionValidator =
WindowsVersionValidator(
processManager: FakeProcessManager.list(
<FakeCommand>[
const FakeCommand(
command: <String>['systeminfo'],
stdout: invalidWindowsStdOut,
),
],
),
);
operatingSystemUtils: FakeValidOperatingSystemUtils(
'Microsoft Windows [Version 8.0.22621.1105]'));
final ValidationResult result = await windowsVersionValidator.validate();
expect(result.type, invalidWindowsValidationResult.type,
reason: 'The ValidationResult type should be the same (missing)');
expect(result.statusInfo, invalidWindowsValidationResult.statusInfo,
reason: 'The ValidationResult statusInfo messages should be the same');
});
testWithoutContext(
'Running into an nonzero exit code from systeminfo command', () async {
final WindowsVersionValidator windowsVersionValidator =
WindowsVersionValidator(
processManager: FakeProcessManager.list(
<FakeCommand>[
const FakeCommand(command: <String>['systeminfo'], exitCode: 1),
],
),
);
final ValidationResult result = await windowsVersionValidator.validate();
expect(result.type, invalidExitCodeValidationResult.type,
reason: 'The ValidationResult type should be the same (missing)');
expect(result.statusInfo, invalidExitCodeValidationResult.statusInfo,
reason: 'The ValidationResult statusInfo messages should be the same');
});
testWithoutContext('Unit testing on a regex pattern validator', () async {
@ -300,10 +96,7 @@ OS 版本: 10.0.22621 暂缺 Build 22621
);
final Iterable<RegExpMatch> matches = regex.allMatches(testStr);
expect(
matches.length,
3,
reason: 'There should be only two matches for the pattern provided',
);
expect(matches.length, 5,
reason: 'There should be only 5 matches for the pattern provided');
});
}