master
cpp 241 lines 9.2 KB
Raw
1 /*++
2
3 Copyright (c) Microsoft. All rights reserved.
4
5 Module Name:
6
7 WSLCE2EVolumePruneTests.cpp
8
9 Abstract:
10
11 This file contains end-to-end tests for the WSLC volume prune command.
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 WSLCE2EVolumePruneTests
24 {
25 WSLC_TEST_CLASS(WSLCE2EVolumePruneTests)
26
27 TEST_CLASS_SETUP(ClassSetup)
28 {
29 TestImageRegistry::Instance().EnsureLoaded(DebianImage);
30 CleanUpAllTestState();
31 return true;
32 }
33
34 TEST_METHOD_SETUP(MethodSetup)
35 {
36 CleanUpAllTestState();
37 return true;
38 }
39
40 TEST_CLASS_CLEANUP(ClassCleanup)
41 {
42 CleanUpAllTestState();
43 return true;
44 }
45
46 WSLC_TEST_METHOD(WSLCE2E_Volume_Prune_HelpCommand)
47 {
48 const auto result = RunWslc(L"volume prune --help");
49 result.Verify({.Stderr = L"", .ExitCode = 0});
50 VERIFY_IS_FALSE(result.Stdout.value().empty());
51 }
52
53 WSLC_TEST_METHOD(WSLCE2E_Volume_Prune_NoVolumes)
54 {
55 // Prune when no volumes exist should succeed and report a reclaimed-space line.
56 const auto result = RunWslc(L"volume prune");
57 result.Verify({.Stderr = L"", .ExitCode = 0});
58
59 // The deleted-volume block, and the blank line that follows it, are only written when
60 // something was actually removed.
61 result.Verify({.Stdout = L"Total reclaimed space: 0B\r\n"});
62 }
63
64 WSLC_TEST_METHOD(WSLCE2E_Volume_Prune_NoAllFlag_PreservesNamedVolumes)
65 {
66 RunWslc(std::format(L"volume create {}", TestVolumeName)).Verify({.Stderr = L"", .ExitCode = 0});
67 VerifyVolumeIsListed(TestVolumeName);
68
69 auto cleanup = wil::scope_exit([&]() { EnsureVolumeDoesNotExist(TestVolumeName); });
70
71 const auto result = RunWslc(L"volume prune");
72 result.Verify({.Stderr = L"", .ExitCode = 0});
73
74 auto output = result.GetStdoutLines();
75 VERIFY_ARE_EQUAL(1u, output.size());
76 VERIFY_ARE_NOT_EQUAL(std::wstring::npos, output[0].find(L"Total reclaimed space:"));
77
78 VerifyVolumeIsListed(TestVolumeName);
79 }
80
81 WSLC_TEST_METHOD(WSLCE2E_Volume_Prune_AllFlag_RemovesNamedVolume)
82 {
83 RunWslc(std::format(L"volume create {}", TestVolumeName)).Verify({.Stderr = L"", .ExitCode = 0});
84 VerifyVolumeIsListed(TestVolumeName);
85
86 auto cleanup = wil::scope_exit([&]() { EnsureVolumeDoesNotExist(TestVolumeName); });
87
88 const auto result = RunWslc(L"volume prune --all");
89 result.Verify({.Stderr = L"", .ExitCode = 0});
90
91 auto output = result.GetStdoutLines();
92 VERIFY_ARE_EQUAL(4u, output.size());
93 VERIFY_ARE_EQUAL(output[0], L"Deleted Volumes:");
94 VERIFY_ARE_EQUAL(output[1], TestVolumeName);
95 VERIFY_ARE_EQUAL(output[2], L"");
96 VERIFY_ARE_NOT_EQUAL(std::wstring::npos, output[3].find(L"Total reclaimed space:"));
97
98 VerifyVolumeIsNotListed(TestVolumeName);
99 }
100
101 WSLC_TEST_METHOD(WSLCE2E_Volume_Prune_AllFlag_RemovesMultipleVolumes)
102 {
103 RunWslc(std::format(L"volume create {}", TestVolumeName)).Verify({.Stderr = L"", .ExitCode = 0});
104 RunWslc(std::format(L"volume create {}", TestVolumeName2)).Verify({.Stderr = L"", .ExitCode = 0});
105 VerifyVolumeIsListed(TestVolumeName);
106 VerifyVolumeIsListed(TestVolumeName2);
107
108 auto cleanup = wil::scope_exit([&]() {
109 EnsureVolumeDoesNotExist(TestVolumeName);
110 EnsureVolumeDoesNotExist(TestVolumeName2);
111 });
112
113 const auto result = RunWslc(L"volume prune --all");
114 result.Verify({.Stderr = L"", .ExitCode = 0});
115
116 VERIFY_IS_TRUE(result.StdoutContainsLine(L"Deleted Volumes:"));
117 VERIFY_IS_TRUE(result.StdoutContainsLine(TestVolumeName));
118 VERIFY_IS_TRUE(result.StdoutContainsLine(TestVolumeName2));
119
120 VerifyVolumeIsNotListed(TestVolumeName);
121 VerifyVolumeIsNotListed(TestVolumeName2);
122 }
123
124 WSLC_TEST_METHOD(WSLCE2E_Volume_Prune_InUseVolume_Preserved)
125 {
126 RunWslc(std::format(L"volume create {}", TestVolumeName)).Verify({.Stderr = L"", .ExitCode = 0});
127 VerifyVolumeIsListed(TestVolumeName);
128
129 // Start a container that holds the volume open.
130 RunWslc(std::format(
131 L"container run -d --name {} -v {}:/data {} sleep infinity", WslcContainerName, TestVolumeName, DebianImage.NameAndTag()))
132 .Verify({.Stderr = L"", .ExitCode = 0});
133
134 auto cleanup = wil::scope_exit([&]() {
135 EnsureContainerDoesNotExist(WslcContainerName);
136 EnsureVolumeDoesNotExist(TestVolumeName);
137 });
138
139 const auto result = RunWslc(L"volume prune --all");
140 result.Verify({.Stderr = L"", .ExitCode = 0});
141
142 VERIFY_IS_FALSE(result.StdoutContainsLine(TestVolumeName), L"Volume in use by a running container must not be pruned");
143
144 VerifyVolumeIsListed(TestVolumeName);
145 }
146
147 WSLC_TEST_METHOD(WSLCE2E_Volume_Prune_LabelFilter_PreservesNonMatchingVolume)
148 {
149 RunWslc(std::format(L"volume create {}", TestVolumeName)).Verify({.Stderr = L"", .ExitCode = 0});
150 VerifyVolumeIsListed(TestVolumeName);
151
152 auto cleanup = wil::scope_exit([&]() { EnsureVolumeDoesNotExist(TestVolumeName); });
153
154 // A label filter that does not match the volume should preserve it
155 const auto filteredPrune = RunWslc(L"volume prune --all --filter label=wslc.test.never=present");
156 filteredPrune.Verify({.Stderr = L"", .ExitCode = 0});
157 VERIFY_IS_FALSE(
158 filteredPrune.StdoutContainsLine(TestVolumeName), L"Filtered prune should not have deleted the non-matching volume");
159 VerifyVolumeIsListed(TestVolumeName);
160
161 // Subsequent unfiltered prune --all should still remove it, proving
162 // the filter was the reason it survived.
163 const auto unfilteredPrune = RunWslc(L"volume prune --all");
164 unfilteredPrune.Verify({.Stderr = L"", .ExitCode = 0});
165 VERIFY_IS_TRUE(unfilteredPrune.StdoutContainsLine(TestVolumeName));
166 VerifyVolumeIsNotListed(TestVolumeName);
167 }
168
169 WSLC_TEST_METHOD(WSLCE2E_Volume_Prune_LabelFilter_MatchingValueIsDeleted)
170 {
171 RunWslc(std::format(L"volume create --label wslc.test.prune=keep {}", TestVolumeName)).Verify({.Stderr = L"", .ExitCode = 0});
172 RunWslc(std::format(L"volume create {}", TestVolumeName2)).Verify({.Stderr = L"", .ExitCode = 0});
173 VerifyVolumeIsListed(TestVolumeName);
174 VerifyVolumeIsListed(TestVolumeName2);
175
176 auto cleanup = wil::scope_exit([&]() {
177 EnsureVolumeDoesNotExist(TestVolumeName);
178 EnsureVolumeDoesNotExist(TestVolumeName2);
179 });
180
181 const auto result = RunWslc(L"volume prune --all --filter label=wslc.test.prune=keep");
182 result.Verify({.Stderr = L"", .ExitCode = 0});
183
184 VERIFY_IS_TRUE(result.StdoutContainsLine(TestVolumeName));
185 VERIFY_IS_FALSE(result.StdoutContainsLine(TestVolumeName2), L"Volume without the matching label must not be deleted");
186
187 VerifyVolumeIsNotListed(TestVolumeName);
188 VerifyVolumeIsListed(TestVolumeName2);
189 }
190
191 WSLC_TEST_METHOD(WSLCE2E_Volume_Prune_NegatedLabelFilter_PreservesLabeledVolume)
192 {
193 RunWslc(std::format(L"volume create --label wslc.test.keep=yes {}", TestVolumeName)).Verify({.Stderr = L"", .ExitCode = 0});
194 RunWslc(std::format(L"volume create {}", TestVolumeName2)).Verify({.Stderr = L"", .ExitCode = 0});
195 VerifyVolumeIsListed(TestVolumeName);
196 VerifyVolumeIsListed(TestVolumeName2);
197
198 auto cleanup = wil::scope_exit([&]() {
199 EnsureVolumeDoesNotExist(TestVolumeName);
200 EnsureVolumeDoesNotExist(TestVolumeName2);
201 });
202
203 const auto result = RunWslc(L"volume prune --all --filter label!=wslc.test.keep");
204 result.Verify({.Stderr = L"", .ExitCode = 0});
205
206 VERIFY_IS_TRUE(result.StdoutContainsLine(TestVolumeName2));
207 VERIFY_IS_FALSE(
208 result.StdoutContainsLine(TestVolumeName), L"Labeled volume must be preserved when prune negates that label");
209
210 VerifyVolumeIsListed(TestVolumeName);
211 VerifyVolumeIsNotListed(TestVolumeName2);
212 }
213
214 WSLC_TEST_METHOD(WSLCE2E_Volume_Prune_Filter_MalformedValue)
215 {
216 const auto result = RunWslc(L"volume prune --filter label");
217 result.Verify({.Stdout = L"", .ExitCode = 1});
218 VERIFY_IS_TRUE(result.StderrContainsSubstring(Localization::WSLCCLI_InvalidFilterError(L"label")));
219 }
220
221 WSLC_TEST_METHOD(WSLCE2E_Volume_Prune_Filter_InvalidKey)
222 {
223 const auto result = RunWslc(L"volume prune --filter color=red");
224 result.Verify({.Stdout = L"", .ExitCode = 1});
225 VERIFY_IS_TRUE(result.StderrContainsSubstring(L"invalid filter 'color'\r\nError code: E_INVALIDARG"));
226 }
227
228 private:
229 const TestImage& DebianImage = DebianTestImage();
230 const std::wstring TestVolumeName = L"wslc-e2e-volume-prune";
231 const std::wstring TestVolumeName2 = L"wslc-e2e-volume-prune-2";
232 const std::wstring WslcContainerName = L"wslc-volume-prune-test-container";
233
234 void CleanUpAllTestState()
235 {
236 EnsureContainerDoesNotExist(WslcContainerName);
237 EnsureVolumeDoesNotExist(TestVolumeName);
238 EnsureVolumeDoesNotExist(TestVolumeName2);
239 }
240 };
241 } // namespace WSLCE2ETests