Skip to content

The nunit engine does not use the extension with the latest version if multiple versions are available #1678

Closed
@m4ggo

Description

@m4ggo

If an extension exists in multiple versions within the packages folder the nunit engine does not select the highest version but always the first it finds - which is in many cases the lowest version.

Precondition:
One extension is installed in multiple versions in the packages directory, e.g.
\packages\nunit.extension.sample\1.0.0
\packages\nunit.extension.sample\2.0.0

Repro steps:

  • Navigate into the folder for the nunit3-console.exe, e.g. packages\nunit.consolerunner\3.20.0\tools
  • List the extensions for the runner via: nunit3-console.exe --list-extensions

Result:

  • The extension with the lower version (1.0.0) is listed

Extension Point: /NUnit/Engine/TypeExtensions/IDriverFactory
Extension: SampleExtension.SampleExtension(.NET 4.0)
Version: 1.0.0.0
Path: C:.nuget\packages\nunit.extension.sample\1.0.0\net48\tools\SampleExtension.dll

Expected Result:
Extension Point: /NUnit/Engine/TypeExtensions/IDriverFactory
Extension: SampleExtension.SampleExtension(.NET 4.0)
Version: 2.0.0.0
Path: C:.nuget\packages\nunit.extension.sample\2.0.0\net48\tools\SampleExtension.dll

Affected Versions:
nunit.consolerunner.3.19.x
nunit.consolerunner.3.20.0

Workaround:
Switch to nunit.consolerunner.3.18.3 version

Root cause:
Project: nunit.engine.core
Class: Services\ExtensionManager.cs

In method ProcessCandidateAssembly the extensions are compared via IsBetterVersionOf but the new assembly is only added ByName and not updated in the _assemblies list.

line 437:

 if (candidateAssembly.IsBetterVersionOf(existing))
     _assemblies.ByName[assemblyName] = candidateAssembly;

line 444 - executed for the first found extension:
_assemblies.Add(candidateAssembly);

In method EnsureExtensionsAreLoaded the _assemblies is iterated but this list only contains the first extension, the latest extension is only in the 'ByName' Dictionary
line 323:

	foreach (var candidate in _assemblies)
            FindExtensionsInAssembly(candidate);

As local hotfix I iterated the ByName values via _assemblies.ByName.Values and after that it selected the latest version again, but I don't know if this is a valid .

	foreach (var candidate in _assemblies.ByName.Values)
            FindExtensionsInAssembly(candidate);

I added the two sample package folders which only contain an extension dll in different major versions which can be used to reproduce the behaviour of the --list-extensions command.
nunit.extension.sample.zip

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions