diff --git a/.travis.yml b/.travis.yml index b5c143a43..12c6eae38 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,6 +19,7 @@ before_install: script: - powershell -c "Import-Module ./PowerShellGitHubDev.psm1; Start-PSBuild" - ./pester.sh + - ./xunit.sh notifications: slack: secure: sKYd4n61+ZFzGZuWGUl8V1kN0NM16wRVOFVlNhlFCwnkrEsKROb++EvXf5uwnKuzxkhEjvPWO+UFgeshQDoR93y4s5YLfhC5JupK4nUzjPzWs208KTrh8u/x9MY8X6Ojxi85EEAiku5GzMoMlkucSStZUYwbIfnelzqdw8uoRwmm2MW4XCPwsuEuDUVghyiva0Mdx1G6MopCrK8T96WywJXT3chhfZQgVt+sQCBt9g+2kjDaObKrzG0P07IVK43ZpDgnu6AoxlyBzIx9mJH2Oa/tki3/kTO72Wcp3ps3qvmiStADamzVKR9p1VlWCLWAd6VOehxuByCGEyujpzk135Wud2DZYO+8LD6inZVhFe3Wt5pCU9BDXZppiATfMCqgXEH7nK54pEn79yHcjthRJ2+Z9ot7As2fu3RSBmTAi8nRP0fxRyX/jctR3S6P0qt0y1ynx9nzBfhmhPQW0PMVazWS/nruQIvK/3iiYXjZxM5bBwIvabmwV00EYeTdbL6ufXWNgQcG1ZWkDsi2I3vst/ytUbHwaFYg83bXWpxg9DCzJeWLVUvE5/3NfBxRAuCTot/fgTEA9IYScvrlL7Q/bT0cOt0vEM98MPf1UO+WP85uxhsRgHtwDEo+jMaL6ZFkPhlV6mmmED4NdY2//a571cLNXdnuMAze5O3TWGBG53g= diff --git a/test/csharp/README.md b/test/csharp/README.md new file mode 100644 index 000000000..cb7983fbb --- /dev/null +++ b/test/csharp/README.md @@ -0,0 +1,13 @@ +# xUnit Tests + +This tests are completely Linux specific. + +Every test class *must* belong to +`[Collection("AssemblyLoadContext")]`. This ensures that PowerShell's +AssemblyLoadContext is initialized before any other code is executed. +When this is not the case, late initialization fails with +`System.InvalidOperationException : Binding model is already locked +for the AppDomain and cannot be reset.` + +Having every class in the same collection is as close to an xUnit +global init hook as can be done. diff --git a/test/csharp/fixture_AssemblyLoadContext.cs b/test/csharp/fixture_AssemblyLoadContext.cs new file mode 100644 index 000000000..71362729e --- /dev/null +++ b/test/csharp/fixture_AssemblyLoadContext.cs @@ -0,0 +1,26 @@ +using Xunit; +using System; +using System.Management.Automation; +using Microsoft.PowerShell.Linux.Host; + +// This collection fixture initializes Core PowerShell's AssemblyLoadContext once and only +// once. Attempting to initialize in a class level fixture will cause multiple +// initializations, resulting in test failure due to "Binding model is already locked for +// the AppDomain and cannot be reset". +namespace PSTests +{ + public class AssemblyLoadContextFixture + { + public AssemblyLoadContextFixture() + { + // Initialize the Core PowerShell AssemblyLoadContext + PowerShellAssemblyLoadContextInitializer.SetPowerShellAssemblyLoadContext(AppContext.BaseDirectory); + } + } + + [CollectionDefinition("AssemblyLoadContext")] + public class AssemblyLoadContextCollection : ICollectionFixture + { + // nothing to do but satisfy the interface + } +} diff --git a/test/csharp/test_Binders.cs b/test/csharp/test_Binders.cs index 6f5a8f7d1..91dc76d25 100644 --- a/test/csharp/test_Binders.cs +++ b/test/csharp/test_Binders.cs @@ -4,6 +4,7 @@ using System.Management.Automation.Language; namespace PSTests { + [Collection("AssemblyLoadContext")] public static class PSEnumerableBinderTests { [Fact] diff --git a/test/csharp/test_CorePsExtensions.cs b/test/csharp/test_CorePsExtensions.cs index 2a736d7f9..97d2ee50f 100644 --- a/test/csharp/test_CorePsExtensions.cs +++ b/test/csharp/test_CorePsExtensions.cs @@ -4,6 +4,7 @@ using System.Management.Automation; namespace PSTests { + [Collection("AssemblyLoadContext")] public static class CorePsExtensionsTests { [Fact] diff --git a/test/csharp/test_CorePsPlatform.cs b/test/csharp/test_CorePsPlatform.cs index 7196862eb..e36f5aa4f 100644 --- a/test/csharp/test_CorePsPlatform.cs +++ b/test/csharp/test_CorePsPlatform.cs @@ -6,6 +6,7 @@ using System.Management.Automation; namespace PSTests { + [Collection("AssemblyLoadContext")] public static class PlatformTests { [Fact] diff --git a/test/csharp/test_ExtensionMethods.cs b/test/csharp/test_ExtensionMethods.cs index e22de8be5..134f94b28 100644 --- a/test/csharp/test_ExtensionMethods.cs +++ b/test/csharp/test_ExtensionMethods.cs @@ -4,6 +4,7 @@ using System.Management.Automation; namespace PSTests { + [Collection("AssemblyLoadContext")] public static class PSTypeExtensionsTests { [Fact] diff --git a/test/csharp/test_FileSystemProvider.cs b/test/csharp/test_FileSystemProvider.cs index 2bdcacbfc..7c33910d8 100644 --- a/test/csharp/test_FileSystemProvider.cs +++ b/test/csharp/test_FileSystemProvider.cs @@ -5,6 +5,7 @@ using Microsoft.PowerShell.Commands; namespace PSTests { + [Collection("AssemblyLoadContext")] public static class FileSystemProviderTests { [Fact] diff --git a/test/csharp/test_MshSnapinInfo.cs b/test/csharp/test_MshSnapinInfo.cs index a283e7995..8a14afb89 100644 --- a/test/csharp/test_MshSnapinInfo.cs +++ b/test/csharp/test_MshSnapinInfo.cs @@ -5,6 +5,7 @@ using System.Management.Automation; namespace PSTests { // Not static because a test requires non-const variables + [Collection("AssemblyLoadContext")] public class MshSnapinInfoTests { // Test that it does not throw an exception diff --git a/test/csharp/test_PSVersionInfo.cs b/test/csharp/test_PSVersionInfo.cs index ef980475e..5bd7acb82 100644 --- a/test/csharp/test_PSVersionInfo.cs +++ b/test/csharp/test_PSVersionInfo.cs @@ -4,6 +4,7 @@ using System.Management.Automation; namespace PSTests { + [Collection("AssemblyLoadContext")] public static class PSVersionInfoTests { [Fact] diff --git a/test/csharp/test_Runspace.cs b/test/csharp/test_Runspace.cs index 96dbe6355..0a7b00eb9 100644 --- a/test/csharp/test_Runspace.cs +++ b/test/csharp/test_Runspace.cs @@ -9,17 +9,12 @@ namespace PSTests // NOTE: do not call AddCommand("out-host") after invoking or MergeMyResults, // otherwise Invoke will not return any objects + [Collection("AssemblyLoadContext")] public class RunspaceTests { private static int count = 3; private static string script = String.Format($"get-process | select-object -first {count}"); - // Initialize the Core PowerShell AssemblyLoadContext - public RunspaceTests() - { - PowerShellAssemblyLoadContextInitializer.SetPowerShellAssemblyLoadContext(AppContext.BaseDirectory); - } - [Fact] public void TestRunspaceWithPipeline() { diff --git a/test/csharp/test_SecuritySupport.cs b/test/csharp/test_SecuritySupport.cs index 962dc6670..33c336308 100644 --- a/test/csharp/test_SecuritySupport.cs +++ b/test/csharp/test_SecuritySupport.cs @@ -4,6 +4,7 @@ using System.Management.Automation; namespace PSTests { + [Collection("AssemblyLoadContext")] public static class SecuritySupportTests { [Fact] diff --git a/test/csharp/test_Utils.cs b/test/csharp/test_Utils.cs index eb5167780..65ded34f6 100644 --- a/test/csharp/test_Utils.cs +++ b/test/csharp/test_Utils.cs @@ -4,6 +4,7 @@ using System.Management.Automation; namespace PSTests { + [Collection("AssemblyLoadContext")] public static class UtilsTests { [Fact] diff --git a/xunit.sh b/xunit.sh index 6b0a7c7d5..a8038da49 100755 --- a/xunit.sh +++ b/xunit.sh @@ -20,9 +20,12 @@ popd # Run xUnit tests pushd test/csharp ## Build -dotnet build +dotnet build -c Linux ## Work-around dotnet/cli#753 -cp -r ../../src/Microsoft.PowerShell.Linux.Host/{Modules,*ps1xml} bin/Debug/netstandardapp1.5/ubuntu.14.04-x64 +cp -r ../../src/Microsoft.PowerShell.Linux.Host/{Modules,*ps1xml} bin/Linux/netstandardapp1.5/ubuntu.14.04-x64 ## Test -dotnet test +dotnet test -c Linux +result=$? popd + +exit $result