Fix ServiceController test (#57116)
authorDan Moseley <danmose@microsoft.com>
Tue, 10 Aug 2021 13:47:40 +0000 (07:47 -0600)
committerGitHub <noreply@github.com>
Tue, 10 Aug 2021 13:47:40 +0000 (07:47 -0600)
src/libraries/System.ServiceProcess.ServiceController/src/System/ServiceProcess/ServiceController.cs
src/libraries/System.ServiceProcess.ServiceController/tests/ServiceBaseTests.cs
src/libraries/System.ServiceProcess.ServiceController/tests/ServiceControllerTests.cs
src/libraries/System.ServiceProcess.ServiceController/tests/ServiceControllerTests.netcoreapp.cs
src/libraries/System.ServiceProcess.ServiceController/tests/System.ServiceProcess.ServiceController.TestService/TestService.cs
src/libraries/System.ServiceProcess.ServiceController/tests/System.ServiceProcess.ServiceController.TestService/TestServiceInstaller.cs
src/libraries/System.ServiceProcess.ServiceController/tests/TestServiceProvider.cs

index 64725f9..e72f882 100644 (file)
@@ -283,7 +283,7 @@ namespace System.ServiceProcess
         }
 
         /// <summary>
-        /// A set of services on which the given service object is depend upon.
+        /// A set of services on which the given service object is dependent upon.
         /// </summary>
         public unsafe ServiceController[] ServicesDependedOn
         {
index 00bcc38..c2af5df 100644 (file)
@@ -183,7 +183,7 @@ namespace System.ServiceProcess.Tests
         public void LogWritten()
         {
             string serviceName = Guid.NewGuid().ToString();
-            // If the username is null, then the service is created under LocalSystem Account which have access to EventLog.
+            // If the username is null, then the service is created under LocalSystem Account which has access to EventLog.
             var testService = new TestServiceProvider(serviceName);
             Assert.True(EventLog.SourceExists(serviceName));
             testService.DeleteTestServices();
index 1f0ead8..8a73b2d 100644 (file)
@@ -148,18 +148,16 @@ namespace System.ServiceProcess.Tests
         [ConditionalFact(nameof(IsProcessElevated))]
         public void Dependencies()
         {
-            // The test service creates a number of dependent services, each of which is depended on
-            // by all the services created after it.
             var controller = new ServiceController(_testService.TestServiceName);
             Assert.Equal(0, controller.DependentServices.Length);
             Assert.Equal(1, controller.ServicesDependedOn.Length);
 
-            var dependentController = new ServiceController(_testService.TestServiceName + ".Dependent");
-            Assert.Equal(1, dependentController.DependentServices.Length);
-            Assert.Equal(0, dependentController.ServicesDependedOn.Length);
+            var prerequisiteServiceController = new ServiceController(_testService.TestServiceName + ".Prerequisite");
+            Assert.Equal(1, prerequisiteServiceController.DependentServices.Length);
+            Assert.Equal(0, prerequisiteServiceController.ServicesDependedOn.Length);
 
-            Assert.Equal(controller.ServicesDependedOn[0].ServiceName, dependentController.ServiceName);
-            Assert.Equal(dependentController.DependentServices[0].ServiceName, controller.ServiceName);
+            Assert.Equal(controller.ServicesDependedOn[0].ServiceName, prerequisiteServiceController.ServiceName);
+            Assert.Equal(prerequisiteServiceController.DependentServices[0].ServiceName, controller.ServiceName);
         }
 
         [ConditionalFact(nameof(IsProcessElevated))]
@@ -168,7 +166,7 @@ namespace System.ServiceProcess.Tests
             var controller = new ServiceController(_testService.TestServiceName);
             Assert.Equal(ServiceStartMode.Manual, controller.StartType);
 
-            // Check for the startType of the dependent services.
+            // Check for the startType of the services that depend on the test service
             for (int i = 0; i < controller.DependentServices.Length; i++)
             {
                 Assert.Equal(ServiceStartMode.Disabled, controller.DependentServices[i].StartType);
index 9b78dfe..687fd26 100644 (file)
@@ -12,8 +12,15 @@ namespace System.ServiceProcess.Tests
         public void Stop_FalseArg_WithDependentServices_ThrowsInvalidOperationException()
         {
             var controller = new ServiceController(_testService.TestServiceName);
-            controller.WaitForStatus(ServiceControllerStatus.Running, _testService.ControlTimeout);
-            Assert.Throws<InvalidOperationException>(() => controller.Stop(stopDependentServices: false));
+            Assert.Equal(0, controller.DependentServices.Length);
+            Assert.Equal(1, controller.ServicesDependedOn.Length);
+
+            var prerequisiteServiceController = new ServiceController(_testService.TestServiceName + ".Prerequisite");
+            Assert.Equal(1, prerequisiteServiceController.DependentServices.Length);
+            Assert.Equal(0, prerequisiteServiceController.ServicesDependedOn.Length);
+
+            prerequisiteServiceController.WaitForStatus(ServiceControllerStatus.Running, _testService.ControlTimeout);
+            Assert.Throws<InvalidOperationException>(() => prerequisiteServiceController.Stop(stopDependentServices: false));
         }
 
         [ConditionalFact(nameof(IsProcessElevated))]
@@ -35,6 +42,7 @@ namespace System.ServiceProcess.Tests
             var controller = new ServiceController(_testService.TestServiceName);
             controller.WaitForStatus(ServiceControllerStatus.Running, _testService.ControlTimeout);
 
+            // stop the services that depend on this service
             foreach (var dependentService in controller.DependentServices)
             {
                 dependentService.Stop(stopDependentServices: false);
index 26aea98..5f0cad1 100644 (file)
@@ -12,7 +12,7 @@ namespace System.ServiceProcess.Tests
         // To view tracing, use DbgView from sysinternals.com;
         // run it elevated, check "Capture>Global Win32" and "Capture>Win32",
         // and filter to just messages beginning with "##"
-        internal const bool DebugTracing = false;
+        internal const bool DebugTracing = false; // toggle in TestServiceProvider.cs as well
 
         private bool _disposed;
         private Task _waitClientConnect;
index daad7d2..5ae0d06 100644 (file)
@@ -31,6 +31,7 @@ namespace System.ServiceProcess.Tests
 
         public string ServiceCommandLine { get; set; }
 
+        // Install and start the test service, after starting any prerequisite services it depends on
         public unsafe void Install()
         {
             string username = Username;
@@ -53,6 +54,7 @@ namespace System.ServiceProcess.Tests
             }
 
             // Build servicesDependedOn string
+            // These are prerequisite services that must be started before this service
             string servicesDependedOn = null;
             if (ServicesDependedOn.Length > 0)
             {
@@ -75,6 +77,8 @@ namespace System.ServiceProcess.Tests
                 if (serviceManagerHandle.IsInvalid)
                     throw new InvalidOperationException("Cannot open Service Control Manager");
 
+                TestService.DebugTrace($"TestServiceInstaller: creating service {ServiceName} with prerequisite services {servicesDependedOn}");
+
                 // Install the service
                 using (var serviceHandle = new SafeServiceHandle(Interop.Advapi32.CreateService(serviceManagerHandle, ServiceName,
                     DisplayName, Interop.Advapi32.ServiceAccessOptions.ACCESS_TYPE_ALL, Interop.Advapi32.ServiceTypeOptions.SERVICE_TYPE_WIN32_OWN_PROCESS,
@@ -102,11 +106,15 @@ namespace System.ServiceProcess.Tests
                     {
                         if (svc.Status != ServiceControllerStatus.Running)
                         {
-                            TestService.DebugTrace("TestServiceInstaller: instructing ServiceController to Start service " + ServiceName);
+                            TestService.DebugTrace($"TestServiceInstaller: instructing ServiceController to start service {ServiceName}");
                             svc.Start();
                             if (!ServiceName.StartsWith("PropagateExceptionFromOnStart"))
                                 svc.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromSeconds(120));
                         }
+                        else
+                        {
+                            TestService.DebugTrace("TestServiceInstaller: service {ServiceName} already running");
+                        }
                     }
                 }
             }
index 1128d2b..4ea0bda 100644 (file)
@@ -13,7 +13,7 @@ namespace System.ServiceProcess.Tests
         // To view tracing, use DbgView from sysinternals.com;
         // run it elevated, check "Capture>Global Win32" and "Capture>Win32",
         // and filter to just messages beginning with "##"
-        internal const bool DebugTracing = false;
+        internal const bool DebugTracing = false; // toggle in TestService.cs as well
 
         private const int readTimeout = 60000;
 
@@ -56,7 +56,9 @@ namespace System.ServiceProcess.Tests
         public readonly string TestServiceName;
         public readonly string TestServiceDisplayName;
 
-        private readonly TestServiceProvider _dependentServices;
+        private readonly TestServiceProvider _prerequisiteServices;
+
+        // Creates a test service with a prerequisite service
         public TestServiceProvider()
         {
             TestMachineName = ".";
@@ -64,19 +66,20 @@ namespace System.ServiceProcess.Tests
             TestServiceName = Guid.NewGuid().ToString();
             TestServiceDisplayName = "Test Service " + TestServiceName;
 
-            _dependentServices = new TestServiceProvider(TestServiceName + ".Dependent");
+            _prerequisiteServices = new TestServiceProvider(TestServiceName + ".Prerequisite");
 
             // Create the service
             CreateTestServices();
         }
 
+        // Creates a test service with no prerequisite services
         public TestServiceProvider(string serviceName)
         {
             TestMachineName = ".";
             ControlTimeout = TimeSpan.FromSeconds(120);
             TestServiceName = serviceName;
             TestServiceDisplayName = "Test Service " + TestServiceName;
-            
+
             // Create the service
             CreateTestServices();
         }
@@ -94,6 +97,7 @@ namespace System.ServiceProcess.Tests
 
         private void CreateTestServices()
         {
+            DebugTrace($"TestServiceProvider: Creating test service {TestServiceName}");
             TestServiceInstaller testServiceInstaller = new TestServiceInstaller();
 
             testServiceInstaller.ServiceName = TestServiceName;
@@ -101,9 +105,10 @@ namespace System.ServiceProcess.Tests
             testServiceInstaller.Description = "__Dummy Test Service__";
             testServiceInstaller.Username = null;
 
-            if (_dependentServices != null)
+            if (_prerequisiteServices != null)
             {
-                testServiceInstaller.ServicesDependedOn = new string[] { _dependentServices.TestServiceName };
+                DebugTrace($"TestServiceProvider: .. with prequisite services {_prerequisiteServices.TestServiceName}");
+                testServiceInstaller.ServicesDependedOn = new string[] { _prerequisiteServices.TestServiceName };
             }
 
             string processName = Process.GetCurrentProcess().MainModule.FileName;
@@ -122,8 +127,9 @@ namespace System.ServiceProcess.Tests
             }
 
             testServiceInstaller.ServiceCommandLine = $"\"{processName}\" {arguments}";
-
+            DebugTrace($"TestServiceProvider: Executing {testServiceInstaller.ServiceCommandLine}");
             testServiceInstaller.Install();
+            DebugTrace("TestServiceProvider: Completed install of test service");
         }
 
         public void DeleteTestServices()
@@ -140,14 +146,16 @@ namespace System.ServiceProcess.Tests
                 TestServiceInstaller testServiceInstaller = new TestServiceInstaller();
                 testServiceInstaller.ServiceName = TestServiceName;
                 testServiceInstaller.RemoveService();
+                DebugTrace("TestServiceProvider: Removed test service");
             }
             finally
             {
-                // Lets be sure to try and clean up dependenct services even if something goes
+                // Lets be sure to try and clean up prerequisite services even if something goes
                 // wrong with the full removal of the other service.
-                if (_dependentServices != null)
+                if (_prerequisiteServices != null)
                 {
-                    _dependentServices.DeleteTestServices();
+                    _prerequisiteServices.DeleteTestServices();
+                    DebugTrace("TestServiceProvider: Deleted test services");
                 }
             }
         }