Skip to content

Commit 31e8b95

Browse files
Fix satellite resolution for Microsoft.TestPlatform.Common (#4147) (#4150)
Fix satellite resolution for Microsoft.TestPlatform.Common
1 parent 3789e2b commit 31e8b95

File tree

2 files changed

+10
-64
lines changed

2 files changed

+10
-64
lines changed

src/Microsoft.TestPlatform.Common/ExtensionFramework/TestPluginCache.cs

+9
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,15 @@ private Dictionary<string, TPluginInfo> GetTestExtensions<TPluginInfo, TExtensio
463463

464464
protected void SetupAssemblyResolver(string? extensionAssembly)
465465
{
466+
// If we don't load the resource for Microsoft.TestPlatform.Common before
467+
// to set the assembly resolver we won't be able to use the resources.
468+
// This should be the algorithm followed during the satellite assembly resolution
469+
// https://learn.microsoft.com/dotnet/core/extensions/package-and-deploy-resources#net-framework-resource-fallback-process
470+
// BUT for some unknown reason the point 10 is not working as explained.
471+
// Satellite resolution should fallback to the NeutralResourcesLanguageAttribute
472+
// that we set to en-US but don't and we fail with FileNotFoundException.
473+
_ = Resources.Resources.FailedToLoadAdapaterFile;
474+
466475
IList<string> resolutionPaths = extensionAssembly.IsNullOrEmpty()
467476
? GetDefaultResolutionPaths()
468477
: GetResolutionPaths(extensionAssembly);

src/Microsoft.TestPlatform.Common/Utilities/AssemblyResolver.cs

+1-64
Original file line numberDiff line numberDiff line change
@@ -122,71 +122,8 @@ internal void AddSearchDirectories(IEnumerable<string> directories)
122122

123123
TPDebug.Assert(requestedName != null && !requestedName.Name.IsNullOrEmpty(), "AssemblyResolver.OnResolve: requested is null or name is empty!");
124124

125-
// Workaround: adding expected folder for the satellite assembly related to the current CurrentThread.CurrentUICulture relative to the current assembly location.
126-
// After the move to the net461 the runtime doesn't resolve anymore the satellite assembly correctly.
127-
// The expected workflow should be https://learn.microsoft.com/en-us/dotnet/core/extensions/package-and-deploy-resources#net-framework-resource-fallback-process
128-
// But the resolution never fallback to the CultureInfo.Parent folder and fusion log return a failure like:
129-
// ...
130-
// LOG: The same bind was seen before, and was failed with hr = 0x80070002.
131-
// ERR: Unrecoverable error occurred during pre - download check(hr = 0x80070002).
132-
// ...
133-
// The bizarre thing is that as a result we're failing caller task like discovery and when for reporting reason
134-
// we're accessing again to the resource it works.
135-
// Looks like a loading timing issue but we're not in control of the assembly loader order.
136125
var isResource = requestedName.Name.EndsWith(".resources");
137-
string[]? satelliteLocation = null;
138-
139-
// We help to resolve only test platform resources to be less invasive as possible with the default/expected behavior
140-
if (isResource && requestedName.Name.StartsWith("Microsoft.VisualStudio.TestPlatform"))
141-
{
142-
try
143-
{
144-
string? currentAssemblyLocation = null;
145-
try
146-
{
147-
currentAssemblyLocation = Assembly.GetExecutingAssembly().Location;
148-
// In .NET 5 and later versions, for bundled assemblies, the value returned is an empty string.
149-
currentAssemblyLocation = currentAssemblyLocation == string.Empty ? null : Path.GetDirectoryName(currentAssemblyLocation);
150-
}
151-
catch (NotSupportedException)
152-
{
153-
// https://learn.microsoft.com/en-us/dotnet/api/system.reflection.assembly.location
154-
}
155-
156-
if (currentAssemblyLocation is not null)
157-
{
158-
List<string> satelliteLocations = new();
159-
160-
// We mimic the satellite workflow and we add CurrentUICulture and CurrentUICulture.Parent folder in order
161-
string? currentUICulture = Thread.CurrentThread.CurrentUICulture?.Name;
162-
if (currentUICulture is not null)
163-
{
164-
satelliteLocations.Add(Path.Combine(currentAssemblyLocation, currentUICulture));
165-
}
166-
167-
// CurrentUICulture.Parent
168-
string? parentCultureInfo = Thread.CurrentThread.CurrentUICulture?.Parent?.Name;
169-
if (parentCultureInfo is not null)
170-
{
171-
satelliteLocations.Add(Path.Combine(currentAssemblyLocation, parentCultureInfo));
172-
}
173-
174-
if (satelliteLocations.Count > 0)
175-
{
176-
satelliteLocation = satelliteLocations.ToArray();
177-
}
178-
}
179-
}
180-
catch (Exception ex)
181-
{
182-
// We catch here because this is a workaround, we're trying to substitute the expected workflow of the runtime
183-
// and this shouldn't be needed, but if we fail we want to log what's happened and give a chance to the in place
184-
// resolution workflow
185-
EqtTrace.Error($"AssemblyResolver.OnResolve: Exception during the custom satellite resolution\n{ex}");
186-
}
187-
}
188-
189-
foreach (var dir in (satelliteLocation is not null) ? _searchDirectories.Union(satelliteLocation) : _searchDirectories)
126+
foreach (var dir in _searchDirectories)
190127
{
191128
if (dir.IsNullOrEmpty())
192129
{

0 commit comments

Comments
 (0)