master
cpp 227 lines 9.65 KB
Raw
1 /*++
2
3 Copyright (c) Microsoft. All rights reserved.
4
5 Module Name:
6
7 WSLCE2EContainerRestartTests.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 WSLCE2EContainerRestartTests
24 {
25 WSLC_TEST_CLASS(WSLCE2EContainerRestartTests)
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_Restart_HelpCommand)
48 {
49 auto result = RunWslc(L"container restart --help");
50 result.Verify({.Stderr = L"", .ExitCode = 0});
51 VERIFY_IS_FALSE(result.Stdout.value().empty());
52 }
53
54 WSLC_TEST_METHOD(WSLCE2E_Container_Restart_RunningContainer)
55 {
56 // Run a container in the background
57 auto result = RunWslc(std::format(L"container run -d --name {} {} sleep infinity", WslcContainerName, DebianImage.NameAndTag()));
58 result.Verify({.Stderr = L"", .ExitCode = 0});
59 const auto containerId = result.GetStdoutOneLine();
60 VERIFY_IS_FALSE(containerId.empty());
61
62 VerifyContainerIsListed(containerId, L"running");
63 const auto startedAt = InspectContainer(WslcContainerName).State.StartedAt;
64
65 result = RunWslc(std::format(L"container restart {} -t 0", containerId));
66 result.Verify({.Stdout = std::format(L"{}\r\n", containerId), .Stderr = L"", .ExitCode = 0});
67
68 // The container is running again, but from a new init process.
69 VerifyContainerIsListed(containerId, L"running");
70 VERIFY_ARE_NOT_EQUAL(startedAt, InspectContainer(WslcContainerName).State.StartedAt);
71 }
72
73 WSLC_TEST_METHOD(WSLCE2E_Container_Restart_ByName)
74 {
75 // Run a container in the background
76 auto result = RunWslc(std::format(L"container run -d --name {} {} sleep infinity", WslcContainerName, DebianImage.NameAndTag()));
77 result.Verify({.Stderr = L"", .ExitCode = 0});
78 const auto containerId = result.GetStdoutOneLine();
79 VERIFY_IS_FALSE(containerId.empty());
80
81 VerifyContainerIsListed(containerId, L"running");
82
83 // Restart by container name
84 result = RunWslc(std::format(L"container restart {} -t 0", WslcContainerName));
85 result.Verify({.Stdout = std::format(L"{}\r\n", WslcContainerName), .Stderr = L"", .ExitCode = 0});
86
87 VerifyContainerIsListed(containerId, L"running");
88 }
89
90 WSLC_TEST_METHOD(WSLCE2E_Container_Restart_StoppedContainer)
91 {
92 // Run a container in the background
93 auto result = RunWslc(std::format(L"container run -d --name {} {} sleep infinity", WslcContainerName, DebianImage.NameAndTag()));
94 result.Verify({.Stderr = L"", .ExitCode = 0});
95 const auto containerId = result.GetStdoutOneLine();
96 VERIFY_IS_FALSE(containerId.empty());
97
98 result = RunWslc(std::format(L"container stop {} -t 0", containerId));
99 result.Verify({.Stderr = L"", .ExitCode = 0});
100 VerifyContainerIsListed(containerId, L"exited");
101
102 // Restarting a stopped container starts it
103 result = RunWslc(std::format(L"container restart {} -t 0", containerId));
104 result.Verify({.Stdout = std::format(L"{}\r\n", containerId), .Stderr = L"", .ExitCode = 0});
105
106 VerifyContainerIsListed(containerId, L"running");
107 }
108
109 WSLC_TEST_METHOD(WSLCE2E_Container_Restart_MultipleContainers)
110 {
111 // Run first container in background
112 auto result = RunWslc(std::format(L"container run -d --name {} {} sleep infinity", WslcContainerName, DebianImage.NameAndTag()));
113 result.Verify({.Stderr = L"", .ExitCode = 0});
114 const auto firstContainerId = result.GetStdoutOneLine();
115 VERIFY_IS_FALSE(firstContainerId.empty());
116
117 // Run second container in background
118 result = RunWslc(std::format(L"container run -d --name {} {} sleep infinity", WslcContainerName2, DebianImage.NameAndTag()));
119 result.Verify({.Stderr = L"", .ExitCode = 0});
120 const auto secondContainerId = result.GetStdoutOneLine();
121 VERIFY_IS_FALSE(secondContainerId.empty());
122
123 result = RunWslc(std::format(L"container restart {} {} -t 0", firstContainerId, secondContainerId));
124 result.Verify({.Stdout = std::format(L"{}\r\n{}\r\n", firstContainerId, secondContainerId), .Stderr = L"", .ExitCode = 0});
125
126 VerifyContainerIsListed(firstContainerId, L"running");
127 VerifyContainerIsListed(secondContainerId, L"running");
128 }
129
130 WSLC_TEST_METHOD(WSLCE2E_Container_Restart_ContinuesAfterFailure)
131 {
132 // Run first container in background
133 auto result = RunWslc(std::format(L"container run -d --name {} {} sleep infinity", WslcContainerName, DebianImage.NameAndTag()));
134 result.Verify({.Stderr = L"", .ExitCode = 0});
135 const auto firstContainerId = result.GetStdoutOneLine();
136 VERIFY_IS_FALSE(firstContainerId.empty());
137
138 // Run second container in background
139 result = RunWslc(std::format(L"container run -d --name {} {} sleep infinity", WslcContainerName2, DebianImage.NameAndTag()));
140 result.Verify({.Stderr = L"", .ExitCode = 0});
141 const auto secondContainerId = result.GetStdoutOneLine();
142 VERIFY_IS_FALSE(secondContainerId.empty());
143
144 // A container that cannot be restarted is reported without skipping the ones after it
145 result = RunWslc(std::format(L"container restart {} {} {} -t 0", firstContainerId, InvalidContainerName, secondContainerId));
146 result.Verify(
147 {.Stdout = std::format(L"{}\r\n{}\r\n", firstContainerId, secondContainerId),
148 .Stderr = FormatErrorMessage(
149 std::format(L"Container '{}' not found.", InvalidContainerName), L"WSLC_E_CONTAINER_NOT_FOUND"),
150 .ExitCode = 1});
151
152 VerifyContainerIsListed(firstContainerId, L"running");
153 VerifyContainerIsListed(secondContainerId, L"running");
154 }
155
156 WSLC_TEST_METHOD(WSLCE2E_Container_Restart_EachFailureIsReported)
157 {
158 VerifyContainerIsNotListed(InvalidContainerName);
159 VerifyContainerIsNotListed(InvalidContainerName2);
160
161 auto result = RunWslc(std::format(L"container restart {} {} -t 0", InvalidContainerName, InvalidContainerName2));
162 result.Verify(
163 {.Stdout = L"",
164 .Stderr = FormatErrorMessage(
165 std::format(L"Container '{}' not found.", InvalidContainerName), L"WSLC_E_CONTAINER_NOT_FOUND") +
166 FormatErrorMessage(
167 std::format(L"Container '{}' not found.", InvalidContainerName2), L"WSLC_E_CONTAINER_NOT_FOUND"),
168 .ExitCode = 1});
169 }
170
171 WSLC_TEST_METHOD(WSLCE2E_Container_Restart_NotFound)
172 {
173 VerifyContainerIsNotListed(WslcContainerName);
174
175 auto result = RunWslc(std::format(L"container restart {} -t 0", WslcContainerName));
176 result.Verify(
177 {.Stderr =
178 FormatErrorMessage(std::format(L"Container '{}' not found.", WslcContainerName), L"WSLC_E_CONTAINER_NOT_FOUND"),
179 .ExitCode = 1});
180 }
181
182 WSLC_TEST_METHOD(WSLCE2E_Container_Restart_InvalidSignalName)
183 {
184 // Run a container in the background
185 auto result = RunWslc(std::format(L"container run -d --name {} {} sleep infinity", WslcContainerName, DebianImage.NameAndTag()));
186 result.Verify({.Stderr = L"", .ExitCode = 0});
187 const auto containerId = result.GetStdoutOneLine();
188 VERIFY_IS_FALSE(containerId.empty());
189
190 VerifyContainerIsListed(containerId, L"running");
191
192 result = RunWslc(std::format(L"container restart {} -s SIGINVALID -t 0", containerId));
193 result.Verify({.Stdout = L"", .ExitCode = 1});
194 VERIFY_IS_TRUE(result.StderrContainsSubstring(
195 L"Invalid signal value: SIGINVALID is not a recognized signal name or number (Example: SIGKILL, kill, or 9)."));
196
197 // Verify container is still running after failed restart request
198 VerifyContainerIsListed(containerId, L"running");
199 }
200
201 WSLC_TEST_METHOD(WSLCE2E_Container_Restart_InvalidTimeout)
202 {
203 // Run a container in the background
204 auto result = RunWslc(std::format(L"container run -d --name {} {} sleep infinity", WslcContainerName, DebianImage.NameAndTag()));
205 result.Verify({.Stderr = L"", .ExitCode = 0});
206 const auto containerId = result.GetStdoutOneLine();
207 VERIFY_IS_FALSE(containerId.empty());
208
209 VerifyContainerIsListed(containerId, L"running");
210
211 result = RunWslc(std::format(L"container restart {} -t abc", containerId));
212 result.Verify({.Stdout = L"", .ExitCode = 1});
213 VERIFY_IS_TRUE(
214 result.StderrContainsSubstring(wsl::shared::Localization::WSLCCLI_InvalidIntegerArgumentError(L"timeout", L"abc")));
215
216 // Verify container is still running after failed restart request
217 VerifyContainerIsListed(containerId, L"running");
218 }
219
220 private:
221 const std::wstring WslcContainerName = L"wslc-test-container";
222 const std::wstring WslcContainerName2 = L"wslc-test-container-2";
223 const std::wstring InvalidContainerName = L"wslc-nonexistent-container-for-restart";
224 const std::wstring InvalidContainerName2 = L"wslc-nonexistent-container-for-restart-2";
225 const TestImage& DebianImage = DebianTestImage();
226 };
227 } // namespace WSLCE2ETests