@@ -11,6 +11,7 @@ import { InstallRecord } from '../../Acquisition/InstallRecord';
1111import { InstallTrackerSingleton } from '../../Acquisition/InstallTrackerSingleton' ;
1212import { LocalInstallUpdateService } from '../../Acquisition/LocalInstallUpdateService' ;
1313import { IEventStream } from '../../EventStream/EventStream' ;
14+ import { SkippingIncompatibleArchitectureInstall } from '../../EventStream/EventStreamEvents' ;
1415import { IDotnetAcquireContext } from '../../IDotnetAcquireContext' ;
1516import { IExtensionState } from '../../IExtensionState' ;
1617import { getDotnetExecutable } from '../../Utils/TypescriptUtilities' ;
@@ -108,12 +109,13 @@ suite('LocalInstallUpdateService Unit Tests', function ()
108109
109110 const directoryProvider = new TestInstallationDirectoryProvider ( '/tmp' ) ;
110111
112+ const currentArch = DotnetCoreAcquisitionWorker . defaultArchitecture ( ) ;
111113 const owners = [ 'sample-owner' ] ;
112114 const legacyInstall : InstallRecord = {
113115 dotnetInstall : {
114116 version : '6.0.100' ,
115- architecture : 'x64' ,
116- installId : ' 6.0.100~x64' ,
117+ architecture : currentArch ,
118+ installId : ` 6.0.100~${ currentArch } ` ,
117119 installMode : 'runtime' ,
118120 isGlobal : false
119121 } ,
@@ -122,8 +124,8 @@ suite('LocalInstallUpdateService Unit Tests', function ()
122124 const updatedInstall : InstallRecord = {
123125 dotnetInstall : {
124126 version : '6.0.120' ,
125- architecture : 'x64' ,
126- installId : ' 6.0.120~x64' ,
127+ architecture : currentArch ,
128+ installId : ` 6.0.120~${ currentArch } ` ,
127129 installMode : 'runtime' ,
128130 isGlobal : false
129131 } ,
@@ -180,8 +182,8 @@ suite('LocalInstallUpdateService Unit Tests', function ()
180182
181183 const directoryProvider = new TestInstallationDirectoryProvider ( '/tmp' ) ;
182184
183- const legacyInstall = createInstallRecord ( '6.0.100' , 'x64' , 'runtime' , [ 'owner-real' ] ) ;
184- const latestInstall = createInstallRecord ( '6.0.150' , 'x64' , 'runtime' , [ ] ) ;
185+ const legacyInstall = createInstallRecord ( '6.0.100' , DotnetCoreAcquisitionWorker . defaultArchitecture ( ) , 'runtime' , [ 'owner-real' ] ) ;
186+ const latestInstall = createInstallRecord ( '6.0.150' , DotnetCoreAcquisitionWorker . defaultArchitecture ( ) , 'runtime' , [ ] ) ;
185187
186188 extensionState . update ( 'installed' , [ legacyInstall ] ) ;
187189
@@ -252,8 +254,8 @@ suite('LocalInstallUpdateService Unit Tests', function ()
252254
253255 const directoryProvider = new TestInstallationDirectoryProvider ( '/tmp' ) ;
254256
255- const legacyInstall = createInstallRecord ( '6.0.100' , 'x64' , 'runtime' , [ 'owner-a' ] ) ;
256- const latestInstall = createInstallRecord ( '6.0.150' , 'x64' , 'runtime' , [ ] ) ;
257+ const legacyInstall = createInstallRecord ( '6.0.100' , DotnetCoreAcquisitionWorker . defaultArchitecture ( ) , 'runtime' , [ 'owner-a' ] ) ;
258+ const latestInstall = createInstallRecord ( '6.0.150' , DotnetCoreAcquisitionWorker . defaultArchitecture ( ) , 'runtime' , [ ] ) ;
257259
258260 const trackerInstance = LocalUpdateServiceTestTracker . getInstance ( eventStream , extensionState ) ;
259261 trackerInstance . setInstallSequences ( [ [ legacyInstall ] , [ legacyInstall , latestInstall ] ] ) ;
@@ -289,16 +291,19 @@ suite('LocalInstallUpdateService Unit Tests', function ()
289291
290292 const directoryProvider = new TestInstallationDirectoryProvider ( '/tmp' ) ;
291293
294+ const currentArch = DotnetCoreAcquisitionWorker . defaultArchitecture ( ) ;
292295 const group1OwnersA : ( string | null ) [ ] = [ 'owner-a' , 'user' ] ;
293296 const group1OwnersB : ( string | null ) [ ] = [ 'owner-b' ] ;
294297 const group2Owners : ( string | null ) [ ] = [ 'owner-c' , null , 'user' ] ;
295298
296- const legacyGroup1Oldest = createInstallRecord ( '6.0.100' , 'x64' , 'runtime' , group1OwnersA ) ;
297- const legacyGroup1Older = createInstallRecord ( '6.0.110' , 'x64' , 'runtime' , group1OwnersB ) ;
298- const latestGroup1 = createInstallRecord ( '6.0.150' , 'x64' , 'runtime' , [ ] ) ;
299+ // Both groups use the current architecture so that they are eligible for auto-update.
300+ // Two different major.minor versions are used so they form distinct groups.
301+ const legacyGroup1Oldest = createInstallRecord ( '6.0.100' , currentArch , 'runtime' , group1OwnersA ) ;
302+ const legacyGroup1Older = createInstallRecord ( '6.0.110' , currentArch , 'runtime' , group1OwnersB ) ;
303+ const latestGroup1 = createInstallRecord ( '6.0.150' , currentArch , 'runtime' , [ ] ) ;
299304
300- const legacyGroup2 = createInstallRecord ( '7.0.150' , 'arm64' , 'runtime' , group2Owners ) ;
301- const latestGroup2 = createInstallRecord ( '7.0.180' , 'arm64' , 'runtime' , [ ] ) ;
305+ const legacyGroup2 = createInstallRecord ( '7.0.150' , currentArch , 'runtime' , group2Owners ) ;
306+ const latestGroup2 = createInstallRecord ( '7.0.180' , currentArch , 'runtime' , [ ] ) ;
302307
303308 const trackerInstance = LocalUpdateServiceTestTracker . getInstance ( eventStream , extensionState ) ;
304309 trackerInstance . setInstallSequences ( [
@@ -356,7 +361,7 @@ suite('LocalInstallUpdateService Unit Tests', function ()
356361
357362 const directoryProvider = new TestInstallationDirectoryProvider ( '/tmp' ) ;
358363
359- const legacyInstall = createInstallRecord ( '6.0.100' , 'x64' , 'runtime' , [ 'owner-a' ] ) ;
364+ const legacyInstall = createInstallRecord ( '6.0.100' , DotnetCoreAcquisitionWorker . defaultArchitecture ( ) , 'runtime' , [ 'owner-a' ] ) ;
360365
361366 const trackerInstance = LocalUpdateServiceTestTracker . getInstance ( eventStream , extensionState ) ;
362367 trackerInstance . setInstallSequences ( [ [ legacyInstall ] , [ legacyInstall ] ] ) ;
@@ -395,7 +400,7 @@ suite('LocalInstallUpdateService Unit Tests', function ()
395400 assert . lengthOf ( trackerInstance . getOwnersAdded ( ) , 0 , 'No owners should be transferred when acquisition fails' ) ;
396401 } ) ;
397402
398- test ( 'It treats installs with the same major.minor but different architecture as separate groups ' , async ( ) =>
403+ test ( 'It skips installs with architectures incompatible with the current machine ' , async ( ) =>
399404 {
400405 const onlineStub = {
401406 isOnline : async ( ) => true
@@ -409,19 +414,21 @@ suite('LocalInstallUpdateService Unit Tests', function ()
409414
410415 const directoryProvider = new TestInstallationDirectoryProvider ( '/tmp' ) ;
411416
412- const x64Owners : ( string | null ) [ ] = [ 'owner-x64' , 'user' ] ;
413- const armOwners : ( string | null ) [ ] = [ 'owner-arm' ] ;
417+ // Use the current machine architecture as the "compatible" arch and a different one as "incompatible".
418+ const currentArch = DotnetCoreAcquisitionWorker . defaultArchitecture ( ) ;
419+ const otherArch = currentArch === 'x64' ? 'arm64' : 'x64' ;
414420
415- const legacyX64 = createInstallRecord ( '6.0.100' , 'x64' , 'runtime' , x64Owners ) ;
416- const latestX64 = createInstallRecord ( '6.0.140' , 'x64' , 'runtime' , [ ] ) ;
417- const legacyArm = createInstallRecord ( '6.0.110' , 'arm64' , 'runtime' , armOwners ) ;
418- const latestArm = createInstallRecord ( '6.0.170' , 'arm64' , 'runtime' , [ ] ) ;
421+ const compatibleOwners : ( string | null ) [ ] = [ 'owner-compatible' , 'user' ] ;
422+ const incompatibleOwners : ( string | null ) [ ] = [ 'owner-incompatible' ] ;
423+
424+ const legacyCompatible = createInstallRecord ( '6.0.100' , currentArch , 'runtime' , compatibleOwners ) ;
425+ const latestCompatible = createInstallRecord ( '6.0.140' , currentArch , 'runtime' , [ ] ) ;
426+ const legacyIncompatible = createInstallRecord ( '6.0.110' , otherArch , 'runtime' , incompatibleOwners ) ;
419427
420428 const trackerInstance = LocalUpdateServiceTestTracker . getInstance ( eventStream , extensionState ) ;
421429 trackerInstance . setInstallSequences ( [
422- [ legacyX64 , legacyArm ] ,
423- [ legacyX64 , latestX64 , legacyArm ] ,
424- [ latestX64 , legacyArm , latestArm ]
430+ [ legacyCompatible , legacyIncompatible ] ,
431+ [ legacyCompatible , latestCompatible , legacyIncompatible ]
425432 ] ) ;
426433
427434 const acquireContexts : IDotnetAcquireContext [ ] = [ ] ;
@@ -442,22 +449,17 @@ suite('LocalInstallUpdateService Unit Tests', function ()
442449
443450 await updateService . ManageInstalls ( 0 ) ;
444451
445- assert . lengthOf ( acquireContexts , 2 , 'Acquire should run for each architecture group' ) ;
446- assert . sameMembers ( acquireContexts . map ( c => `${ c . version } |${ c . architecture } ` ) , [ '6.0|x64' , '6.0|arm64' ] , 'Contexts should reflect each architecture separately' ) ;
447-
448- assert . lengthOf ( uninstallContexts , 2 , 'Each architecture group should have one outdated install removed' ) ;
449- assert . sameMembers ( uninstallContexts . map ( c => `${ c . version } |${ c . architecture } ` ) , [ '6.0.100|x64' , '6.0.110|arm64' ] ) ;
450-
451- const ownersAdded = trackerInstance . getOwnersAdded ( ) ;
452- assert . lengthOf ( ownersAdded , 2 , 'Latest installs for each architecture should receive owners' ) ;
452+ // Only the compatible architecture should be acquired/updated
453+ assert . lengthOf ( acquireContexts , 1 , 'Acquire should only run for the compatible architecture group' ) ;
454+ assert . strictEqual ( acquireContexts [ 0 ] . architecture , currentArch , 'Only the current architecture should be updated' ) ;
453455
454- const x64OwnersAdded = ownersAdded . find ( entry => entry . install . installId === latestX64 . dotnetInstall . installId ) ;
455- assert . isDefined ( x64OwnersAdded , 'Latest x64 install should receive owners ') ;
456- assert . sameMembers ( x64OwnersAdded ! . owners . filter ( ( owner ) : owner is string => owner !== null ) , [ 'owner-x64' ] , 'Only non-user owners should be transferred for x64 ' ) ;
456+ // Only the outdated compatible-arch install should be uninstalled
457+ assert . lengthOf ( uninstallContexts , 1 , 'Only the outdated compatible-arch install should be scheduled for uninstall ') ;
458+ assert . strictEqual ( uninstallContexts [ 0 ] . architecture , currentArch , 'Uninstall should only target the current architecture ' ) ;
457459
458- const armOwnersAdded = ownersAdded . find ( entry => entry . install . installId === latestArm . dotnetInstall . installId ) ;
459- assert . isDefined ( armOwnersAdded , 'Latest arm64 install should receive owners' ) ;
460- assert . sameMembers ( armOwnersAdded ! . owners . filter ( ( owner ) : owner is string => owner !== null ) , [ 'owner-arm' ] , 'Owners for arm64 should remain separate from x64 ' ) ;
460+ // The incompatible-arch install should have triggered a skip event
461+ const skipEvents = eventStream . events . filter ( e => e instanceof SkippingIncompatibleArchitectureInstall ) ;
462+ assert . isAbove ( skipEvents . length , 0 , 'A skip event should be emitted for the incompatible architecture install ' ) ;
461463 } ) ;
462464
463465 test ( 'It forces updates immediately when delay is zero and refreshes the last update timestamp' , async ( ) =>
@@ -476,8 +478,8 @@ suite('LocalInstallUpdateService Unit Tests', function ()
476478 const directoryProvider = new TestInstallationDirectoryProvider ( '/tmp' ) ;
477479
478480 const owners : ( string | null ) [ ] = [ 'owner-force' ] ;
479- const legacyInstall = createInstallRecord ( '8.0.120' , 'x64' , 'runtime' , owners ) ;
480- const latestInstall = createInstallRecord ( '8.0.180' , 'x64' , 'runtime' , [ ] ) ;
481+ const legacyInstall = createInstallRecord ( '8.0.120' , DotnetCoreAcquisitionWorker . defaultArchitecture ( ) , 'runtime' , owners ) ;
482+ const latestInstall = createInstallRecord ( '8.0.180' , DotnetCoreAcquisitionWorker . defaultArchitecture ( ) , 'runtime' , [ ] ) ;
481483
482484 const trackerInstance = LocalUpdateServiceTestTracker . getInstance ( eventStream , extensionState ) ;
483485 trackerInstance . setInstallSequences ( [ [ legacyInstall ] , [ legacyInstall , latestInstall ] ] ) ;
@@ -530,10 +532,10 @@ suite('LocalInstallUpdateService Unit Tests', function ()
530532
531533 const directoryProvider = new TestInstallationDirectoryProvider ( '/tmp' ) ;
532534
533- const sdkInstall = createInstallRecord ( '8.0.302' , 'x64' , 'sdk' , [ 'sdk-owner' ] ) ;
534- const globalRuntime = createInstallRecord ( '8.0.180' , 'x64' , 'runtime' , [ 'global-owner' ] , true ) ;
535- const legacyRuntime = createInstallRecord ( '8.0.150' , 'x64' , 'runtime' , [ 'runtime-owner' ] ) ;
536- const latestRuntime = createInstallRecord ( '8.0.190' , 'x64' , 'runtime' , [ ] ) ;
535+ const sdkInstall = createInstallRecord ( '8.0.302' , DotnetCoreAcquisitionWorker . defaultArchitecture ( ) , 'sdk' , [ 'sdk-owner' ] ) ;
536+ const globalRuntime = createInstallRecord ( '8.0.180' , DotnetCoreAcquisitionWorker . defaultArchitecture ( ) , 'runtime' , [ 'global-owner' ] , true ) ;
537+ const legacyRuntime = createInstallRecord ( '8.0.150' , DotnetCoreAcquisitionWorker . defaultArchitecture ( ) , 'runtime' , [ 'runtime-owner' ] ) ;
538+ const latestRuntime = createInstallRecord ( '8.0.190' , DotnetCoreAcquisitionWorker . defaultArchitecture ( ) , 'runtime' , [ ] ) ;
537539
538540 const trackerInstance = LocalUpdateServiceTestTracker . getInstance ( eventStream , extensionState ) ;
539541 trackerInstance . setInstallSequences ( [
@@ -586,8 +588,8 @@ suite('LocalInstallUpdateService Unit Tests', function ()
586588 const directoryProvider = new TestInstallationDirectoryProvider ( '/tmp' ) ;
587589
588590 const owners : ( string | null ) [ ] = [ 'runtime-owner' ] ;
589- const legacyInstall = createInstallRecord ( '8.0.99' , 'x64' , 'runtime' , owners ) ;
590- const latestInstall = createInstallRecord ( '8.0.100' , 'x64' , 'runtime' , [ ] ) ;
591+ const legacyInstall = createInstallRecord ( '8.0.99' , DotnetCoreAcquisitionWorker . defaultArchitecture ( ) , 'runtime' , owners ) ;
592+ const latestInstall = createInstallRecord ( '8.0.100' , DotnetCoreAcquisitionWorker . defaultArchitecture ( ) , 'runtime' , [ ] ) ;
591593
592594 const trackerInstance = LocalUpdateServiceTestTracker . getInstance ( eventStream , extensionState ) ;
593595 trackerInstance . setInstallSequences ( [ [ legacyInstall ] , [ legacyInstall , latestInstall ] ] ) ;
@@ -635,8 +637,8 @@ suite('LocalInstallUpdateService Unit Tests', function ()
635637
636638 const directoryProvider = new TestInstallationDirectoryProvider ( '/tmp' ) ;
637639
638- const legacyInstall = createInstallRecord ( '10.0.1' , 'x64' , 'runtime' , [ 'ms-dotnettools.sample-extension' ] ) ;
639- const latestInstall = createInstallRecord ( '10.0.5' , 'x64' , 'runtime' , [ ] ) ;
640+ const legacyInstall = createInstallRecord ( '10.0.1' , DotnetCoreAcquisitionWorker . defaultArchitecture ( ) , 'runtime' , [ 'ms-dotnettools.sample-extension' ] ) ;
641+ const latestInstall = createInstallRecord ( '10.0.5' , DotnetCoreAcquisitionWorker . defaultArchitecture ( ) , 'runtime' , [ ] ) ;
640642
641643 extensionState . update ( 'installed' , [ legacyInstall ] ) ;
642644
0 commit comments