Skip to content
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

Preserve TestIdGenerationStrategy in the execution AppDomain #4942

Merged
merged 3 commits into from
Feb 8, 2025
Merged
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ internal static object CreateInstance(AppDomain appDomain, Type type, object?[]?
string? typeAssemblyLocation = type.Assembly.Location;
string? fullFilePath = typeAssemblyLocation == null ? null : Path.Combine(appDomain.SetupInformation.ApplicationBase, Path.GetFileName(typeAssemblyLocation));

EnsureAppDomainUsesCorrectUICulture(appDomain, CultureInfo.DefaultThreadCurrentUICulture);
EnsureRelevantStaticStateIsRestored(appDomain);

if (fullFilePath == null || File.Exists(fullFilePath))
{
Expand Down Expand Up @@ -241,22 +241,37 @@ internal static Version GetTargetFrameworkVersionFromVersionString(string versio
return DefaultVersion;
}

internal /* for testing purposes */ static void EnsureAppDomainUsesCorrectUICulture(AppDomain appDomain, CultureInfo uiCulture)
private static void EnsureRelevantStaticStateIsRestored(AppDomain appDomain)
{
// AppDomain is not preserving the culture info. So we need to set it explicitly.
// The overloads of CreateInstanceAndUnwrap that takes the culture info are actually not setting the culture
// of the AppDomain but only using this culture for the cast/conversion of the arguments.
// For the problem reported by vendors, we would only need to set the DefaultThreadCurrentUICulture as it's
// the culture we want to use for the resx.
Type cultureHelperType = typeof(AppDomainCultureHelper);
var appDomainCultureHelper = appDomain.CreateInstanceFromAndUnwrap(cultureHelperType.Assembly.Location, cultureHelperType.FullName) as AppDomainCultureHelper;
appDomainCultureHelper?.SetUICulture(uiCulture);
// AppDomain is not preserving the state static (by-design, as it's for isolation).
// However, there is some static state that we want to preserve, so we need to set it explicitly.
Type staticStateHelperType = typeof(StaticStateHelper);
var staticStateHelper = appDomain.CreateInstanceFromAndUnwrap(staticStateHelperType.Assembly.Location, staticStateHelperType.FullName) as StaticStateHelper;
staticStateHelper?.SetUICulture(CultureInfo.DefaultThreadCurrentUICulture);
staticStateHelper?.SetTestIdGenerationStrategy((int)DataRowAttribute.TestIdGenerationStrategy, (int)DynamicDataAttribute.TestIdGenerationStrategy);
}

private sealed class AppDomainCultureHelper : MarshalByRefObject
private sealed class StaticStateHelper : MarshalByRefObject
{
#pragma warning disable CA1822 // Mark members as static - Should not be static for our need
// The overloads of CreateInstanceAndUnwrap that takes the culture info are actually not setting the culture
// of the AppDomain but only using this culture for the cast/conversion of the arguments.
// For the problem reported by vendors, we would only need to set the DefaultThreadCurrentUICulture as it's
// the culture we want to use for the resx.
public void SetUICulture(CultureInfo uiCulture) => CultureInfo.DefaultThreadCurrentUICulture = uiCulture;

// Very early during discovery, we set TestIdGenerationStrategy static property.
// We want to preserve the values in the app domain where UnitTestRunner is created.
public void SetTestIdGenerationStrategy(
int dataRowTestIdGenerationStrategy,
int dynamicDataTestIdGenerationStrategy)
{
// Normally, these two properties should have the same value.
// But just in case they diverged for any reason, we just
// preserve whatever values in each correctly.
DataRowAttribute.TestIdGenerationStrategy = (TestIdGenerationStrategy)dataRowTestIdGenerationStrategy;
DynamicDataAttribute.TestIdGenerationStrategy = (TestIdGenerationStrategy)dynamicDataTestIdGenerationStrategy;
}
}
}

Expand Down
Loading