Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Windows version check in doctor #110013

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
84c033f
validator created -- logic to be developed on windows
eliasyishak Aug 8, 2022
23f9270
Merge branch 'flutter:master' into master
eliasyishak Aug 9, 2022
bb7eb0c
Merge branch 'flutter:master' into master
eliasyishak Aug 12, 2022
2664b1b
logic added for validator -- to be tested in windows env next
eliasyishak Aug 18, 2022
babffa0
making call to built in windows 'systeminfo' from dart
eliasyishak Aug 18, 2022
4857b5c
Update windows_version_validator.dart
eliasyishak Aug 18, 2022
cc19dc7
conditional to only run on windows
eliasyishak Aug 18, 2022
d4a408c
Update doctor.dart
eliasyishak Aug 18, 2022
2b9d07b
Merge pull request #1 from eliasyishak/master
eliasyishak Aug 22, 2022
e64af10
clean up
eliasyishak Aug 22, 2022
682cf63
conditional update to check for version
eliasyishak Aug 22, 2022
08a88ea
conditional status info message added
eliasyishak Aug 22, 2022
e1693c1
refactoring to not use `dart:io`
eliasyishak Aug 22, 2022
46abe7c
changes requested during review
eliasyishak Aug 22, 2022
fafc09d
adding documentation for validator
eliasyishak Aug 22, 2022
4b65652
fix to license file
eliasyishak Aug 23, 2022
6ee8e93
Merge branch 'flutter:master' into master
eliasyishak Aug 23, 2022
939ee81
fix to license file
eliasyishak Aug 23, 2022
c0a9191
Merge branch 'windows-version-check-in-doctor' of https://github.com/…
eliasyishak Aug 23, 2022
38d6b5e
Merge branch 'windows-version-check-in-doctor' into master
eliasyishak Aug 23, 2022
64ee21f
Merge pull request #2 from eliasyishak/master
eliasyishak Aug 23, 2022
00b93b5
fixing merging error
eliasyishak Aug 23, 2022
b45ae7e
added 3 tests for each return case for windows version
eliasyishak Aug 23, 2022
35fc46f
update to documentation + using async process run
eliasyishak Aug 23, 2022
8939a3f
simplified string parsing to utilize builtin regex functionality
eliasyishak Aug 24, 2022
a284788
remove todo
eliasyishak Aug 24, 2022
add6386
add optional indicator for new line chars
eliasyishak Aug 24, 2022
3c8c1a3
fixing regex pattern to look for start of line
eliasyishak Aug 24, 2022
ad3bf7c
added unit test for regex pattern validator
eliasyishak Sep 6, 2022
42c3607
Merge branch 'flutter:master' into master
eliasyishak Sep 6, 2022
50fbbb5
Merge pull request #3 from eliasyishak/windows-version-check-in-doctor
eliasyishak Sep 6, 2022
cb4badc
Merge pull request #4 from eliasyishak/master
eliasyishak Sep 6, 2022
618b94d
removing ProcessException catch since doctor validator handles it alr…
eliasyishak Sep 7, 2022
b650586
Apply Jonah suggestions from code review
eliasyishak Sep 7, 2022
7f690ae
renaming variable
eliasyishak Sep 7, 2022
899a221
additional test added for a nonzero exit code from systeminfo
eliasyishak Sep 7, 2022
ababef6
removing trivial static method, added constant for semver pattern
eliasyishak Sep 7, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions packages/flutter_tools/lib/src/doctor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import 'web/chrome.dart';
import 'web/web_validator.dart';
import 'web/workflow.dart';
import 'windows/visual_studio_validator.dart';
import 'windows/windows_version_validator.dart';
import 'windows/windows_workflow.dart';

abstract class DoctorValidatorsProvider {
Expand Down Expand Up @@ -129,6 +130,10 @@ class _DefaultDoctorValidatorsProvider implements DoctorValidatorsProvider {
flutterRoot: () => Cache.flutterRoot!,
operatingSystemUtils: globals.os,
),
if (platform.isWindows)
WindowsVersionValidator(
processManager: globals.processManager,
),
if (androidWorkflow!.appliesToHostPlatform)
GroupedValidator(<DoctorValidator>[androidValidator!, androidLicenseValidator!]),
if (globals.iosWorkflow!.appliesToHostPlatform || macOSWorkflow.appliesToHostPlatform)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright 2014 The Flutter Authors. All rights reserved.
// 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 '../doctor_validator.dart';

/// Flutter only supports development on Windows host machines version 10 and greater.
const List<String> kUnsupportedVersions = <String>[
'6',
'7',
'8',
];

/// Regex pattern for identifying line from systeminfo stdout with windows version
/// (ie. 10.5.4123)
const String kWindowsOSVersionSemVerPattern =
r'^(OS Version:\s*)([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,
super('Windows Version');

final ProcessManager _processManager;

@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);

// 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(2)?.split('.').elementAt(0))) {
windowsVersionStatus = ValidationType.installed;
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';
}

return ValidationResult(
windowsVersionStatus,
const <ValidationMessage>[],
statusInfo: statusInfo,
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
// Copyright 2014 The Flutter Authors. All rights reserved.
// 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/doctor_validator.dart';
import 'package:flutter_tools/src/windows/windows_version_validator.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.
''';

/// 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.
''';

/// The expected validation result object for
/// a passing windows version test
const ValidationResult validWindows10ValidationResult = ValidationResult(
ValidationType.installed,
<ValidationMessage>[],
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(
ValidationType.missing,
<ValidationMessage>[],
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,
),
],
),
);

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 {
final WindowsVersionValidator windowsVersionValidator =
WindowsVersionValidator(
processManager: FakeProcessManager.list(
<FakeCommand>[
const FakeCommand(
command: <String>['systeminfo'],
stdout: validWindows10StdOut,
exitCode: 1,
),
],
),
);

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,
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,
),
],
),
);

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 {
const String testStr = r'''
OS Version: 10.0.19044 N/A Build 19044
OSz Version: 10.0.19044 N/A Build 19044
OS 6Version: 10.0.19044 N/A Build 19044
OxS Version: 10.0.19044 N/A Build 19044
OS Version: 10.19044 N/A Build 19044
OS Version: 10.x.19044 N/A Build 19044
OS Version: 10.0.19044 N/A Build 19044
OS Version: .0.19044 N/A Build 19044
''';

final RegExp regex =
RegExp(kWindowsOSVersionSemVerPattern, multiLine: true);
final Iterable<RegExpMatch> matches = regex.allMatches(testStr);

expect(matches.length, 2,
reason: 'There should be only two matches for the pattern provided');
});
}