[release/6.0] Port test-only test fixes (#63507)
authorDan Moseley <danmose@microsoft.com>
Fri, 7 Jan 2022 23:33:19 +0000 (16:33 -0700)
committerGitHub <noreply@github.com>
Fri, 7 Jan 2022 23:33:19 +0000 (16:33 -0700)
* Outerloop ports

* Port EFS test fix

* Partially disable test (#59760)

* fix build

src/libraries/Common/tests/TestUtilities/System/PlatformDetection.Windows.cs
src/libraries/Common/tests/TestUtilities/System/WindowsIdentityFixture.cs
src/libraries/System.IO.FileSystem/tests/Enumeration/SpecialDirectoryTests.cs
src/libraries/System.IO.FileSystem/tests/File/EncryptDecrypt.Windows.cs [new file with mode: 0644]
src/libraries/System.IO.FileSystem/tests/File/EncryptDecrypt.cs
src/libraries/System.IO.FileSystem/tests/Net5CompatTests/System.IO.FileSystem.Net5Compat.Tests.csproj
src/libraries/System.IO.FileSystem/tests/System.IO.FileSystem.Tests.csproj
src/libraries/System.IO.Ports/tests/SerialPort/DosDevices.cs
src/libraries/System.Net.Http/tests/FunctionalTests/ImpersonatedAuthTests.cs
src/libraries/System.Net.Ping/tests/FunctionalTests/PingTest.cs
src/libraries/System.Security.Principal.Windows/tests/WindowsIdentityImpersonatedTests.netcoreapp.cs

index d5b2c36e961e0e2558f87122c4b6ac4b3485533e..cf5e4b86b87b8402f6e3b9f565e3038ddd96fef2 100644 (file)
@@ -234,6 +234,8 @@ namespace System
             }
         }
 
+        public static bool CanRunImpersonatedTests => PlatformDetection.IsNotWindowsNanoServer && PlatformDetection.IsWindowsAndElevated;
+
         private static int s_isWindowsElevated = -1;
         public static bool IsWindowsAndElevated
         {
index 360fbe68bb7ac4327d8f3ecbb0841a041a64d91c..b0355f923295e4a8c23371e1fc438f7bb527494f 100644 (file)
@@ -10,6 +10,7 @@ using System.Security.Cryptography;
 using System.Security.Principal;
 using System.Threading.Tasks;
 using Microsoft.Win32.SafeHandles;
+using Xunit;
 
 namespace System
 {
@@ -37,6 +38,8 @@ namespace System
 
         public WindowsTestAccount(string userName)
         {
+            Assert.True(PlatformDetection.IsWindowsAndElevated);
+
             _userName = userName;
             CreateUser();
         }
@@ -77,6 +80,10 @@ namespace System
                         throw new Win32Exception((int)result);
                     }
                 }
+                else if (result != 0)
+                {
+                    throw new Win32Exception((int)result);
+                }
 
                 const int LOGON32_PROVIDER_DEFAULT = 0;
                 const int LOGON32_LOGON_INTERACTIVE = 2;
index 39a747179481a86ef127b2d72b3f6ea72570517e..12edab6601e803277285907f35247ef680a28d60 100644 (file)
@@ -60,7 +60,14 @@ namespace System.IO.Tests.Enumeration
         {
             // Files that begin with periods are considered hidden on Unix
             string[] paths = GetNames(TestDirectory, new EnumerationOptions { ReturnSpecialDirectories = true, AttributesToSkip = 0 });
-            Assert.Contains(".", paths);
+
+            if (!PlatformDetection.IsWindows10Version22000OrGreater)
+            {
+                // Sometimes this is not returned - presumably an OS bug.
+                // This occurs often on Windows 11, very rarely otherwise.
+                Assert.Contains(".", paths);
+            }
+
             Assert.Contains("..", paths);
         }
     }
diff --git a/src/libraries/System.IO.FileSystem/tests/File/EncryptDecrypt.Windows.cs b/src/libraries/System.IO.FileSystem/tests/File/EncryptDecrypt.Windows.cs
new file mode 100644 (file)
index 0000000..015ba30
--- /dev/null
@@ -0,0 +1,85 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Microsoft.DotNet.XUnitExtensions;
+using System.Diagnostics;
+using System.Diagnostics.Eventing.Reader;
+using System.Linq;
+using System.Security;
+using System.ServiceProcess;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace System.IO.Tests
+{
+    public partial class EncryptDecrypt
+    {
+        partial void EnsureEFSServiceStarted()
+        {
+            try
+            {
+                using var sc = new ServiceController("EFS");
+                _output.WriteLine($"EFS service is: {sc.Status}");
+                if (sc.Status != ServiceControllerStatus.Running)
+                {
+                    _output.WriteLine("Trying to start EFS service");
+                    sc.Start();
+                    _output.WriteLine($"EFS service is now: {sc.Status}");
+                }
+            }
+            catch (Exception e)
+            {
+                _output.WriteLine(e.ToString());
+            }
+        }
+
+        partial void LogEFSDiagnostics()
+        {
+            int hours = 1; // how many hours to look backwards
+            string query = @$"
+                        <QueryList>
+                          <Query Id='0' Path='System'>
+                            <Select Path='System'>
+                                *[System[Provider/@Name='Server']]
+                            </Select>
+                            <Select Path='System'>
+                                *[System[Provider/@Name='Service Control Manager']]
+                            </Select>
+                            <Select Path='System'>
+                                *[System[Provider/@Name='Microsoft-Windows-EFS']]
+                            </Select>
+                            <Suppress Path='System'>
+                                *[System[TimeCreated[timediff(@SystemTime) &gt;= {hours * 60 * 60 * 1000L}]]]
+                            </Suppress>
+                          </Query>
+                        </QueryList> ";
+
+            var eventQuery = new EventLogQuery("System", PathType.LogName, query);
+
+            using var eventReader = new EventLogReader(eventQuery);
+
+            EventRecord record = eventReader.ReadEvent();
+            var garbage = new string[] { "Background Intelligent", "Intel", "Defender", "Intune", "BITS", "NetBT"};
+
+            _output.WriteLine("=====  Dumping recent relevant events: =====");
+            while (record != null)
+            {
+                string description = "";
+                try
+                {
+                    description = record.FormatDescription();
+                }
+                catch (EventLogException) { }
+
+                if (!garbage.Any(term => description.Contains(term, StringComparison.OrdinalIgnoreCase)))
+                {
+                    _output.WriteLine($"{record.TimeCreated} {record.ProviderName} [{record.LevelDisplayName} {record.Id}] {description.Replace("\r\n", "  ")}");
+                }
+
+                record = eventReader.ReadEvent();
+            }
+
+            _output.WriteLine("==== Finished dumping =====");
+        }
+    }
+}
index 984afef972bc41e38b6fef47afa1418029025cc9..1dbac453e4829748dcf756b0a0fb30316c011165 100644 (file)
@@ -1,17 +1,28 @@
 // Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 
+using Microsoft.DotNet.XUnitExtensions;
 using System.Diagnostics;
+using System.Diagnostics.Eventing.Reader;
 using System.Security;
+using System.ServiceProcess;
 using Xunit;
+using Xunit.Abstractions;
 
 namespace System.IO.Tests
 {
     [ActiveIssue("https://github.com/dotnet/runtime/issues/34582", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)]
-    public class EncryptDecrypt : FileSystemTest
+    public partial class EncryptDecrypt : FileSystemTest
     {
+        private readonly ITestOutputHelper _output;
+
+        public EncryptDecrypt(ITestOutputHelper output)
+        {
+            _output = output;
+        }
+
         [Fact]
-        public static void NullArg_ThrowsException()
+        public void NullArg_ThrowsException()
         {
             AssertExtensions.Throws<ArgumentNullException>("path", () => File.Encrypt(null));
             AssertExtensions.Throws<ArgumentNullException>("path", () => File.Decrypt(null));
@@ -19,7 +30,7 @@ namespace System.IO.Tests
 
         [SkipOnTargetFramework(TargetFrameworkMonikers.Netcoreapp)]
         [Fact]
-        public static void EncryptDecrypt_NotSupported()
+        public void EncryptDecrypt_NotSupported()
         {
             Assert.Throws<PlatformNotSupportedException>(() => File.Encrypt("path"));
             Assert.Throws<PlatformNotSupportedException>(() => File.Decrypt("path"));
@@ -29,7 +40,8 @@ namespace System.IO.Tests
         // because EFS (Encrypted File System), its underlying technology, is not available on these operating systems.
         [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindowsNanoServer), nameof(PlatformDetection.IsNotWindowsHomeEdition))]
         [PlatformSpecific(TestPlatforms.Windows)]
-        public static void EncryptDecrypt_Read()
+        [OuterLoop] // Occasional failures: https://github.com/dotnet/runtime/issues/12339
+        public void EncryptDecrypt_Read()
         {
             string tmpFileName = Path.GetTempFileName();
             string textContentToEncrypt = "Content to encrypt";
@@ -39,14 +51,26 @@ namespace System.IO.Tests
                 string fileContentRead = File.ReadAllText(tmpFileName);
                 Assert.Equal(textContentToEncrypt, fileContentRead);
 
+                EnsureEFSServiceStarted();
+
                 try
                 {
                     File.Encrypt(tmpFileName);
                 }
-                catch (IOException e) when (e.HResult == unchecked((int)0x80070490))
+                catch (IOException e) when (e.HResult == unchecked((int)0x80070490) ||
+                                            e.HResult == unchecked((int)0x80071776) ||
+                                            e.HResult == unchecked((int)0x800701AE))
                 {
                     // Ignore ERROR_NOT_FOUND 1168 (0x490). It is reported when EFS is disabled by domain policy.
-                    return;
+                    // Ignore ERROR_NO_USER_KEYS (0x1776). This occurs when no user key exists to encrypt with.
+                    // Ignore ERROR_ENCRYPTION_DISABLED (0x1AE). This occurs when EFS is disabled by group policy on the volume.
+                    throw new SkipTestException($"Encrypt not available. Error 0x{e.HResult:X}");
+                }
+                catch (IOException e)
+                {
+                    _output.WriteLine($"Encrypt failed with {e.Message} 0x{e.HResult:X}");
+                    LogEFSDiagnostics();
+                    throw;
                 }
 
                 Assert.Equal(fileContentRead, File.ReadAllText(tmpFileName));
@@ -61,5 +85,9 @@ namespace System.IO.Tests
                 File.Delete(tmpFileName);
             }
         }
+
+        partial void EnsureEFSServiceStarted(); // no-op on Unix
+
+        partial void LogEFSDiagnostics(); // no-op on Unix currently
     }
 }
index 438e076c3e778e59ea10bf39e5d7057f2022b649..385c3afb569c49d072e2ea3bd3b842894dee5452 100644 (file)
@@ -32,6 +32,7 @@
     <Compile Include="$(CommonPath)System\Text\ValueStringBuilder.cs" Link="Common\System\Text\ValueStringBuilder.cs" />
     <Compile Include="$(CoreLibSharedDir)System\IO\PathInternal.cs" Link="Common\System\IO\PathInternal.cs" />
     <Compile Include="$(CoreLibSharedDir)System\IO\PathInternal.Windows.cs" Link="Common\System\IO\PathInternal.Windows.cs" />
+    <ProjectReference Include="$(LibrariesProjectRoot)System.ServiceProcess.ServiceController\src\System.ServiceProcess.ServiceController.csproj" />
   </ItemGroup>
   <ItemGroup Condition="'$(TargetsBrowser)' == 'true'">
     <Compile Remove="..\**\*.Unix.cs" />
index 1ffb30f887c2465e010f3a8351c27833ba81a2d4..4c8fa1c23be5b88ce8bd1b86604a84a9c4b07c8d 100644 (file)
@@ -77,6 +77,7 @@
   <ItemGroup Condition="'$(TargetsWindows)' == 'true'">
     <Compile Include="Base\SymbolicLinks\BaseSymbolicLinks.Windows.cs" />
     <Compile Include="Directory\Delete.Windows.cs" />
+    <Compile Include="File\EncryptDecrypt.Windows.cs" />
     <Compile Include="FileSystemTest.Windows.cs" />
     <Compile Include="FileStream\ctor_options.Windows.cs" />
     <Compile Include="FileStream\FileStreamConformanceTests.Windows.cs" />
index 3fe9493c0a30e51c3e0d8abd1ef74e6c7837313d..2d74327f97eb0d29d4032d05901701862be4bf3b 100644 (file)
@@ -3,6 +3,7 @@
 
 using System.Collections;
 using System.Collections.Generic;
+using System.ComponentModel;
 using System.Runtime.InteropServices;
 
 namespace System.IO.Ports.Tests
@@ -127,14 +128,20 @@ namespace System.IO.Ports.Tests
                     buffer = new char[buffer.Length * 2];
                     dataSize = QueryDosDevice(null, buffer, buffer.Length);
                 }
+                else if (lastError == ERROR_ACCESS_DENIED) // Access denied eg for "MSSECFLTSYS" - just skip
+                {
+                    dataSize = 0;
+                    break;
+                }
                 else
                 {
-                    throw new Exception("Unknown Win32 Error: " + lastError);
+                    throw new Exception($"Error {lastError} calling QueryDosDevice for '{name}' with buffer size {buffer.Length}. {new Win32Exception((int)lastError).Message}");
                 }
             }
             return buffer;
         }
 
+        public const int ERROR_ACCESS_DENIED = 5;
         public const int ERROR_INSUFFICIENT_BUFFER = 122;
         public const int ERROR_MORE_DATA = 234;
 
index 6b56d3590d9ad0076215214068685311a0339084..32f44d5e00f705ab18c25aebd09ba89313ced963 100644 (file)
@@ -14,7 +14,6 @@ namespace System.Net.Http.Functional.Tests
 {
     public class ImpersonatedAuthTests: IClassFixture<WindowsIdentityFixture>
     {
-        public static bool CanRunImpersonatedTests = PlatformDetection.IsWindows && PlatformDetection.IsNotWindowsNanoServer;
         private readonly WindowsIdentityFixture _fixture;
         private readonly ITestOutputHelper _output;
 
@@ -28,11 +27,11 @@ namespace System.Net.Http.Functional.Tests
         }
 
         [OuterLoop]
-        [ConditionalTheory(nameof(CanRunImpersonatedTests))]
+        [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.CanRunImpersonatedTests))]
         [InlineData(true)]
         [InlineData(false)]
         [PlatformSpecific(TestPlatforms.Windows)]
-        public async Task DefaultHandler_ImpersonificatedUser_Success(bool useNtlm)
+        public async Task DefaultHandler_ImpersonatedUser_Success(bool useNtlm)
         {
             await LoopbackServer.CreateClientAndServerAsync(
                 async uri =>
index b206e1e0f165d98b6d16a7f8607402d24d2023f5..32ef250d8657ebb9323bc7fa4d1d99c0d1f04acc 100644 (file)
@@ -878,7 +878,9 @@ namespace System.Net.NetworkInformation.Tests
             options.Ttl = 1;
             // This should always fail unless host is one IP hop away.
             pingReply = await ping.SendPingAsync(host, TestSettings.PingTimeout, TestSettings.PayloadAsBytesShort, options);
-            Assert.NotEqual(IPStatus.Success, pingReply.Status);
+
+            Assert.True(pingReply.Status == IPStatus.TimeExceeded || pingReply.Status == IPStatus.TtlExpired);
+            Assert.NotEqual(IPAddress.Any, pingReply.Address);
         }
 
         [Fact]
index 4bfb059d708c8c8bfb1b4518f5aa1c995ae666f3..0a7c1745ed9f427a5950db3312522b1d7c39f604 100644 (file)
@@ -26,7 +26,7 @@ public class WindowsIdentityImpersonatedTests : IClassFixture<WindowsIdentityFix
         Assert.False(string.IsNullOrEmpty(_fixture.TestAccount.AccountName));
     }
 
-    [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindowsNanoServer))]
+    [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.CanRunImpersonatedTests))]
     [OuterLoop]
     public async Task RunImpersonatedAsync_TaskAndTaskOfT()
     {
@@ -60,7 +60,7 @@ public class WindowsIdentityImpersonatedTests : IClassFixture<WindowsIdentityFix
         }
     }
 
-    [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindowsNanoServer))]
+    [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.CanRunImpersonatedTests))]
     [OuterLoop]
     public void RunImpersonated_NameResolution()
     {
@@ -78,7 +78,7 @@ public class WindowsIdentityImpersonatedTests : IClassFixture<WindowsIdentityFix
         });
     }
 
-    [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindowsNanoServer))]
+    [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.CanRunImpersonatedTests))]
     [OuterLoop]
     public async Task RunImpersonatedAsync_NameResolution()
     {