Skip to content

Commit c269248

Browse files
authored
Fix .NET Version Parsing for FindPath API (#2000)
* Fix Version Parsing for FindPath API The old comparison used string comparison which is fine for versions of dotnet until dotnet 10. '10.0' < '9.0'. 😂 This fixes that. I suppose it's a bit clunky and we could dedupe / share the compare logic but it's not being used elsewhere in this same form, so I don't plan to do that right now. There are also places that depend on the output versions being strings, so that's a problem to change that now too. It probably should have been a class from the beginning but unfortunately that just isn't how it was initially done, which is understandable because the scope at that time was much more limited. * Fix some of the code * Fix test * Dont comment out the other tests * update comment
1 parent b63c499 commit c269248

5 files changed

Lines changed: 75 additions & 21 deletions

File tree

vscode-dotnet-runtime-extension/src/test/functional/DotnetCoreAcquisitionExtension.test.ts

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ suite('DotnetCoreAcquisitionExtension End to End', function()
243243
if(shouldFind)
244244
{
245245
assert.exists(result.dotnetPath, 'find path command returned a result');
246-
assert.equal(result.dotnetPath, installPath, 'The path returned by findPath is correct');
246+
assert.equal(result.dotnetPath.toLowerCase(), installPath.toLowerCase(), 'The path returned by findPath is correct');
247247
}
248248
else
249249
{
@@ -316,13 +316,28 @@ suite('DotnetCoreAcquisitionExtension End to End', function()
316316
}
317317
}).timeout(standardTimeoutTime);
318318

319-
test('Find dotnet PATH Command Unmet Version Condition', async () => {
320-
// Install 3.1, look for 8.0 which is not less than or equal to 3.1
321-
await findPathWithRequirementAndInstall('8.0', 'runtime', os.arch(), 'less_than_or_equal', false,
319+
test('Find dotnet PATH Command Met Version Condition', async () => {
320+
// Install 8.0, look for 3.1 with accepting dotnet gr than or eq to 3.1
321+
322+
await findPathWithRequirementAndInstall('8.0', 'runtime', os.arch(), 'greater_than_or_equal', true,
322323
{version : '3.1', mode : 'runtime', architecture : os.arch(), requestingExtensionId : requestingExtensionId}
323324
);
324325
}).timeout(standardTimeoutTime);
325326

327+
test('Find dotnet PATH Command Met Version Condition with Double Digit Major', async () => {
328+
await findPathWithRequirementAndInstall('9.0', 'runtime', os.arch(), 'less_than_or_equal', true,
329+
{version : '11.0', mode : 'runtime', architecture : os.arch(), requestingExtensionId : requestingExtensionId}
330+
);
331+
}).timeout(standardTimeoutTime);
332+
333+
334+
test('Find dotnet PATH Command Unmet Version Condition', async () => {
335+
// Install 9.0, look for 90.0 which is not equal to 9.0
336+
await findPathWithRequirementAndInstall('9.0', 'runtime', os.arch(), 'equal', false,
337+
{version : '90.0', mode : 'runtime', architecture : os.arch(), requestingExtensionId : requestingExtensionId}
338+
);
339+
}).timeout(standardTimeoutTime);
340+
326341
test('Find dotnet PATH Command Unmet Mode Condition', async () => {
327342
// look for 3.1 runtime but install 3.1 aspnetcore
328343
await findPathWithRequirementAndInstall('3.1', 'runtime', os.arch(), 'equal', false,

vscode-dotnet-runtime-library/src/Acquisition/DotnetConditionValidator.ts

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ export class DotnetConditionValidator implements IDotnetConditionValidator
3131

3232
if(availableRuntimes.some((runtime) =>
3333
{
34-
const foundVersion = versionUtils.getMajorMinor(runtime.version, this.workerContext.eventStream, this.workerContext);
34+
const availableVersion = versionUtils.getMajorMinor(runtime.version, this.workerContext.eventStream, this.workerContext);
3535
return runtime.mode === requirement.acquireContext.mode && this.stringArchitectureMeetsRequirement(hostArch, requirement.acquireContext.architecture) &&
36-
this.stringVersionMeetsRequirement(foundVersion, requestedMajorMinor, requirement.versionSpecRequirement);
36+
this.stringVersionMeetsRequirement(availableVersion, requestedMajorMinor, requirement.versionSpecRequirement);
3737
}))
3838
{
3939
return true;
@@ -44,8 +44,8 @@ export class DotnetConditionValidator implements IDotnetConditionValidator
4444
if(availableSDKs.some((sdk) =>
4545
{
4646
// The SDK includes the Runtime, ASP.NET Core Runtime, and Windows Desktop Runtime. So, we don't need to check the mode.
47-
const foundVersion = versionUtils.getMajorMinor(sdk.version, this.workerContext.eventStream, this.workerContext);
48-
return this.stringArchitectureMeetsRequirement(hostArch, requirement.acquireContext.architecture) && this.stringVersionMeetsRequirement(foundVersion, requestedMajorMinor, requirement.versionSpecRequirement);
47+
const availableVersion = versionUtils.getMajorMinor(sdk.version, this.workerContext.eventStream, this.workerContext);
48+
return this.stringArchitectureMeetsRequirement(hostArch, requirement.acquireContext.architecture) && this.stringVersionMeetsRequirement(availableVersion, requestedMajorMinor, requirement.versionSpecRequirement);
4949
}))
5050
{
5151
return true;
@@ -136,22 +136,38 @@ Please set the PATH to a dotnet host that matches the architecture ${requirement
136136
return os.platform() === 'win32' ? (await this.executor!.tryFindWorkingCommand([CommandExecutor.makeCommand('chcp', ['65001'])])) !== null : false;
137137
}
138138

139-
private stringVersionMeetsRequirement(foundVersion : string, requiredVersion : string, requirement : DotnetVersionSpecRequirement) : boolean
139+
private stringVersionMeetsRequirement(availableVersion : string, requestedVersion : string, requirement : DotnetVersionSpecRequirement) : boolean
140140
{
141-
if(requirement === 'equal')
142-
{
143-
return foundVersion === requiredVersion;
144-
}
145-
else if(requirement === 'greater_than_or_equal')
141+
const availableMajor = Number(versionUtils.getMajor(availableVersion, this.workerContext.eventStream, this.workerContext));
142+
const requestedMajor = Number(versionUtils.getMajor(requestedVersion, this.workerContext.eventStream, this.workerContext));
143+
144+
if(availableMajor === requestedMajor)
146145
{
147-
return foundVersion >= requiredVersion;
146+
const availableMinor = Number(versionUtils.getMinor(availableVersion, this.workerContext.eventStream, this.workerContext));
147+
const requestedMinor = Number(versionUtils.getMinor(requestedVersion, this.workerContext.eventStream, this.workerContext));
148+
149+
switch(requirement)
150+
{
151+
case 'equal':
152+
return availableMinor === requestedMinor;
153+
case 'greater_than_or_equal':
154+
return availableMinor >= requestedMinor;
155+
case 'less_than_or_equal':
156+
return availableMinor <= requestedMinor;
157+
}
148158
}
149-
else if(requirement === 'less_than_or_equal')
159+
else
150160
{
151-
return foundVersion <= requiredVersion;
161+
switch(requirement)
162+
{
163+
case 'equal':
164+
return false;
165+
case 'greater_than_or_equal':
166+
return availableMajor >= requestedMajor;
167+
case 'less_than_or_equal':
168+
return availableMajor <= requestedMajor;
169+
}
152170
}
153-
154-
return false;
155171
}
156172

157173
private stringArchitectureMeetsRequirement(outputArchitecture : string, requiredArchitecture : string | null | undefined) : boolean

vscode-dotnet-runtime-library/src/Acquisition/VersionUtilities.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,26 @@ const invalidFeatureBandErrorString = `A feature band couldn't be determined for
1313
/**
1414
*
1515
* @param fullySpecifiedVersion the fully specified version of the sdk, e.g. 7.0.301 to get the major from.
16-
* @returns the major.minor in the form of '3', etc.
16+
* @returns the major in the form of '3', etc.
1717
*/
1818
export function getMajor(fullySpecifiedVersion : string, eventStream : IEventStream, context : IAcquisitionWorkerContext) : string
1919
{
2020
// The called function will check that we can do the split, so we don't need to check again.
2121
return getMajorMinor(fullySpecifiedVersion, eventStream, context).split('.')[0];
2222
}
2323

24+
/**
25+
*
26+
* @param fullySpecifiedVersion the fully specified version of the sdk, e.g. 7.0.301 to get the minor from.
27+
* @returns the major.minor in the form of '0', etc.
28+
*/
29+
export function getMinor(fullySpecifiedVersion : string, eventStream : IEventStream, context : IAcquisitionWorkerContext) : string
30+
{
31+
// The called function will check that we can do the split, so we don't need to check again.
32+
return getMajorMinor(fullySpecifiedVersion, eventStream, context).split('.')[1];
33+
}
34+
35+
2436
/**
2537
*
2638
* @param fullySpecifiedVersion the fully specified version, e.g. 7.0.301 to get the major minor from.

vscode-dotnet-runtime-library/src/DotnetVersionSpecRequirement.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
* Licensed to the .NET Foundation under one or more agreements.
33
* The .NET Foundation licenses this file to you under the MIT license.
44
*--------------------------------------------------------------------------------------------*/
5-
5+
/**
6+
* @remarks A condition to be met when searching for .NET. This refers to the major.minor of .NET versions.
7+
* When this condition is used, the available version is compared to the required version.
8+
* For example, if the request is made looking for 8.0 and allowing 'greater_than_or_equal', then 10.0 would be accepted,
9+
* because 10.0 >= 8.0.
10+
*/
611
export type DotnetVersionSpecRequirement = 'equal' | 'greater_than_or_equal' | 'less_than_or_equal';
712

vscode-dotnet-runtime-library/src/test/unit/VersionUtilities.test.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ suite('Version Utilities Unit Tests', () => {
3232
assert.equal(resolver.getMajor(twoDigitMajorVersion, mockEventStream, mockCtx), '10');
3333
});
3434

35+
test('Get Minor from SDK Version', async () => {
36+
assert.equal(resolver.getMinor(fullySpecifiedVersion, mockEventStream, mockCtx), '0');
37+
assert.equal(resolver.getMinor(uniqueMajorMinorVersion, mockEventStream, mockCtx), '1');
38+
assert.equal(resolver.getMinor(twoDigitMajorVersion, mockEventStream, mockCtx), '0');
39+
});
40+
3541
test('Get Major.Minor from SDK Version', async () => {
3642
assert.equal(resolver.getMajorMinor(fullySpecifiedVersion, mockEventStream, mockCtx), '7.0');
3743
assert.equal(resolver.getMajorMinor(featureBandVersion, mockEventStream, mockCtx), '7.0');

0 commit comments

Comments
 (0)