Cache container images during tests to prevent unnecessary loading (#41353)

Each wslc E2E suite re-ran image list and image load during setup, reloading the same test image tars many times across test classes. Add TestImageRegistry, a per-process cache that seeds itself from one image list query per session and then loads an image only when it is not already present, deletes through the live image inventory so images created outside the registry are still removed, and exposes Restore for tests such as image prune that remove images another way. Replace EnsureImageIsLoaded/EnsureImageIsDeleted in WSLCE2EHelpers with calls into the registry and drop the now-unused helpers. Also give the session test's container a GUID-suffixed name, since "test-cont" is a prefix of container names other tests leave behind and made the substring-based listing checks ambiguous. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

ggarzia-MSFT committed Aug 20, 2026 at 11:44 UTC 3ae2ead88cf51e94a86f5c2dd0a7eb27cb5d54ff
36 files changed +330 -174
test/windows/wslc/e2e/TestImageRegistry.cpp new
+124
@@ -0,0 +1,124 @@
1 +/*++
2 +
3 +Copyright (c) Microsoft. All rights reserved.
4 +
5 +Module Name:
6 +
7 + TestImageRegistry.cpp
8 +
9 +Abstract:
10 +
11 + This file contains the implementation of the test image registry.
12 +--*/
13 +
14 +#include "precomp.h"
15 +#include "ImageModel.h"
16 +#include "WSLCExecutor.h"
17 +#include "WSLCE2EHelpers.h"
18 +#include "TestImageRegistry.h"
19 +
20 +namespace WSLCE2ETests {
21 +
22 +std::wstring TestImageRegistry::FormatCommand(const std::wstring& sessionName, const std::wstring& command)
23 +{
24 + if (sessionName.empty())
25 + {
26 + return command;
27 + }
28 +
29 + return std::format(L"--session \"{}\" {}", sessionName, command);
30 +}
31 +
32 +TestImageRegistry& TestImageRegistry::Instance()
33 +{
34 + static TestImageRegistry registry;
35 + return registry;
36 +}
37 +
38 +TestImageRegistry::ImageKey TestImageRegistry::MakeKey(const TestImage& image, const std::wstring& sessionName)
39 +{
40 + return ImageKey{sessionName, image.Name, image.Tag};
41 +}
42 +
43 +void TestImageRegistry::EnsureSeeded(const std::wstring& sessionName)
44 +{
45 + if (m_seededSessions.contains(sessionName))
46 + {
47 + return;
48 + }
49 +
50 + auto result = RunWslc(FormatCommand(sessionName, L"image list --format json"));
51 + result.Verify({.Stderr = L"", .ExitCode = 0});
52 +
53 + const auto images = ParseNdjsonOutputAs<wsl::windows::wslc::models::ImageOutputInformation>(result);
54 +
55 + for (const auto& image : images)
56 + {
57 + if (image.Repository != wsl::windows::wslc::models::c_none && image.Tag != wsl::windows::wslc::models::c_none)
58 + {
59 + m_loaded.insert(ImageKey{
60 + sessionName, wsl::shared::string::MultiByteToWide(image.Repository), wsl::shared::string::MultiByteToWide(image.Tag)});
61 + }
62 + }
63 +
64 + m_seededSessions.insert(sessionName);
65 +}
66 +
67 +void TestImageRegistry::EnsureLoaded(const TestImage& image, const std::wstring& sessionName)
68 +{
69 + EnsureSeeded(sessionName);
70 +
71 + if (m_loaded.contains(MakeKey(image, sessionName)))
72 + {
73 + return;
74 + }
75 +
76 + Load(image, sessionName);
77 +}
78 +
79 +void TestImageRegistry::Restore(const TestImage& image, const std::wstring& sessionName)
80 +{
81 + EnsureSeeded(sessionName);
82 + m_loaded.erase(MakeKey(image, sessionName));
83 + Load(image, sessionName);
84 +}
85 +
86 +void TestImageRegistry::Load(const TestImage& image, const std::wstring& sessionName)
87 +{
88 + auto result = RunWslc(FormatCommand(sessionName, std::format(L"image load --input \"{}\"", image.Path.wstring())));
89 + result.Verify({.Stderr = L"", .ExitCode = 0});
90 +
91 + m_loaded.insert(MakeKey(image, sessionName));
92 +}
93 +
94 +void TestImageRegistry::Delete(const TestImage& image, const std::wstring& sessionName)
95 +{
96 + auto result = RunWslc(FormatCommand(sessionName, L"image list --format json"));
97 + result.Verify({.Stderr = L"", .ExitCode = 0});
98 +
99 + const auto images = ParseNdjsonOutputAs<wsl::windows::wslc::models::ImageOutputInformation>(result);
100 + const auto name = wsl::shared::string::WideToMultiByte(image.Name);
101 + const auto tag = wsl::shared::string::WideToMultiByte(image.Tag);
102 + const bool present =
103 + std::ranges::any_of(images, [&](const auto& candidate) { return candidate.Repository == name && candidate.Tag == tag; });
104 +
105 + if (!present)
106 + {
107 + m_loaded.erase(MakeKey(image, sessionName));
108 + return;
109 + }
110 +
111 + // Container enumeration is scoped to the default session, so named sessions rely on the
112 + // force flag to remove the image out from under any containers still referencing it.
113 + if (sessionName.empty())
114 + {
115 + EnsureImageContainersAreDeleted(image);
116 + }
117 +
118 + auto deleteResult = RunWslc(FormatCommand(sessionName, std::format(L"image delete --force {}", image.NameAndTag())));
119 + deleteResult.Verify({.Stderr = L"", .ExitCode = 0});
120 +
121 + m_loaded.erase(MakeKey(image, sessionName));
122 +}
123 +
124 +} // namespace WSLCE2ETests
test/windows/wslc/e2e/TestImageRegistry.h new
+78
@@ -0,0 +1,78 @@
1 +/*++
2 +
3 +Copyright (c) Microsoft. All rights reserved.
4 +
5 +Module Name:
6 +
7 + TestImageRegistry.h
8 +
9 +Abstract:
10 +
11 + This file contains a per-process registry that tracks which test images are loaded in a
12 + session, so that repeated setup across test classes does not reload the same image tar.
13 +--*/
14 +
15 +#pragma once
16 +
17 +#include <set>
18 +#include <string>
19 +#include <tuple>
20 +
21 +namespace WSLCE2ETests {
22 +
23 +struct TestImage;
24 +
25 +// The cache is only correct as long as every removal is either routed through Delete or followed
26 +// by Restore, so a test that removes images another way has to put the session back itself.
27 +class TestImageRegistry
28 +{
29 +public:
30 + static TestImageRegistry& Instance();
31 +
32 + NON_COPYABLE(TestImageRegistry);
33 + NON_MOVABLE(TestImageRegistry);
34 +
35 + // Loads the image only if it is not already present in the session.
36 + void EnsureLoaded(const TestImage& image, const std::wstring& sessionName = L"");
37 +
38 + // Deletes the image if present, along with any containers using it, and drops it from the cache.
39 + // The image inventory is queried directly rather than through the cache, so images created outside
40 + // the registry, such as built or imported ones, are still removed.
41 + void Delete(const TestImage& image, const std::wstring& sessionName = L"");
42 +
43 + // Loads the image back without consulting the cache. Tests that remove images without going
44 + // through Delete, such as those exercising image prune, call this to restore the session.
45 + void Restore(const TestImage& image, const std::wstring& sessionName = L"");
46 +
47 +private:
48 + TestImageRegistry() = default;
49 +
50 + // Loads the image without consulting the cache.
51 + void Load(const TestImage& image, const std::wstring& sessionName);
52 +
53 + struct ImageKey
54 + {
55 + std::wstring SessionName;
56 + std::wstring Name;
57 + std::wstring Tag;
58 +
59 + bool operator<(const ImageKey& other) const
60 + {
61 + return std::tie(SessionName, Name, Tag) < std::tie(other.SessionName, other.Name, other.Tag);
62 + }
63 + };
64 +
65 + static ImageKey MakeKey(const TestImage& image, const std::wstring& sessionName);
66 +
67 + // Populates the cache for a session from a live image list query the first time it is used.
68 + void EnsureSeeded(const std::wstring& sessionName);
69 +
70 + // Prefixes a command with the session flag when the command targets a named session.
71 + static std::wstring FormatCommand(const std::wstring& sessionName, const std::wstring& command);
72 +
73 + // Test methods run one at a time in a single process, so the cache needs no synchronization.
74 + std::set<ImageKey> m_loaded;
75 + std::set<std::wstring> m_seededSessions;
76 +};
77 +
78 +} // namespace WSLCE2ETests
test/windows/wslc/e2e/WSLCE2EContainerAttachTests.cpp
+2 -2
@@ -15,6 +15,7 @@ Abstract:
15 #include "windows/Common.h"
16 #include "WSLCExecutor.h"
17 #include "WSLCE2EHelpers.h"
18 +#include "TestImageRegistry.h"
19
20 namespace WSLCE2ETests {
21
@@ -24,14 +25,13 @@ class WSLCE2EContainerAttachTests
25
26 TEST_CLASS_SETUP(ClassSetup)
27 {
27 - EnsureImageIsLoaded(DebianImage);
28 + TestImageRegistry::Instance().EnsureLoaded(DebianImage);
29 return true;
30 }
31
32 TEST_CLASS_CLEANUP(ClassCleanup)
33 {
34 EnsureContainerDoesNotExist(WslcContainerName);
34 - EnsureImageIsDeleted(DebianImage);
35 return true;
36 }
37
test/windows/wslc/e2e/WSLCE2EContainerCpTests.cpp
+2 -2
@@ -4,6 +4,7 @@
4 #include "windows/Common.h"
5 #include "WSLCExecutor.h"
6 #include "WSLCE2EHelpers.h"
7 +#include "TestImageRegistry.h"
8
9 namespace WSLCE2ETests {
10 using namespace wsl::shared;
@@ -14,14 +15,13 @@ class WSLCE2EContainerCpTests
15
16 TEST_CLASS_SETUP(ClassSetup)
17 {
17 - EnsureImageIsLoaded(DebianImage);
18 + TestImageRegistry::Instance().EnsureLoaded(DebianImage);
19 return true;
20 }
21
22 TEST_CLASS_CLEANUP(ClassCleanup)
23 {
24 EnsureContainerDoesNotExist(WslcContainerName);
24 - EnsureImageIsDeleted(DebianImage);
25 return true;
26 }
27
test/windows/wslc/e2e/WSLCE2EContainerCreateTests.cpp
+6 -8
@@ -15,6 +15,7 @@ Abstract:
15 #include "windows/Common.h"
16 #include "WSLCExecutor.h"
17 #include "WSLCE2EHelpers.h"
18 +#include "TestImageRegistry.h"
19 #include <fstream>
20 #include <wil/network.h>
21 #include <wil/resource.h>
@@ -30,9 +31,9 @@ class WSLCE2EContainerCreateTests
31
32 TEST_CLASS_SETUP(ClassSetup)
33 {
33 - EnsureImageIsLoaded(AlpineImage);
34 - EnsureImageIsLoaded(DebianImage);
35 - EnsureImageIsLoaded(HelloWorldImage);
34 + TestImageRegistry::Instance().EnsureLoaded(AlpineImage);
35 + TestImageRegistry::Instance().EnsureLoaded(DebianImage);
36 + TestImageRegistry::Instance().EnsureLoaded(HelloWorldImage);
37
38 VERIFY_IS_TRUE(::SetEnvironmentVariableW(HostEnvVariableName.c_str(), HostEnvVariableValue.c_str()));
39 VERIFY_IS_TRUE(::SetEnvironmentVariableW(HostEnvVariableName2.c_str(), HostEnvVariableValue2.c_str()));
@@ -43,9 +44,6 @@ class WSLCE2EContainerCreateTests
44 TEST_CLASS_CLEANUP(ClassCleanup)
45 {
46 EnsureContainerDoesNotExist(WslcContainerName);
46 - EnsureImageIsDeleted(AlpineImage);
47 - EnsureImageIsDeleted(DebianImage);
48 - EnsureImageIsDeleted(HelloWorldImage);
47 EnsureVolumeDoesNotExist(WslcVolumeName);
48 EnsureNetworkDoesNotExist(TestNetworkName);
49
@@ -1749,11 +1747,11 @@ class WSLCE2EContainerCreateTests
1747 // to arm before either resource exists.
1748 auto cleanup = wil::scope_exit([&] {
1749 EnsureContainerDoesNotExist(WslcContainerName);
1752 - EnsureImageIsDeleted(PublishAllImage);
1750 + TestImageRegistry::Instance().Delete(PublishAllImage);
1751 });
1752
1753 // Load the Python base image so the test image can be built offline.
1756 - EnsureImageIsLoaded(PythonImage);
1754 + TestImageRegistry::Instance().EnsureLoaded(PythonImage);
1755
1756 // Build an image that exposes a TCP and a UDP port and ships a server that listens on both,
1757 // so publish-all can be exercised end to end.
test/windows/wslc/e2e/WSLCE2EContainerExecTests.cpp
+2 -2
@@ -15,6 +15,7 @@ Abstract:
15 #include "windows/Common.h"
16 #include "WSLCExecutor.h"
17 #include "WSLCE2EHelpers.h"
18 +#include "TestImageRegistry.h"
19
20 namespace WSLCE2ETests {
21
@@ -28,14 +29,13 @@ class WSLCE2EContainerExecTests
29 VERIFY_IS_TRUE(::SetEnvironmentVariableW(HostEnvVariableName2.c_str(), HostEnvVariableValue2.c_str()));
30 VERIFY_IS_TRUE(::SetEnvironmentVariableW(MissingHostEnvVariableName.c_str(), nullptr));
31
31 - EnsureImageIsLoaded(DebianImage);
32 + TestImageRegistry::Instance().EnsureLoaded(DebianImage);
33 return true;
34 }
35
36 TEST_CLASS_CLEANUP(ClassCleanup)
37 {
38 EnsureContainerDoesNotExist(WslcContainerName);
38 - EnsureImageIsDeleted(DebianImage);
39
40 VERIFY_IS_TRUE(::SetEnvironmentVariableW(HostEnvVariableName.c_str(), nullptr));
41 VERIFY_IS_TRUE(::SetEnvironmentVariableW(HostEnvVariableName2.c_str(), nullptr));
test/windows/wslc/e2e/WSLCE2EContainerExportTests.cpp
+2 -2
@@ -15,6 +15,7 @@ Abstract:
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;
@@ -25,14 +26,13 @@ class WSLCE2EContainerExportTests
26
27 TEST_CLASS_SETUP(ClassSetup)
28 {
28 - EnsureImageIsLoaded(DebianImage);
29 + TestImageRegistry::Instance().EnsureLoaded(DebianImage);
30 return true;
31 }
32
33 TEST_CLASS_CLEANUP(ClassCleanup)
34 {
35 EnsureContainerDoesNotExist(WslcContainerName);
35 - EnsureImageIsDeleted(DebianImage);
36 return true;
37 }
38
test/windows/wslc/e2e/WSLCE2EContainerInspectTests.cpp
+2 -2
@@ -15,6 +15,7 @@ Abstract:
15 #include "windows/Common.h"
16 #include "WSLCExecutor.h"
17 #include "WSLCE2EHelpers.h"
18 +#include "TestImageRegistry.h"
19 #include <wslc_schema.h>
20
21 namespace WSLCE2ETests {
@@ -27,7 +28,7 @@ class WSLCE2EContainerInspectTests
28
29 TEST_CLASS_SETUP(ClassSetup)
30 {
30 - EnsureImageIsLoaded(DebianImage);
31 + TestImageRegistry::Instance().EnsureLoaded(DebianImage);
32 return true;
33 }
34
@@ -35,7 +36,6 @@ class WSLCE2EContainerInspectTests
36 {
37 EnsureContainerDoesNotExist(TestContainerName1);
38 EnsureContainerDoesNotExist(TestContainerName2);
38 - EnsureImageIsDeleted(DebianImage);
39 return true;
40 }
41
test/windows/wslc/e2e/WSLCE2EContainerKillTests.cpp
+2 -2
@@ -15,6 +15,7 @@ Abstract:
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;
@@ -25,7 +26,7 @@ class WSLCE2EContainerKillTests
26
27 TEST_CLASS_SETUP(ClassSetup)
28 {
28 - EnsureImageIsLoaded(DebianImage);
29 + TestImageRegistry::Instance().EnsureLoaded(DebianImage);
30 return true;
31 }
32
@@ -33,7 +34,6 @@ class WSLCE2EContainerKillTests
34 {
35 EnsureContainerDoesNotExist(WslcContainerName);
36 EnsureContainerDoesNotExist(WslcContainerName2);
36 - EnsureImageIsDeleted(DebianImage);
37 return true;
38 }
39
test/windows/wslc/e2e/WSLCE2EContainerListTests.cpp
+3 -3
@@ -16,6 +16,7 @@ Abstract:
16 #include "ContainerModel.h"
17 #include "WSLCExecutor.h"
18 #include "WSLCE2EHelpers.h"
19 +#include "TestImageRegistry.h"
20
21 namespace WSLCE2ETests {
22 using namespace wsl::shared;
@@ -29,7 +30,7 @@ class WSLCE2EContainerListTests
30
31 TEST_CLASS_SETUP(ClassSetup)
32 {
32 - EnsureImageIsLoaded(DebianImage);
33 + TestImageRegistry::Instance().EnsureLoaded(DebianImage);
34 return true;
35 }
36
@@ -37,7 +38,6 @@ class WSLCE2EContainerListTests
38 {
39 EnsureContainerDoesNotExist(WslcContainerName);
40 EnsureContainerDoesNotExist(WslcContainerName2);
40 - EnsureImageIsDeleted(DebianImage);
41 return true;
42 }
43
@@ -495,4 +495,4 @@ private:
495 const std::wstring WslcContainerName2 = L"wslc-test-container-2";
496 const TestImage& DebianImage = DebianTestImage();
497 };
498 -} // namespace WSLCE2ETests
\ No newline at end of file
498 +} // namespace WSLCE2ETests
test/windows/wslc/e2e/WSLCE2EContainerLogsTests.cpp
+2 -2
@@ -15,6 +15,7 @@ Abstract:
15 #include "windows/Common.h"
16 #include "WSLCExecutor.h"
17 #include "WSLCE2EHelpers.h"
18 +#include "TestImageRegistry.h"
19
20 namespace WSLCE2ETests {
21
@@ -24,14 +25,13 @@ class WSLCE2EContainerLogsTests
25
26 TEST_CLASS_SETUP(ClassSetup)
27 {
27 - EnsureImageIsLoaded(DebianImage);
28 + TestImageRegistry::Instance().EnsureLoaded(DebianImage);
29 return true;
30 }
31
32 TEST_CLASS_CLEANUP(ClassCleanup)
33 {
34 EnsureContainerDoesNotExist(WslcContainerName);
34 - EnsureImageIsDeleted(DebianImage);
35 return true;
36 }
37
test/windows/wslc/e2e/WSLCE2EContainerPruneTests.cpp
+2 -1
@@ -15,6 +15,7 @@ Abstract:
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;
@@ -25,7 +26,7 @@ class WSLCE2EContainerPruneTests
26
27 TEST_CLASS_SETUP(ClassSetup)
28 {
28 - EnsureImageIsLoaded(DebianImage);
29 + TestImageRegistry::Instance().EnsureLoaded(DebianImage);
30
31 // Clean up any leftover containers from previous failed runs
32 EnsureContainerDoesNotExist(L"prune-test-container");
test/windows/wslc/e2e/WSLCE2EContainerRemoveTests.cpp
+4 -4
@@ -15,6 +15,7 @@ Abstract:
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;
@@ -25,7 +26,7 @@ class WSLCE2EContainerRemoveTests
26
27 TEST_CLASS_SETUP(ClassSetup)
28 {
28 - EnsureImageIsLoaded(DebianImage);
29 + TestImageRegistry::Instance().EnsureLoaded(DebianImage);
30 BuildAnonymousVolumeImage();
31 return true;
32 }
@@ -35,8 +36,7 @@ class WSLCE2EContainerRemoveTests
36 EnsureContainerDoesNotExist(WslcContainerName);
37 EnsureContainerDoesNotExist(WslcContainerName2);
38 EnsureVolumeDoesNotExist(TestVolumeName);
38 - EnsureImageIsDeleted(AnonymousVolumeImage);
39 - EnsureImageIsDeleted(DebianImage);
39 + TestImageRegistry::Instance().Delete(AnonymousVolumeImage);
40 return true;
41 }
42
@@ -268,4 +268,4 @@ private:
268 // Derived from DebianImage, so it must be deleted first in ClassCleanup.
269 const TestImage AnonymousVolumeImage{.Name = L"wslc-e2e-container-remove-anon", .Tag = L"latest"};
270 };
271 -} // namespace WSLCE2ETests
\ No newline at end of file
271 +} // namespace WSLCE2ETests
test/windows/wslc/e2e/WSLCE2EContainerRunTests.cpp
+4 -6
@@ -15,6 +15,7 @@ Abstract:
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;
@@ -25,9 +26,9 @@ class WSLCE2EContainerRunTests
26
27 TEST_CLASS_SETUP(ClassSetup)
28 {
28 - EnsureImageIsLoaded(DebianImage);
29 - EnsureImageIsLoaded(HelloWorldImage);
30 - EnsureImageIsLoaded(PythonImage);
29 + TestImageRegistry::Instance().EnsureLoaded(DebianImage);
30 + TestImageRegistry::Instance().EnsureLoaded(HelloWorldImage);
31 + TestImageRegistry::Instance().EnsureLoaded(PythonImage);
32
33 VERIFY_IS_TRUE(::SetEnvironmentVariableW(HostEnvVariableName.c_str(), HostEnvVariableValue.c_str()));
34 VERIFY_IS_TRUE(::SetEnvironmentVariableW(HostEnvVariableName2.c_str(), HostEnvVariableValue2.c_str()));
@@ -43,9 +44,6 @@ class WSLCE2EContainerRunTests
44 {
45 EnsureContainerDoesNotExist(WslcContainerName);
46 EnsureContainerDoesNotExist(WslcContainerName2);
46 - EnsureImageIsDeleted(DebianImage);
47 - EnsureImageIsDeleted(HelloWorldImage);
48 - EnsureImageIsDeleted(PythonImage);
47 EnsureVolumeDoesNotExist(WslcVolumeName);
48 EnsureNetworkDoesNotExist(TestNetworkName);
49
test/windows/wslc/e2e/WSLCE2EContainerStatsTests.cpp
+2 -2
@@ -15,6 +15,7 @@ Abstract:
15 #include "windows/Common.h"
16 #include "WSLCExecutor.h"
17 #include "WSLCE2EHelpers.h"
18 +#include "TestImageRegistry.h"
19
20 namespace WSLCE2ETests {
21
@@ -27,14 +28,13 @@ class WSLCE2EContainerStatsTests
28
29 TEST_CLASS_SETUP(ClassSetup)
30 {
30 - EnsureImageIsLoaded(DebianImage);
31 + TestImageRegistry::Instance().EnsureLoaded(DebianImage);
32 return true;
33 }
34
35 TEST_CLASS_CLEANUP(ClassCleanup)
36 {
37 EnsureContainerDoesNotExist(WslcContainerName);
37 - EnsureImageIsDeleted(DebianImage);
38 return true;
39 }
40
test/windows/wslc/e2e/WSLCE2EContainerStopTests.cpp
+2 -2
@@ -15,6 +15,7 @@ Abstract:
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;
@@ -25,7 +26,7 @@ class WSLCE2EContainerStopTests
26
27 TEST_CLASS_SETUP(ClassSetup)
28 {
28 - EnsureImageIsLoaded(DebianImage);
29 + TestImageRegistry::Instance().EnsureLoaded(DebianImage);
30 return true;
31 }
32
@@ -33,7 +34,6 @@ class WSLCE2EContainerStopTests
34 {
35 EnsureContainerDoesNotExist(WslcContainerName);
36 EnsureContainerDoesNotExist(WslcContainerName2);
36 - EnsureImageIsDeleted(DebianImage);
37 return true;
38 }
39
test/windows/wslc/e2e/WSLCE2EGlobalTests.cpp
+9 -5
@@ -16,6 +16,7 @@ Abstract:
16 #include "WSLCCLITestHelpers.h"
17 #include "WSLCExecutor.h"
18 #include "WSLCE2EHelpers.h"
19 +#include "TestImageRegistry.h"
20 #include "WSLCSessionDefaults.h"
21 #include "Argument.h"
22
@@ -485,7 +486,7 @@ class WSLCE2EGlobalTests
486 auto session = TestSession::Create(sessionName);
487
488 // Load the Debian image into the test session to avoid hitting Docker Hub rate limits.
488 - EnsureImageIsLoaded(DebianTestImage(), session.Name());
489 + TestImageRegistry::Instance().EnsureLoaded(DebianTestImage(), session.Name());
490
491 // Verify targeting a non-existent session fails.
492 auto result = RunWslc(L"--session INVALID_SESSION_NAME container list");
@@ -505,17 +506,20 @@ class WSLCE2EGlobalTests
506 result = RunWslc(std::format(L"--session \"{}\" container list", session.Name()));
507 result.Verify({.Stderr = L"", .ExitCode = 0});
508
508 - // Add a container to the new session.
509 + // Add a container to the new session. The listing checks below match on substrings, so the
510 + // name carries the session's unique suffix: "test-cont" on its own is a prefix of the
511 + // "wslc-test-container" names other tests leave in the default session.
512 + const auto containerName = std::format(L"wslc-session-cont-{}", guidStr.substr(0, 8));
513 result = RunWslc(std::format(
510 - L"--session \"{}\" container create --name {} {}", session.Name(), L"test-cont", DebianTestImage().NameAndTag()));
514 + L"--session \"{}\" container create --name {} {}", session.Name(), containerName, DebianTestImage().NameAndTag()));
515 result.Dump(); // Dump so it is easier to find any potential issues with the pull in the test output.
516 result.Verify({.ExitCode = 0});
517
518 // Verify container exists in the custom session
515 - VerifyContainerIsListed(L"test-cont", L"created", session.Name());
519 + VerifyContainerIsListed(containerName, L"created", session.Name());
520
521 // Verify container does not exist in the default CLI session.
518 - VerifyContainerIsNotListed(L"test-cont");
522 + VerifyContainerIsNotListed(containerName);
523 }
524
525 WSLC_TEST_METHOD(WSLCE2E_Session_Shell)
test/windows/wslc/e2e/WSLCE2EHelpers.cpp
+1 -51
@@ -18,6 +18,7 @@ Abstract:
18 #include "windows/Common.h"
19 #include "WSLCExecutor.h"
20 #include "WSLCE2EHelpers.h"
21 +#include "TestImageRegistry.h"
22 #include <JsonUtils.h>
23 #include <wslutil.h>
24
@@ -382,25 +383,6 @@ void EnsureImageContainersAreDeleted(const TestImage& image)
383 }
384 }
385
385 -void EnsureImageIsDeleted(const TestImage& image)
386 -{
387 - auto result = RunWslc(L"image list --format json");
388 - result.Verify({.Stderr = L"", .ExitCode = 0});
389 -
390 - auto images = ParseNdjsonOutputAs<wsl::windows::wslc::models::ImageOutputInformation>(result);
391 - for (const auto& img : images)
392 - {
393 - if (img.Repository == wsl::shared::string::WideToMultiByte(image.Name) &&
394 - img.Tag == wsl::shared::string::WideToMultiByte(image.Tag))
395 - {
396 - EnsureImageContainersAreDeleted(image);
397 - auto deleteResult = RunWslc(std::format(L"image delete --force {}", image.NameAndTag()));
398 - deleteResult.Verify({.Stderr = L"", .ExitCode = 0});
399 - break;
400 - }
401 - }
402 -}
403 -
386 void DeleteImagesWithRepositoryPrefix(const std::wstring& repositoryPrefix)
387 {
388 auto result = RunWslc(L"image list --format json");
@@ -443,38 +425,6 @@ void EnsureNoUntaggedImages()
425 }
426 }
427
446 -void EnsureImageIsLoaded(const TestImage& image, const std::wstring& sessionName)
447 -{
448 - std::wstring listCommand = L"image list --format json";
449 - if (!sessionName.empty())
450 - {
451 - listCommand = std::format(L"--session \"{}\" image list --format json", sessionName);
452 - }
453 -
454 - auto result = RunWslc(listCommand);
455 - result.Verify({.Stderr = L"", .ExitCode = 0});
456 -
457 - auto images = ParseNdjsonOutputAs<wsl::windows::wslc::models::ImageOutputInformation>(result);
458 - for (const auto& img : images)
459 - {
460 - if (img.Repository == wsl::shared::string::WideToMultiByte(image.Name) &&
461 - img.Tag == wsl::shared::string::WideToMultiByte(image.Tag))
462 - {
463 - return;
464 - }
465 - }
466 -
467 - // Image not found, load it
468 - std::wstring loadCommand = std::format(L"image load --input \"{}\"", image.Path.wstring());
469 - if (!sessionName.empty())
470 - {
471 - loadCommand = std::format(L"--session \"{}\" image load --input \"{}\"", sessionName, image.Path.wstring());
472 - }
473 -
474 - auto loadResult = RunWslc(loadCommand);
475 - loadResult.Verify({.Stderr = L"", .ExitCode = 0});
476 -}
477 -
428 void EnsureSessionIsTerminated(const std::wstring& sessionName)
429 {
430 std::wstring targetSession = sessionName;
test/windows/wslc/e2e/WSLCE2EHelpers.h
-2
@@ -147,8 +147,6 @@ wsl::windows::common::wslc_schema::Network InspectNetwork(const std::wstring& ne
147 std::vector<wsl::windows::wslc::models::ContainerInformation> ListAllContainers();
148
149 void EnsureContainerDoesNotExist(const std::wstring& containerName);
150 -void EnsureImageIsLoaded(const TestImage& image, const std::wstring& sessionName = L"");
151 -void EnsureImageIsDeleted(const TestImage& image);
150 void DeleteImagesWithRepositoryPrefix(const std::wstring& repositoryPrefix);
151 void EnsureImageContainersAreDeleted(const TestImage& image);
152 void EnsureNoUntaggedImages();
test/windows/wslc/e2e/WSLCE2EImageBuildTests.cpp
+3 -3
@@ -15,6 +15,7 @@ Abstract:
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;
@@ -26,14 +27,13 @@ class WSLCE2EImageBuildTests
27 TEST_CLASS_SETUP(ClassSetup)
28 {
29 DeleteImagesWithRepositoryPrefix(c_builtImagePrefix);
29 - EnsureImageIsLoaded(DebianTestImage());
30 + TestImageRegistry::Instance().EnsureLoaded(DebianTestImage());
31 return true;
32 }
33
34 TEST_CLASS_CLEANUP(ClassCleanup)
35 {
36 DeleteImagesWithRepositoryPrefix(c_builtImagePrefix);
36 - EnsureImageIsDeleted(DebianTestImage());
37 return true;
38 }
39
@@ -173,7 +173,7 @@ class WSLCE2EImageBuildTests
173 WSLC_TEST_METHOD(WSLCE2E_Image_Build_Pull_Success)
174 {
175 // A local registry acts as the private image source that --pull re-resolves the base image from.
176 - EnsureImageIsLoaded(AlpineTestImage());
176 + TestImageRegistry::Instance().EnsureLoaded(AlpineTestImage());
177
178 auto session = OpenDefaultElevatedSession();
179 auto [registryContainer, registryAddress] = StartLocalRegistry(*session, "", "", c_registryPort);
test/windows/wslc/e2e/WSLCE2EImageDeleteTests.cpp
+14 -13
@@ -15,6 +15,7 @@ Abstract:
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;
@@ -26,18 +27,18 @@ class WSLCE2EImageDeleteTests
27 TEST_METHOD_SETUP(MethodSetup)
28 {
29 EnsureContainerDoesNotExist(WslcContainerName);
29 - EnsureImageIsDeleted(DebianImage);
30 - EnsureImageIsDeleted(AlpineImage);
31 - EnsureImageIsDeleted(NoPruneTaggedImage);
30 + TestImageRegistry::Instance().Delete(DebianImage);
31 + TestImageRegistry::Instance().Delete(AlpineImage);
32 + TestImageRegistry::Instance().Delete(NoPruneTaggedImage);
33 return true;
34 }
35
36 TEST_CLASS_CLEANUP(ClassCleanup)
37 {
38 EnsureContainerDoesNotExist(WslcContainerName);
38 - EnsureImageIsDeleted(DebianImage);
39 - EnsureImageIsDeleted(AlpineImage);
40 - EnsureImageIsDeleted(NoPruneTaggedImage);
39 + TestImageRegistry::Instance().Delete(DebianImage);
40 + TestImageRegistry::Instance().Delete(AlpineImage);
41 + TestImageRegistry::Instance().Delete(NoPruneTaggedImage);
42 return true;
43 }
44
@@ -64,7 +65,7 @@ class WSLCE2EImageDeleteTests
65
66 WSLC_TEST_METHOD(WSLCE2E_Image_Delete_UnusedImage_Success)
67 {
67 - EnsureImageIsLoaded(DebianImage);
68 + TestImageRegistry::Instance().EnsureLoaded(DebianImage);
69 VerifyImageIsNotUsed(DebianImage);
70
71 auto result = RunWslc(std::format(L"image delete {}", DebianImage.Name));
@@ -73,8 +74,8 @@ class WSLCE2EImageDeleteTests
74
75 WSLC_TEST_METHOD(WSLCE2E_Image_Delete_MultipleUnusedImages_Success)
76 {
76 - EnsureImageIsLoaded(DebianImage);
77 - EnsureImageIsLoaded(AlpineImage);
77 + TestImageRegistry::Instance().EnsureLoaded(DebianImage);
78 + TestImageRegistry::Instance().EnsureLoaded(AlpineImage);
79 VerifyImageIsNotUsed(DebianImage);
80 VerifyImageIsNotUsed(AlpineImage);
81
@@ -84,7 +85,7 @@ class WSLCE2EImageDeleteTests
85
86 WSLC_TEST_METHOD(WSLCE2E_Image_Delete_UsedImage_Failure)
87 {
87 - EnsureImageIsLoaded(DebianImage);
88 + TestImageRegistry::Instance().EnsureLoaded(DebianImage);
89 VerifyImageIsNotUsed(DebianImage);
90
91 auto createResult = RunWslc(std::format(L"container create --name {} {}", WslcContainerName, DebianImage.NameAndTag()));
@@ -109,7 +110,7 @@ class WSLCE2EImageDeleteTests
110
111 WSLC_TEST_METHOD(WSLCE2E_Image_DeleteForce_UsedImage_Success)
112 {
112 - EnsureImageIsLoaded(DebianImage);
113 + TestImageRegistry::Instance().EnsureLoaded(DebianImage);
114 VerifyImageIsNotUsed(DebianImage);
115
116 auto createResult = RunWslc(std::format(L"container create --name {} {}", WslcContainerName, DebianImage.NameAndTag()));
@@ -125,8 +126,8 @@ class WSLCE2EImageDeleteTests
126 {
127 // Tag debian a second time, then remove via the alias with --no-prune.
128 // The alias must disappear while the original tag stays resolvable.
128 - EnsureImageIsLoaded(DebianImage);
129 - EnsureImageIsDeleted(NoPruneTaggedImage);
129 + TestImageRegistry::Instance().EnsureLoaded(DebianImage);
130 + TestImageRegistry::Instance().Delete(NoPruneTaggedImage);
131
132 auto tagResult = RunWslc(std::format(L"image tag {} {}", DebianImage.NameAndTag(), NoPruneTaggedImage.NameAndTag()));
133 tagResult.Verify({.Stderr = L"", .ExitCode = 0});
test/windows/wslc/e2e/WSLCE2EImageImportTests.cpp
+4 -4
@@ -15,6 +15,7 @@ Abstract:
15 #include "windows/Common.h"
16 #include "WSLCExecutor.h"
17 #include "WSLCE2EHelpers.h"
18 +#include "TestImageRegistry.h"
19 #include "ImageModel.h"
20
21 namespace WSLCE2ETests {
@@ -26,16 +27,15 @@ class WSLCE2EImageImportTests
27
28 TEST_CLASS_CLEANUP(ClassCleanup)
29 {
29 - EnsureImageIsDeleted(DebianImage);
30 - EnsureImageIsDeleted(ImportedImage);
30 + TestImageRegistry::Instance().Delete(ImportedImage);
31 EnsureNoUntaggedImages();
32 return true;
33 }
34
35 TEST_METHOD_SETUP(MethodSetup)
36 {
37 - EnsureImageIsLoaded(DebianImage);
38 - EnsureImageIsDeleted(ImportedImage);
37 + TestImageRegistry::Instance().EnsureLoaded(DebianImage);
38 + TestImageRegistry::Instance().Delete(ImportedImage);
39 EnsureNoUntaggedImages();
40 SavedArchivePath = wsl::windows::common::filesystem::GetTempFilename();
41 return true;
test/windows/wslc/e2e/WSLCE2EImageInspectTests.cpp
+4 -4
@@ -15,6 +15,7 @@ Abstract:
15 #include "windows/Common.h"
16 #include "WSLCExecutor.h"
17 #include "WSLCE2EHelpers.h"
18 +#include "TestImageRegistry.h"
19 #include <wslc_schema.h>
20
21 namespace WSLCE2ETests {
@@ -26,14 +27,13 @@ class WSLCE2EImageInspectTests
27
28 TEST_CLASS_SETUP(ClassSetup)
29 {
29 - EnsureImageIsLoaded(DebianImage);
30 + TestImageRegistry::Instance().EnsureLoaded(DebianImage);
31 return true;
32 }
33
34 TEST_CLASS_CLEANUP(ClassCleanup)
35 {
35 - EnsureImageIsDeleted(BuiltExposeImage);
36 - EnsureImageIsDeleted(DebianImage);
36 + TestImageRegistry::Instance().Delete(BuiltExposeImage);
37 return true;
38 }
39
@@ -140,4 +140,4 @@ private:
140 const TestImage& InvalidImage = InvalidTestImage();
141 const TestImage BuiltExposeImage{L"wslc-e2e-inspect-config-extras", L"latest", L""};
142 };
143 -} // namespace WSLCE2ETests
\ No newline at end of file
143 +} // namespace WSLCE2ETests
test/windows/wslc/e2e/WSLCE2EImageListTests.cpp
+4 -5
@@ -16,6 +16,7 @@ Abstract:
16 #include "ImageModel.h"
17 #include "WSLCExecutor.h"
18 #include "WSLCE2EHelpers.h"
19 +#include "TestImageRegistry.h"
20
21 namespace WSLCE2ETests {
22 using namespace wsl::shared;
@@ -28,15 +29,13 @@ class WSLCE2EImageListTests
29
30 TEST_CLASS_SETUP(ClassSetup)
31 {
31 - EnsureImageIsLoaded(DebianImage);
32 - EnsureImageIsLoaded(AlpineImage);
32 + TestImageRegistry::Instance().EnsureLoaded(DebianImage);
33 + TestImageRegistry::Instance().EnsureLoaded(AlpineImage);
34 return true;
35 }
36
37 TEST_CLASS_CLEANUP(ClassCleanup)
38 {
38 - EnsureImageIsDeleted(DebianImage);
39 - EnsureImageIsDeleted(AlpineImage);
39 return true;
40 }
41
@@ -476,4 +475,4 @@ private:
475 const TestImage& DebianImage = DebianTestImage();
476 const TestImage& AlpineImage = AlpineTestImage();
477 };
479 -} // namespace WSLCE2ETests
\ No newline at end of file
478 +} // namespace WSLCE2ETests
test/windows/wslc/e2e/WSLCE2EImagePruneTests.cpp
+12 -11
@@ -15,6 +15,7 @@ Abstract:
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;
@@ -25,13 +26,13 @@ class WSLCE2EImagePruneTests
26
27 TEST_CLASS_SETUP(ClassSetup)
28 {
28 - EnsureImageIsLoaded(DebianImage);
29 + TestImageRegistry::Instance().EnsureLoaded(DebianImage);
30 return true;
31 }
32
33 TEST_CLASS_CLEANUP(ClassCleanup)
34 {
34 - EnsureImageIsLoaded(DebianImage);
35 + TestImageRegistry::Instance().EnsureLoaded(DebianImage);
36 return true;
37 }
38
@@ -57,12 +58,12 @@ class WSLCE2EImagePruneTests
58 // 1. Tag debian as prune-target:v1
59 // 2. Delete the original debian:latest tag so prune-target:v1 is the only reference
60 // 3. Tag alpine as prune-target:v1, overwriting it — debian image is now dangling
60 - EnsureImageIsLoaded(AlpineImage);
61 - auto cleanup = wil::scope_exit([&]() {
61 + TestImageRegistry::Instance().EnsureLoaded(AlpineImage);
62 + auto cleanup = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [&]() {
63 RunWslc(L"image prune");
64 RunWslc(L"image delete prune-target:v1");
64 - EnsureImageIsDeleted(AlpineImage);
65 - EnsureImageIsLoaded(DebianImage);
65 + TestImageRegistry::Instance().Delete(AlpineImage);
66 + TestImageRegistry::Instance().Restore(DebianImage);
67 });
68
69 RunWslc(std::format(L"image tag {} prune-target:v1", DebianImage.NameAndTag())).Verify({.Stderr = L"", .ExitCode = 0});
@@ -92,7 +93,7 @@ class WSLCE2EImagePruneTests
93
94 WSLC_TEST_METHOD(WSLCE2E_Image_Prune_AllFlag)
95 {
95 - auto cleanup = wil::scope_exit([&]() { EnsureImageIsLoaded(DebianImage); });
96 + auto cleanup = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [&]() { TestImageRegistry::Instance().Restore(DebianImage); });
97
98 // --all should prune unused images (not just dangling)
99 const auto result = RunWslc(L"image prune --all");
@@ -131,12 +132,12 @@ class WSLCE2EImagePruneTests
132 WSLC_TEST_METHOD(WSLCE2E_Image_Prune_Filter_LabelPreservesDangling)
133 {
134 // Create a dangling debian image (same trick as WSLCE2E_Image_Prune_DanglingImage).
134 - EnsureImageIsLoaded(AlpineImage);
135 - auto cleanup = wil::scope_exit([&]() {
135 + TestImageRegistry::Instance().EnsureLoaded(AlpineImage);
136 + auto cleanup = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [&]() {
137 RunWslc(L"image prune");
138 RunWslc(L"image delete prune-target:v1");
138 - EnsureImageIsDeleted(AlpineImage);
139 - EnsureImageIsLoaded(DebianImage);
139 + TestImageRegistry::Instance().Delete(AlpineImage);
140 + TestImageRegistry::Instance().Restore(DebianImage);
141 });
142
143 RunWslc(std::format(L"image tag {} prune-target:v1", DebianImage.NameAndTag())).Verify({.Stderr = L"", .ExitCode = 0});
test/windows/wslc/e2e/WSLCE2EImageSaveTests.cpp
+10 -9
@@ -15,6 +15,7 @@ Abstract:
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;
@@ -25,14 +26,14 @@ class WSLCE2EImageSaveTests
26
27 TEST_CLASS_CLEANUP(ClassCleanup)
28 {
28 - EnsureImageIsDeleted(DebianImage);
29 - EnsureImageIsDeleted(AlpineImage);
29 + TestImageRegistry::Instance().Delete(DebianImage);
30 + TestImageRegistry::Instance().Delete(AlpineImage);
31 return true;
32 }
33
34 TEST_METHOD_SETUP(MethodSetup)
35 {
35 - EnsureImageIsLoaded(DebianImage);
36 + TestImageRegistry::Instance().EnsureLoaded(DebianImage);
37 SavedArchivePath = wsl::windows::common::filesystem::GetTempFilename();
38 return true;
39 }
@@ -81,7 +82,7 @@ class WSLCE2EImageSaveTests
82 saveResult.Verify({.Stdout = L"", .Stderr = L"", .ExitCode = 0});
83
84 // Delete source image
84 - EnsureImageIsDeleted(DebianImage);
85 + TestImageRegistry::Instance().Delete(DebianImage);
86
87 // Load from saved archive
88 auto loadResult = RunWslc(std::format(L"image load --input \"{}\"", SavedArchivePath.wstring()));
@@ -120,7 +121,7 @@ class WSLCE2EImageSaveTests
121 saveResult.Verify({.Stdout = L"", .Stderr = L"", .ExitCode = 0});
122
123 // Delete source image
123 - EnsureImageIsDeleted(DebianImage);
124 + TestImageRegistry::Instance().Delete(DebianImage);
125
126 // Load from saved archive
127 auto loadResult = RunWslc(std::format(L"image load --input \"{}\"", SavedArchivePath.wstring()));
@@ -132,13 +133,13 @@ class WSLCE2EImageSaveTests
133 }
134 WSLC_TEST_METHOD(WSLCE2E_Image_Save_MultipleImages_Load)
135 {
135 - EnsureImageIsLoaded(AlpineImage);
136 + TestImageRegistry::Instance().EnsureLoaded(AlpineImage);
137
138 // Force a pristine re-load of DebianImage at the end so subsequent tests (in fast mode)
139 // see the same on-disk tar as DebianImage.Path. Without this, reloading from a
140 // multi-image archive can produce a slightly different on-disk representation that
141 // breaks byte-exact size checks in WSLCE2E_Image_Save_Success.
141 - auto restoreDebian = wil::scope_exit([&]() { EnsureImageIsDeleted(DebianImage); });
142 + auto restoreDebian = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [&]() { TestImageRegistry::Instance().Delete(DebianImage); });
143
144 // Save both images into a single archive.
145 const auto saveResult = RunWslc(std::format(
@@ -146,8 +147,8 @@ class WSLCE2EImageSaveTests
147 saveResult.Verify({.Stdout = L"", .Stderr = L"", .ExitCode = 0});
148
149 // Delete both source images.
149 - EnsureImageIsDeleted(DebianImage);
150 - EnsureImageIsDeleted(AlpineImage);
150 + TestImageRegistry::Instance().Delete(DebianImage);
151 + TestImageRegistry::Instance().Delete(AlpineImage);
152
153 // Load both images back from the single archive.
154 const auto loadResult = RunWslc(std::format(L"image load --input \"{}\"", SavedArchivePath.wstring()));
test/windows/wslc/e2e/WSLCE2EImageTagTests.cpp
+8 -9
@@ -15,6 +15,7 @@ Abstract:
15 #include "windows/Common.h"
16 #include "WSLCExecutor.h"
17 #include "WSLCE2EHelpers.h"
18 +#include "TestImageRegistry.h"
19
20 namespace WSLCE2ETests {
21
@@ -26,17 +27,15 @@ class WSLCE2EImageTagTests
27
28 TEST_METHOD_SETUP(MethodSetup)
29 {
29 - EnsureImageIsDeleted(DebianTaggedImage);
30 - EnsureImageIsLoaded(DebianImage);
31 - EnsureImageIsLoaded(AlpineImage);
30 + TestImageRegistry::Instance().Delete(DebianTaggedImage);
31 + TestImageRegistry::Instance().EnsureLoaded(DebianImage);
32 + TestImageRegistry::Instance().EnsureLoaded(AlpineImage);
33 return true;
34 }
35
36 TEST_CLASS_CLEANUP(ClassCleanup)
37 {
37 - EnsureImageIsDeleted(DebianTaggedImage);
38 - EnsureImageIsDeleted(DebianImage);
39 - EnsureImageIsDeleted(AlpineImage);
38 + TestImageRegistry::Instance().Delete(DebianTaggedImage);
39 return true;
40 }
41
@@ -152,7 +151,7 @@ class WSLCE2EImageTagTests
151 auto result = RunWslc(std::format(L"image tag {} {}", DebianImage.NameAndTag(), DebianTaggedImage.NameAndTag()));
152 result.Verify({.Stdout = L"", .Stderr = L"", .ExitCode = 0});
153
155 - EnsureImageIsDeleted(DebianImage);
154 + TestImageRegistry::Instance().Delete(DebianImage);
155 VerifyImageIsListed(DebianTaggedImage);
156 }
157
@@ -161,7 +160,7 @@ class WSLCE2EImageTagTests
160 auto result = RunWslc(std::format(L"image tag {} {}", DebianImage.NameAndTag(), DebianTaggedImage.NameAndTag()));
161 result.Verify({.Stdout = L"", .Stderr = L"", .ExitCode = 0});
162
164 - EnsureImageIsDeleted(DebianTaggedImage);
163 + TestImageRegistry::Instance().Delete(DebianTaggedImage);
164 VerifyImageIsListed(DebianImage);
165 }
166
@@ -171,4 +170,4 @@ private:
170 const TestImage& InvalidImage = InvalidTestImage();
171 const TestImage DebianTaggedImage{L"debian", L"e2e-new-tag"};
172 };
174 -} // namespace WSLCE2ETests
\ No newline at end of file
173 +} // namespace WSLCE2ETests
test/windows/wslc/e2e/WSLCE2EInspectTests.cpp
+4 -3
@@ -15,6 +15,7 @@ Abstract:
15 #include "windows/Common.h"
16 #include "WSLCExecutor.h"
17 #include "WSLCE2EHelpers.h"
18 +#include "TestImageRegistry.h"
19 #include <wslc_schema.h>
20 #include <JsonUtils.h>
21
@@ -27,7 +28,7 @@ class WSLCE2EInspectTests
28
29 TEST_CLASS_SETUP(ClassSetup)
30 {
30 - EnsureImageIsLoaded(DebianImage);
31 + TestImageRegistry::Instance().EnsureLoaded(DebianImage);
32 return true;
33 }
34
@@ -37,7 +38,6 @@ class WSLCE2EInspectTests
38 EnsureContainerDoesNotExist(DebianImage.Name);
39 EnsureNetworkDoesNotExist(WslcNetworkName);
40 EnsureNetworkDoesNotExist(DebianImage.Name);
40 - EnsureImageIsDeleted(DebianImage);
41 return true;
42 }
43
@@ -166,7 +166,8 @@ class WSLCE2EInspectTests
166
167 WSLC_TEST_METHOD(WSLCE2E_Inspect_Container_InheritsImageLabels)
168 {
169 - auto imageCleanup = wil::scope_exit([&]() { EnsureImageIsDeleted(LabelInheritImage); });
169 + auto imageCleanup =
170 + wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [&]() { TestImageRegistry::Instance().Delete(LabelInheritImage); });
171 auto testRoot = std::filesystem::current_path() / L"wslc-e2e-inspect-inherit-labels";
172 auto cleanup = SetupTestDirectory(testRoot);
173
test/windows/wslc/e2e/WSLCE2ENetworkPruneTests.cpp
+2 -2
@@ -15,6 +15,7 @@ Abstract:
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;
@@ -25,7 +26,7 @@ class WSLCE2ENetworkPruneTests
26
27 TEST_CLASS_SETUP(ClassSetup)
28 {
28 - EnsureImageIsLoaded(DebianImage);
29 + TestImageRegistry::Instance().EnsureLoaded(DebianImage);
30 CleanUpAllTestState();
31 return true;
32 }
@@ -39,7 +40,6 @@ class WSLCE2ENetworkPruneTests
40 TEST_CLASS_CLEANUP(ClassCleanup)
41 {
42 CleanUpAllTestState();
42 - EnsureImageIsDeleted(DebianImage);
43 return true;
44 }
45
test/windows/wslc/e2e/WSLCE2ENetworkTests.cpp
+2 -2
@@ -15,6 +15,7 @@ Abstract:
15 #include "windows/Common.h"
16 #include "WSLCExecutor.h"
17 #include "WSLCE2EHelpers.h"
18 +#include "TestImageRegistry.h"
19 #include "Argument.h"
20
21 namespace WSLCE2ETests {
@@ -26,7 +27,7 @@ class WSLCE2ENetworkTests
27
28 TEST_CLASS_SETUP(ClassSetup)
29 {
29 - EnsureImageIsLoaded(DebianImage);
30 + TestImageRegistry::Instance().EnsureLoaded(DebianImage);
31 return true;
32 }
33
@@ -35,7 +36,6 @@ class WSLCE2ENetworkTests
36 EnsureContainerDoesNotExist(WslcContainerName);
37 EnsureContainerDoesNotExist(WslcTargetContainerName);
38 EnsureNetworkDoesNotExist(TestNetworkName);
38 - EnsureImageIsDeleted(DebianImage);
39 return true;
40 }
41
test/windows/wslc/e2e/WSLCE2EPushPullTests.cpp
+3 -2
@@ -16,6 +16,7 @@ Abstract:
16 #include "windows/Common.h"
17 #include "WSLCExecutor.h"
18 #include "WSLCE2EHelpers.h"
19 +#include "TestImageRegistry.h"
20 #include "Argument.h"
21
22 namespace WSLCE2ETests {
@@ -56,7 +57,7 @@ class WSLCE2EPushPullTests
57 WSLC_TEST_METHOD(WSLCE2E_Image_PushPull)
58 {
59 const auto& testImage = AlpineTestImage();
59 - EnsureImageIsLoaded(testImage);
60 + TestImageRegistry::Instance().EnsureLoaded(testImage);
61
62 // Start a local registry without auth.
63 auto session = OpenDefaultElevatedSession();
@@ -96,7 +97,7 @@ class WSLCE2EPushPullTests
97 WSLC_TEST_METHOD(WSLCE2E_Image_Pull_QuietOption)
98 {
99 const auto& testImage = AlpineTestImage();
99 - EnsureImageIsLoaded(testImage);
100 + TestImageRegistry::Instance().EnsureLoaded(testImage);
101
102 auto session = OpenDefaultElevatedSession();
103
test/windows/wslc/e2e/WSLCE2ERegistryTests.cpp
+2 -1
@@ -16,6 +16,7 @@ Abstract:
16 #include "windows/Common.h"
17 #include "WSLCExecutor.h"
18 #include "WSLCE2EHelpers.h"
19 +#include "TestImageRegistry.h"
20 #include "Argument.h"
21 #include <wslutil.h>
22
@@ -49,7 +50,7 @@ class WSLCE2ERegistryTests
50 WSLC_TEST_METHOD(WSLCE2E_Registry_LoginLogout_PushPull_AuthFlow)
51 {
52 const auto& testImage = AlpineTestImage();
52 - EnsureImageIsLoaded(testImage);
53 + TestImageRegistry::Instance().EnsureLoaded(testImage);
54
55 auto session = OpenDefaultElevatedSession();
56
test/windows/wslc/e2e/WSLCE2ETlsRegistryTests.cpp
+3 -2
@@ -19,6 +19,7 @@ Abstract:
19 #include "windows/Common.h"
20 #include "WSLCExecutor.h"
21 #include "WSLCE2EHelpers.h"
22 +#include "TestImageRegistry.h"
23 #include <wslutil.h>
24 #include <ncrypt.h>
25
@@ -223,7 +224,7 @@ class WSLCE2ETlsRegistryTests
224
225 auto cleanup = wil::scope_exit([&] { EnsureSessionIsTerminated(L"wslc-tls-untrusted"); });
226
226 - EnsureImageIsLoaded(image, session.Name());
227 + TestImageRegistry::Instance().EnsureLoaded(image, session.Name());
228
229 auto [registry, address] = StartLocalRegistry(session.Session(), "", "", c_registryPort, certDir.wstring());
230 VERIFY_ARE_EQUAL(std::format("{}:{}", c_registryIp, c_registryPort), address);
@@ -248,7 +249,7 @@ class WSLCE2ETlsRegistryTests
249
250 auto cleanup = wil::scope_exit([&] { EnsureSessionIsTerminated(L"wslc-tls-trusted"); });
251
251 - EnsureImageIsLoaded(image, session.Name());
252 + TestImageRegistry::Instance().EnsureLoaded(image, session.Name());
253
254 auto [registry, address] = StartLocalRegistry(session.Session(), "", "", c_registryPort, certDir.wstring());
255 VERIFY_ARE_EQUAL(std::format("{}:{}", c_registryIp, c_registryPort), address);
test/windows/wslc/e2e/WSLCE2EVolumePruneTests.cpp
+2 -2
@@ -15,6 +15,7 @@ Abstract:
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;
@@ -25,7 +26,7 @@ class WSLCE2EVolumePruneTests
26
27 TEST_CLASS_SETUP(ClassSetup)
28 {
28 - EnsureImageIsLoaded(DebianImage);
29 + TestImageRegistry::Instance().EnsureLoaded(DebianImage);
30 CleanUpAllTestState();
31 return true;
32 }
@@ -39,7 +40,6 @@ class WSLCE2EVolumePruneTests
40 TEST_CLASS_CLEANUP(ClassCleanup)
41 {
42 CleanUpAllTestState();
42 - EnsureImageIsDeleted(DebianImage);
43 return true;
44 }
45
test/windows/wslc/e2e/WSLCE2EVolumeRemoveTests.cpp
+2 -2
@@ -15,6 +15,7 @@ Abstract:
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;
@@ -25,7 +26,7 @@ class WSLCE2EVolumeRemoveTests
26
27 TEST_CLASS_SETUP(ClassSetup)
28 {
28 - EnsureImageIsLoaded(DebianImage);
29 + TestImageRegistry::Instance().EnsureLoaded(DebianImage);
30 return true;
31 }
32
@@ -40,7 +41,6 @@ class WSLCE2EVolumeRemoveTests
41 TEST_CLASS_CLEANUP(ClassCleanup)
42 {
43 EnsureContainerDoesNotExist(WslcContainerName);
43 - EnsureImageIsDeleted(DebianImage);
44 EnsureVolumeDoesNotExist(TestVolumeName);
45 EnsureVolumeDoesNotExist(TestVolumeName2);
46 return true;
test/windows/wslc/e2e/WSLCE2EWarningTests.cpp
+2 -2
@@ -17,6 +17,7 @@ Abstract:
17 #include "windows/Common.h"
18 #include "WSLCExecutor.h"
19 #include "WSLCE2EHelpers.h"
20 +#include "TestImageRegistry.h"
21 #include <WSLCProcessLauncher.h>
22
23 namespace WSLCE2ETests {
@@ -32,13 +33,12 @@ class WSLCE2EWarningTests
33 TEST_CLASS_SETUP(ClassSetup)
34 {
35 THROW_IF_WIN32_ERROR(WSAStartup(MAKEWORD(2, 2), &m_wsaData));
35 - EnsureImageIsLoaded(AlpineImage);
36 + TestImageRegistry::Instance().EnsureLoaded(AlpineImage);
37 return true;
38 }
39
40 TEST_CLASS_CLEANUP(ClassCleanup)
41 {
41 - EnsureImageIsDeleted(AlpineImage);
42 WSACleanup();
43 return true;
44 }