Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit c78d3d4

Browse files
authored
ServiceBase And ServiceController Tests using NamedPipes (#26524)
ServiceBase And ServiceController tests using NamedPipes
1 parent bcc2940 commit c78d3d4

File tree

6 files changed

+180
-108
lines changed

6 files changed

+180
-108
lines changed

src/System.ServiceProcess.ServiceController/tests/ServiceBaseTests.cs

Lines changed: 37 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System.Diagnostics;
88
using System.Security.Principal;
99
using Xunit;
10+
using System.Threading.Tasks;
1011

1112
/// <summary>
1213
/// NOTE: All tests checking the output file should always call Stop before checking because Stop will flush the file to disk.
@@ -16,6 +17,7 @@ namespace System.ServiceProcess.Tests
1617
[OuterLoop(/* Modifies machine state */)]
1718
public class ServiceBaseTests : IDisposable
1819
{
20+
private const int connectionTimeout = 30000;
1921
private readonly TestServiceProvider _testService;
2022

2123
private static readonly Lazy<bool> s_isElevated = new Lazy<bool>(() => AdminHelpers.IsProcessElevated());
@@ -75,104 +77,102 @@ public void Cleanup()
7577
[ConditionalFact(nameof(IsProcessElevated))]
7678
public void TestOnStartThenStop()
7779
{
80+
_testService.Client.Connect(connectionTimeout);
7881
var controller = new ServiceController(_testService.TestServiceName);
7982
AssertExpectedProperties(controller);
80-
string expected =
81-
@"OnStart args=
82-
OnStop
83-
";
83+
8484
controller.Stop();
85+
Assert.Equal((int)PipeMessageByteCode.Stop, _testService.GetByte());
8586
controller.WaitForStatus(ServiceControllerStatus.Stopped);
86-
Assert.Equal(expected, _testService.GetServiceOutput());
8787
}
8888

8989
[ConditionalFact(nameof(IsProcessElevated))]
9090
public void TestOnStartWithArgsThenStop()
9191
{
9292
var controller = new ServiceController(_testService.TestServiceName);
93+
_testService.Client.Connect(connectionTimeout);
9394
AssertExpectedProperties(controller);
95+
9496
controller.Stop();
97+
Assert.Equal((int)PipeMessageByteCode.Stop, _testService.GetByte());
9598
controller.WaitForStatus(ServiceControllerStatus.Stopped);
9699

97-
string expected =
98-
@"OnStart args=a,b,c
99-
OnStop
100-
";
101-
controller.Start(new string[] { "a", "b", "c" });
100+
controller.Start(new string[] { "StartWithArguments", "a", "b", "c" });
101+
_testService.Client = null;
102+
_testService.Client.Connect();
103+
104+
Assert.Equal((int)PipeMessageByteCode.Start, _testService.GetByte());
102105
controller.WaitForStatus(ServiceControllerStatus.Running);
106+
103107
controller.Stop();
108+
Assert.Equal((int)PipeMessageByteCode.Stop, _testService.GetByte());
104109
controller.WaitForStatus(ServiceControllerStatus.Stopped);
105-
Assert.Equal(expected, _testService.GetServiceOutput());
106110
}
107111

108112
[ConditionalFact(nameof(IsProcessElevated))]
109113
public void TestOnPauseThenStop()
110114
{
115+
_testService.Client.Connect(connectionTimeout);
111116
var controller = new ServiceController(_testService.TestServiceName);
112117
AssertExpectedProperties(controller);
113-
string expected =
114-
@"OnStart args=
115-
OnPause
116-
OnStop
117-
";
118+
118119
controller.Pause();
120+
Assert.Equal((int)PipeMessageByteCode.Pause, _testService.GetByte());
119121
controller.WaitForStatus(ServiceControllerStatus.Paused);
122+
120123
controller.Stop();
124+
Assert.Equal((int)PipeMessageByteCode.Stop, _testService.GetByte());
121125
controller.WaitForStatus(ServiceControllerStatus.Stopped);
122-
Assert.Equal(expected, _testService.GetServiceOutput());
123126
}
124127

125128
[ConditionalFact(nameof(IsProcessElevated))]
126129
public void TestOnPauseAndContinueThenStop()
127130
{
131+
_testService.Client.Connect(connectionTimeout);
128132
var controller = new ServiceController(_testService.TestServiceName);
129133
AssertExpectedProperties(controller);
130-
string expected =
131-
@"OnStart args=
132-
OnPause
133-
OnContinue
134-
OnStop
135-
";
134+
136135
controller.Pause();
136+
Assert.Equal((int)PipeMessageByteCode.Pause, _testService.GetByte());
137137
controller.WaitForStatus(ServiceControllerStatus.Paused);
138+
138139
controller.Continue();
140+
Assert.Equal((int)PipeMessageByteCode.Continue, _testService.GetByte());
139141
controller.WaitForStatus(ServiceControllerStatus.Running);
142+
140143
controller.Stop();
144+
Assert.Equal((int)PipeMessageByteCode.Stop, _testService.GetByte());
141145
controller.WaitForStatus(ServiceControllerStatus.Stopped);
142-
Assert.Equal(expected, _testService.GetServiceOutput());
143146
}
144147

145148
[ConditionalFact(nameof(IsProcessElevated))]
146149
public void TestOnExecuteCustomCommand()
147150
{
151+
_testService.Client.Connect(connectionTimeout);
148152
var controller = new ServiceController(_testService.TestServiceName);
149153
AssertExpectedProperties(controller);
150-
string expected =
151-
@"OnStart args=
152-
OnCustomCommand command=128
153-
OnStop
154-
";
154+
155155
controller.ExecuteCommand(128);
156-
controller.WaitForStatus(ServiceControllerStatus.Running);
156+
Assert.Equal(128, _testService.GetByte());
157+
157158
controller.Stop();
159+
Assert.Equal((int)PipeMessageByteCode.Stop, _testService.GetByte());
158160
controller.WaitForStatus(ServiceControllerStatus.Stopped);
159-
Assert.Equal(expected, _testService.GetServiceOutput());
160161
}
161162

162163
[ConditionalFact(nameof(IsProcessElevated))]
163164
public void TestOnContinueBeforePause()
164165
{
166+
_testService.Client.Connect(connectionTimeout);
165167
var controller = new ServiceController(_testService.TestServiceName);
166168
AssertExpectedProperties(controller);
167-
string expected =
168-
@"OnStart args=
169-
OnStop
170-
";
169+
171170
controller.Continue();
172171
controller.WaitForStatus(ServiceControllerStatus.Running);
172+
173173
controller.Stop();
174+
Assert.Equal((int)PipeMessageByteCode.Stop, _testService.GetByte());
174175
controller.WaitForStatus(ServiceControllerStatus.Stopped);
175-
Assert.Equal(expected, _testService.GetServiceOutput());
176176
}
177177

178178
[ConditionalFact(nameof(IsElevatedAndSupportsEventLogs))]
@@ -193,7 +193,7 @@ public void LogWritten()
193193
sb.Stop();
194194
EventLog.DeleteEventSource(sb.ServiceName);
195195
}
196-
}
196+
}
197197
}
198198

199199
[ConditionalFact(nameof(IsElevatedAndSupportsEventLogs))]

src/System.ServiceProcess.ServiceController/tests/ServiceControllerTests.cs

Lines changed: 17 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using Microsoft.Win32;
66
using System;
77
using System.Diagnostics;
8+
using System.IO.Pipes;
89
using System.Security.Principal;
910
using Xunit;
1011

@@ -76,27 +77,6 @@ public void ControlCapabilities()
7677
Assert.True(controller.CanShutdown);
7778
}
7879

79-
[ConditionalFact(nameof(IsProcessElevated))]
80-
public void StartWithArguments()
81-
{
82-
var controller = new ServiceController(_testService.TestServiceName);
83-
controller.WaitForStatus(ServiceControllerStatus.Running, _testService.ControlTimeout);
84-
Assert.Equal(ServiceControllerStatus.Running, controller.Status);
85-
86-
controller.Stop();
87-
controller.WaitForStatus(ServiceControllerStatus.Stopped, _testService.ControlTimeout);
88-
Assert.Equal(ServiceControllerStatus.Stopped, controller.Status);
89-
90-
var args = new[] { "a", "b", "c", "d", "e" };
91-
controller.Start(args);
92-
controller.WaitForStatus(ServiceControllerStatus.Running, _testService.ControlTimeout);
93-
Assert.Equal(ServiceControllerStatus.Running, controller.Status);
94-
95-
string argsOutput = _testService.GetServiceOutput().Trim();
96-
string argsInput = "OnStart args=" + string.Join(",", args);
97-
Assert.Equal(argsInput, argsOutput);
98-
}
99-
10080
[ConditionalFact(nameof(IsProcessElevated))]
10181
public void Start_NullArg_ThrowsArgumentNullException()
10282
{
@@ -126,19 +106,26 @@ public void StopAndStart()
126106
[ConditionalFact(nameof(IsProcessElevated))]
127107
public void PauseAndContinue()
128108
{
129-
var controller = new ServiceController(_testService.TestServiceName);
109+
string serviceName = _testService.TestServiceName;
110+
var controller = new ServiceController(serviceName);
130111
controller.WaitForStatus(ServiceControllerStatus.Running, _testService.ControlTimeout);
131112
Assert.Equal(ServiceControllerStatus.Running, controller.Status);
132113

133-
for (int i = 0; i < 2; i++)
114+
using (var client = new NamedPipeClientStream(".", serviceName, PipeDirection.In))
134115
{
135-
controller.Pause();
136-
controller.WaitForStatus(ServiceControllerStatus.Paused, _testService.ControlTimeout);
137-
Assert.Equal(ServiceControllerStatus.Paused, controller.Status);
138-
139-
controller.Continue();
140-
controller.WaitForStatus(ServiceControllerStatus.Running, _testService.ControlTimeout);
141-
Assert.Equal(ServiceControllerStatus.Running, controller.Status);
116+
client.Connect();
117+
for (int i = 0; i < 2; i++)
118+
{
119+
controller.Pause();
120+
client.ReadByte();
121+
controller.WaitForStatus(ServiceControllerStatus.Paused, _testService.ControlTimeout);
122+
Assert.Equal(ServiceControllerStatus.Paused, controller.Status);
123+
124+
controller.Continue();
125+
client.ReadByte();
126+
controller.WaitForStatus(ServiceControllerStatus.Running, _testService.ControlTimeout);
127+
Assert.Equal(ServiceControllerStatus.Running, controller.Status);
128+
}
142129
}
143130
}
144131

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System.Threading;
6+
using System.Threading.Tasks;
7+
8+
namespace System.ServiceProcess.Tests
9+
{
10+
public enum PipeMessageByteCode
11+
{
12+
Start = 0,
13+
Continue = 1,
14+
Pause = 2,
15+
Stop = 3,
16+
OnCustomCommand = 4
17+
};
18+
19+
public static class TaskTimeoutExtensions
20+
{
21+
public static async Task TimeoutAfter(this Task task, int millisecondsTimeout)
22+
{
23+
var cts = new CancellationTokenSource();
24+
25+
if (task == await Task.WhenAny(task, Task.Delay(millisecondsTimeout, cts.Token)))
26+
{
27+
cts.Cancel();
28+
await task;
29+
}
30+
else
31+
{
32+
throw new TimeoutException($"Task timed out after {millisecondsTimeout}");
33+
}
34+
}
35+
}
36+
}

src/System.ServiceProcess.ServiceController/tests/System.ServiceProcess.ServiceController.TestService/System.ServiceProcess.ServiceController.TestService.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netfx-Debug|AnyCPU'" />
1212
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netfx-Release|AnyCPU'" />
1313
<ItemGroup>
14+
<Compile Include="Helpers.cs" />
1415
<Compile Include="Program.cs" />
1516
<Compile Include="TestServiceInstaller.cs" />
1617
<Compile Include="TestService.cs">

0 commit comments

Comments
 (0)