master
cpp 284 lines 11.7 KB
Raw
1 /*++
2
3 Copyright (c) Microsoft. All rights reserved.
4
5 Module Name:
6
7 WSLCE2EContainerStopTests.cpp
8
9 Abstract:
10
11 This file contains end-to-end tests for WSLC.
12 --*/
13
14 #include "precomp.h"
15 #include "windows/Common.h"
16 #include "WSLCExecutor.h"
17 #include "WSLCE2EHelpers.h"
18 #include "TestImageRegistry.h"
19
20 namespace WSLCE2ETests {
21 using namespace wsl::shared;
22
23 class WSLCE2EContainerStopTests
24 {
25 WSLC_TEST_CLASS(WSLCE2EContainerStopTests)
26
27 TEST_CLASS_SETUP(ClassSetup)
28 {
29 TestImageRegistry::Instance().EnsureLoaded(DebianImage);
30 return true;
31 }
32
33 TEST_CLASS_CLEANUP(ClassCleanup)
34 {
35 EnsureContainerDoesNotExist(WslcContainerName);
36 EnsureContainerDoesNotExist(WslcContainerName2);
37 return true;
38 }
39
40 TEST_METHOD_SETUP(TestMethodSetup)
41 {
42 EnsureContainerDoesNotExist(WslcContainerName);
43 EnsureContainerDoesNotExist(WslcContainerName2);
44 return true;
45 }
46
47 WSLC_TEST_METHOD(WSLCE2E_Container_Stop_HelpCommand)
48 {
49 auto result = RunWslc(L"container stop --help");
50 result.Verify({.Stderr = L"", .ExitCode = 0});
51 VERIFY_IS_FALSE(result.Stdout.value().empty());
52 }
53
54 WSLC_TEST_METHOD(WSLCE2E_Container_Stop_InvalidSignal)
55 {
56 auto result = RunWslc(std::format(L"container run --name {} {}", WslcContainerName, DebianImage.NameAndTag()));
57 result.Verify({.Stderr = L"", .ExitCode = 0});
58
59 {
60 result = RunWslc(std::format(L"container stop {} -s 0 -t 0", WslcContainerName));
61 result.Verify({.Stdout = L"", .ExitCode = 1});
62 VERIFY_IS_TRUE(result.StderrContainsSubstring(L"Invalid signal value: 0 is out of valid range (1-31)."));
63 }
64
65 {
66 result = RunWslc(std::format(L"container stop {} -s 32 -t 0", WslcContainerName));
67 result.Verify({.Stdout = L"", .ExitCode = 1});
68 VERIFY_IS_TRUE(result.StderrContainsSubstring(L"Invalid signal value: 32 is out of valid range (1-31)."));
69 }
70 }
71
72 WSLC_TEST_METHOD(WSLCE2E_Container_Stop_KillsRunningContainer)
73 {
74 // Run a container in the background
75 auto result = RunWslc(std::format(L"container run -d --name {} {} sleep infinity", WslcContainerName, DebianImage.NameAndTag()));
76 result.Verify({.Stderr = L"", .ExitCode = 0});
77 auto containerId = result.GetStdoutOneLine();
78 VERIFY_IS_FALSE(containerId.empty());
79
80 // Verify container is running
81 VerifyContainerIsListed(containerId, L"running");
82
83 // Stop the container
84 result = RunWslc(std::format(L"container stop {} -t 0", containerId));
85 result.Verify({.Stdout = std::format(L"{}\r\n", containerId), .Stderr = L"", .ExitCode = 0});
86
87 // Verify the container is no longer running
88 VerifyContainerIsListed(containerId, L"exited");
89 }
90
91 WSLC_TEST_METHOD(WSLCE2E_Container_Stop_ByName)
92 {
93 // Run a container in the background
94 auto result = RunWslc(std::format(L"container run -d --name {} {} sleep infinity", WslcContainerName, DebianImage.NameAndTag()));
95 result.Verify({.Stderr = L"", .ExitCode = 0});
96 const auto containerId = result.GetStdoutOneLine();
97 VERIFY_IS_FALSE(containerId.empty());
98
99 // Verify container is running
100 VerifyContainerIsListed(containerId, L"running");
101
102 // Stop by container name
103 result = RunWslc(std::format(L"container stop {} -t 0", WslcContainerName));
104 result.Verify({.Stdout = std::format(L"{}\r\n", WslcContainerName), .Stderr = L"", .ExitCode = 0});
105
106 // Verify container is no longer running
107 VerifyContainerIsListed(containerId, L"exited");
108 }
109
110 WSLC_TEST_METHOD(WSLCE2E_Container_Stop_AlreadyStopped)
111 {
112 // Run a container in the background
113 auto result = RunWslc(std::format(L"container run -d --name {} {} sleep infinity", WslcContainerName, DebianImage.NameAndTag()));
114 result.Verify({.Stderr = L"", .ExitCode = 0});
115 auto containerId = result.GetStdoutOneLine();
116 VERIFY_IS_FALSE(containerId.empty());
117
118 // Stop the container
119 result = RunWslc(std::format(L"container stop {} -t 0", containerId));
120 result.Verify({.Stderr = L"", .ExitCode = 0});
121 VerifyContainerIsListed(containerId, L"exited");
122
123 // Stop again - should succeed without error
124 result = RunWslc(std::format(L"container stop {} -t 0", containerId));
125 result.Verify({.Stderr = L"", .ExitCode = 0});
126 VerifyContainerIsListed(containerId, L"exited");
127 }
128
129 WSLC_TEST_METHOD(WSLCE2E_Container_Stop_NotFound)
130 {
131 VerifyContainerIsNotListed(WslcContainerName);
132
133 auto result = RunWslc(std::format(L"container stop {} -t 0", WslcContainerName));
134 result.Verify(
135 {.Stderr =
136 FormatErrorMessage(std::format(L"Container '{}' not found.", WslcContainerName), L"WSLC_E_CONTAINER_NOT_FOUND"),
137 .ExitCode = 1});
138 }
139
140 WSLC_TEST_METHOD(WSLCE2E_Container_Stop_TargetedContainerOnly)
141 {
142 // Run first container in background
143 auto result = RunWslc(std::format(L"container run -d --name {} {} sleep infinity", WslcContainerName, DebianImage.NameAndTag()));
144 result.Verify({.Stderr = L"", .ExitCode = 0});
145 const auto firstContainerId = result.GetStdoutOneLine();
146 VERIFY_IS_FALSE(firstContainerId.empty());
147
148 // Run second container in background
149 result = RunWslc(std::format(L"container run -d --name {} {} sleep infinity", WslcContainerName2, DebianImage.NameAndTag()));
150 result.Verify({.Stderr = L"", .ExitCode = 0});
151 const auto secondContainerId = result.GetStdoutOneLine();
152 VERIFY_IS_FALSE(secondContainerId.empty());
153
154 // Verify both are running
155 VerifyContainerIsListed(firstContainerId, L"running");
156 VerifyContainerIsListed(secondContainerId, L"running");
157
158 // Stop only the first container
159 result = RunWslc(std::format(L"container stop {} -t 0", firstContainerId));
160 result.Verify({.Stdout = std::format(L"{}\r\n", firstContainerId), .Stderr = L"", .ExitCode = 0});
161
162 // Verify first exited, second still running
163 VerifyContainerIsListed(firstContainerId, L"exited");
164 VerifyContainerIsListed(secondContainerId, L"running");
165 }
166
167 WSLC_TEST_METHOD(WSLCE2E_Container_Stop_SignalByName)
168 {
169 // Run a container in the background
170 auto result = RunWslc(std::format(L"container run -d --name {} {} sleep infinity", WslcContainerName, DebianImage.NameAndTag()));
171 result.Verify({.Stderr = L"", .ExitCode = 0});
172 const auto containerId = result.GetStdoutOneLine();
173 VERIFY_IS_FALSE(containerId.empty());
174
175 // Verify container is running
176 VerifyContainerIsListed(containerId, L"running");
177
178 // Stop the container using signal name
179 result = RunWslc(std::format(L"container stop {} -s SIGKILL -t 0", containerId));
180 result.Verify({.Stdout = std::format(L"{}\r\n", containerId), .Stderr = L"", .ExitCode = 0});
181
182 // Verify the container is no longer running
183 VerifyContainerIsListed(containerId, L"exited");
184 }
185
186 WSLC_TEST_METHOD(WSLCE2E_Container_Stop_InvalidSignalName)
187 {
188 // Run a container in the background
189 auto result = RunWslc(std::format(L"container run -d --name {} {} sleep infinity", WslcContainerName, DebianImage.NameAndTag()));
190 result.Verify({.Stderr = L"", .ExitCode = 0});
191 const auto containerId = result.GetStdoutOneLine();
192 VERIFY_IS_FALSE(containerId.empty());
193
194 // Verify container is running
195 VerifyContainerIsListed(containerId, L"running");
196
197 // Try to stop with an invalid signal name
198 result = RunWslc(std::format(L"container stop {} -s SIGINVALID -t 0", containerId));
199 result.Verify({.Stdout = L"", .ExitCode = 1});
200 VERIFY_IS_TRUE(result.StderrContainsSubstring(
201 L"Invalid signal value: SIGINVALID is not a recognized signal name or number (Example: SIGKILL, kill, or 9)."));
202
203 // Verify container is still running after failed stop request
204 VerifyContainerIsListed(containerId, L"running");
205 }
206
207 WSLC_TEST_METHOD(WSLCE2E_Container_Stop_InvalidTimeout)
208 {
209 // Run a container in the background
210 auto result = RunWslc(std::format(L"container run -d --name {} {} sleep infinity", WslcContainerName, DebianImage.NameAndTag()));
211 result.Verify({.Stderr = L"", .ExitCode = 0});
212 const auto containerId = result.GetStdoutOneLine();
213 VERIFY_IS_FALSE(containerId.empty());
214
215 // Verify container is running
216 VerifyContainerIsListed(containerId, L"running");
217
218 {
219 // Invalid integer
220 result = RunWslc(std::format(L"container stop {} -t abc", containerId));
221 result.Verify({.Stdout = L"", .ExitCode = 1});
222 VERIFY_IS_TRUE(
223 result.StderrContainsSubstring(wsl::shared::Localization::WSLCCLI_InvalidIntegerArgumentError(L"time", L"abc")));
224
225 // Should still be running after failed stop
226 VerifyContainerIsListed(containerId, L"running");
227 }
228
229 {
230 // Another invalid integer shape
231 result = RunWslc(std::format(L"container stop {} -t 1.5", containerId));
232 result.Verify({.Stdout = L"", .ExitCode = 1});
233 VERIFY_IS_TRUE(
234 result.StderrContainsSubstring(wsl::shared::Localization::WSLCCLI_InvalidIntegerArgumentError(L"time", L"1.5")));
235
236 // Should still be running after failed stop
237 VerifyContainerIsListed(containerId, L"running");
238 }
239
240 {
241 // Invalid integer prefixed
242 result = RunWslc(std::format(L"container stop {} -t 9abc", containerId));
243 result.Verify({.Stdout = L"", .ExitCode = 1});
244 VERIFY_IS_TRUE(
245 result.StderrContainsSubstring(wsl::shared::Localization::WSLCCLI_InvalidIntegerArgumentError(L"time", L"9abc")));
246
247 // Should still be running after failed stop
248 VerifyContainerIsListed(containerId, L"running");
249 }
250 }
251
252 WSLC_TEST_METHOD(WSLCE2E_Container_Stop_ContinuesAfterFailure)
253 {
254 // Run first container in background
255 auto result = RunWslc(std::format(L"container run -d --name {} {} sleep infinity", WslcContainerName, DebianImage.NameAndTag()));
256 result.Verify({.Stderr = L"", .ExitCode = 0});
257 const auto firstContainerId = result.GetStdoutOneLine();
258 VERIFY_IS_FALSE(firstContainerId.empty());
259
260 // Run second container in background
261 result = RunWslc(std::format(L"container run -d --name {} {} sleep infinity", WslcContainerName2, DebianImage.NameAndTag()));
262 result.Verify({.Stderr = L"", .ExitCode = 0});
263 const auto secondContainerId = result.GetStdoutOneLine();
264 VERIFY_IS_FALSE(secondContainerId.empty());
265
266 // A container that cannot be stopped is reported without skipping the ones after it
267 result = RunWslc(std::format(L"container stop {} {} {} -t 0", firstContainerId, InvalidContainerName, secondContainerId));
268 result.Verify(
269 {.Stdout = std::format(L"{}\r\n{}\r\n", firstContainerId, secondContainerId),
270 .Stderr = FormatErrorMessage(
271 std::format(L"Container '{}' not found.", InvalidContainerName), L"WSLC_E_CONTAINER_NOT_FOUND"),
272 .ExitCode = 1});
273
274 VerifyContainerIsListed(firstContainerId, L"exited");
275 VerifyContainerIsListed(secondContainerId, L"exited");
276 }
277
278 private:
279 const std::wstring WslcContainerName = L"wslc-test-container";
280 const std::wstring WslcContainerName2 = L"wslc-test-container-2";
281 const std::wstring InvalidContainerName = L"wslc-nonexistent-container-for-stop";
282 const TestImage& DebianImage = DebianTestImage();
283 };
284 } // namespace WSLCE2ETests