master
cpp 130 lines 3.83 KB
Raw
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::InvalidateSession(const std::wstring& sessionName)
87 {
88 std::erase_if(m_loaded, [&](const auto& image) { return image.SessionName == sessionName; });
89 m_seededSessions.erase(sessionName);
90 }
91
92 void TestImageRegistry::Load(const TestImage& image, const std::wstring& sessionName)
93 {
94 auto result = RunWslc(FormatCommand(sessionName, std::format(L"image load --input \"{}\"", image.Path.wstring())));
95 result.Verify({.Stderr = L"", .ExitCode = 0});
96
97 m_loaded.insert(MakeKey(image, sessionName));
98 }
99
100 void TestImageRegistry::Delete(const TestImage& image, const std::wstring& sessionName)
101 {
102 auto result = RunWslc(FormatCommand(sessionName, L"image list --format json"));
103 result.Verify({.Stderr = L"", .ExitCode = 0});
104
105 const auto images = ParseNdjsonOutputAs<wsl::windows::wslc::models::ImageOutputInformation>(result);
106 const auto name = wsl::shared::string::WideToMultiByte(image.Name);
107 const auto tag = wsl::shared::string::WideToMultiByte(image.Tag);
108 const bool present =
109 std::ranges::any_of(images, [&](const auto& candidate) { return candidate.Repository == name && candidate.Tag == tag; });
110
111 if (!present)
112 {
113 m_loaded.erase(MakeKey(image, sessionName));
114 return;
115 }
116
117 // Container enumeration is scoped to the default session, so named sessions rely on the
118 // force flag to remove the image out from under any containers still referencing it.
119 if (sessionName.empty())
120 {
121 EnsureImageContainersAreDeleted(image);
122 }
123
124 auto deleteResult = RunWslc(FormatCommand(sessionName, std::format(L"image delete --force {}", image.NameAndTag())));
125 deleteResult.Verify({.Stderr = L"", .ExitCode = 0});
126
127 m_loaded.erase(MakeKey(image, sessionName));
128 }
129
130 } // namespace WSLCE2ETests