Search code examples
visual-studio-2010tfsbuildmstestcultureinfo

VSTS test deployment and invalid assembly culture


I have a DLL that I'm testing, which links to a DLL that has what I think is an invalid value for AssemblyCulture. The value is "Neutral" (notice the upper-case "N"), whereas the DLL I'm testing, and every other DLL in my project, has a value of "neutral" (because they specify AssemblyCulture("")).

When I try to deploy the DLL that links to the problem DLL, I get this error in VSTS:

Failed to queue test run '...': Culture is not supported.
Parameter name: name
Neutral is an invalid culture identifier.

<Exception>System.Globalization.CultureNotFoundException: Culture is not supported. Parameter name: name
Neutral is an invalid culture identifier.
   at System.Globalization.CultureInfo..ctor(String name, Boolean useUserOverride)
   at System.Globalization.CultureInfo..ctor(String name)
   at System.Reflection.RuntimeAssembly.GetReferencedAssemblies(RuntimeAssembly assembly)
   at System.Reflection.RuntimeAssembly.GetReferencedAssemblies()
   at Microsoft.VisualStudio.TestTools.Utility.AssemblyLoadWorker.ProcessChildren(Assembly assembly)
   at Microsoft.VisualStudio.TestTools.Utility.AssemblyLoadWorker.GetDependentAssemblies(String path)
   at Microsoft.VisualStudio.TestTools.Utility.AssemblyLoadWorker.GetDependentAssemblies(String path)
   at Microsoft.VisualStudio.TestTools.Utility.AssemblyLoadStrategy.GetDependentAssemblies(String path)
   at Microsoft.VisualStudio.TestTools.Utility.AssemblyHelper.GetDependentAssemblies(String path, DependentAssemblyOptions options, String configFile)
   at Microsoft.VisualStudio.TestTools.TestManagement.DeploymentManager.GetDependencies(String master, String configFile, TestRunConfiguration runConfig, DeploymentItemOrigin dependencyOrigin, List`1 dependencyDeploymentItems, Dictionary`2 missingDependentAssemblies)
   at Microsoft.VisualStudio.TestTools.TestManagement.DeploymentManager.DoDeployment(TestRun run, FileCopyService fileCopyService)
   at Microsoft.VisualStudio.TestTools.TestManagement.ControllerProxy.SetupTestRun(TestRun run, Boolean isNewTestRun, FileCopyService fileCopyService, DeploymentManager deploymentManager)
   at Microsoft.VisualStudio.TestTools.TestManagement.ControllerProxy.SetupRunAndListener(TestRun run, FileCopyService fileCopyService, DeploymentManager deploymentManager)
   at Microsoft.VisualStudio.TestTools.TestManagement.ControllerProxy.QueueTestRunWorker(Object state)</Exception>

Even if I don't link to the DLL (in my VSTS wrapper test, or in the NUnit test), as soon as I add it in my GenericTest file (I'm wrapping NUnit tests), I get that exception.

We don't have the source for the problem DLL, and it is also code signed, so I can't solve this by recompiling.

Is there a way to skip deploying the dependencies of a DLL DeploymentItem, to fix or disable the culture check, or to work around this by convoluted means (maybe somehow embed the assembly)? Is there a way to override the value for the culture, short of hacking the DLL (and removing code signing so the hack works)? Maybe with an external manifest?

Any correct solution must work without weird changes to production code. We can't deploy a hacked DLL, for example. It also must allow the DLL to be instrumented for code coverage.

Additional note: I do get a linker warning when compiling the DLL under test that links to the problem DLL, but this hasn't broken anything but VSTS, and multiple versions have shipped.


Solution

  • I found out that if I do instrumentation (which was the point of me even bothering with the NUnit VS integration), then I manage to avoid these problems. Not sure which exact combination of settings did the trick, but these are the settings I am using:

    • In-place instrumentation
    • The MSTest test project only has a dependency on the NUnit test project
    • The generic test deploys the NUnit test (from the MSTest bin output folder), the NUnit test app.config (from the NUnit test bin output folder), and the problem DLL. The rest of the dependencies, including the DLL under test, get deployed by code coverage.

    If you don't need instrumentation, I found this work-around:

    • Don't link to the top-level DLL that's causing a problem (in this case, the DLL under test)
    • Modify the solution build setting to make your project dependent on that project
    • Embed all DLLs in the dependency chain that are causing problems as Embedded Resources
    • During runtime, grab the resource stream for each DLL, create a file, and copy the stream across. Basically, extract the resources and output them again as files

    Write file from assembly resource stream to disk

    Then, there is no link-time dependency, so MSTest won't see those DLLs. This won't work well with instrumentation because the DLLs only appear at runtime, and MSTest wants to instrument during deploy time. It also won't work well if you actually have to link to those DLLs :) In my case, they derived from an abstract interface, which was free from the problem.