From ac077646b0d18a37078f7ddda620896126bb63c4 Mon Sep 17 00:00:00 2001 From: Ben Hillis Date: Fri, 10 Jul 2026 11:15:59 -0700 Subject: [PATCH 1/5] Move OneBranch pipelines to Windows Server 2025 / VSE 2026 image Switch the OneBranch container image from the Server 2022 / VS 2022 image to the Server 2025 / VS Enterprise 2026 image. This brings the LLVM/Clang toolset from 19.1.x up to 20.1.8. Per the OneBranch "2025 Infra Support" guidance, the Server 2025 host is selected via the structured featureFlags.WindowsHostVersion Version field rather than a host-name string. The top-level WindowsHostVersion pipeline variable was unreferenced and is removed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: c700591a-bd3e-4ae9-996e-61b14b693852 --- .pipelines/wsl-build-nightly-onebranch.yml | 6 +++--- .pipelines/wsl-build-pr-onebranch.yml | 6 +++--- .pipelines/wsl-build-release-onebranch.yml | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.pipelines/wsl-build-nightly-onebranch.yml b/.pipelines/wsl-build-nightly-onebranch.yml index 1434dd233..4d0c0273d 100644 --- a/.pipelines/wsl-build-nightly-onebranch.yml +++ b/.pipelines/wsl-build-nightly-onebranch.yml @@ -9,8 +9,7 @@ schedules: always: true variables: - WindowsContainerImage: "onebranch.azurecr.io/windows/ltsc2022/vse2022:latest" - WindowsHostVersion: '1ESWindows2022' + WindowsContainerImage: "onebranch.azurecr.io/windows/ltsc2025/vse2026:latest" resources: repositories: @@ -26,7 +25,8 @@ extends: name: "windows_undocked" featureFlags: EnableCDPxPAT: false - WindowsHostVersion: 1ESWindows2022 + WindowsHostVersion: + Version: 2025 globalSdl: credscan: enabled: true diff --git a/.pipelines/wsl-build-pr-onebranch.yml b/.pipelines/wsl-build-pr-onebranch.yml index 92a8a4cbd..60d7d0085 100644 --- a/.pipelines/wsl-build-pr-onebranch.yml +++ b/.pipelines/wsl-build-pr-onebranch.yml @@ -5,8 +5,7 @@ trigger: - release/* variables: - WindowsContainerImage: "onebranch.azurecr.io/windows/ltsc2022/vse2022:latest" - WindowsHostVersion: '1ESWindows2022' + WindowsContainerImage: "onebranch.azurecr.io/windows/ltsc2025/vse2026:latest" resources: repositories: @@ -22,7 +21,8 @@ extends: name: "windows_undocked" featureFlags: EnableCDPxPAT: false - WindowsHostVersion: 1ESWindows2022 + WindowsHostVersion: + Version: 2025 globalSdl: suppression: suppressionFile: $(Build.SourcesDirectory)\.gdnsuppress diff --git a/.pipelines/wsl-build-release-onebranch.yml b/.pipelines/wsl-build-release-onebranch.yml index 3c63e0189..75ceb32f3 100644 --- a/.pipelines/wsl-build-release-onebranch.yml +++ b/.pipelines/wsl-build-release-onebranch.yml @@ -24,8 +24,7 @@ trigger: include: ['*.*.*'] variables: - WindowsContainerImage: "onebranch.azurecr.io/windows/ltsc2022/vse2022:latest" - WindowsHostVersion: '1ESWindows2022' + WindowsContainerImage: "onebranch.azurecr.io/windows/ltsc2025/vse2026:latest" resources: repositories: @@ -41,7 +40,8 @@ extends: name: "windows_undocked" featureFlags: EnableCDPxPAT: false - WindowsHostVersion: 1ESWindows2022 + WindowsHostVersion: + Version: 2025 globalSdl: credscan: enabled: true From 7636e812e81a063f2b91807b10b3787ddc6198f2 Mon Sep 17 00:00:00 2001 From: Ben Hillis Date: Fri, 10 Jul 2026 13:14:30 -0700 Subject: [PATCH 2/5] Reformat with clang-format 20.1.8 and prefer VS2026 for the VSE2026 image The OneBranch pipelines now run on the VSE2026 image, which ships clang-format 20.1.8 instead of VS2022's 19.1.5. Reformat the 52 files that 20.1.8 formats differently, and flip CMakeLists to prefer VS2026 (falling back to VS2022) so local formatting matches the pipeline again. This resolves the TODO to require VS2026 once CI supports it. Also replace the credential-looking example password in the WSLc C# API docs with a placeholder to clear a Credential Scanner (CSCAN-MSFT0090) hit. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d3de59ec-7508-440a-b7e5-1345aad2096a --- CMakeLists.txt | 11 +- .../csharp/core-classes/session.md | 2 +- src/linux/init/GnsEngine.cpp | 13 +- src/linux/netlinkutil/Address.cpp | 4 +- src/shared/inc/SocketChannel.h | 5 +- src/windows/common/NatNetworking.cpp | 10 +- src/windows/common/SubProcess.cpp | 10 +- src/windows/common/WslCoreConfig.cpp | 5 +- src/windows/common/WslSecurity.cpp | 19 +- src/windows/common/filesystem.cpp | 21 +- src/windows/common/notifications.cpp | 9 +- src/windows/common/wslutil.cpp | 15 +- src/windows/libwsl/WslCoreConfigInterface.cpp | 5 +- src/windows/service/exe/LxssInstance.cpp | 8 +- src/windows/service/exe/LxssUserSession.cpp | 18 +- .../service/exe/WSLCSessionManager.cpp | 5 +- src/windows/service/exe/WslCoreVm.cpp | 29 +- .../service/exe/WslMirroredNetworking.cpp | 5 +- .../wslc/arguments/ArgumentValidation.cpp | 4 +- .../wslc/services/ContainerService.cpp | 10 +- src/windows/wslcsession/DockerHTTPClient.h | 10 +- src/windows/wslcsession/WSLCContainer.cpp | 37 +- src/windows/wslcsession/WSLCSession.cpp | 20 +- src/windows/wslcsession/main.cpp | 5 +- src/windows/wslhost/main.cpp | 10 +- test/windows/Common.cpp | 11 +- test/windows/InstallerTests.cpp | 9 +- test/windows/NetworkTests.cpp | 92 ++-- test/windows/Plan9Tests.cpp | 7 +- test/windows/UnitTests.cpp | 84 ++-- test/windows/WSLCTests.cpp | 37 +- test/windows/WslcSdkTests.cpp | 40 +- test/windows/WslcSdkWinRTTests.cpp | 74 +-- test/windows/testplugin/Plugin.cpp | 10 +- test/windows/wslc/WSLCCLICommandUnitTests.cpp | 35 +- .../wslc/e2e/WSLCE2EContainerAttachTests.cpp | 4 +- .../wslc/e2e/WSLCE2EContainerCpTests.cpp | 5 +- .../wslc/e2e/WSLCE2EContainerCreateTests.cpp | 356 ++++++++------ .../wslc/e2e/WSLCE2EContainerExecTests.cpp | 43 +- .../wslc/e2e/WSLCE2EContainerListTests.cpp | 7 +- .../wslc/e2e/WSLCE2EContainerLogsTests.cpp | 19 +- .../wslc/e2e/WSLCE2EContainerRunTests.cpp | 445 ++++++++++-------- test/windows/wslc/e2e/WSLCE2EGlobalTests.cpp | 4 +- test/windows/wslc/e2e/WSLCE2EHelpers.cpp | 22 +- .../wslc/e2e/WSLCE2EImageBuildTests.cpp | 48 +- .../wslc/e2e/WSLCE2EImageInspectTests.cpp | 4 +- .../wslc/e2e/WSLCE2EImageListTests.cpp | 9 +- .../wslc/e2e/WSLCE2EImageSaveTests.cpp | 8 +- .../wslc/e2e/WSLCE2ENetworkPruneTests.cpp | 5 +- test/windows/wslc/e2e/WSLCE2ENetworkTests.cpp | 10 +- .../windows/wslc/e2e/WSLCE2ERegistryTests.cpp | 8 +- .../wslc/e2e/WSLCE2EVolumePruneTests.cpp | 5 +- .../wslc/e2e/WSLCE2EVolumeRemoveTests.cpp | 26 +- test/windows/wslc/e2e/WSLCExecutor.cpp | 10 +- 54 files changed, 971 insertions(+), 756 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c88fbb8e9..6c66e8a77 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -367,8 +367,8 @@ else() endif() # Determine the Visual Studio installation directory which contains LLVM tools. -# Supported versions: VS2022 and VS2026. -# Prefer VS2022 to keep local clang-format output aligned with pipeline expectations. +# Supported versions: VS2026 and VS2022. +# Prefer VS2026 to keep local clang-format output aligned with pipeline expectations. function(find_vs_install_dir VERSION_RANGE OUTPUT_VAR) execute_process( COMMAND "${VSWHERE_SOURCE_DIR}/vswhere.exe" -version "${VERSION_RANGE}" -products * -requires Microsoft.VisualStudio.Component.VC.Llvm.Clang -property installationPath -prerelease -latest @@ -380,12 +380,12 @@ function(find_vs_install_dir VERSION_RANGE OUTPUT_VAR) set(${OUTPUT_VAR} "${_vs_install_dir}" PARENT_SCOPE) endfunction() -find_vs_install_dir("[17.0,18.0)" VS_INSTALL_DIR) +find_vs_install_dir("[18.0,19.0)" VS_INSTALL_DIR) if (NOT VS_INSTALL_DIR) - find_vs_install_dir("[18.0,19.0)" VS_INSTALL_DIR) + find_vs_install_dir("[17.0,18.0)" VS_INSTALL_DIR) if (VS_INSTALL_DIR) - message(WARNING "Visual Studio 2022 was not found; using Visual Studio 2026 instead. clang-format output may differ from pipeline expectations.") + message(WARNING "Visual Studio 2026 was not found; using Visual Studio 2022 instead. clang-format output may differ from pipeline expectations.") endif() endif() @@ -394,7 +394,6 @@ if (NOT VS_INSTALL_DIR) endif() # Pick the first line returned from vswhere, in case multiple versions are returned. -# TODO: Remove this and require VS 2026 once the CI supports it. string(REGEX MATCH "([^\n\r]+)" VS_INSTALL_DIR "${VS_INSTALL_DIR}") if("${CMAKE_HOST_SYSTEM_PROCESSOR}" STREQUAL "AMD64") diff --git a/doc/docs/api-reference/csharp/core-classes/session.md b/doc/docs/api-reference/csharp/core-classes/session.md index d0a6da1e8..90c5c90a5 100644 --- a/doc/docs/api-reference/csharp/core-classes/session.md +++ b/doc/docs/api-reference/csharp/core-classes/session.md @@ -181,7 +181,7 @@ Authenticates to a registry and returns an identity token string. string token = session.Authenticate( new Uri("https://registry.example.com"), "user1", - "p@ssw0rd"); + ""); ``` ## Session.GetImages() diff --git a/src/linux/init/GnsEngine.cpp b/src/linux/init/GnsEngine.cpp index 5057e591a..d05f1cd32 100644 --- a/src/linux/init/GnsEngine.cpp +++ b/src/linux/init/GnsEngine.cpp @@ -182,8 +182,8 @@ void GnsEngine::ProcessNotification(const nlohmann::json& payload, Interface& in break; default: - throw RuntimeErrorWithSourceLocation(std::format( - "Unexpected LxGnsMessageNotification for interfaceName {}: {}", interface.Name(), payload["ResourceType"].get())); + throw RuntimeErrorWithSourceLocation( + std::format("Unexpected LxGnsMessageNotification for interfaceName {}: {}", interface.Name(), payload["ResourceType"].get())); break; } } @@ -573,8 +573,9 @@ std::tuple GnsEngine::ProcessNextMessage(wsl::shared::Transaction& tr auto table = manager.FindRoutingTableIdForInterface(interface); if (!table.has_value()) { - throw RuntimeErrorWithSourceLocation(std::format( - "LxGnsMessageInitialIpConfigurationNotification: failed to find routing table with name {}", interface.Name())); + throw RuntimeErrorWithSourceLocation( + std::format( + "LxGnsMessageInitialIpConfigurationNotification: failed to find routing table with name {}", interface.Name())); } GNS_LOG_INFO( @@ -706,8 +707,8 @@ std::tuple GnsEngine::ProcessNextMessage(wsl::shared::Transaction& tr break; } default: - throw RuntimeErrorWithSourceLocation(std::format( - "Unexpected Wslcore::Networking::OperationType : {}", static_cast(interfaceNetFilterRequest.operation))); + throw RuntimeErrorWithSourceLocation( + std::format("Unexpected Wslcore::Networking::OperationType : {}", static_cast(interfaceNetFilterRequest.operation))); break; } break; diff --git a/src/linux/netlinkutil/Address.cpp b/src/linux/netlinkutil/Address.cpp index e0b2d1ea8..c14c83395 100644 --- a/src/linux/netlinkutil/Address.cpp +++ b/src/linux/netlinkutil/Address.cpp @@ -73,8 +73,8 @@ Address Address::FromPrefixString(int family, const std::string& prefix) int err = inet_pton(family, match.str(1).c_str(), &tmpAddr); if (err != 1) { - throw RuntimeErrorWithSourceLocation(std::format( - "Parsed invalid address ({}) from prefix: {} and family: {} with error {} and errno {}", match.str(1), prefix, family, err, errno)); + throw RuntimeErrorWithSourceLocation( + std::format("Parsed invalid address ({}) from prefix: {} and family: {} with error {} and errno {}", match.str(1), prefix, family, err, errno)); } return Address{family, std::stoul(match.str(2)), match.str(1)}; diff --git a/src/shared/inc/SocketChannel.h b/src/shared/inc/SocketChannel.h index 9094b6876..ed0101913 100644 --- a/src/shared/inc/SocketChannel.h +++ b/src/shared/inc/SocketChannel.h @@ -637,8 +637,9 @@ class SocketChannel auto io = CreateIO(); gsl::span message; - io.AddHandle(std::make_unique( - m_socket.get(), m_buffer, m_pendingBytes, [&message](auto& received) { message = received; })); + io.AddHandle( + std::make_unique( + m_socket.get(), m_buffer, m_pendingBytes, [&message](auto& received) { message = received; })); io.Run(TimeoutToMilliseconds(timeout)); diff --git a/src/windows/common/NatNetworking.cpp b/src/windows/common/NatNetworking.cpp index 04f3db9a3..87bd98644 100644 --- a/src/windows/common/NatNetworking.cpp +++ b/src/windows/common/NatNetworking.cpp @@ -302,8 +302,9 @@ void NatNetworking::Initialize() if (!m_config.NatIpAddress.empty()) { - EMIT_USER_WARNING(wsl::shared::Localization::MessageFailedToCreateNetworkEndpoint( - m_config.NatIpAddress.c_str(), endpointProperties.IPAddress.c_str())); + EMIT_USER_WARNING( + wsl::shared::Localization::MessageFailedToCreateNetworkEndpoint( + m_config.NatIpAddress.c_str(), endpointProperties.IPAddress.c_str())); } // Record the new IP address associated to the endpoint. @@ -671,8 +672,9 @@ wsl::windows::common::hcs::unique_hcn_network NatNetworking::CreateNetwork(wsl:: // Note that the firewall config is NOT cleared here as we MUST always configure firewall if it has been requested natNetwork = CreateNetworkInternal(config); - EMIT_USER_WARNING(wsl::shared::Localization::MessageFailedToCreateNetwork( - previousRange.c_str(), config.NatNetwork.c_str(), wsl::windows::common::wslutil::GetSystemErrorString(error).c_str())); + EMIT_USER_WARNING( + wsl::shared::Localization::MessageFailedToCreateNetwork( + previousRange.c_str(), config.NatNetwork.c_str(), wsl::windows::common::wslutil::GetSystemErrorString(error).c_str())); } }); diff --git a/src/windows/common/SubProcess.cpp b/src/windows/common/SubProcess.cpp index edea07dc2..04e993604 100644 --- a/src/windows/common/SubProcess.cpp +++ b/src/windows/common/SubProcess.cpp @@ -245,8 +245,9 @@ SubProcess::ProcessOutput SubProcess::RunAndCaptureOutput(DWORD Timeout, HANDLE std::string stdoutNative; std::string stderrNative; - io.AddHandle(std::make_unique( - std::move(stdoutRead), [&](const gsl::span& buffer) { stdoutNative.append(buffer.data(), buffer.size()); })); + io.AddHandle(std::make_unique(std::move(stdoutRead), [&](const gsl::span& buffer) { + stdoutNative.append(buffer.data(), buffer.size()); + })); wil::unique_hfile stderrWrite; if (StdErr == nullptr) @@ -257,8 +258,9 @@ SubProcess::ProcessOutput SubProcess::RunAndCaptureOutput(DWORD Timeout, HANDLE m_stdErr = stderrWrite.get(); - io.AddHandle(std::make_unique( - std::move(stderrRead), [&](const gsl::span& buffer) { stderrNative.append(buffer.data(), buffer.size()); })); + io.AddHandle(std::make_unique(std::move(stderrRead), [&](const gsl::span& buffer) { + stderrNative.append(buffer.data(), buffer.size()); + })); } else { diff --git a/src/windows/common/WslCoreConfig.cpp b/src/windows/common/WslCoreConfig.cpp index 11ab27285..b80110f5f 100644 --- a/src/windows/common/WslCoreConfig.cpp +++ b/src/windows/common/WslCoreConfig.cpp @@ -138,8 +138,9 @@ void wsl::core::Config::ParseConfigFile(_In_opt_ LPCWSTR ConfigFilePath, _In_opt LOG_WIN32_MSG(error, "opening config file failed"); if (error != ERROR_FILE_NOT_FOUND) { - EMIT_USER_WARNING(wsl::shared::Localization::MessageFailedToOpenConfigFile( - ConfigFilePath, wsl::windows::common::wslutil::GetErrorString(HRESULT_FROM_WIN32(error)))); + EMIT_USER_WARNING( + wsl::shared::Localization::MessageFailedToOpenConfigFile( + ConfigFilePath, wsl::windows::common::wslutil::GetErrorString(HRESULT_FROM_WIN32(error)))); } } } diff --git a/src/windows/common/WslSecurity.cpp b/src/windows/common/WslSecurity.cpp index 1cf656375..4907b3e8e 100644 --- a/src/windows/common/WslSecurity.cpp +++ b/src/windows/common/WslSecurity.cpp @@ -73,8 +73,8 @@ wil::unique_handle wsl::windows::common::security::CreateRestrictedToken(_In_ HA // Get the thread token with appropriate access rights. wil::unique_handle newToken{}; - THROW_IF_WIN32_BOOL_FALSE(::OpenThreadToken( - ::GetCurrentThread(), (TOKEN_DUPLICATE | TOKEN_QUERY | TOKEN_ADJUST_DEFAULT | TOKEN_ASSIGN_PRIMARY), TRUE, &newToken)); + THROW_IF_WIN32_BOOL_FALSE( + ::OpenThreadToken(::GetCurrentThread(), (TOKEN_DUPLICATE | TOKEN_QUERY | TOKEN_ADJUST_DEFAULT | TOKEN_ASSIGN_PRIMARY), TRUE, &newToken)); // Create a restricted token with only the SeChangeNotifyPrivilege privilege. wil::unique_handle restrictedToken{}; @@ -161,13 +161,14 @@ wil::unique_handle wsl::windows::common::security::GetUserToken(_In_ TOKEN_TYPE } wil::unique_handle newToken; - THROW_IF_WIN32_BOOL_FALSE(::DuplicateTokenEx( - contextToken.get(), - TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_DEFAULT, - nullptr, - SecurityImpersonation, - tokenType, - &newToken)); + THROW_IF_WIN32_BOOL_FALSE( + ::DuplicateTokenEx( + contextToken.get(), + TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_DEFAULT, + nullptr, + SecurityImpersonation, + tokenType, + &newToken)); // If the token integrity level is system, reduce it to high integrity level. The VM worker process runs at // high integrity level and objects created with a higher integrity level token may be inaccessible. diff --git a/src/windows/common/filesystem.cpp b/src/windows/common/filesystem.cpp index 0441fb2c2..d282b35c6 100644 --- a/src/windows/common/filesystem.cpp +++ b/src/windows/common/filesystem.cpp @@ -161,8 +161,8 @@ void SetNtfsDirCaseSensitivityFlags(_In_ ULONG Flags) CaseSensitivity GetCaseSensitivity() { ULONG caseSensitiveRaw; - THROW_IF_NTSTATUS_FAILED(::NtQueryInformationThread( - GetCurrentThread(), ThreadExplicitCaseSensitivity, &caseSensitiveRaw, sizeof(caseSensitiveRaw), nullptr)); + THROW_IF_NTSTATUS_FAILED( + ::NtQueryInformationThread(GetCurrentThread(), ThreadExplicitCaseSensitivity, &caseSensitiveRaw, sizeof(caseSensitiveRaw), nullptr)); return (caseSensitiveRaw == 0) ? Disabled : Enabled; } @@ -362,14 +362,15 @@ void SetDirectoryCaseSensitive(_In_ PCWSTR Path) void SetExtendedAttributesLxFs(_In_ PCWSTR Path, _In_ ULONG Mode, _In_ ULONG Uid, _In_ ULONG Gid) { - const wil::unique_hfile FileHandle(::CreateFileW( - Path, - FILE_GENERIC_READ | FILE_GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - nullptr, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, - nullptr)); + const wil::unique_hfile FileHandle( + ::CreateFileW( + Path, + FILE_GENERIC_READ | FILE_GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + nullptr, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, + nullptr)); THROW_LAST_ERROR_IF(!FileHandle); diff --git a/src/windows/common/notifications.cpp b/src/windows/common/notifications.cpp index 5e4090483..9f6a85f74 100644 --- a/src/windows/common/notifications.cpp +++ b/src/windows/common/notifications.cpp @@ -29,8 +29,9 @@ namespace { HRESULT CreateToastNotifier(IToastNotifier** notifier) { ComPtr toastStatics; - RETURN_IF_FAILED(Windows::Foundation::GetActivationFactory( - HStringReference(RuntimeClass_Windows_UI_Notifications_ToastNotificationManager).Get(), &toastStatics)); + RETURN_IF_FAILED( + Windows::Foundation::GetActivationFactory( + HStringReference(RuntimeClass_Windows_UI_Notifications_ToastNotificationManager).Get(), &toastStatics)); return toastStatics->CreateToastNotifierWithId(HStringReference(L"Microsoft.WSL").Get(), notifier); } @@ -51,8 +52,8 @@ HRESULT CreateXmlDocumentFromString(const wchar_t* xmlString, IXmlDocument** doc HRESULT CreateToastNotification(IXmlDocument* content, IToastNotification** notification) { ComPtr factory; - RETURN_IF_FAILED(Windows::Foundation::GetActivationFactory( - HStringReference(RuntimeClass_Windows_UI_Notifications_ToastNotification).Get(), &factory)); + RETURN_IF_FAILED( + Windows::Foundation::GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_Notifications_ToastNotification).Get(), &factory)); return factory->CreateToastNotification(content, notification); } diff --git a/src/windows/common/wslutil.cpp b/src/windows/common/wslutil.cpp index 97909107a..42849fc36 100644 --- a/src/windows/common/wslutil.cpp +++ b/src/windows/common/wslutil.cpp @@ -458,8 +458,9 @@ std::wstring wsl::windows::common::wslutil::DownloadFileImpl( [[nodiscard]] HANDLE wsl::windows::common::wslutil::DuplicateHandle(_In_ HANDLE Handle, _In_ std::optional DesiredAccess, _In_ BOOL InheritHandle) { HANDLE newHandle; - THROW_IF_WIN32_BOOL_FALSE(::DuplicateHandle( - GetCurrentProcess(), Handle, GetCurrentProcess(), &newHandle, DesiredAccess.value_or(0), InheritHandle, DesiredAccess.has_value() ? 0 : DUPLICATE_SAME_ACCESS)); + THROW_IF_WIN32_BOOL_FALSE( + ::DuplicateHandle( + GetCurrentProcess(), Handle, GetCurrentProcess(), &newHandle, DesiredAccess.value_or(0), InheritHandle, DesiredAccess.has_value() ? 0 : DUPLICATE_SAME_ACCESS)); return newHandle; } @@ -470,8 +471,9 @@ std::wstring wsl::windows::common::wslutil::DownloadFileImpl( THROW_LAST_ERROR_IF(!caller); HANDLE newHandle; - THROW_IF_WIN32_BOOL_FALSE(::DuplicateHandle( - caller.get(), Handle, GetCurrentProcess(), &newHandle, DesiredAccess.value_or(0), FALSE, DesiredAccess.has_value() ? 0 : DUPLICATE_SAME_ACCESS)); + THROW_IF_WIN32_BOOL_FALSE( + ::DuplicateHandle( + caller.get(), Handle, GetCurrentProcess(), &newHandle, DesiredAccess.value_or(0), FALSE, DesiredAccess.has_value() ? 0 : DUPLICATE_SAME_ACCESS)); return newHandle; } @@ -482,8 +484,9 @@ std::wstring wsl::windows::common::wslutil::DownloadFileImpl( THROW_LAST_ERROR_IF(!caller); HANDLE newHandle; - THROW_IF_WIN32_BOOL_FALSE(::DuplicateHandle( - GetCurrentProcess(), Handle, caller.get(), &newHandle, DesiredAccess.value_or(0), FALSE, DesiredAccess.has_value() ? 0 : DUPLICATE_SAME_ACCESS)); + THROW_IF_WIN32_BOOL_FALSE( + ::DuplicateHandle( + GetCurrentProcess(), Handle, caller.get(), &newHandle, DesiredAccess.value_or(0), FALSE, DesiredAccess.has_value() ? 0 : DUPLICATE_SAME_ACCESS)); return newHandle; } diff --git a/src/windows/libwsl/WslCoreConfigInterface.cpp b/src/windows/libwsl/WslCoreConfigInterface.cpp index 920a238e2..63cca2117 100644 --- a/src/windows/libwsl/WslCoreConfigInterface.cpp +++ b/src/windows/libwsl/WslCoreConfigInterface.cpp @@ -367,8 +367,9 @@ unsigned long SetWslConfigSetting(WslConfig_t wslConfig, WslConfigSetting wslCon } std::string ignoredPortsUtf8; - if (FAILED(wil::ResultFromException( - [&]() { ignoredPortsUtf8 = wsl::shared::string::WideToMultiByte(wslConfigSetting.StringValue); }))) + if (FAILED(wil::ResultFromException([&]() { + ignoredPortsUtf8 = wsl::shared::string::WideToMultiByte(wslConfigSetting.StringValue); + }))) { return ERROR_INVALID_PARAMETER; } diff --git a/src/windows/service/exe/LxssInstance.cpp b/src/windows/service/exe/LxssInstance.cpp index 54fe3b186..5318f78dd 100644 --- a/src/windows/service/exe/LxssInstance.cpp +++ b/src/windows/service/exe/LxssInstance.cpp @@ -821,8 +821,12 @@ void LxssInstance::_InitializeNetworking() m_ipTables.EnableIpTablesSupport(m_instanceHandle); // Register for network connectivity change notifications to update network information. - LOG_IF_WIN32_ERROR(::NotifyNetworkConnectivityHintChange( - [](PVOID context, NL_NETWORK_CONNECTIVITY_HINT) { static_cast(context)->_UpdateNetworkInformation(); }, this, TRUE, &m_networkNotificationHandle)); + LOG_IF_WIN32_ERROR( + ::NotifyNetworkConnectivityHintChange( + [](PVOID context, NL_NETWORK_CONNECTIVITY_HINT) { static_cast(context)->_UpdateNetworkInformation(); }, + this, + TRUE, + &m_networkNotificationHandle)); } void LxssInstance::_InitiateConnectionToInitProcess() diff --git a/src/windows/service/exe/LxssUserSession.cpp b/src/windows/service/exe/LxssUserSession.cpp index ef4cfd704..2ceb3d9a3 100644 --- a/src/windows/service/exe/LxssUserSession.cpp +++ b/src/windows/service/exe/LxssUserSession.cpp @@ -2474,8 +2474,9 @@ std::vector LxssUserSess auto runAsUser = wil::CoImpersonateClient(); const auto rootFsPath = Configuration.BasePath / LXSS_ROOTFS_DIRECTORY; std::vector mounts; - mounts.emplace_back(wsl::windows::common::filesystem::CreateMount( - rootFsPath.c_str(), LXSS_ROOTFS_DIRECTORY, LXSS_ROOTFS_MOUNT, LXSS_DISTRO_USES_WSL_FS(Configuration.Version) ? LXSS_FS_TYPE_WSLFS : LXSS_FS_TYPE_LXFS, 0755)); + mounts.emplace_back( + wsl::windows::common::filesystem::CreateMount( + rootFsPath.c_str(), LXSS_ROOTFS_DIRECTORY, LXSS_ROOTFS_MOUNT, LXSS_DISTRO_USES_WSL_FS(Configuration.Version) ? LXSS_FS_TYPE_WSLFS : LXSS_FS_TYPE_LXFS, 0755)); // Add a read only sharefs mount to the inbox tools directory which contains the bsdtar binary. std::wstring systemDirectory; @@ -2483,8 +2484,8 @@ std::vector LxssUserSess // Add a read only sharefs mount to the packaged tools directory which contains the init binary. const auto initPath = wsl::windows::common::wslutil::GetBasePath() / L"tools"; - mounts.emplace_back(wsl::windows::common::filesystem::CreateMount( - initPath.c_str(), initPath.c_str(), LXSS_TOOLS_MOUNT, LXSS_FS_TYPE_SHAREFS, 0755, false)); + mounts.emplace_back( + wsl::windows::common::filesystem::CreateMount(initPath.c_str(), initPath.c_str(), LXSS_TOOLS_MOUNT, LXSS_FS_TYPE_SHAREFS, 0755, false)); return mounts; } @@ -2764,8 +2765,9 @@ try auto distributionProfileId = wsl::shared::string::GuidToString(CreateV5Uuid(WslTerminalNamespace, std::as_bytes(std::span{distributionIdString}))); - auto hideGeneratedProfileGuid = WideToMultiByte(wsl::shared::string::GuidToString( - CreateV5Uuid(GeneratedProfilesTerminalNamespace, std::as_bytes(std::span{Configuration.Name})))); + auto hideGeneratedProfileGuid = WideToMultiByte( + wsl::shared::string::GuidToString( + CreateV5Uuid(GeneratedProfilesTerminalNamespace, std::as_bytes(std::span{Configuration.Name})))); bool foundHideProfile = false; @@ -4020,8 +4022,8 @@ try const auto userToken = wsl::windows::common::security::GetUserToken(TokenImpersonation); // This is needed to launch the OOBE process as the user. wil::unique_handle userTokenCreateProcess; - THROW_IF_WIN32_BOOL_FALSE(::DuplicateTokenEx( - userToken.get(), MAXIMUM_ALLOWED, nullptr, SecurityImpersonation, TokenImpersonation, &userTokenCreateProcess)); + THROW_IF_WIN32_BOOL_FALSE( + ::DuplicateTokenEx(userToken.get(), MAXIMUM_ALLOWED, nullptr, SecurityImpersonation, TokenImpersonation, &userTokenCreateProcess)); wsl::windows::common::helpers::LaunchWslSettingsOOBE(userTokenCreateProcess.get()); wsl::windows::common::registry::WriteDword(lxssKey.get(), nullptr, LXSS_OOBE_COMPLETE_NAME, true); } diff --git a/src/windows/service/exe/WSLCSessionManager.cpp b/src/windows/service/exe/WSLCSessionManager.cpp index 7ccf4724d..d0149d22c 100644 --- a/src/windows/service/exe/WSLCSessionManager.cpp +++ b/src/windows/service/exe/WSLCSessionManager.cpp @@ -309,8 +309,9 @@ void WSLCSessionManagerImpl::CreateSession( } // Track the session via its service ref, along with metadata and security info. - m_sessions.push_back(SessionEntry{ - std::move(serviceRef), sessionId, creatorPid, resolvedDisplayName, std::move(tokenInfo), notifier, false, sharedToken, std::move(storedSid), std::move(sessionJob)}); + m_sessions.push_back( + SessionEntry{ + std::move(serviceRef), sessionId, creatorPid, resolvedDisplayName, std::move(tokenInfo), notifier, false, sharedToken, std::move(storedSid), std::move(sessionJob)}); // For persistent sessions, also hold a strong reference to keep them alive. const bool persistent = WI_IsFlagSet(Flags, WSLCSessionFlagsPersistent); diff --git a/src/windows/service/exe/WslCoreVm.cpp b/src/windows/service/exe/WslCoreVm.cpp index 9705e9cc2..3365b2225 100644 --- a/src/windows/service/exe/WslCoreVm.cpp +++ b/src/windows/service/exe/WslCoreVm.cpp @@ -519,8 +519,9 @@ void WslCoreVm::Initialize(const GUID& VmId, const wil::shared_handle& UserToken } else if (FAILED(result)) { - EMIT_USER_WARNING(wsl::shared::Localization::MessagedFailedToCreateSwapVhd( - m_vmConfig.SwapFilePath.c_str(), wsl::windows::common::wslutil::GetSystemErrorString(result).c_str())); + EMIT_USER_WARNING( + wsl::shared::Localization::MessagedFailedToCreateSwapVhd( + m_vmConfig.SwapFilePath.c_str(), wsl::windows::common::wslutil::GetSystemErrorString(result).c_str())); THROW_HR(result); } @@ -583,8 +584,9 @@ void WslCoreVm::Initialize(const GUID& VmId, const wil::shared_handle& UserToken } if (!natNetwork) { - EMIT_USER_WARNING(wsl::shared::Localization::MessageNetworkInitializationFailedFallback2( - ToString(m_vmConfig.NetworkingMode), ToString(NetworkingMode::Consomme))); + EMIT_USER_WARNING( + wsl::shared::Localization::MessageNetworkInitializationFailedFallback2( + ToString(m_vmConfig.NetworkingMode), ToString(NetworkingMode::Consomme))); m_vmConfig.NetworkingMode = NetworkingMode::Consomme; } @@ -685,8 +687,9 @@ void WslCoreVm::Initialize(const GUID& VmId, const wil::shared_handle& UserToken } // Fall back to no networking. - EMIT_USER_WARNING(wsl::shared::Localization::MessageNetworkInitializationFailedFallback2( - ToString(m_vmConfig.NetworkingMode), ToString(NetworkingMode::None))); + EMIT_USER_WARNING( + wsl::shared::Localization::MessageNetworkInitializationFailedFallback2( + ToString(m_vmConfig.NetworkingMode), ToString(NetworkingMode::None))); m_vmConfig.NetworkingMode = NetworkingMode::None; m_networkingEngine.reset(); @@ -2942,8 +2945,8 @@ void WslCoreVm::ValidateNetworkingMode() if (disabledComponents == c_ipv6Disabled) { m_vmConfig.NetworkingMode = NetworkingMode::Nat; - EMIT_USER_WARNING(Localization::MessageMirroredNetworkingNotSupportedReason( - Localization::MessageMirroredNetworkingNotSupportedIpv6Disabled())); + EMIT_USER_WARNING( + Localization::MessageMirroredNetworkingNotSupportedReason(Localization::MessageMirroredNetworkingNotSupportedIpv6Disabled())); } } @@ -2953,14 +2956,16 @@ void WslCoreVm::ValidateNetworkingMode() if ((m_kernelVersion < std::make_tuple(5u, 10u, 0u)) || !m_seccompAvailable) { m_vmConfig.NetworkingMode = NetworkingMode::Nat; - EMIT_USER_WARNING(Localization::MessageMirroredNetworkingNotSupportedReason( - Localization::MessageMirroredNetworkingNotSupportedKernel())); + EMIT_USER_WARNING( + Localization::MessageMirroredNetworkingNotSupportedReason(Localization::MessageMirroredNetworkingNotSupportedKernel())); } else if (!wsl::core::networking::IsFlowSteeringSupportedByHns() || !m_vmConfig.FirewallConfig.Enabled()) { m_vmConfig.NetworkingMode = NetworkingMode::Nat; - EMIT_USER_WARNING(Localization::MessageMirroredNetworkingNotSupportedReason(Localization::MessageMirroredNetworkingNotSupportedWindowsVersion( - m_windowsVersion.BuildNumber, m_windowsVersion.UpdateBuildRevision))); + EMIT_USER_WARNING( + Localization::MessageMirroredNetworkingNotSupportedReason( + Localization::MessageMirroredNetworkingNotSupportedWindowsVersion( + m_windowsVersion.BuildNumber, m_windowsVersion.UpdateBuildRevision))); } } diff --git a/src/windows/service/exe/WslMirroredNetworking.cpp b/src/windows/service/exe/WslMirroredNetworking.cpp index 28b8d3137..e721b889e 100644 --- a/src/windows/service/exe/WslMirroredNetworking.cpp +++ b/src/windows/service/exe/WslMirroredNetworking.cpp @@ -1556,8 +1556,9 @@ try // Set the due time just past the debounce timer duration, relative to the last update time. m_IsDebounceUpdateAllEndpointsDefaultTimerSet = true; - FILETIME dueTime = wil::filetime::from_int64(static_cast( - -1 * (wil::filetime_duration::one_millisecond * (20 + m_debounceUpdateAllEndpointsTimerMs - timeFromLastUpdate)))); + FILETIME dueTime = wil::filetime::from_int64( + static_cast( + -1 * (wil::filetime_duration::one_millisecond * (20 + m_debounceUpdateAllEndpointsTimerMs - timeFromLastUpdate)))); SetThreadpoolTimer(m_debounceUpdateAllEndpointsDefaultTimer.get(), &dueTime, 0, 0); return; } diff --git a/src/windows/wslc/arguments/ArgumentValidation.cpp b/src/windows/wslc/arguments/ArgumentValidation.cpp index 4b2995e8e..848a70c44 100644 --- a/src/windows/wslc/arguments/ArgumentValidation.cpp +++ b/src/windows/wslc/arguments/ArgumentValidation.cpp @@ -384,8 +384,8 @@ FormatType GetFormatTypeFromString(const std::wstring& input, const std::wstring } else { - throw ArgumentException(std::format( - L"Invalid {} value: {} is not a recognized format type. Supported format types are: json, table.", argName, input)); + throw ArgumentException( + std::format(L"Invalid {} value: {} is not a recognized format type. Supported format types are: json, table.", argName, input)); } } diff --git a/src/windows/wslc/services/ContainerService.cpp b/src/windows/wslc/services/ContainerService.cpp index 3f7a029e2..b63f5cb51 100644 --- a/src/windows/wslc/services/ContainerService.cpp +++ b/src/windows/wslc/services/ContainerService.cpp @@ -673,13 +673,15 @@ void ContainerService::Logs(Session& session, const std::string& id, bool follow THROW_IF_FAILED(container->Logs(flags, &stdoutHandle, &stderrHandle, since, until, tail)); wsl::windows::common::io::MultiHandleWait io; - io.AddHandle(std::make_unique>( - stdoutHandle.Release(), GetStdHandle(STD_OUTPUT_HANDLE))); + io.AddHandle( + std::make_unique>( + stdoutHandle.Release(), GetStdHandle(STD_OUTPUT_HANDLE))); if (!stderrHandle.Empty()) // This handle is only used for non-tty processes. { - io.AddHandle(std::make_unique>( - stderrHandle.Release(), GetStdHandle(STD_ERROR_HANDLE))); + io.AddHandle( + std::make_unique>( + stderrHandle.Release(), GetStdHandle(STD_ERROR_HANDLE))); } // TODO: Handle ctrl-c. diff --git a/src/windows/wslcsession/DockerHTTPClient.h b/src/windows/wslcsession/DockerHTTPClient.h index c95794001..28483a53b 100644 --- a/src/windows/wslcsession/DockerHTTPClient.h +++ b/src/windows/wslcsession/DockerHTTPClient.h @@ -50,8 +50,14 @@ class DockerHTTPException : public std::runtime_error std::string&& Url, std::string&& RequestContent, std::string&& ResponseContent) : - std::runtime_error(std::format( - "HTTP request failed: {} {} -> {} (Request: {}, Response: {})", boost::beast::http::to_string(Method), Url, Response.result_int(), RequestContent, ResponseContent)), + std::runtime_error( + std::format( + "HTTP request failed: {} {} -> {} (Request: {}, Response: {})", + boost::beast::http::to_string(Method), + Url, + Response.result_int(), + RequestContent, + ResponseContent)), m_response(std::move(Response)), m_url(std::move(Url)), m_request(std::move(RequestContent)), diff --git a/src/windows/wslcsession/WSLCContainer.cpp b/src/windows/wslcsession/WSLCContainer.cpp index 24c739993..904aed291 100644 --- a/src/windows/wslcsession/WSLCContainer.cpp +++ b/src/windows/wslcsession/WSLCContainer.cpp @@ -338,8 +338,9 @@ void UnmountVolumes(std::vector& volumes, WSLCVirtualMachine& p else { LOG_HR(result); - EMIT_USER_WARNING(wsl::shared::Localization::MessageWslcVolumeUnmountFailed( - volume.HostPath, wsl::windows::common::wslutil::GetErrorString(result))); + EMIT_USER_WARNING( + wsl::shared::Localization::MessageWslcVolumeUnmountFailed( + volume.HostPath, wsl::windows::common::wslutil::GetErrorString(result))); } } } @@ -727,8 +728,9 @@ void WSLCContainerImpl::Attach(LPCSTR DetachKeys, WSLCHandle* Stdin, WSLCHandle* handles.emplace_back( std::make_unique>(HandleWrapper{std::move(stdinRead), std::move(onInputComplete)}, ioHandle.get())); - handles.emplace_back(std::make_unique( - std::move(ioHandle), std::move(stdoutWrite), std::move(stderrWrite), DockerIORelayHandle::Format::Raw)); + handles.emplace_back( + std::make_unique( + std::move(ioHandle), std::move(stdoutWrite), std::move(stderrWrite), DockerIORelayHandle::Format::Raw)); m_ioRelay.AddHandles(std::move(handles)); @@ -859,8 +861,8 @@ void WSLCContainerImpl::Start(WSLCContainerStartFlags Flags, const WSLCProcessSt catch (...) { LOG_CAUGHT_EXCEPTION(); - EMIT_USER_WARNING(wsl::shared::Localization::MessageWslcContainerStopAfterPluginRejectionFailed( - wsl::shared::string::MultiByteToWide(m_id))); + EMIT_USER_WARNING( + wsl::shared::Localization::MessageWslcContainerStopAfterPluginRejectionFailed(wsl::shared::string::MultiByteToWide(m_id))); } if (comError.has_value() && comError->Message) @@ -1119,8 +1121,8 @@ void WSLCContainerImpl::Export(WSLCHandle OutHandle) const } else { - io.AddHandle(std::make_unique>( - HandleWrapper{std::move(SocketCodePair.second)}, userHandle.Get())); + io.AddHandle( + std::make_unique>(HandleWrapper{std::move(SocketCodePair.second)}, userHandle.Get())); } // Release the lock so the container can still be interacted with while the export is in progress. @@ -1179,8 +1181,9 @@ void WSLCContainerImpl::UploadArchive(WSLCHandle TarHandle, LPCSTR DestPath, ULO LOG_LAST_ERROR_IF(shutdown(socket, SD_SEND) == SOCKET_ERROR); }; - io.AddHandle(std::make_unique>( - HandleWrapper{userHandle.Get(), std::move(onInputComplete)}, HandleWrapper{requestContext->stream.native_handle()})); + io.AddHandle( + std::make_unique>( + HandleWrapper{userHandle.Get(), std::move(onInputComplete)}, HandleWrapper{requestContext->stream.native_handle()})); io.AddHandle( std::make_unique(*requestContext, std::move(onHttpResponse), std::move(onProgress)), @@ -1883,8 +1886,8 @@ std::shared_ptr WSLCContainerImpl::Create( auto hostPort = e.VmMapping.VmPort ? e.VmMapping.VmPort->Port() : e.VmMapping.HostPort(); // Use catch-all binding address based on the address family. :: binds all ipv6 interfaces, and 0:0:0:0 binds all ipv4 interfaces. - portEntry.emplace_back(common::docker_schema::PortMapping{ - .HostIp = e.VmMapping.IsIPv6() ? "::" : "0.0.0.0", .HostPort = std::to_string(hostPort)}); + portEntry.emplace_back( + common::docker_schema::PortMapping{.HostIp = e.VmMapping.IsIPv6() ? "::" : "0.0.0.0", .HostPort = std::to_string(hostPort)}); } auto labels = ParseKeyValuePairs(containerOptions.Labels, containerOptions.LabelsCount, WSLCContainerMetadataLabel); @@ -2097,8 +2100,9 @@ std::shared_ptr WSLCContainerImpl::Open( catch (...) { LOG_CAUGHT_EXCEPTION(); - EMIT_USER_WARNING(wsl::shared::Localization::MessageWslcContainerTimestampRecoveryFailed( - wsl::shared::string::MultiByteToWide(dockerContainer.Id))); + EMIT_USER_WARNING( + wsl::shared::Localization::MessageWslcContainerTimestampRecoveryFailed( + wsl::shared::string::MultiByteToWide(dockerContainer.Id))); } return container; @@ -2219,8 +2223,9 @@ std::unique_ptr WSLCContainerImpl::CreateRelayedProcessIO(wil: fds.emplace(WSLCFDStdout, TypedHandle{wil::unique_handle{stdoutRead.release()}, WSLCHandleTypePipe}); fds.emplace(WSLCFDStderr, TypedHandle{wil::unique_handle{stderrRead.release()}, WSLCHandleTypePipe}); - ioHandles.emplace_back(std::make_unique( - std::move(stream), std::move(stdoutWrite), std::move(stderrWrite), common::io::DockerIORelayHandle::Format::Raw)); + ioHandles.emplace_back( + std::make_unique( + std::move(stream), std::move(stdoutWrite), std::move(stderrWrite), common::io::DockerIORelayHandle::Format::Raw)); m_ioRelay.AddHandles(std::move(ioHandles)); diff --git a/src/windows/wslcsession/WSLCSession.cpp b/src/windows/wslcsession/WSLCSession.cpp index 6c82d61a4..4ac9b0d1b 100644 --- a/src/windows/wslcsession/WSLCSession.cpp +++ b/src/windows/wslcsession/WSLCSession.cpp @@ -631,11 +631,13 @@ ServiceRunningProcess WSLCSession::StartProcess( auto process = launcher.Launch(*m_virtualMachine); - m_ioRelay.AddHandle(std::make_unique( - process.GetStdHandle(1), [this, LogSource](const auto& data) { OnProcessLog(data, LogSource); }, false)); + m_ioRelay.AddHandle( + std::make_unique( + process.GetStdHandle(1), [this, LogSource](const auto& data) { OnProcessLog(data, LogSource); }, false)); - m_ioRelay.AddHandle(std::make_unique( - process.GetStdHandle(2), [this, LogSource](const auto& data) { OnProcessLog(data, LogSource); }, false)); + m_ioRelay.AddHandle( + std::make_unique( + process.GetStdHandle(2), [this, LogSource](const auto& data) { OnProcessLog(data, LogSource); }, false)); m_ioRelay.AddHandle(std::make_unique(process.GetExitEvent(), std::move(ExitCallback))); @@ -1147,8 +1149,9 @@ try // With --progress=rawjson, docker writes progress to stderr and the final image ID to stdout on success (empty on // failure). Stdout is drained into allOutput (shown only on error) and its EOF signals build completion. - io.AddHandle(std::make_unique( - buildProcess.GetStdHandle(1), [&](const auto& content) { allOutput.append(content.begin(), content.end()); })); + io.AddHandle(std::make_unique(buildProcess.GetStdHandle(1), [&](const auto& content) { + allOutput.append(content.begin(), content.end()); + })); io.AddHandle(std::make_unique(buildProcess.GetStdHandle(2), captureOutput, false)); @@ -1500,8 +1503,9 @@ void WSLCSession::SaveImageImpl(std::pair& SocketC } else { - io.AddHandle(std::make_unique>( - common::io::HandleWrapper{std::move(SocketCodePair.second)}, userHandle.Get())); + io.AddHandle( + std::make_unique>( + common::io::HandleWrapper{std::move(SocketCodePair.second)}, userHandle.Get())); } io.Run({}); diff --git a/src/windows/wslcsession/main.cpp b/src/windows/wslcsession/main.cpp index d04d10c26..ccee293f3 100644 --- a/src/windows/wslcsession/main.cpp +++ b/src/windows/wslcsession/main.cpp @@ -80,8 +80,9 @@ try // Register the class factory (single-use: one factory per process) auto factory = winrt::make(); wil::unique_com_class_object_cookie cookie; - THROW_IF_FAILED(::CoRegisterClassObject( - __uuidof(wsl::windows::service::wslc::WSLCSessionFactory), factory.get(), CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie)); + THROW_IF_FAILED( + ::CoRegisterClassObject( + __uuidof(wsl::windows::service::wslc::WSLCSessionFactory), factory.get(), CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie)); WSL_LOG("Per-user session server registered, waiting for activations", TraceLoggingLevel(WINEVENT_LEVEL_INFO)); diff --git a/src/windows/wslhost/main.cpp b/src/windows/wslhost/main.cpp index e89dbe7ab..51cef7fdc 100644 --- a/src/windows/wslhost/main.cpp +++ b/src/windows/wslhost/main.cpp @@ -90,8 +90,9 @@ class DECLSPEC_UUID("2B9C59C3-98F1-45C8-B87B-12AE3C7927E8") NotificationActivato parser.AddArgument( [](auto) { - LaunchWsl(std::format(L"{} {} {}", WSL_INSTALL_ARG, WSL_INSTALL_ARG_NO_DISTRIBUTION_OPTION, WSL_INSTALL_ARG_PROMPT_BEFORE_EXIT_OPTION) - .c_str()); + LaunchWsl( + std::format(L"{} {} {}", WSL_INSTALL_ARG, WSL_INSTALL_ARG_NO_DISTRIBUTION_OPTION, WSL_INSTALL_ARG_PROMPT_BEFORE_EXIT_OPTION) + .c_str()); }, wslhost::install_prerequisites_arg); @@ -194,8 +195,9 @@ try // Create an event to be signaled when the last COM object is released. g_exitEvent = wil::unique_event(wil::EventOptions::ManualReset); - THROW_IF_FAILED(::CoRegisterClassObject( - __uuidof(NotificationActivator), winrt::make().get(), CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &cookie)); + THROW_IF_FAILED( + ::CoRegisterClassObject( + __uuidof(NotificationActivator), winrt::make().get(), CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &cookie)); return 0; }, diff --git a/test/windows/Common.cpp b/test/windows/Common.cpp index 8549ee617..7c80d0e9d 100644 --- a/test/windows/Common.cpp +++ b/test/windows/Common.cpp @@ -2854,11 +2854,12 @@ void PartialHandleRead::ExpectConsume(const std::string& Expected) if (content != Expected) { - VERIFY_FAIL(std::format( - L"Expected: '{}' but got: '{}'", - wsl::shared::string::MultiByteToWide(EscapeString(Expected)), - wsl::shared::string::MultiByteToWide(EscapeString(content))) - .c_str()); + VERIFY_FAIL( + std::format( + L"Expected: '{}' but got: '{}'", + wsl::shared::string::MultiByteToWide(EscapeString(Expected)), + wsl::shared::string::MultiByteToWide(EscapeString(content))) + .c_str()); } } diff --git a/test/windows/InstallerTests.cpp b/test/windows/InstallerTests.cpp index 31677e7ac..f2b71dc29 100644 --- a/test/windows/InstallerTests.cpp +++ b/test/windows/InstallerTests.cpp @@ -707,8 +707,8 @@ class InstallerTests // // N.B. The file handle will be closed before the cleanup lambda runs. std::filesystem::create_directories(m_installedPath); - wil::unique_hfile fileHandle(::CreateFileW( - (m_installedPath / WSL_BINARY_NAME).c_str(), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr)); + wil::unique_hfile fileHandle( + ::CreateFileW((m_installedPath / WSL_BINARY_NAME).c_str(), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr)); // Install the installer MSIX InstallMsix(); @@ -1195,8 +1195,9 @@ class InstallerTests void VerifyWslSettingsProtocolAssociationExistsWithRetry() { - VERIFY_NO_THROW(wsl::shared::retry::RetryWithTimeout( - [&]() { THROW_HR_IF(E_UNEXPECTED, !WslSettingsProtocolAssociationExists()); }, std::chrono::seconds(1), std::chrono::minutes(2))); + VERIFY_NO_THROW( + wsl::shared::retry::RetryWithTimeout( + [&]() { THROW_HR_IF(E_UNEXPECTED, !WslSettingsProtocolAssociationExists()); }, std::chrono::seconds(1), std::chrono::minutes(2))); } TEST_METHOD(WslValidateWslSettingsProtocol) diff --git a/test/windows/NetworkTests.cpp b/test/windows/NetworkTests.cpp index 101b7baf7..9b6485009 100644 --- a/test/windows/NetworkTests.cpp +++ b/test/windows/NetworkTests.cpp @@ -2132,18 +2132,19 @@ class NetworkTests // The port-0 resolution is asynchronous (deferred to a background thread). // Retry until the host port tracker registers the port, blocking the host bind. - VERIFY_NO_THROW(wsl::shared::retry::RetryWithTimeout( - [&assignedPort]() { - wil::unique_socket sock(socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)); - THROW_LAST_ERROR_IF(!sock); - - SOCKADDR_IN addr{}; - addr.sin_family = AF_INET; - addr.sin_port = htons(assignedPort); - THROW_HR_IF(E_FAIL, bind(sock.get(), reinterpret_cast(&addr), sizeof(addr)) != SOCKET_ERROR); - }, - std::chrono::seconds(1), - std::chrono::seconds(30))); + VERIFY_NO_THROW( + wsl::shared::retry::RetryWithTimeout( + [&assignedPort]() { + wil::unique_socket sock(socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)); + THROW_LAST_ERROR_IF(!sock); + + SOCKADDR_IN addr{}; + addr.sin_family = AF_INET; + addr.sin_port = htons(assignedPort); + THROW_HR_IF(E_FAIL, bind(sock.get(), reinterpret_cast(&addr), sizeof(addr)) != SOCKET_ERROR); + }, + std::chrono::seconds(1), + std::chrono::seconds(30))); if (!verifyRelease) { @@ -2154,18 +2155,19 @@ class NetworkTests guestProcess.reset(); // Retry until the host can bind the port again, confirming it was released. - VERIFY_NO_THROW(wsl::shared::retry::RetryWithTimeout( - [&assignedPort]() { - wil::unique_socket sock(socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)); - THROW_LAST_ERROR_IF(!sock); + VERIFY_NO_THROW( + wsl::shared::retry::RetryWithTimeout( + [&assignedPort]() { + wil::unique_socket sock(socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)); + THROW_LAST_ERROR_IF(!sock); - SOCKADDR_IN addr{}; - addr.sin_family = AF_INET; - addr.sin_port = htons(assignedPort); - THROW_HR_IF(E_FAIL, bind(sock.get(), reinterpret_cast(&addr), sizeof(addr)) == SOCKET_ERROR); - }, - std::chrono::seconds(1), - std::chrono::minutes(2))); + SOCKADDR_IN addr{}; + addr.sin_family = AF_INET; + addr.sin_port = htons(assignedPort); + THROW_HR_IF(E_FAIL, bind(sock.get(), reinterpret_cast(&addr), sizeof(addr)) == SOCKET_ERROR); + }, + std::chrono::seconds(1), + std::chrono::minutes(2))); } static void VerifyPortZeroRebindSucceeds() @@ -2174,15 +2176,16 @@ class NetworkTests // Uses a perl one-liner to perform the entire sequence in a single process, // matching the semantics of a native C test (no SO_REUSEADDR, same-process rebind). VERIFY_ARE_EQUAL( - LxsstuLaunchWsl(L"perl -MSocket -e '" - L"socket(S1,AF_INET,SOCK_STREAM,0) or die;" - L"bind(S1,sockaddr_in(0,INADDR_ANY)) or die;" - L"my $port=(sockaddr_in(getsockname(S1)))[0];" - L"close(S1);" - L"socket(S2,AF_INET,SOCK_STREAM,0) or die;" - L"bind(S2,sockaddr_in($port,INADDR_ANY)) or die;" - L"close(S2)" - L"'"), + LxsstuLaunchWsl( + L"perl -MSocket -e '" + L"socket(S1,AF_INET,SOCK_STREAM,0) or die;" + L"bind(S1,sockaddr_in(0,INADDR_ANY)) or die;" + L"my $port=(sockaddr_in(getsockname(S1)))[0];" + L"close(S1);" + L"socket(S2,AF_INET,SOCK_STREAM,0) or die;" + L"bind(S2,sockaddr_in($port,INADDR_ANY)) or die;" + L"close(S2)" + L"'"), 0L); } @@ -2481,8 +2484,10 @@ class NetworkTests VERIFY_ARE_EQUAL(LxsstuLaunchWsl(L"ip addr add 192.168.15.1/24 dev testbridge"), 0); VERIFY_ARE_EQUAL(LxsstuLaunchWsl(L"ip -n testns route add default via 192.168.15.1 dev veth-test"), 0); VERIFY_ARE_EQUAL(LxsstuLaunchWsl(L"--system --user root nft add table nat"), 0); - VERIFY_ARE_EQUAL(LxsstuLaunchWsl(L"--system --user root nft \"add chain nat POSTROUTING { type nat hook postrouting priority srcnat; }\""), 0); - VERIFY_ARE_EQUAL(LxsstuLaunchWsl(L"--system --user root nft add rule nat POSTROUTING ip saddr 192.168.15.0/24 oif != testbridge masquerade"), 0); + VERIFY_ARE_EQUAL( + LxsstuLaunchWsl(L"--system --user root nft \"add chain nat POSTROUTING { type nat hook postrouting priority srcnat; }\""), 0); + VERIFY_ARE_EQUAL( + LxsstuLaunchWsl(L"--system --user root nft add rule nat POSTROUTING ip saddr 192.168.15.0/24 oif != testbridge masquerade"), 0); VERIFY_ARE_EQUAL(LxsstuLaunchWsl(L"sysctl -w net.ipv4.ip_forward=1"), 0); // Verify we have connectivity from the networking namespace when using ephemeral port selection. @@ -2968,8 +2973,8 @@ class NetworkTests } else if (std::regex_search(line, match, routePattern) && match.size() >= 4) { - state.Routes.emplace_back(Route{ - match.str(2), match.str(3), {match.str(1)}, match.size() > 5 && match[5].matched ? std::stoi(match.str(5)) : 0}); + state.Routes.emplace_back( + Route{match.str(2), match.str(3), {match.str(1)}, match.size() > 5 && match[5].matched ? std::stoi(match.str(5)) : 0}); } } @@ -4412,12 +4417,15 @@ class MirroredTests VERIFY_ARE_EQUAL(LxsstuLaunchWsl(L"ip addr add 192.168.15.1/24 dev testbridge"), 0); VERIFY_ARE_EQUAL(LxsstuLaunchWsl(L"ip -n testns route add default via 192.168.15.1 dev veth-test"), 0); VERIFY_ARE_EQUAL(LxsstuLaunchWsl(L"--system --user root nft add table nat"), 0); - VERIFY_ARE_EQUAL(LxsstuLaunchWsl(L"--system --user root nft \"add chain nat POSTROUTING { type nat hook postrouting priority srcnat; }\""), 0); - VERIFY_ARE_EQUAL(LxsstuLaunchWsl(L"--system --user root nft add rule nat POSTROUTING ip saddr 192.168.15.0/24 oif != testbridge masquerade"), 0); + VERIFY_ARE_EQUAL( + LxsstuLaunchWsl(L"--system --user root nft \"add chain nat POSTROUTING { type nat hook postrouting priority srcnat; }\""), 0); + VERIFY_ARE_EQUAL( + LxsstuLaunchWsl(L"--system --user root nft add rule nat POSTROUTING ip saddr 192.168.15.0/24 oif != testbridge masquerade"), 0); VERIFY_ARE_EQUAL(LxsstuLaunchWsl(L"sysctl -w net.ipv4.ip_forward=1"), 0); // Add rule for port forwarding traffic with destination port 8080 to port 80 in the new namespace - VERIFY_ARE_EQUAL(LxsstuLaunchWsl(L"--system --user root nft \"add chain nat PREROUTING { type nat hook prerouting priority dstnat; }\""), 0); + VERIFY_ARE_EQUAL( + LxsstuLaunchWsl(L"--system --user root nft \"add chain nat PREROUTING { type nat hook prerouting priority dstnat; }\""), 0); VERIFY_ARE_EQUAL(LxsstuLaunchWsl(L"--system --user root nft add rule nat PREROUTING tcp dport 8080 dnat to 192.168.15.2:80"), 0); // Start listeners in root namespace on port 8080 and new namespace on port 80 @@ -4491,8 +4499,10 @@ class MirroredTests VERIFY_ARE_EQUAL(LxsstuLaunchWsl(L"ip addr add 192.168.15.1/24 dev testbridge"), 0); VERIFY_ARE_EQUAL(LxsstuLaunchWsl(L"ip -n testns route add default via 192.168.15.1 dev veth-test"), 0); VERIFY_ARE_EQUAL(LxsstuLaunchWsl(L"--system --user root nft add table nat"), 0); - VERIFY_ARE_EQUAL(LxsstuLaunchWsl(L"--system --user root nft \"add chain nat POSTROUTING { type nat hook postrouting priority srcnat; }\""), 0); - VERIFY_ARE_EQUAL(LxsstuLaunchWsl(L"--system --user root nft add rule nat POSTROUTING ip saddr 192.168.15.0/24 oif != testbridge masquerade"), 0); + VERIFY_ARE_EQUAL( + LxsstuLaunchWsl(L"--system --user root nft \"add chain nat POSTROUTING { type nat hook postrouting priority srcnat; }\""), 0); + VERIFY_ARE_EQUAL( + LxsstuLaunchWsl(L"--system --user root nft add rule nat POSTROUTING ip saddr 192.168.15.0/24 oif != testbridge masquerade"), 0); VERIFY_ARE_EQUAL(LxsstuLaunchWsl(L"sysctl -w net.ipv4.ip_forward=1"), 0); // Create a listener on the Windows host on port 1234 diff --git a/test/windows/Plan9Tests.cpp b/test/windows/Plan9Tests.cpp index a6aa5e0bc..59a1ec1fd 100644 --- a/test/windows/Plan9Tests.cpp +++ b/test/windows/Plan9Tests.cpp @@ -447,9 +447,10 @@ class Plan9Tests // Create a folder that's unaccessible to plan9testuser VERIFY_ARE_EQUAL( - LxsstuLaunchWsl(L"mkdir -p /tmp/plan9-group-test && groupadd -f plan9testgroup && chown root:plan9testgroup " - L"/tmp/plan9-group-test && " - L"echo -n foo > /tmp/plan9-group-test/bar && chmod 770 /tmp/plan9-group-test"), + LxsstuLaunchWsl( + L"mkdir -p /tmp/plan9-group-test && groupadd -f plan9testgroup && chown root:plan9testgroup " + L"/tmp/plan9-group-test && " + L"echo -n foo > /tmp/plan9-group-test/bar && chmod 770 /tmp/plan9-group-test"), 0u); auto cleanup = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [&]() { diff --git a/test/windows/UnitTests.cpp b/test/windows/UnitTests.cpp index ab76caec7..6c7230c3a 100644 --- a/test/windows/UnitTests.cpp +++ b/test/windows/UnitTests.cpp @@ -338,8 +338,9 @@ class UnitTests auto cleanup = EnableSystemd("initTimeout=0"); // Wait for systemd to be started - VERIFY_NO_THROW(wsl::shared::retry::RetryWithTimeout( - [&]() { THROW_HR_IF(E_UNEXPECTED, !IsSystemdRunning(L"--system")); }, std::chrono::seconds(1), std::chrono::minutes(1))); + VERIFY_NO_THROW( + wsl::shared::retry::RetryWithTimeout( + [&]() { THROW_HR_IF(E_UNEXPECTED, !IsSystemdRunning(L"--system")); }, std::chrono::seconds(1), std::chrono::minutes(1))); // Validate that the X11 socket has not been deleted VERIFY_ARE_EQUAL(LxsstuLaunchWsl(L"test -d /tmp/.X11-unix"), 0L); @@ -391,7 +392,8 @@ class UnitTests VERIFY_ARE_EQUAL(LxsstuLaunchWsl(L"test -e /proc/sys/fs/binfmt_misc/WSLInterop"), 0L); // Runtime registration via /register still works (we only block /status). - VERIFY_ARE_EQUAL(LxsstuLaunchWsl(L"sh -c 'echo \":wsltestbinfmt:M::WSLTESTMAGIC::/bin/echo:\" > /proc/sys/fs/binfmt_misc/register'"), 0L); + VERIFY_ARE_EQUAL( + LxsstuLaunchWsl(L"sh -c 'echo \":wsltestbinfmt:M::WSLTESTMAGIC::/bin/echo:\" > /proc/sys/fs/binfmt_misc/register'"), 0L); // binfmt_misc is VM-global, so a leftover wsltestbinfmt entry would // cascade into later tests. Always remove it on scope exit. @@ -434,15 +436,17 @@ class UnitTests WslConfigChange config(LxssGenerateTestConfig() + L"[general]\ninstanceIdleTimeout=-1"); auto revert = EnableSystemd("initTimeout=0"); // Wait for systemd to start - VERIFY_NO_THROW(wsl::shared::retry::RetryWithTimeout( - [&]() { THROW_HR_IF(E_UNEXPECTED, !IsSystemdRunning(L"--system")); }, std::chrono::seconds(1), std::chrono::minutes(1))); + VERIFY_NO_THROW( + wsl::shared::retry::RetryWithTimeout( + [&]() { THROW_HR_IF(E_UNEXPECTED, !IsSystemdRunning(L"--system")); }, std::chrono::seconds(1), std::chrono::minutes(1))); // Kill the WSL init process VERIFY_ARE_EQUAL(LxsstuLaunchWsl(L"kill -9 2"), 0L); // Wait for the distro to exit. - VERIFY_NO_THROW(wsl::shared::retry::RetryWithTimeout( - [&]() { THROW_HR_IF(E_ABORT, GetDistroState() == LxssDistributionStateRunning); }, std::chrono::seconds(1), std::chrono::seconds(30))); + VERIFY_NO_THROW( + wsl::shared::retry::RetryWithTimeout( + [&]() { THROW_HR_IF(E_ABORT, GetDistroState() == LxssDistributionStateRunning); }, std::chrono::seconds(1), std::chrono::seconds(30))); // Verify that a new WSL command succeeds (the distro restarts cleanly). auto [out, err] = LxsstuLaunchWslAndCaptureOutput(L"echo hello"); @@ -4221,8 +4225,9 @@ localhostForwarding=true VERIFY_IS_FALSE(std::filesystem::exists(testDistroRootfsPath)); VERIFY_IS_TRUE(service.EnumerateDistributions().empty()); VERIFY_ARE_EQUAL( - LxsstuLaunchWsl(std::format( - L"--import {} \"{}\" \"{}\" --version 1", testDistro.DistroName, testDistroBasePath, testDistroExported.c_str())), + LxsstuLaunchWsl( + std::format( + L"--import {} \"{}\" \"{}\" --version 1", testDistro.DistroName, testDistroBasePath, testDistroExported.c_str())), 0L); } @@ -6837,8 +6842,7 @@ Error code: Wsl/InstallDistro/WSL_E_INVALID_JSON\r\n", auto [dmesg, __] = LxsstuLaunchWslAndCaptureOutput(L"dmesg"); VERIFY_ARE_NOT_EQUAL( - dmesg.find( - L"Distribution has cgroupv1 enabled, but kernel command line has cgroup_no_v1=all. Falling back to cgroupv2"), + dmesg.find(L"Distribution has cgroupv1 enabled, but kernel command line has cgroup_no_v1=all. Falling back to cgroupv2"), std::wstring::npos); } @@ -7022,14 +7026,15 @@ Error code: Wsl/InstallDistro/WSL_E_INVALID_JSON\r\n", std::vector message; wsl::windows::common::io::MultiHandleWait io; - io.AddHandle(std::make_unique( - wsl::windows::common::io::HandleWrapper{std::move(server)}, - buffer, - pendingBytes, - [&callbackInvoked, &message](const gsl::span& received) { - callbackInvoked = true; - message.assign(received.begin(), received.end()); - })); + io.AddHandle( + std::make_unique( + wsl::windows::common::io::HandleWrapper{std::move(server)}, + buffer, + pendingBytes, + [&callbackInvoked, &message](const gsl::span& received) { + callbackInvoked = true; + message.assign(received.begin(), received.end()); + })); const auto hr = wil::ResultFromException([&]() { io.Run(std::chrono::seconds(60)); }); VERIFY_ARE_EQUAL(hr, expectedHr); @@ -7241,11 +7246,12 @@ Error code: Wsl/InstallDistro/WSL_E_INVALID_JSON\r\n", bool callbackInvoked = false; const auto hr = wil::ResultFromException([&]() { wsl::windows::common::io::MultiHandleWait io; - io.AddHandle(std::make_unique( - wsl::windows::common::io::HandleWrapper{std::move(server)}, - buffer, - pendingBytes, - [&callbackInvoked](const gsl::span&) { callbackInvoked = true; })); + io.AddHandle( + std::make_unique( + wsl::windows::common::io::HandleWrapper{std::move(server)}, + buffer, + pendingBytes, + [&callbackInvoked](const gsl::span&) { callbackInvoked = true; })); io.Run(std::chrono::seconds(60)); }); VERIFY_ARE_EQUAL(hr, E_UNEXPECTED); @@ -7275,13 +7281,14 @@ Error code: Wsl/InstallDistro/WSL_E_INVALID_JSON\r\n", wsl::windows::common::io::MultiHandleWait io; for (size_t i = 0; i < handleCount; ++i) { - io.AddHandle(std::make_unique( - wsl::windows::common::io::HandleWrapper{events[i].get()}, [&fired, &firedCount, &firedLock, i]() { - std::lock_guard lock{firedLock}; - VERIFY_IS_FALSE(fired[i]); - fired[i] = true; - firedCount.fetch_add(1); - })); + io.AddHandle( + std::make_unique( + wsl::windows::common::io::HandleWrapper{events[i].get()}, [&fired, &firedCount, &firedLock, i]() { + std::lock_guard lock{firedLock}; + VERIFY_IS_FALSE(fired[i]); + fired[i] = true; + firedCount.fetch_add(1); + })); } for (auto& e : events) @@ -7313,13 +7320,14 @@ Error code: Wsl/InstallDistro/WSL_E_INVALID_JSON\r\n", wsl::windows::common::io::MultiHandleWait io; for (size_t i = 0; i < handleCount; ++i) { - io.AddHandle(std::make_unique( - wsl::windows::common::io::HandleWrapper{events[i].get()}, [&fired, &firedCount, &firedLock, i]() { - std::lock_guard lock{firedLock}; - VERIFY_IS_FALSE(fired[i]); - fired[i] = true; - firedCount.fetch_add(1); - })); + io.AddHandle( + std::make_unique( + wsl::windows::common::io::HandleWrapper{events[i].get()}, [&fired, &firedCount, &firedLock, i]() { + std::lock_guard lock{firedLock}; + VERIFY_IS_FALSE(fired[i]); + fired[i] = true; + firedCount.fetch_add(1); + })); } std::thread signaller([&events]() { diff --git a/test/windows/WSLCTests.cpp b/test/windows/WSLCTests.cpp index edc13644b..5e4691fa1 100644 --- a/test/windows/WSLCTests.cpp +++ b/test/windows/WSLCTests.cpp @@ -3241,8 +3241,8 @@ class WSLCTests HRESULT OnCrashDump(LPCWSTR DumpPath, LPCSTR ProcessName, ULONG Pid, ULONG Signal, ULONGLONG Timestamp) override { - m_promise.set_value(Invocation{ - DumpPath ? std::wstring{DumpPath} : std::wstring{}, ProcessName ? std::string{ProcessName} : std::string{}, Pid, Signal, Timestamp}); + m_promise.set_value( + Invocation{DumpPath ? std::wstring{DumpPath} : std::wstring{}, ProcessName ? std::string{ProcessName} : std::string{}, Pid, Signal, Timestamp}); // Block until the test has finished probing, so anything the test verifies is observed mid-callback. m_release.wait(); @@ -7747,10 +7747,10 @@ class WSLCTests wil::com_ptr container; VERIFY_ARE_EQUAL(E_NOTIMPL, m_defaultSession->CreateContainer(&options, nullptr, &container)); - ValidateCOMErrorMessage(std::format( - L"Endpoint settings are not yet supported (network '{}').", - std::wstring(networkName.begin(), networkName.end())) - .c_str()); + ValidateCOMErrorMessage( + std::format( + L"Endpoint settings are not yet supported (network '{}').", std::wstring(networkName.begin(), networkName.end())) + .c_str()); } } @@ -9540,15 +9540,18 @@ class WSLCTests std::string readStdout; std::string readStderr; - io.AddHandle(std::make_unique( - std::move(readPipe), std::move(stdoutWrite), std::move(stderrWrite), DockerIORelayHandle::Format::Raw)); + io.AddHandle( + std::make_unique( + std::move(readPipe), std::move(stdoutWrite), std::move(stderrWrite), DockerIORelayHandle::Format::Raw)); io.AddHandle(std::make_unique(std::move(writePipe), Input)); - io.AddHandle(std::make_unique( - std::move(stdoutRead), [&](const auto& buffer) { readStdout.append(buffer.data(), buffer.size()); })); + io.AddHandle(std::make_unique(std::move(stdoutRead), [&](const auto& buffer) { + readStdout.append(buffer.data(), buffer.size()); + })); - io.AddHandle(std::make_unique( - std::move(stderrRead), [&](const auto& buffer) { readStderr.append(buffer.data(), buffer.size()); })); + io.AddHandle(std::make_unique(std::move(stderrRead), [&](const auto& buffer) { + readStderr.append(buffer.data(), buffer.size()); + })); io.Run({}); @@ -9627,8 +9630,9 @@ class WSLCTests std::string output; MultiHandleWait io; - io.AddHandle(std::make_unique( - std::move(inputRead), std::move(stdoutWrite), std::move(stderrWrite), DockerIORelayHandle::Format::Raw)); + io.AddHandle( + std::make_unique( + std::move(inputRead), std::move(stdoutWrite), std::move(stderrWrite), DockerIORelayHandle::Format::Raw)); io.AddHandle(std::make_unique(std::move(stdoutRead), [&](const auto& buffer) { output.append(buffer.data(), buffer.size()); @@ -9668,8 +9672,9 @@ class WSLCTests // Collect the relayed output. std::string output; - io.AddHandle(std::make_unique( - std::move(dstRead), [&](const gsl::span& buffer) { output.append(buffer.data(), buffer.size()); })); + io.AddHandle(std::make_unique(std::move(dstRead), [&](const gsl::span& buffer) { + output.append(buffer.data(), buffer.size()); + })); io.Run({}); diff --git a/test/windows/WslcSdkTests.cpp b/test/windows/WslcSdkTests.cpp index d314462bb..c4c06758a 100644 --- a/test/windows/WslcSdkTests.cpp +++ b/test/windows/WslcSdkTests.cpp @@ -92,11 +92,13 @@ ProcessOutput WaitForProcessOutput(WslcProcess process, std::chrono::millisecond ProcessOutput output; wsl::windows::common::io::MultiHandleWait io; - io.AddHandle(std::make_unique( - std::move(ownedStdout), [&](const auto& buffer) { output.stdoutOutput.append(buffer.data(), buffer.size()); })); + io.AddHandle(std::make_unique(std::move(ownedStdout), [&](const auto& buffer) { + output.stdoutOutput.append(buffer.data(), buffer.size()); + })); - io.AddHandle(std::make_unique( - std::move(ownedStderr), [&](const auto& buffer) { output.stderrOutput.append(buffer.data(), buffer.size()); })); + io.AddHandle(std::make_unique(std::move(ownedStderr), [&](const auto& buffer) { + output.stderrOutput.append(buffer.data(), buffer.size()); + })); auto timeoutTime = std::chrono::steady_clock::now() + timeout; io.Run(timeout); @@ -332,12 +334,13 @@ class WslcSdkTests auto callback = [](const WslcSessionCrashDumpInfo* info, PVOID context) { auto* p = static_cast*>(context); - p->set_value(Invocation{ - info->dumpPath ? std::wstring{info->dumpPath} : std::wstring{}, - info->processName ? std::string{info->processName} : std::string{}, - info->pid, - info->signal, - info->timestamp}); + p->set_value( + Invocation{ + info->dumpPath ? std::wstring{info->dumpPath} : std::wstring{}, + info->processName ? std::string{info->processName} : std::string{}, + info->pid, + info->signal, + info->timestamp}); }; std::filesystem::path extraStorage = m_storagePath / "wslc-crash-callback-storage"; @@ -2652,14 +2655,15 @@ class WslcSdkTests auto output = WaitForProcessOutput(process.get()); VERIFY_ARE_EQUAL(output.stdoutOutput, "wslc-auto-remove\n"); - VERIFY_NO_THROW(wsl::shared::retry::RetryWithTimeout( - [&]() { - WslcContainerState state{}; - THROW_IF_FAILED(WslcGetContainerState(container.get(), &state)); - THROW_WIN32_IF(ERROR_RETRY, state != WSLC_CONTAINER_STATE_DELETED); - }, - std::chrono::milliseconds{100}, - std::chrono::seconds{30})); + VERIFY_NO_THROW( + wsl::shared::retry::RetryWithTimeout( + [&]() { + WslcContainerState state{}; + THROW_IF_FAILED(WslcGetContainerState(container.get(), &state)); + THROW_WIN32_IF(ERROR_RETRY, state != WSLC_CONTAINER_STATE_DELETED); + }, + std::chrono::milliseconds{100}, + std::chrono::seconds{30})); } WSLC_TEST_METHOD(DeleteRunningContainerWithForce) diff --git a/test/windows/WslcSdkWinRTTests.cpp b/test/windows/WslcSdkWinRTTests.cpp index 577ed0d4d..ae422c8b5 100644 --- a/test/windows/WslcSdkWinRTTests.cpp +++ b/test/windows/WslcSdkWinRTTests.cpp @@ -718,8 +718,9 @@ class WslcSdkWinRtTests { auto containerSettings = WSLCSDK::ContainerSettings(L"debian:latest"); containerSettings.NetworkingMode(WSLCSDK::ContainerNetworkingMode::None); - containerSettings.PortMappings(winrt::single_threaded_vector( - {WSLCSDK::ContainerPortMapping(12342, 8000, WSLCSDK::PortProtocol::TCP)})); + containerSettings.PortMappings( + winrt::single_threaded_vector( + {WSLCSDK::ContainerPortMapping(12342, 8000, WSLCSDK::PortProtocol::TCP)})); VERIFY_THROWS_HR(m_defaultSession.CreateContainer(containerSettings), E_INVALIDARG); } @@ -735,8 +736,9 @@ class WslcSdkWinRtTests auto containerSettings = WSLCSDK::ContainerSettings(L"python:3.12-alpine"); containerSettings.InitProcess(procSettings); containerSettings.NetworkingMode(WSLCSDK::ContainerNetworkingMode::Bridged); - containerSettings.PortMappings(winrt::single_threaded_vector( - {WSLCSDK::ContainerPortMapping(12341, 8000, WSLCSDK::PortProtocol::TCP)})); + containerSettings.PortMappings( + winrt::single_threaded_vector( + {WSLCSDK::ContainerPortMapping(12341, 8000, WSLCSDK::PortProtocol::TCP)})); auto container = m_defaultSession.CreateContainer(containerSettings); container.Start(); @@ -813,8 +815,8 @@ class WslcSdkWinRtTests VERIFY_THROWS_HR( { auto containerSettings = WSLCSDK::ContainerSettings(L"debian:latest"); - containerSettings.Volumes(winrt::single_threaded_vector( - {WSLCSDK::ContainerVolume(L"relative", L"/mnt/path", false)})); + containerSettings.Volumes( + winrt::single_threaded_vector({WSLCSDK::ContainerVolume(L"relative", L"/mnt/path", false)})); m_defaultSession.CreateContainer(containerSettings); }, E_INVALIDARG); @@ -823,8 +825,9 @@ class WslcSdkWinRtTests VERIFY_THROWS_HR( { auto containerSettings = WSLCSDK::ContainerSettings(L"debian:latest"); - containerSettings.Volumes(winrt::single_threaded_vector( - {WSLCSDK::ContainerVolume(currentDirectory, L"./mnt/path", false)})); + containerSettings.Volumes( + winrt::single_threaded_vector( + {WSLCSDK::ContainerVolume(currentDirectory, L"./mnt/path", false)})); m_defaultSession.CreateContainer(containerSettings); }, E_INVALIDARG); @@ -832,8 +835,8 @@ class WslcSdkWinRtTests // Positive: absolute paths must succeed. { auto containerSettings = WSLCSDK::ContainerSettings(L"debian:latest"); - containerSettings.Volumes(winrt::single_threaded_vector( - {WSLCSDK::ContainerVolume(currentDirectory, L"/mnt/path", false)})); + containerSettings.Volumes( + winrt::single_threaded_vector({WSLCSDK::ContainerVolume(currentDirectory, L"/mnt/path", false)})); auto container = m_defaultSession.CreateContainer(containerSettings); container.Delete(WSLCSDK::DeleteContainerOption::None); } @@ -871,10 +874,11 @@ class WslcSdkWinRtTests auto containerSettings = WSLCSDK::ContainerSettings(L"debian:latest"); containerSettings.InitProcess(procSettings); - containerSettings.Volumes(winrt::single_threaded_vector({ - WSLCSDK::ContainerVolume(hostRwDir.wstring(), L"/mnt/rw", false), - WSLCSDK::ContainerVolume(hostRoDir.wstring(), L"/mnt/ro", true), - })); + containerSettings.Volumes( + winrt::single_threaded_vector({ + WSLCSDK::ContainerVolume(hostRwDir.wstring(), L"/mnt/rw", false), + WSLCSDK::ContainerVolume(hostRoDir.wstring(), L"/mnt/ro", true), + })); auto container = m_defaultSession.CreateContainer(containerSettings); StartContainerAndWaitForInitProcessExit(container); @@ -1339,8 +1343,9 @@ class WslcSdkWinRtTests std::promise exitPromise; auto procSettings = WSLCSDK::ProcessSettings(); - procSettings.CommandLine(winrt::single_threaded_vector( - {L"/bin/sh", L"-c", winrt::hstring(std::format(L"echo HELLO && exit {}", exitCodeArg))})); + procSettings.CommandLine( + winrt::single_threaded_vector( + {L"/bin/sh", L"-c", winrt::hstring(std::format(L"echo HELLO && exit {}", exitCodeArg))})); procSettings.OutputMode(WSLCSDK::ProcessOutputMode::Event); auto containerSettings = WSLCSDK::ContainerSettings(L"debian:latest"); @@ -1439,8 +1444,9 @@ class WslcSdkWinRtTests stdoutData.reserve(c_expectedBytes + 4096); auto procSettings = WSLCSDK::ProcessSettings(); - procSettings.CommandLine(winrt::single_threaded_vector( - {L"/bin/sh", L"-c", L"dd if=/dev/zero bs=1024 count=1024 2>/dev/null | base64 -w 0"})); + procSettings.CommandLine( + winrt::single_threaded_vector( + {L"/bin/sh", L"-c", L"dd if=/dev/zero bs=1024 count=1024 2>/dev/null | base64 -w 0"})); procSettings.OutputMode(WSLCSDK::ProcessOutputMode::Event); auto containerSettings = WSLCSDK::ContainerSettings(L"debian:latest"); @@ -1493,13 +1499,14 @@ class WslcSdkWinRtTests // Positive: write a marker via a container that mounts the named volume. { auto procSettings = WSLCSDK::ProcessSettings(); - procSettings.CommandLine(winrt::single_threaded_vector( - {L"/bin/sh", L"-c", L"echo wslc-winrt-vhd-test > /data/marker.txt"})); + procSettings.CommandLine( + winrt::single_threaded_vector( + {L"/bin/sh", L"-c", L"echo wslc-winrt-vhd-test > /data/marker.txt"})); auto containerSettings = WSLCSDK::ContainerSettings(L"debian:latest"); containerSettings.InitProcess(procSettings); - containerSettings.NamedVolumes(winrt::single_threaded_vector( - {WSLCSDK::ContainerNamedVolume(c_volumeName, L"/data", false)})); + containerSettings.NamedVolumes( + winrt::single_threaded_vector({WSLCSDK::ContainerNamedVolume(c_volumeName, L"/data", false)})); auto container = session.CreateContainer(containerSettings); StartContainerAndWaitForInitProcessExit(container); @@ -1510,13 +1517,14 @@ class WslcSdkWinRtTests // Positive: read back the marker in a second container (read-only mount). { auto procSettings = WSLCSDK::ProcessSettings(); - procSettings.CommandLine(winrt::single_threaded_vector( - {L"/bin/sh", L"-c", L"test \"$(cat /data/marker.txt)\" = wslc-winrt-vhd-test"})); + procSettings.CommandLine( + winrt::single_threaded_vector( + {L"/bin/sh", L"-c", L"test \"$(cat /data/marker.txt)\" = wslc-winrt-vhd-test"})); auto containerSettings = WSLCSDK::ContainerSettings(L"debian:latest"); containerSettings.InitProcess(procSettings); - containerSettings.NamedVolumes(winrt::single_threaded_vector( - {WSLCSDK::ContainerNamedVolume(c_volumeName, L"/data", true)})); + containerSettings.NamedVolumes( + winrt::single_threaded_vector({WSLCSDK::ContainerNamedVolume(c_volumeName, L"/data", true)})); auto container = session.CreateContainer(containerSettings); StartContainerAndWaitForInitProcessExit(container); @@ -1560,8 +1568,9 @@ class WslcSdkWinRtTests auto containerSettings = WSLCSDK::ContainerSettings(L"debian:latest"); containerSettings.InitProcess(procSettings); - containerSettings.NamedVolumes(winrt::single_threaded_vector( - {WSLCSDK::ContainerNamedVolume(c_ownedVolumeName, L"/data", false)})); + containerSettings.NamedVolumes( + winrt::single_threaded_vector( + {WSLCSDK::ContainerNamedVolume(c_ownedVolumeName, L"/data", false)})); auto container = session.CreateContainer(containerSettings); StartContainerAndWaitForInitProcessExit(container); @@ -1790,10 +1799,11 @@ class WslcSdkWinRtTests // the WSL GPU libraries inside a GPU container. { auto procSettings = WSLCSDK::ProcessSettings(); - procSettings.CommandLine(winrt::single_threaded_vector( - {L"/bin/sh", - L"-c", - L"test -c /dev/dxg && test -r /dev/dxg && test -w /dev/dxg && cat /etc/ld.so.conf.d/ld.wsl.conf"})); + procSettings.CommandLine( + winrt::single_threaded_vector( + {L"/bin/sh", + L"-c", + L"test -c /dev/dxg && test -r /dev/dxg && test -w /dev/dxg && cat /etc/ld.so.conf.d/ld.wsl.conf"})); procSettings.OutputMode(WSLCSDK::ProcessOutputMode::Stream); auto containerSettings = WSLCSDK::ContainerSettings(L"debian:latest"); diff --git a/test/windows/testplugin/Plugin.cpp b/test/windows/testplugin/Plugin.cpp index 17087e6ed..becf00f9d 100644 --- a/test/windows/testplugin/Plugin.cpp +++ b/test/windows/testplugin/Plugin.cpp @@ -380,11 +380,13 @@ try std::string err; MultiHandleWait io; - io.AddHandle(std::make_unique( - std::move(stdoutHandle), [&out](const auto& span) { out.append(span.begin(), span.end()); })); + io.AddHandle(std::make_unique(std::move(stdoutHandle), [&out](const auto& span) { + out.append(span.begin(), span.end()); + })); - io.AddHandle(std::make_unique( - std::move(stderrHandle), [&err](const auto& span) { err.append(span.begin(), span.end()); })); + io.AddHandle(std::make_unique(std::move(stderrHandle), [&err](const auto& span) { + err.append(span.begin(), span.end()); + })); io.AddHandle(std::make_unique(std::move(exitEvent))); diff --git a/test/windows/wslc/WSLCCLICommandUnitTests.cpp b/test/windows/wslc/WSLCCLICommandUnitTests.cpp index 12e7b02a0..94905f185 100644 --- a/test/windows/wslc/WSLCCLICommandUnitTests.cpp +++ b/test/windows/wslc/WSLCCLICommandUnitTests.cpp @@ -278,8 +278,9 @@ class WSLCCLICommandUnitTests // Check for duplicate ArgType registration. if (!seenTypes.emplace(static_cast(arg.Type())).second) { - VERIFY_FAIL(std::format(L"Command '{}' registers ArgType '{}' more than once", commandFullName, ArgTypeName(arg.Type())) - .c_str()); + VERIFY_FAIL( + std::format(L"Command '{}' registers ArgType '{}' more than once", commandFullName, ArgTypeName(arg.Type())) + .c_str()); } // Check name collision between distinct ArgTypes. @@ -287,13 +288,14 @@ class WSLCCLICommandUnitTests auto [nameIt, nameInserted] = seenNames.emplace(name, arg.Type()); if (!nameInserted) { - VERIFY_FAIL(std::format( - L"Command '{}' has duplicate name '--{}' (ArgType '{}' conflicts with ArgType '{}')", - commandFullName, - name, - ArgTypeName(arg.Type()), - ArgTypeName(nameIt->second)) - .c_str()); + VERIFY_FAIL( + std::format( + L"Command '{}' has duplicate name '--{}' (ArgType '{}' conflicts with ArgType '{}')", + commandFullName, + name, + ArgTypeName(arg.Type()), + ArgTypeName(nameIt->second)) + .c_str()); } // Check alias collision between distinct ArgTypes; skip empty aliases (NO_ALIAS). @@ -303,13 +305,14 @@ class WSLCCLICommandUnitTests auto [aliasIt, aliasInserted] = seenAliases.emplace(alias, arg.Type()); if (!aliasInserted) { - VERIFY_FAIL(std::format( - L"Command '{}' has duplicate alias '-{}' (ArgType '{}' conflicts with ArgType '{}')", - commandFullName, - alias, - ArgTypeName(arg.Type()), - ArgTypeName(aliasIt->second)) - .c_str()); + VERIFY_FAIL( + std::format( + L"Command '{}' has duplicate alias '-{}' (ArgType '{}' conflicts with ArgType '{}')", + commandFullName, + alias, + ArgTypeName(arg.Type()), + ArgTypeName(aliasIt->second)) + .c_str()); } } } diff --git a/test/windows/wslc/e2e/WSLCE2EContainerAttachTests.cpp b/test/windows/wslc/e2e/WSLCE2EContainerAttachTests.cpp index 0d1cd6e53..3b597428d 100644 --- a/test/windows/wslc/e2e/WSLCE2EContainerAttachTests.cpp +++ b/test/windows/wslc/e2e/WSLCE2EContainerAttachTests.cpp @@ -52,8 +52,8 @@ class WSLCE2EContainerAttachTests VerifyContainerIsNotListed(WslcContainerName); const auto& prompt = ">"; - auto result = RunWslc(std::format( - L"container run -itd -e PS1={} --name {} {} bash --norc", prompt, WslcContainerName, DebianImage.NameAndTag())); + auto result = RunWslc( + std::format(L"container run -itd -e PS1={} --name {} {} bash --norc", prompt, WslcContainerName, DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); auto containerId = result.GetStdoutOneLine(); diff --git a/test/windows/wslc/e2e/WSLCE2EContainerCpTests.cpp b/test/windows/wslc/e2e/WSLCE2EContainerCpTests.cpp index 4918ce620..aa7795dec 100644 --- a/test/windows/wslc/e2e/WSLCE2EContainerCpTests.cpp +++ b/test/windows/wslc/e2e/WSLCE2EContainerCpTests.cpp @@ -510,8 +510,9 @@ class WSLCE2EContainerCpTests WSLC_TEST_METHOD(WSLCE2E_Container_Cp_FromStoppedContainer) { // Create a container, put a file in it, stop it, then copy out. - auto runResult = RunWslc(std::format( - L"container run --name {} {} sh -c \"echo stopped-content > /tmp/stopped.txt\"", WslcContainerName, DebianImage.NameAndTag())); + auto runResult = RunWslc( + std::format( + L"container run --name {} {} sh -c \"echo stopped-content > /tmp/stopped.txt\"", WslcContainerName, DebianImage.NameAndTag())); runResult.Verify({.Stderr = L"", .ExitCode = 0}); // Container has exited (ran a one-shot command). Copy from the stopped container. diff --git a/test/windows/wslc/e2e/WSLCE2EContainerCreateTests.cpp b/test/windows/wslc/e2e/WSLCE2EContainerCreateTests.cpp index 7de665c8e..ff307ec4b 100644 --- a/test/windows/wslc/e2e/WSLCE2EContainerCreateTests.cpp +++ b/test/windows/wslc/e2e/WSLCE2EContainerCreateTests.cpp @@ -120,8 +120,12 @@ class WSLCE2EContainerCreateTests VERIFY_IS_TRUE(DeleteFileW(cidFilePath.c_str())); auto deleteCidFile = wil::scope_exit([&]() { VERIFY_IS_TRUE(DeleteFileW(cidFilePath.c_str())); }); - auto result = RunWslc(std::format( - L"container create --cidfile \"{}\" --name {} {}", EscapePath(cidFilePath.wstring()), WslcContainerName, DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + L"container create --cidfile \"{}\" --name {} {}", + EscapePath(cidFilePath.wstring()), + WslcContainerName, + DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); const auto containerId = result.GetStdoutOneLine(); @@ -134,8 +138,12 @@ class WSLCE2EContainerCreateTests const auto cidFilePath = wsl::windows::common::filesystem::GetTempFilename(); auto deleteCidFile = wil::scope_exit([&]() { VERIFY_IS_TRUE(DeleteFileW(cidFilePath.c_str())); }); - auto result = RunWslc(std::format( - L"container create --cidfile \"{}\" --name {} {}", EscapePath(cidFilePath.wstring()), WslcContainerName, DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + L"container create --cidfile \"{}\" --name {} {}", + EscapePath(cidFilePath.wstring()), + WslcContainerName, + DebianImage.NameAndTag())); result.Verify( {.Stderr = std::format(L"CID file '{}' already exists\r\nError code: ERROR_FILE_EXISTS\r\n", EscapePath(cidFilePath.wstring())), .ExitCode = 1}); @@ -170,12 +178,13 @@ class WSLCE2EContainerCreateTests auto hostDirectory = VolumeTestFile1.parent_path(); auto fileName = VolumeTestFile1.filename().wstring(); - auto result = RunWslc(std::format( - L"container run --name {} --volume \"{}:/data:ro\" {} cat /data/{}", - WslcContainerName, - hostDirectory.wstring(), - AlpineImage.NameAndTag(), - fileName)); + auto result = RunWslc( + std::format( + L"container run --name {} --volume \"{}:/data:ro\" {} cat /data/{}", + WslcContainerName, + hostDirectory.wstring(), + AlpineImage.NameAndTag(), + fileName)); result.Verify({.Stdout = L"WSLC Volume Test", .Stderr = L"", .ExitCode = 0}); } @@ -183,12 +192,13 @@ class WSLCE2EContainerCreateTests { auto hostDirectory = VolumeTestFile1.parent_path(); auto fileName = VolumeTestFile1.filename().wstring(); - auto result = RunWslc(std::format( - L"container run --name {} --volume \"{}:/data\" {} sh -c \"echo -n 'WSLC Volume Test' > /data/{}\"", - WslcContainerName, - hostDirectory.wstring(), - AlpineImage.NameAndTag(), - fileName)); + auto result = RunWslc( + std::format( + L"container run --name {} --volume \"{}:/data\" {} sh -c \"echo -n 'WSLC Volume Test' > /data/{}\"", + WslcContainerName, + hostDirectory.wstring(), + AlpineImage.NameAndTag(), + fileName)); result.Verify({.Stdout = L"", .Stderr = L"", .ExitCode = 0}); // Read all file content @@ -200,12 +210,13 @@ class WSLCE2EContainerCreateTests { auto hostDirectory = VolumeTestFile1.parent_path(); auto fileName = VolumeTestFile1.filename().wstring(); - auto result = RunWslc(std::format( - L"container run --name {} --volume \"{}:/data:rw\" {} sh -c \"echo -n 'WSLC Volume Test' > /data/{}\"", - WslcContainerName, - hostDirectory.wstring(), - AlpineImage.NameAndTag(), - fileName)); + auto result = RunWslc( + std::format( + L"container run --name {} --volume \"{}:/data:rw\" {} sh -c \"echo -n 'WSLC Volume Test' > /data/{}\"", + WslcContainerName, + hostDirectory.wstring(), + AlpineImage.NameAndTag(), + fileName)); result.Verify({.Stdout = L"", .Stderr = L"", .ExitCode = 0}); // Read all file content @@ -219,12 +230,13 @@ class WSLCE2EContainerCreateTests { auto hostDirectory = VolumeTestFile1.parent_path(); auto fileName = VolumeTestFile1.filename().wstring(); - auto result = RunWslc(std::format( - L"container run --name {} --volume \"{}:/data:ro\" {} sh -c \"echo -n 'WSLC Volume Test' > /data/{}\"", - WslcContainerName, - hostDirectory.wstring(), - AlpineImage.NameAndTag(), - fileName)); + auto result = RunWslc( + std::format( + L"container run --name {} --volume \"{}:/data:ro\" {} sh -c \"echo -n 'WSLC Volume Test' > /data/{}\"", + WslcContainerName, + hostDirectory.wstring(), + AlpineImage.NameAndTag(), + fileName)); auto errorMessage = std::format(L"sh: can't create /data/{}: Read-only file system\n", fileName); result.Verify({.Stdout = L"", .Stderr = errorMessage, .ExitCode = 1}); } @@ -236,16 +248,17 @@ class WSLCE2EContainerCreateTests auto fileName1 = VolumeTestFile1.filename().wstring(); auto hostDirectory2 = VolumeTestFile2.parent_path(); auto fileName2 = VolumeTestFile2.filename().wstring(); - auto result = RunWslc(std::format( - L"container run --name {} --volume \"{}:/data1:rw\" --volume \"{}:/data2:rw\" {} sh -c \"echo -n 'Test1' > " - L"/data1/{} && " - L"echo -n 'Test2' > /data2/{}\"", - WslcContainerName, - hostDirectory1.wstring(), - hostDirectory2.wstring(), - AlpineImage.NameAndTag(), - fileName1, - fileName2)); + auto result = RunWslc( + std::format( + L"container run --name {} --volume \"{}:/data1:rw\" --volume \"{}:/data2:rw\" {} sh -c \"echo -n 'Test1' > " + L"/data1/{} && " + L"echo -n 'Test2' > /data2/{}\"", + WslcContainerName, + hostDirectory1.wstring(), + hostDirectory2.wstring(), + AlpineImage.NameAndTag(), + fileName1, + fileName2)); result.Verify({.Stdout = L"", .Stderr = L"", .ExitCode = 0}); @@ -285,22 +298,24 @@ class WSLCE2EContainerCreateTests VERIFY_IS_TRUE(out.good(), L"Failed to write to test file (host -> container test)"); } - auto result = RunWslc(std::format( - L"container run --rm --name {} --volume \"{}:/data:ro\" {} cat /data/reltest.txt", - WslcContainerName, - relativeDir, - AlpineImage.NameAndTag())); + auto result = RunWslc( + std::format( + L"container run --rm --name {} --volume \"{}:/data:ro\" {} cat /data/reltest.txt", + WslcContainerName, + relativeDir, + AlpineImage.NameAndTag())); result.Verify({.Stdout = L"WSLC Relative Path Test", .Stderr = L"", .ExitCode = 0}); EnsureContainerDoesNotExist(WslcContainerName); // Write a file from the container and verify the host can read it back via the relative path mount. - result = RunWslc(std::format( - L"container run --rm --name {} --volume \"{}:/data:rw\" {} sh -c \"echo -n 'WSLC Relative Path Write Test' > " - L"/data/reltest.txt\"", - WslcContainerName, - relativeDir, - AlpineImage.NameAndTag())); + result = RunWslc( + std::format( + L"container run --rm --name {} --volume \"{}:/data:rw\" {} sh -c \"echo -n 'WSLC Relative Path Write Test' > " + L"/data/reltest.txt\"", + WslcContainerName, + relativeDir, + AlpineImage.NameAndTag())); result.Verify({.Stdout = L"", .Stderr = L"", .ExitCode = 0}); std::ifstream in(testFile); @@ -368,22 +383,26 @@ class WSLCE2EContainerCreateTests } { - auto result = RunWslc(std::format( - L"container run --name {} --volume C:\\hostPath:/containerPath:invalid_mode {}", WslcContainerName, AlpineImage.NameAndTag())); + auto result = RunWslc( + std::format( + L"container run --name {} --volume C:\\hostPath:/containerPath:invalid_mode {}", + WslcContainerName, + AlpineImage.NameAndTag())); result.Verify({.Stderr = L"Invalid volume specifications: 'C:\\hostPath:/containerPath:invalid_mode'. Container path must be an absolute path (starting with '/'). Expected format: :[:mode]\r\nError code: E_INVALIDARG\r\n", .ExitCode = 1}); EnsureContainerDoesNotExist(WslcContainerName); } { - auto result = RunWslc(std::format( - L"container run --name {} --volume C:\\hostPath:/containerPath:ro:extra {}", WslcContainerName, AlpineImage.NameAndTag())); + auto result = RunWslc( + std::format( + L"container run --name {} --volume C:\\hostPath:/containerPath:ro:extra {}", WslcContainerName, AlpineImage.NameAndTag())); result.Verify({.Stderr = L"Invalid volume specifications: 'C:\\hostPath:/containerPath:ro:extra'. Container path must be an absolute path (starting with '/'). Expected format: :[:mode]\r\nError code: E_INVALIDARG\r\n", .ExitCode = 1}); EnsureContainerDoesNotExist(WslcContainerName); } { - auto result = RunWslc(std::format( - L"container run --name {} --volume C:\\hostPath:/containerPath: {}", WslcContainerName, AlpineImage.NameAndTag())); + auto result = RunWslc( + std::format(L"container run --name {} --volume C:\\hostPath:/containerPath: {}", WslcContainerName, AlpineImage.NameAndTag())); result.Verify({.Stderr = L"Invalid volume specifications: 'C:\\hostPath:/containerPath:'. Container path cannot be empty. Expected format: :[:mode]\r\nError code: E_INVALIDARG\r\n", .ExitCode = 1}); EnsureContainerDoesNotExist(WslcContainerName); } @@ -469,8 +488,8 @@ class WSLCE2EContainerCreateTests VerifyContainerIsNotListed(WslcContainerName); const auto& prompt = ">"; - auto result = RunWslc(std::format( - L"container create -it -e PS1={} --name {} {} bash --norc", prompt, WslcContainerName, DebianImage.NameAndTag())); + auto result = RunWslc( + std::format(L"container create -it -e PS1={} --name {} {} bash --norc", prompt, WslcContainerName, DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); auto containerId = result.GetStdoutOneLine(); @@ -530,8 +549,8 @@ class WSLCE2EContainerCreateTests constexpr auto ExpectedExitCode = 37; - auto result = RunWslc(std::format( - L"container create --name {} {} sh -c \"echo lifecycle works; exit {}\"", WslcContainerName, AlpineImage.NameAndTag(), ExpectedExitCode)); + auto result = RunWslc( + std::format(L"container create --name {} {} sh -c \"echo lifecycle works; exit {}\"", WslcContainerName, AlpineImage.NameAndTag(), ExpectedExitCode)); result.Verify({.Stderr = L"", .ExitCode = 0}); @@ -551,8 +570,9 @@ class WSLCE2EContainerCreateTests WSLC_TEST_METHOD(WSLCE2E_Container_Create_UserOption_NameGroupRoot) { - auto result = RunWslc(std::format( - L"container create --name {} -u root:root {} sh -c \"id -un; id -u; id -g\"", WslcContainerName, DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + L"container create --name {} -u root:root {} sh -c \"id -un; id -u; id -g\"", WslcContainerName, DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); result = RunWslc(std::format(L"container start -a {}", WslcContainerName)); @@ -572,11 +592,12 @@ class WSLCE2EContainerCreateTests WSLC_TEST_METHOD(WSLCE2E_Container_Create_Tmpfs) { - auto result = RunWslc(std::format( - L"container create --name {} --tmpfs /wslc-tmpfs {} sh -c \"echo -n 'tmpfs_test' > /wslc-tmpfs/data && cat " - L"/wslc-tmpfs/data\"", - WslcContainerName, - DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + L"container create --name {} --tmpfs /wslc-tmpfs {} sh -c \"echo -n 'tmpfs_test' > /wslc-tmpfs/data && cat " + L"/wslc-tmpfs/data\"", + WslcContainerName, + DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); result = RunWslc(std::format(L"container start -a {}", WslcContainerName)); @@ -585,11 +606,13 @@ class WSLCE2EContainerCreateTests WSLC_TEST_METHOD(WSLCE2E_Container_Create_Tmpfs_With_Options) { - auto result = RunWslc(std::format( - L"container create --name {} --tmpfs /wslc-tmpfs:size=64k {} sh -c \"mount | grep -q ' on /wslc-tmpfs type tmpfs ' " - L"&& echo mounted\"", - WslcContainerName, - DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + L"container create --name {} --tmpfs /wslc-tmpfs:size=64k {} sh -c \"mount | grep -q ' on /wslc-tmpfs type tmpfs " + L"' " + L"&& echo mounted\"", + WslcContainerName, + DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); result = RunWslc(std::format(L"container start -a {}", WslcContainerName)); @@ -598,11 +621,13 @@ class WSLCE2EContainerCreateTests WSLC_TEST_METHOD(WSLCE2E_Container_Create_Tmpfs_Multiple_With_Options) { - auto result = RunWslc(std::format( - L"container create --name {} --tmpfs /wslc-tmpfs1:size=64k --tmpfs /wslc-tmpfs2:size=128k {} sh -c \"mount | grep -q " - L"' on /wslc-tmpfs1 type tmpfs ' && mount | grep -q ' on /wslc-tmpfs2 type tmpfs ' && echo mounted\"", - WslcContainerName, - DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + L"container create --name {} --tmpfs /wslc-tmpfs1:size=64k --tmpfs /wslc-tmpfs2:size=128k {} sh -c \"mount | " + L"grep -q " + L"' on /wslc-tmpfs1 type tmpfs ' && mount | grep -q ' on /wslc-tmpfs2 type tmpfs ' && echo mounted\"", + WslcContainerName, + DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); result = RunWslc(std::format(L"container start -a {}", WslcContainerName)); @@ -646,8 +671,8 @@ class WSLCE2EContainerCreateTests WSLC_TEST_METHOD(WSLCE2E_Container_Create_Hostname) { - auto result = RunWslc(std::format( - L"container create --name {} --hostname my-test-host {} hostname", WslcContainerName, DebianImage.NameAndTag())); + auto result = RunWslc( + std::format(L"container create --name {} --hostname my-test-host {} hostname", WslcContainerName, DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); result = RunWslc(std::format(L"container start -a {}", WslcContainerName)); @@ -656,8 +681,8 @@ class WSLCE2EContainerCreateTests WSLC_TEST_METHOD(WSLCE2E_Container_Create_Domainname) { - auto result = RunWslc(std::format( - L"container create --name {} --domainname my-test-domain {} dnsdomainname", WslcContainerName, DebianImage.NameAndTag())); + auto result = RunWslc( + std::format(L"container create --name {} --domainname my-test-domain {} dnsdomainname", WslcContainerName, DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); result = RunWslc(std::format(L"container start -a {}", WslcContainerName)); @@ -666,8 +691,9 @@ class WSLCE2EContainerCreateTests WSLC_TEST_METHOD(WSLCE2E_Container_Create_DNS) { - auto result = RunWslc(std::format( - L"container create --name {} --dns 1.1.1.1 --dns 8.8.8.8 {} cat /etc/resolv.conf", WslcContainerName, DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + L"container create --name {} --dns 1.1.1.1 --dns 8.8.8.8 {} cat /etc/resolv.conf", WslcContainerName, DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); result = RunWslc(std::format(L"container start -a {}", WslcContainerName)); @@ -678,10 +704,11 @@ class WSLCE2EContainerCreateTests WSLC_TEST_METHOD(WSLCE2E_Container_Create_DNSSearch) { - auto result = RunWslc(std::format( - L"container create --name {} --dns-search example.com --dns-search test.local {} cat /etc/resolv.conf", - WslcContainerName, - DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + L"container create --name {} --dns-search example.com --dns-search test.local {} cat /etc/resolv.conf", + WslcContainerName, + DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); result = RunWslc(std::format(L"container start -a {}", WslcContainerName)); @@ -691,10 +718,11 @@ class WSLCE2EContainerCreateTests WSLC_TEST_METHOD(WSLCE2E_Container_Create_DNSOption) { - auto result = RunWslc(std::format( - L"container create --name {} --dns-option ndots:5 --dns-option timeout:3 {} cat /etc/resolv.conf", - WslcContainerName, - DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + L"container create --name {} --dns-option ndots:5 --dns-option timeout:3 {} cat /etc/resolv.conf", + WslcContainerName, + DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); result = RunWslc(std::format(L"container start -a {}", WslcContainerName)); @@ -705,11 +733,12 @@ class WSLCE2EContainerCreateTests WSLC_TEST_METHOD(WSLCE2E_Container_Create_StopSignal) { constexpr int ExpectedExitCode = 42; - auto result = RunWslc(std::format( - LR"(container create --stop-signal SIGUSR1 --name {} {} bash -c "trap 'exit {}' SIGUSR1; while true; do sleep 1; done")", - WslcContainerName, - DebianImage.NameAndTag(), - ExpectedExitCode)); + auto result = RunWslc( + std::format( + LR"(container create --stop-signal SIGUSR1 --name {} {} bash -c "trap 'exit {}' SIGUSR1; while true; do sleep 1; done")", + WslcContainerName, + DebianImage.NameAndTag(), + ExpectedExitCode)); result.Verify({.Stderr = L"", .ExitCode = 0}); const auto containerId = result.GetStdoutOneLine(); VerifyContainerIsListed(containerId, L"created"); @@ -731,8 +760,9 @@ class WSLCE2EContainerCreateTests // A positive value is forwarded to the container configuration. { constexpr int ExpectedStopTimeout = 30; - auto result = RunWslc(std::format( - L"container create --stop-timeout {} --name {} {}", ExpectedStopTimeout, WslcContainerName, DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + L"container create --stop-timeout {} --name {} {}", ExpectedStopTimeout, WslcContainerName, DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); const auto inspect = InspectContainer(WslcContainerName); @@ -825,10 +855,11 @@ class WSLCE2EContainerCreateTests { // All health-check options are forwarded to the container configuration. { - auto result = RunWslc(std::format( - LR"(container create --health-cmd "exit 0" --health-interval 5s --health-timeout 3s --health-retries 2 --health-start-period 1s --name {} {})", - WslcContainerName, - DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + LR"(container create --health-cmd "exit 0" --health-interval 5s --health-timeout 3s --health-retries 2 --health-start-period 1s --name {} {})", + WslcContainerName, + DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); const auto inspect = InspectContainer(WslcContainerName); @@ -883,8 +914,8 @@ class WSLCE2EContainerCreateTests WSLC_TEST_METHOD(WSLCE2E_Container_Create_HealthCheck_Invalid) { { - auto result = RunWslc(std::format( - L"container create --health-interval notaduration --name {} {}", WslcContainerName, DebianImage.NameAndTag())); + auto result = RunWslc( + std::format(L"container create --health-interval notaduration --name {} {}", WslcContainerName, DebianImage.NameAndTag())); result.Verify( {.Stderr = L"Invalid health-interval argument value: 'notaduration'. Expected a duration (e.g. 30s, 1m30s)\r\n", .ExitCode = 1}); VerifyContainerIsNotListed(WslcContainerName); @@ -898,15 +929,16 @@ class WSLCE2EContainerCreateTests } { - auto result = RunWslc(std::format( - LR"(container create --no-healthcheck --health-cmd "exit 0" --name {} {})", WslcContainerName, DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + LR"(container create --no-healthcheck --health-cmd "exit 0" --name {} {})", WslcContainerName, DebianImage.NameAndTag())); result.Verify({.Stderr = L"The --no-healthcheck option cannot be combined with other health check options.\r\n", .ExitCode = 1}); VerifyContainerIsNotListed(WslcContainerName); } { - auto result = RunWslc(std::format( - L"container create --no-healthcheck --health-interval 5s --name {} {}", WslcContainerName, DebianImage.NameAndTag())); + auto result = RunWslc( + std::format(L"container create --no-healthcheck --health-interval 5s --name {} {}", WslcContainerName, DebianImage.NameAndTag())); result.Verify({.Stderr = L"The --no-healthcheck option cannot be combined with other health check options.\r\n", .ExitCode = 1}); VerifyContainerIsNotListed(WslcContainerName); } @@ -955,8 +987,8 @@ class WSLCE2EContainerCreateTests WSLC_TEST_METHOD(WSLCE2E_Container_Create_Network_HostMode_WithMultipleNetworks_Rejected) { - auto result = RunWslc(std::format( - L"container create --name {} --network bridge --network host {} true", WslcContainerName, DebianImage.NameAndTag())); + auto result = RunWslc( + std::format(L"container create --name {} --network bridge --network host {} true", WslcContainerName, DebianImage.NameAndTag())); result.Verify({.Stderr = L"host mode networking is not supported\r\n", .ExitCode = 1}); VerifyContainerIsNotListed(WslcContainerName); } @@ -967,8 +999,8 @@ class WSLCE2EContainerCreateTests result.Verify({.Stderr = L"", .ExitCode = 0}); auto cleanupNetwork = wil::scope_exit([&] { EnsureNetworkDoesNotExist(TestNetworkName); }); - result = RunWslc(std::format( - L"container create --name {} --network {} {} true", WslcContainerName, TestNetworkName, DebianImage.NameAndTag())); + result = RunWslc( + std::format(L"container create --name {} --network {} {} true", WslcContainerName, TestNetworkName, DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); const auto inspect = InspectContainer(WslcContainerName); @@ -996,8 +1028,12 @@ class WSLCE2EContainerCreateTests result.Verify({.Stderr = L"", .ExitCode = 0}); auto cleanupNetwork = wil::scope_exit([&] { EnsureNetworkDoesNotExist(TestNetworkName); }); - result = RunWslc(std::format( - L"container create --name {} --network {} --network-alias db {} true", WslcContainerName, TestNetworkName, DebianImage.NameAndTag())); + result = RunWslc( + std::format( + L"container create --name {} --network {} --network-alias db {} true", + WslcContainerName, + TestNetworkName, + DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); const auto inspect = InspectContainer(WslcContainerName); @@ -1020,8 +1056,8 @@ class WSLCE2EContainerCreateTests WSLC_TEST_METHOD(WSLCE2E_Container_Create_NetworkAlias_NoneMode_Rejected) { - auto result = RunWslc(std::format( - L"container create --network none --network-alias db --name {} {} true", WslcContainerName, DebianImage.NameAndTag())); + auto result = RunWslc( + std::format(L"container create --network none --network-alias db --name {} {} true", WslcContainerName, DebianImage.NameAndTag())); result.Verify( {.Stderr = L"Network aliases require a user-defined network. Use --network to specify one.\r\nError code: E_INVALIDARG\r\n", @@ -1031,10 +1067,11 @@ class WSLCE2EContainerCreateTests WSLC_TEST_METHOD(WSLCE2E_Container_Create_NetworkAlias_MultipleNetworks_Rejected) { - auto result = RunWslc(std::format( - L"container create --network bridge --network bridge --network-alias db --name {} {} true", - WslcContainerName, - DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + L"container create --network bridge --network bridge --network-alias db --name {} {} true", + WslcContainerName, + DebianImage.NameAndTag())); result.Verify({.Stderr = L"Network aliases cannot be specified when multiple networks are requested. Use a single --network argument.\r\nError code: E_INVALIDARG\r\n", .ExitCode = 1}); VerifyContainerIsNotListed(WslcContainerName); } @@ -1084,8 +1121,9 @@ class WSLCE2EContainerCreateTests WSLC_TEST_METHOD(WSLCE2E_Container_Create_Ulimit) { - auto result = RunWslc(std::format( - L"container create --name {} --ulimit nofile=1024:2048 --ulimit nproc=512 {} true", WslcContainerName, DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + L"container create --name {} --ulimit nofile=1024:2048 --ulimit nproc=512 {} true", WslcContainerName, DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); const auto inspect = InspectContainer(WslcContainerName); @@ -1129,8 +1167,12 @@ class WSLCE2EContainerCreateTests WriteTestFile( EnvTestFile1, {"WSLC_TEST_CREATE_ENV_FILE_A=create-env-file-a", "WSLC_TEST_CREATE_ENV_FILE_B=create-env-file-b"}); - auto result = RunWslc(std::format( - L"container create --name {} --env-file {} {} env", WslcContainerName, EscapePath(EnvTestFile1.wstring()), DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + L"container create --name {} --env-file {} {} env", + WslcContainerName, + EscapePath(EnvTestFile1.wstring()), + DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); result = RunWslc(std::format(L"container start -a {}", WslcContainerName)); @@ -1142,8 +1184,8 @@ class WSLCE2EContainerCreateTests WSLC_TEST_METHOD(WSLCE2E_Container_Create_EnvFile_MissingFile) { - auto result = RunWslc(std::format( - L"container create --name {} --env-file ENV_FILE_NOT_FOUND {} env", WslcContainerName, DebianImage.NameAndTag())); + auto result = RunWslc( + std::format(L"container create --name {} --env-file ENV_FILE_NOT_FOUND {} env", WslcContainerName, DebianImage.NameAndTag())); result.Verify( {.Stderr = L"Environment file 'ENV_FILE_NOT_FOUND' cannot be opened for reading\r\nError code: E_INVALIDARG\r\n", .ExitCode = 1}); EnsureContainerDoesNotExist(WslcContainerName); @@ -1153,8 +1195,12 @@ class WSLCE2EContainerCreateTests { WriteTestFile(EnvTestFile1, {"WSLC_TEST_ENV_VALID=ok", "BAD KEY=value"}); - auto result = RunWslc(std::format( - L"container create --name {} --env-file {} {} env", WslcContainerName, EscapePath(EnvTestFile1.wstring()), DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + L"container create --name {} --env-file {} {} env", + WslcContainerName, + EscapePath(EnvTestFile1.wstring()), + DebianImage.NameAndTag())); result.Verify({.Stderr = L"Environment variable key 'BAD KEY' cannot contain whitespace\r\nError code: E_INVALIDARG\r\n", .ExitCode = 1}); EnsureContainerDoesNotExist(WslcContainerName); } @@ -1162,8 +1208,13 @@ class WSLCE2EContainerCreateTests WSLC_TEST_METHOD(WSLCE2E_Container_Create_Publish_TCP) { // Port bindings only show up in inspect after start, so create then start before inspecting. - auto result = RunWslc(std::format( - L"container create --name {} -p {}:{} {} sleep 5", WslcContainerName, HostTestPort1, ContainerTestPort, DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + L"container create --name {} -p {}:{} {} sleep 5", + WslcContainerName, + HostTestPort1, + ContainerTestPort, + DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); result = RunWslc(std::format(L"container start {}", WslcContainerName)); @@ -1183,14 +1234,15 @@ class WSLCE2EContainerCreateTests WSLC_TEST_METHOD(WSLCE2E_Container_Create_Publish_MultipleMappings) { // Map two host ports to the same container port. - auto result = RunWslc(std::format( - L"container create --name {} -p {}:{} -p {}:{} {} sleep 5", - WslcContainerName, - HostTestPort1, - ContainerTestPort, - HostTestPort2, - ContainerTestPort, - DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + L"container create --name {} -p {}:{} -p {}:{} {} sleep 5", + WslcContainerName, + HostTestPort1, + ContainerTestPort, + HostTestPort2, + ContainerTestPort, + DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); result = RunWslc(std::format(L"container start {}", WslcContainerName)); @@ -1225,8 +1277,8 @@ class WSLCE2EContainerCreateTests WSLC_TEST_METHOD(WSLCE2E_Container_Create_Publish_Ephemeral) { // -p (no host port) means the host picks a random port. - auto result = RunWslc(std::format( - L"container create --name {} -p {} {} sleep 5", WslcContainerName, ContainerTestPort, DebianImage.NameAndTag())); + auto result = RunWslc( + std::format(L"container create --name {} -p {} {} sleep 5", WslcContainerName, ContainerTestPort, DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); result = RunWslc(std::format(L"container start {}", WslcContainerName)); @@ -1246,12 +1298,13 @@ class WSLCE2EContainerCreateTests WSLC_TEST_METHOD(WSLCE2E_Container_Create_Publish_UDP) { // Port bindings only show up in inspect after start, so create then start before inspecting. - auto result = RunWslc(std::format( - L"container create --name {} -p {}:{}/udp {} sleep 5", - WslcContainerName, - HostTestPort1, - ContainerTestPort, - DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + L"container create --name {} -p {}:{}/udp {} sleep 5", + WslcContainerName, + HostTestPort1, + ContainerTestPort, + DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); result = RunWslc(std::format(L"container start {}", WslcContainerName)); @@ -1272,12 +1325,13 @@ class WSLCE2EContainerCreateTests WSLC_TEST_METHOD(WSLCE2E_Container_Create_Publish_HostIP) { // Port bindings only show up in inspect after start, so create then start before inspecting. - auto result = RunWslc(std::format( - L"container create --name {} -p 127.0.0.1:{}:{} {} sleep 5", - WslcContainerName, - HostTestPort1, - ContainerTestPort, - DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + L"container create --name {} -p 127.0.0.1:{}:{} {} sleep 5", + WslcContainerName, + HostTestPort1, + ContainerTestPort, + DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); result = RunWslc(std::format(L"container start {}", WslcContainerName)); diff --git a/test/windows/wslc/e2e/WSLCE2EContainerExecTests.cpp b/test/windows/wslc/e2e/WSLCE2EContainerExecTests.cpp index 81a02e1ae..38dfb71a1 100644 --- a/test/windows/wslc/e2e/WSLCE2EContainerExecTests.cpp +++ b/test/windows/wslc/e2e/WSLCE2EContainerExecTests.cpp @@ -268,8 +268,7 @@ class WSLCE2EContainerExecTests auto result = RunWslc(std::format(L"container run -d --name {} {} sleep infinity", WslcContainerName, DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); - result = RunWslc(std::format( - L"container exec -e {}=value-a -e {}=value-b {} env", HostEnvVariableName, HostEnvVariableName2, WslcContainerName)); + result = RunWslc(std::format(L"container exec -e {}=value-a -e {}=value-b {} env", HostEnvVariableName, HostEnvVariableName2, WslcContainerName)); result.Verify({.Stderr = L"", .ExitCode = 0}); VERIFY_IS_TRUE(result.StdoutContainsLine(std::format(L"{}=value-a", HostEnvVariableName))); @@ -307,8 +306,8 @@ class WSLCE2EContainerExecTests auto result = RunWslc(std::format(L"container run -d --name {} {} sleep infinity", WslcContainerName, DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); - result = RunWslc(std::format( - L"container exec -e WSLC_TEST_EXEC_ENV_MIX_CLI=from-cli --env-file {} {} env", EscapePath(EnvTestFile1.wstring()), WslcContainerName)); + result = RunWslc( + std::format(L"container exec -e WSLC_TEST_EXEC_ENV_MIX_CLI=from-cli --env-file {} {} env", EscapePath(EnvTestFile1.wstring()), WslcContainerName)); result.Verify({.Stderr = L"", .ExitCode = 0}); VERIFY_IS_TRUE(result.StdoutContainsLine(L"WSLC_TEST_EXEC_ENV_MIX_FILE_A=from-file-a")); @@ -334,8 +333,9 @@ class WSLCE2EContainerExecTests auto result = RunWslc(std::format(L"container run -d --name {} {} sleep infinity", WslcContainerName, DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); - result = RunWslc(std::format( - L"container exec --env-file {} --env-file {} {} env", EscapePath(EnvTestFile1.wstring()), EscapePath(EnvTestFile2.wstring()), WslcContainerName)); + result = RunWslc( + std::format( + L"container exec --env-file {} --env-file {} {} env", EscapePath(EnvTestFile1.wstring()), EscapePath(EnvTestFile2.wstring()), WslcContainerName)); result.Verify({.Stderr = L"", .ExitCode = 0}); VERIFY_IS_TRUE(result.StdoutContainsLine(L"WSLC_TEST_EXEC_ENV_FILE_MULTI_A=file1-a")); @@ -364,18 +364,20 @@ class WSLCE2EContainerExecTests result.Verify({.Stderr = L"", .ExitCode = 0}); // Later --env-file wins - result = RunWslc(std::format( - L"container exec --env-file {} --env-file {} {} env", EscapePath(EnvTestFile1.wstring()), EscapePath(EnvTestFile2.wstring()), WslcContainerName)); + result = RunWslc( + std::format( + L"container exec --env-file {} --env-file {} {} env", EscapePath(EnvTestFile1.wstring()), EscapePath(EnvTestFile2.wstring()), WslcContainerName)); result.Verify({.Stderr = L"", .ExitCode = 0}); VERIFY_IS_TRUE(result.StdoutContainsLine(L"WSLC_TEST_EXEC_ENV_DUP=from-file-2")); // Explicit -e wins over env-file - result = RunWslc(std::format( - L"container exec -e WSLC_TEST_EXEC_ENV_DUP=from-cli --env-file {} --env-file {} {} env", - EscapePath(EnvTestFile1.wstring()), - EscapePath(EnvTestFile2.wstring()), - WslcContainerName)); + result = RunWslc( + std::format( + L"container exec -e WSLC_TEST_EXEC_ENV_DUP=from-cli --env-file {} --env-file {} {} env", + EscapePath(EnvTestFile1.wstring()), + EscapePath(EnvTestFile2.wstring()), + WslcContainerName)); result.Verify({.Stderr = L"", .ExitCode = 0}); VERIFY_IS_TRUE(result.StdoutContainsLine(L"WSLC_TEST_EXEC_ENV_DUP=from-cli")); @@ -477,13 +479,14 @@ class WSLCE2EContainerExecTests result = RunWslc(std::format(L"container exec -d {} sh -c \"sleep 1 && echo wslc-detach-ok > {}\"", WslcContainerName, markerPath)); result.Verify({.Stdout = L"", .Stderr = L"", .ExitCode = 0}); - VERIFY_NO_THROW(wsl::shared::retry::RetryWithTimeout( - [&]() { - auto readResult = RunWslc(std::format(L"container exec {} cat {}", WslcContainerName, markerPath)); - readResult.Verify({.Stdout = L"wslc-detach-ok\n", .Stderr = L"", .ExitCode = 0}); - }, - std::chrono::milliseconds(200), - std::chrono::seconds(10))); + VERIFY_NO_THROW( + wsl::shared::retry::RetryWithTimeout( + [&]() { + auto readResult = RunWslc(std::format(L"container exec {} cat {}", WslcContainerName, markerPath)); + readResult.Verify({.Stdout = L"wslc-detach-ok\n", .Stderr = L"", .ExitCode = 0}); + }, + std::chrono::milliseconds(200), + std::chrono::seconds(10))); } private: diff --git a/test/windows/wslc/e2e/WSLCE2EContainerListTests.cpp b/test/windows/wslc/e2e/WSLCE2EContainerListTests.cpp index 10e231f2e..1b7ce9453 100644 --- a/test/windows/wslc/e2e/WSLCE2EContainerListTests.cpp +++ b/test/windows/wslc/e2e/WSLCE2EContainerListTests.cpp @@ -299,8 +299,11 @@ class WSLCE2EContainerListTests VerifyContainerIsNotListed(WslcContainerName2); // First container has both labels; second has only one of them. - auto result = RunWslc(std::format( - L"container create --name {} --label filter.test=yes --label filter.role=primary {}", WslcContainerName, DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + L"container create --name {} --label filter.test=yes --label filter.role=primary {}", + WslcContainerName, + DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); result = RunWslc(std::format(L"container create --name {} --label filter.test=yes {}", WslcContainerName2, DebianImage.NameAndTag())); diff --git a/test/windows/wslc/e2e/WSLCE2EContainerLogsTests.cpp b/test/windows/wslc/e2e/WSLCE2EContainerLogsTests.cpp index 2aab308a5..c165359e3 100644 --- a/test/windows/wslc/e2e/WSLCE2EContainerLogsTests.cpp +++ b/test/windows/wslc/e2e/WSLCE2EContainerLogsTests.cpp @@ -44,8 +44,8 @@ class WSLCE2EContainerLogsTests WSLC_TEST_METHOD(WSLCE2E_Container_Logs_Tail) { // Run a container that outputs two lines - auto result = RunWslc(std::format( - L"container run --name {} {} sh -c \"echo line1 && echo line2\"", WslcContainerName, DebianImage.NameAndTag())); + auto result = RunWslc( + std::format(L"container run --name {} {} sh -c \"echo line1 && echo line2\"", WslcContainerName, DebianImage.NameAndTag())); result.Verify({.Stdout = L"line1\nline2\n", .Stderr = L"", .ExitCode = 0}); // Verify --tail 1 only shows the last line @@ -180,8 +180,8 @@ class WSLCE2EContainerLogsTests WSLC_TEST_METHOD(WSLCE2E_Container_Logs_AllOptionsCombined) { // Run a container that outputs multiple lines - auto result = RunWslc(std::format( - L"container run --name {} {} sh -c \"echo a && echo b && echo c\"", WslcContainerName, DebianImage.NameAndTag())); + auto result = RunWslc( + std::format(L"container run --name {} {} sh -c \"echo a && echo b && echo c\"", WslcContainerName, DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); // Combine --timestamps --since 0 --tail 2 @@ -210,11 +210,12 @@ class WSLCE2EContainerLogsTests { // Sleep between the two lines so the second is not produced until after line 1 is read. constexpr int InterLineSleepSeconds = 2; - auto result = RunWslc(std::format( - L"container run -d --name {} {} sh -c \"echo follow-line-1; sleep {}; echo follow-line-2\"", - WslcContainerName, - DebianImage.NameAndTag(), - InterLineSleepSeconds)); + auto result = RunWslc( + std::format( + L"container run -d --name {} {} sh -c \"echo follow-line-1; sleep {}; echo follow-line-2\"", + WslcContainerName, + DebianImage.NameAndTag(), + InterLineSleepSeconds)); result.Verify({.Stderr = L"", .ExitCode = 0}); auto logsSession = RunWslcInteractive(std::format(L"container logs -f {}", WslcContainerName)); diff --git a/test/windows/wslc/e2e/WSLCE2EContainerRunTests.cpp b/test/windows/wslc/e2e/WSLCE2EContainerRunTests.cpp index 4ad50632f..d74d6db48 100644 --- a/test/windows/wslc/e2e/WSLCE2EContainerRunTests.cpp +++ b/test/windows/wslc/e2e/WSLCE2EContainerRunTests.cpp @@ -97,11 +97,12 @@ class WSLCE2EContainerRunTests VERIFY_IS_TRUE(DeleteFileW(cidFilePath.c_str())); auto deleteCidFile = wil::scope_exit([&]() { VERIFY_IS_TRUE(DeleteFileW(cidFilePath.c_str())); }); - auto result = RunWslc(std::format( - L"container run -d --cidfile \"{}\" --name {} {} sleep infinity", - EscapePath(cidFilePath.wstring()), - WslcContainerName, - DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + L"container run -d --cidfile \"{}\" --name {} {} sleep infinity", + EscapePath(cidFilePath.wstring()), + WslcContainerName, + DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); const auto containerId = result.GetStdoutOneLine(); @@ -114,8 +115,9 @@ class WSLCE2EContainerRunTests const auto cidFilePath = wsl::windows::common::filesystem::GetTempFilename(); auto deleteCidFile = wil::scope_exit([&]() { VERIFY_IS_TRUE(DeleteFileW(cidFilePath.c_str())); }); - auto result = RunWslc(std::format( - L"container run --cidfile \"{}\" --name {} {}", EscapePath(cidFilePath.wstring()), WslcContainerName, DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + L"container run --cidfile \"{}\" --name {} {}", EscapePath(cidFilePath.wstring()), WslcContainerName, DebianImage.NameAndTag())); result.Verify( {.Stderr = std::format(L"CID file '{}' already exists\r\nError code: ERROR_FILE_EXISTS\r\n", EscapePath(cidFilePath.wstring())), .ExitCode = 1}); @@ -145,8 +147,8 @@ class WSLCE2EContainerRunTests WSLC_TEST_METHOD(WSLCE2E_Container_Run_Entrypoint_Detach_Lifecycle) { - auto result = RunWslc(std::format( - L"container run --name {} -d --entrypoint /bin/sleep {} infinity", WslcContainerName, DebianImage.NameAndTag())); + auto result = RunWslc( + std::format(L"container run --name {} -d --entrypoint /bin/sleep {} infinity", WslcContainerName, DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); VerifyContainerIsListed(WslcContainerName, L"running"); @@ -168,8 +170,8 @@ class WSLCE2EContainerRunTests { VerifyContainerIsNotListed(WslcContainerName); - auto result = RunWslc(std::format( - L"container run --rm --name {} -e {}=A {} env", WslcContainerName, HostEnvVariableName, DebianImage.NameAndTag())); + auto result = RunWslc( + std::format(L"container run --rm --name {} -e {}=A {} env", WslcContainerName, HostEnvVariableName, DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); VERIFY_IS_TRUE(result.StdoutContainsLine(std::format(L"{}=A", HostEnvVariableName))); @@ -179,12 +181,13 @@ class WSLCE2EContainerRunTests { VerifyContainerIsNotListed(WslcContainerName); - auto result = RunWslc(std::format( - L"container run --rm --name {} -e {}=A -e {}=B {} env", - WslcContainerName, - HostEnvVariableName, - HostEnvVariableName2, - DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + L"container run --rm --name {} -e {}=A -e {}=B {} env", + WslcContainerName, + HostEnvVariableName, + HostEnvVariableName2, + DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); VERIFY_IS_TRUE(result.StdoutContainsLine(std::format(L"{}=A", HostEnvVariableName))); @@ -195,8 +198,8 @@ class WSLCE2EContainerRunTests { VerifyContainerIsNotListed(WslcContainerName); - auto result = RunWslc(std::format( - L"container run --rm --name {} -e {} {} env", WslcContainerName, HostEnvVariableName, DebianImage.NameAndTag())); + auto result = RunWslc( + std::format(L"container run --rm --name {} -e {} {} env", WslcContainerName, HostEnvVariableName, DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); VERIFY_IS_TRUE(result.StdoutContainsLine(std::format(L"{}={}", HostEnvVariableName, HostEnvVariableValue))); @@ -206,12 +209,13 @@ class WSLCE2EContainerRunTests { VerifyContainerIsNotListed(WslcContainerName); - auto result = RunWslc(std::format( - L"container run --rm --name {} -e {} -e {} {} env", - WslcContainerName, - HostEnvVariableName, - HostEnvVariableName2, - DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + L"container run --rm --name {} -e {} -e {} {} env", + WslcContainerName, + HostEnvVariableName, + HostEnvVariableName2, + DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); VERIFY_IS_TRUE(result.StdoutContainsLine(std::format(L"{}={}", HostEnvVariableName, HostEnvVariableValue))); @@ -222,8 +226,8 @@ class WSLCE2EContainerRunTests { VerifyContainerIsNotListed(WslcContainerName); - auto result = RunWslc(std::format( - L"container run --rm --name {} -e {}= {} env", WslcContainerName, HostEnvVariableName, DebianImage.NameAndTag())); + auto result = RunWslc( + std::format(L"container run --rm --name {} -e {}= {} env", WslcContainerName, HostEnvVariableName, DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); VERIFY_IS_TRUE(result.StdoutContainsLine(std::format(L"{}=", HostEnvVariableName))); @@ -235,11 +239,12 @@ class WSLCE2EContainerRunTests WriteTestFile(EnvTestFile1, {"WSLC_TEST_ENV_FILE_A=env-file-a", "WSLC_TEST_ENV_FILE_B=env-file-b"}); - auto result = RunWslc(std::format( - L"container run --rm --name {} --env-file {} {} env", - WslcContainerName, - EscapePath(EnvTestFile1.wstring()), - DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + L"container run --rm --name {} --env-file {} {} env", + WslcContainerName, + EscapePath(EnvTestFile1.wstring()), + DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); VERIFY_IS_TRUE(result.StdoutContainsLine(L"WSLC_TEST_ENV_FILE_A=env-file-a")); @@ -252,11 +257,12 @@ class WSLCE2EContainerRunTests WriteTestFile(EnvTestFile1, {"WSLC_TEST_ENV_MIX_FILE_A=from-file-a", "WSLC_TEST_ENV_MIX_FILE_B=from-file-b"}); - auto result = RunWslc(std::format( - L"container run --rm --name {} -e WSLC_TEST_ENV_MIX_CLI=from-cli --env-file {} {} env", - WslcContainerName, - EscapePath(EnvTestFile1.wstring()), - DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + L"container run --rm --name {} -e WSLC_TEST_ENV_MIX_CLI=from-cli --env-file {} {} env", + WslcContainerName, + EscapePath(EnvTestFile1.wstring()), + DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); VERIFY_IS_TRUE(result.StdoutContainsLine(L"WSLC_TEST_ENV_MIX_FILE_A=from-file-a")); @@ -272,12 +278,13 @@ class WSLCE2EContainerRunTests WriteTestFile(EnvTestFile2, {"WSLC_TEST_ENV_FILE_MULTI_C=file2-c", "WSLC_TEST_ENV_FILE_MULTI_D=file2-d"}); - auto result = RunWslc(std::format( - L"container run --rm --name {} --env-file {} --env-file {} {} env", - WslcContainerName, - EscapePath(EnvTestFile1.wstring()), - EscapePath(EnvTestFile2.wstring()), - DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + L"container run --rm --name {} --env-file {} --env-file {} {} env", + WslcContainerName, + EscapePath(EnvTestFile1.wstring()), + EscapePath(EnvTestFile2.wstring()), + DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); VERIFY_IS_TRUE(result.StdoutContainsLine(L"WSLC_TEST_ENV_FILE_MULTI_A=file1-a")); @@ -290,8 +297,8 @@ class WSLCE2EContainerRunTests { VerifyContainerIsNotListed(WslcContainerName); - auto result = RunWslc(std::format( - L"container run --rm --name {} --env-file ENV_FILE_NOT_FOUND {} env", WslcContainerName, DebianImage.NameAndTag())); + auto result = RunWslc( + std::format(L"container run --rm --name {} --env-file ENV_FILE_NOT_FOUND {} env", WslcContainerName, DebianImage.NameAndTag())); result.Verify( {.Stderr = L"Environment file 'ENV_FILE_NOT_FOUND' cannot be opened for reading\r\nError code: E_INVALIDARG\r\n", .ExitCode = 1}); } @@ -302,11 +309,12 @@ class WSLCE2EContainerRunTests WriteTestFile(EnvTestFile1, {"WSLC_TEST_ENV_VALID=ok", "BAD KEY=value"}); - auto result = RunWslc(std::format( - L"container run --rm --name {} --env-file {} {} env", - WslcContainerName, - EscapePath(EnvTestFile1.wstring()), - DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + L"container run --rm --name {} --env-file {} {} env", + WslcContainerName, + EscapePath(EnvTestFile1.wstring()), + DebianImage.NameAndTag())); result.Verify({.Stderr = L"Environment variable key 'BAD KEY' cannot contain whitespace\r\nError code: E_INVALIDARG\r\n", .ExitCode = 1}); } @@ -319,23 +327,25 @@ class WSLCE2EContainerRunTests WriteTestFile(EnvTestFile2, {"WSLC_TEST_ENV_DUP=from-file-2"}); // Later --env-file should win over earlier --env-file for duplicate keys - auto result = RunWslc(std::format( - L"container run --rm --name {} --env-file {} --env-file {} {} env", - WslcContainerName, - EscapePath(EnvTestFile1.wstring()), - EscapePath(EnvTestFile2.wstring()), - DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + L"container run --rm --name {} --env-file {} --env-file {} {} env", + WslcContainerName, + EscapePath(EnvTestFile1.wstring()), + EscapePath(EnvTestFile2.wstring()), + DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); VERIFY_IS_TRUE(result.StdoutContainsLine(L"WSLC_TEST_ENV_DUP=from-file-2")); // Explicit -e should win over env-file value for duplicate keys - result = RunWslc(std::format( - L"container run --rm --name {} -e WSLC_TEST_ENV_DUP=from-cli --env-file {} --env-file {} {} env", - WslcContainerName, - EscapePath(EnvTestFile1.wstring()), - EscapePath(EnvTestFile2.wstring()), - DebianImage.NameAndTag())); + result = RunWslc( + std::format( + L"container run --rm --name {} -e WSLC_TEST_ENV_DUP=from-cli --env-file {} --env-file {} {} env", + WslcContainerName, + EscapePath(EnvTestFile1.wstring()), + EscapePath(EnvTestFile2.wstring()), + DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); VERIFY_IS_TRUE(result.StdoutContainsLine(L"WSLC_TEST_ENV_DUP=from-cli")); @@ -347,11 +357,12 @@ class WSLCE2EContainerRunTests WriteTestFile(EnvTestFile1, {"WSLC_TEST_ENV_EQUALS=value=with=equals"}); - auto result = RunWslc(std::format( - L"container run --rm --name {} --env-file {} {} env", - WslcContainerName, - EscapePath(EnvTestFile1.wstring()), - DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + L"container run --rm --name {} --env-file {} {} env", + WslcContainerName, + EscapePath(EnvTestFile1.wstring()), + DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); VERIFY_IS_TRUE(result.StdoutContainsLine(L"WSLC_TEST_ENV_EQUALS=value=with=equals")); @@ -405,15 +416,16 @@ class WSLCE2EContainerRunTests { // Start a container with a simple server listening on a port // Map two host ports to the same container port - auto result = RunWslc(std::format( - L"container run -d --name {} -p {}:{} -p {}:{} {} {}", - WslcContainerName, - HostTestPort1, - ContainerTestPort, - HostTestPort2, - ContainerTestPort, - PythonImage.NameAndTag(), - GetPythonHttpServerScript(ContainerTestPort))); + auto result = RunWslc( + std::format( + L"container run -d --name {} -p {}:{} -p {}:{} {} {}", + WslcContainerName, + HostTestPort1, + ContainerTestPort, + HostTestPort2, + ContainerTestPort, + PythonImage.NameAndTag(), + GetPythonHttpServerScript(ContainerTestPort))); result.Verify({.Stderr = L"", .ExitCode = 0}); WaitForContainerOutput(WslcContainerName, "Serving HTTP on"); @@ -426,13 +438,14 @@ class WSLCE2EContainerRunTests WSLC_TEST_METHOD(WSLCE2E_Container_Run_PortAlreadyInUse) { // Start a container with a simple server listening on a port - auto result1 = RunWslc(std::format( - L"container run -d --name {} -p {}:{} {} {}", - WslcContainerName, - HostTestPort1, - ContainerTestPort, - PythonImage.NameAndTag(), - GetPythonHttpServerScript(ContainerTestPort))); + auto result1 = RunWslc( + std::format( + L"container run -d --name {} -p {}:{} {} {}", + WslcContainerName, + HostTestPort1, + ContainerTestPort, + PythonImage.NameAndTag(), + GetPythonHttpServerScript(ContainerTestPort))); result1.Verify({.Stderr = L"", .ExitCode = 0}); // Create a second container mapping the same host port to validate the full error message @@ -454,20 +467,21 @@ class WSLCE2EContainerRunTests RunWslc(std::format(L"container rm {}", containerId)).Verify({.Stderr = L"", .ExitCode = 0}); // Verify 'container run' auto-cleans up on port conflict (no ghost container) - auto runResult = RunWslc(std::format( - L"container run --name {} -p {}:{} {}", WslcContainerName2, HostTestPort1, ContainerTestPort, DebianImage.NameAndTag())); + auto runResult = RunWslc( + std::format(L"container run --name {} -p {}:{} {}", WslcContainerName2, HostTestPort1, ContainerTestPort, DebianImage.NameAndTag())); runResult.Verify({.ExitCode = 1}); VerifyContainerIsNotListed(WslcContainerName2); // Repeat the conflict scenario for an IPv6 loopback ([::1]) binding to validate the IPv6 error message. - auto ipv6Server = RunWslc(std::format( - L"container run -d --name {} -p [::1]:{}:{} {} {}", - WslcContainerName2, - HostTestPort2, - ContainerTestPort, - PythonImage.NameAndTag(), - GetPythonHttpServerScript(ContainerTestPort))); + auto ipv6Server = RunWslc( + std::format( + L"container run -d --name {} -p [::1]:{}:{} {} {}", + WslcContainerName2, + HostTestPort2, + ContainerTestPort, + PythonImage.NameAndTag(), + GetPythonHttpServerScript(ContainerTestPort))); ipv6Server.Verify({.Stderr = L"", .ExitCode = 0}); // Create a second container mapping the same IPv6 address/port to validate the full error message. @@ -493,8 +507,8 @@ class WSLCE2EContainerRunTests WSLC_TEST_METHOD(WSLCE2E_Container_Run_PortEphemeral) { // Start a container with an ephemeral host port mapping (-p 8080 means host picks a random port) - auto result = RunWslc(std::format( - L"container run -d --name {} -p {} {} {}", WslcContainerName, ContainerTestPort, PythonImage.NameAndTag(), GetPythonHttpServerScript(ContainerTestPort))); + auto result = RunWslc( + std::format(L"container run -d --name {} -p {} {} {}", WslcContainerName, ContainerTestPort, PythonImage.NameAndTag(), GetPythonHttpServerScript(ContainerTestPort))); result.Verify({.Stderr = L"", .ExitCode = 0}); // Wait for the in-container HTTP server to start listening before connecting. @@ -518,13 +532,14 @@ class WSLCE2EContainerRunTests WSLC_TEST_METHOD(WSLCE2E_Container_Run_Port_UDP) { // Start a container with a UDP echo server listening on a port. - auto result = RunWslc(std::format( - L"container run -d --name {} -p {}:{}/udp {} {}", - WslcContainerName, - HostTestPort1, - ContainerTestPort, - PythonImage.NameAndTag(), - GetPythonUdpEchoServerScript(ContainerTestPort))); + auto result = RunWslc( + std::format( + L"container run -d --name {} -p {}:{}/udp {} {}", + WslcContainerName, + HostTestPort1, + ContainerTestPort, + PythonImage.NameAndTag(), + GetPythonUdpEchoServerScript(ContainerTestPort))); result.Verify({.Stderr = L"", .ExitCode = 0}); // Send a datagram from the host and verify the container echoes it back uppercased. @@ -545,13 +560,14 @@ class WSLCE2EContainerRunTests WSLC_TEST_METHOD(WSLCE2E_Container_Run_Port_HostIP) { // Start a container with a server listening on a port, bound to a specific host IP (127.0.0.1). - auto result = RunWslc(std::format( - L"container run -d --name {} -p 127.0.0.1:{}:{} {} {}", - WslcContainerName, - HostTestPort1, - ContainerTestPort, - PythonImage.NameAndTag(), - GetPythonHttpServerScript(ContainerTestPort))); + auto result = RunWslc( + std::format( + L"container run -d --name {} -p 127.0.0.1:{}:{} {} {}", + WslcContainerName, + HostTestPort1, + ContainerTestPort, + PythonImage.NameAndTag(), + GetPythonHttpServerScript(ContainerTestPort))); result.Verify({.Stderr = L"", .ExitCode = 0}); WaitForContainerOutput(WslcContainerName, "Serving HTTP on"); @@ -575,13 +591,14 @@ class WSLCE2EContainerRunTests const auto settingsPath = wsl::windows::common::filesystem::GetLocalAppDataPath(nullptr) / L"wslc" / L"settings.yaml"; HostFileChange settings(settingsPath, "session:\n defaultBindingAddress: default\n"); - auto result = RunWslc(std::format( - L"container run -d --name {} -p {}:{} {} {}", - WslcContainerName, - HostTestPort1, - ContainerTestPort, - PythonImage.NameAndTag(), - GetPythonHttpServerScript(ContainerTestPort))); + auto result = RunWslc( + std::format( + L"container run -d --name {} -p {}:{} {} {}", + WslcContainerName, + HostTestPort1, + ContainerTestPort, + PythonImage.NameAndTag(), + GetPythonHttpServerScript(ContainerTestPort))); result.Verify({.Stderr = L"", .ExitCode = 0}); WaitForContainerOutput(WslcContainerName, "Serving HTTP on"); @@ -612,13 +629,14 @@ class WSLCE2EContainerRunTests const auto settingsPath = wsl::windows::common::filesystem::GetLocalAppDataPath(nullptr) / L"wslc" / L"settings.yaml"; HostFileChange settings(settingsPath, std::format("session:\n defaultBindingAddress: {}\n", *hostIp)); - auto result = RunWslc(std::format( - L"container run -d --name {} -p {}:{} {} {}", - WslcContainerName, - HostTestPort1, - ContainerTestPort, - PythonImage.NameAndTag(), - GetPythonHttpServerScript(ContainerTestPort))); + auto result = RunWslc( + std::format( + L"container run -d --name {} -p {}:{} {} {}", + WslcContainerName, + HostTestPort1, + ContainerTestPort, + PythonImage.NameAndTag(), + GetPythonHttpServerScript(ContainerTestPort))); result.Verify({.Stderr = L"", .ExitCode = 0}); WaitForContainerOutput(WslcContainerName, "Serving HTTP on"); @@ -639,13 +657,14 @@ class WSLCE2EContainerRunTests WSLC_TEST_METHOD(WSLCE2E_Container_Run_Port_TCP) { // Start a container with a simple server listening on a port - auto result = RunWslc(std::format( - L"container run -d --name {} -p {}:{} {} {}", - WslcContainerName, - HostTestPort1, - ContainerTestPort, - PythonImage.NameAndTag(), - GetPythonHttpServerScript(ContainerTestPort))); + auto result = RunWslc( + std::format( + L"container run -d --name {} -p {}:{} {} {}", + WslcContainerName, + HostTestPort1, + ContainerTestPort, + PythonImage.NameAndTag(), + GetPythonHttpServerScript(ContainerTestPort))); result.Verify({.Stderr = L"", .ExitCode = 0}); // Wait for the in-container HTTP server to start listening before connecting. @@ -774,28 +793,33 @@ class WSLCE2EContainerRunTests WSLC_TEST_METHOD(WSLCE2E_Container_Run_Tmpfs) { - auto result = RunWslc(std::format( - L"container run --rm --tmpfs /wslc-tmpfs {} sh -c \"echo -n 'tmpfs_test' > /wslc-tmpfs/data && cat " - L"/wslc-tmpfs/data\"", - DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + L"container run --rm --tmpfs /wslc-tmpfs {} sh -c \"echo -n 'tmpfs_test' > /wslc-tmpfs/data && cat " + L"/wslc-tmpfs/data\"", + DebianImage.NameAndTag())); result.Verify({.Stdout = L"tmpfs_test", .Stderr = L"", .ExitCode = 0}); } WSLC_TEST_METHOD(WSLCE2E_Container_Run_Tmpfs_With_Options) { - auto result = RunWslc(std::format( - L"container run --rm --tmpfs /wslc-tmpfs:size=64k {} sh -c \"mount | grep -q ' on /wslc-tmpfs type tmpfs ' && echo " - L"mounted\"", - DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + L"container run --rm --tmpfs /wslc-tmpfs:size=64k {} sh -c \"mount | grep -q ' on /wslc-tmpfs type tmpfs ' && " + L"echo " + L"mounted\"", + DebianImage.NameAndTag())); result.Verify({.Stdout = L"mounted\n", .Stderr = L"", .ExitCode = 0}); } WSLC_TEST_METHOD(WSLCE2E_Container_Run_Tmpfs_Multiple_With_Options) { - auto result = RunWslc(std::format( - L"container run --rm --tmpfs /wslc-tmpfs1:size=64k --tmpfs /wslc-tmpfs2:size=128k {} sh -c \"mount | grep -q ' on " - L"/wslc-tmpfs1 type tmpfs ' && mount | grep -q ' on /wslc-tmpfs2 type tmpfs ' && echo mounted\"", - DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + L"container run --rm --tmpfs /wslc-tmpfs1:size=64k --tmpfs /wslc-tmpfs2:size=128k {} sh -c \"mount | grep -q ' " + L"on " + L"/wslc-tmpfs1 type tmpfs ' && mount | grep -q ' on /wslc-tmpfs2 type tmpfs ' && echo mounted\"", + DebianImage.NameAndTag())); result.Verify({.Stdout = L"mounted\n", .Stderr = L"", .ExitCode = 0}); } @@ -840,16 +864,17 @@ class WSLCE2EContainerRunTests WSLC_TEST_METHOD(WSLCE2E_Container_Run_DNSSearch) { - auto result = RunWslc(std::format( - L"container run --rm --dns-search example.com --dns-search test.local {} cat /etc/resolv.conf", DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + L"container run --rm --dns-search example.com --dns-search test.local {} cat /etc/resolv.conf", DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); VERIFY_IS_TRUE(result.Stdout->find(L"search example.com test.local") != std::wstring::npos); } WSLC_TEST_METHOD(WSLCE2E_Container_Run_DNSOption) { - auto result = RunWslc(std::format( - L"container run --rm --dns-option ndots:5 --dns-option timeout:3 {} cat /etc/resolv.conf", DebianImage.NameAndTag())); + auto result = RunWslc( + std::format(L"container run --rm --dns-option ndots:5 --dns-option timeout:3 {} cat /etc/resolv.conf", DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); VERIFY_IS_TRUE(result.Stdout->find(L"options ndots:5 timeout:3") != std::wstring::npos); } @@ -877,8 +902,8 @@ class WSLCE2EContainerRunTests result.Verify({.Stderr = L"", .ExitCode = 0}); auto cleanupNetwork = wil::scope_exit([&] { EnsureNetworkDoesNotExist(TestNetworkName); }); - result = RunWslc(std::format( - L"container run --name {} --network {} {} true", WslcContainerName, TestNetworkName, DebianImage.NameAndTag())); + result = RunWslc( + std::format(L"container run --name {} --network {} {} true", WslcContainerName, TestNetworkName, DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); const auto inspect = InspectContainer(WslcContainerName); @@ -895,8 +920,8 @@ class WSLCE2EContainerRunTests WSLC_TEST_METHOD(WSLCE2E_Container_Run_Network_NonexistentNetwork_Rejected) { - auto result = RunWslc(std::format( - L"container run --rm --network does-not-exist --name {} {} true", WslcContainerName, DebianImage.NameAndTag())); + auto result = RunWslc( + std::format(L"container run --rm --network does-not-exist --name {} {} true", WslcContainerName, DebianImage.NameAndTag())); result.Verify({.Stderr = L"Network not found: 'does-not-exist'\r\nError code: WSLC_E_NETWORK_NOT_FOUND\r\n", .ExitCode = 1}); } @@ -906,8 +931,12 @@ class WSLCE2EContainerRunTests result.Verify({.Stderr = L"", .ExitCode = 0}); auto cleanupNetwork = wil::scope_exit([&] { EnsureNetworkDoesNotExist(TestNetworkName); }); - result = RunWslc(std::format( - L"container run --name {} --network {} --network-alias db {} true", WslcContainerName, TestNetworkName, DebianImage.NameAndTag())); + result = RunWslc( + std::format( + L"container run --name {} --network {} --network-alias db {} true", + WslcContainerName, + TestNetworkName, + DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); const auto inspect = InspectContainer(WslcContainerName); @@ -929,8 +958,8 @@ class WSLCE2EContainerRunTests WSLC_TEST_METHOD(WSLCE2E_Container_Run_NetworkAlias_NoneMode_Rejected) { - auto result = RunWslc(std::format( - L"container run --rm --network none --network-alias db --name {} {} true", WslcContainerName, DebianImage.NameAndTag())); + auto result = RunWslc( + std::format(L"container run --rm --network none --network-alias db --name {} {} true", WslcContainerName, DebianImage.NameAndTag())); result.Verify( {.Stderr = L"Network aliases require a user-defined network. Use --network to specify one.\r\nError code: E_INVALIDARG\r\n", @@ -939,10 +968,11 @@ class WSLCE2EContainerRunTests WSLC_TEST_METHOD(WSLCE2E_Container_Run_NetworkAlias_MultipleNetworks_Rejected) { - auto result = RunWslc(std::format( - L"container run --rm --network bridge --network bridge --network-alias db --name {} {} true", - WslcContainerName, - DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + L"container run --rm --network bridge --network bridge --network-alias db --name {} {} true", + WslcContainerName, + DebianImage.NameAndTag())); result.Verify({.Stderr = L"Network aliases cannot be specified when multiple networks are requested. Use a single --network argument.\r\nError code: E_INVALIDARG\r\n", .ExitCode = 1}); } @@ -960,10 +990,11 @@ class WSLCE2EContainerRunTests result.Verify({.Stderr = L"", .ExitCode = 0}); // Create a container with --rm that uses the named volume and writes a file to it - result = RunWslc(std::format( - L"container run --rm --volume {}:/data {} sh -c \"echo -n 'WSLC Named Volume Test' > /data/test.txt\"", - WslcVolumeName, - DebianImage.NameAndTag())); + result = RunWslc( + std::format( + L"container run --rm --volume {}:/data {} sh -c \"echo -n 'WSLC Named Volume Test' > /data/test.txt\"", + WslcVolumeName, + DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); // Create another container that mounts the same named volume and verify the file content @@ -973,10 +1004,11 @@ class WSLCE2EContainerRunTests WSLC_TEST_METHOD(WSLCE2E_Container_Run_Volume_NamedVolume_AutoCreate) { - auto result = RunWslc(std::format( - L"container run --rm --volume {}:/data {} sh -c \"echo -n 'WSLC Named Volume Test' > /data/test.txt\"", - WslcVolumeName, - DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + L"container run --rm --volume {}:/data {} sh -c \"echo -n 'WSLC Named Volume Test' > /data/test.txt\"", + WslcVolumeName, + DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); // Verify the volume was auto-created by removing it (fails if it doesn't exist). @@ -986,8 +1018,8 @@ class WSLCE2EContainerRunTests WSLC_TEST_METHOD(WSLCE2E_Container_Run_WithLabel_Success) { - auto result = RunWslc(std::format( - L"container run --name {} --label A=1 --label B=2 {} echo hello", WslcContainerName, DebianImage.NameAndTag())); + auto result = RunWslc( + std::format(L"container run --name {} --label A=1 --label B=2 {} echo hello", WslcContainerName, DebianImage.NameAndTag())); result.Verify({.Stdout = L"hello\n", .Stderr = L"", .ExitCode = 0}); auto inspect = InspectContainer(WslcContainerName); @@ -998,11 +1030,12 @@ class WSLCE2EContainerRunTests WSLC_TEST_METHOD(WSLCE2E_Container_Run_StopSignal) { constexpr int ExpectedExitCode = 42; - auto result = RunWslc(std::format( - LR"(container run -d --stop-signal SIGUSR1 --name {} {} bash -c "trap 'exit {}' SIGUSR1; while true; do sleep 1; done")", - WslcContainerName, - DebianImage.NameAndTag(), - ExpectedExitCode)); + auto result = RunWslc( + std::format( + LR"(container run -d --stop-signal SIGUSR1 --name {} {} bash -c "trap 'exit {}' SIGUSR1; while true; do sleep 1; done")", + WslcContainerName, + DebianImage.NameAndTag(), + ExpectedExitCode)); result.Verify({.Stderr = L"", .ExitCode = 0}); result = RunWslc(std::format(L"container stop {}", WslcContainerName)); @@ -1018,11 +1051,12 @@ class WSLCE2EContainerRunTests // A positive value is forwarded to the container configuration. { constexpr int ExpectedStopTimeout = 25; - auto result = RunWslc(std::format( - L"container run -d --stop-timeout {} --name {} {} sleep infinity", - ExpectedStopTimeout, - WslcContainerName, - DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + L"container run -d --stop-timeout {} --name {} {} sleep infinity", + ExpectedStopTimeout, + WslcContainerName, + DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); const auto inspect = InspectContainer(WslcContainerName); @@ -1033,8 +1067,8 @@ class WSLCE2EContainerRunTests // A value of 0 (stop the container immediately) is a valid, explicit timeout. { - auto result = RunWslc(std::format( - L"container run -d --stop-timeout 0 --name {} {} sleep infinity", WslcContainerName, DebianImage.NameAndTag())); + auto result = RunWslc( + std::format(L"container run -d --stop-timeout 0 --name {} {} sleep infinity", WslcContainerName, DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); const auto inspect = InspectContainer(WslcContainerName); @@ -1045,8 +1079,8 @@ class WSLCE2EContainerRunTests // A value of -1 means "no timeout"; it is a valid, explicit value forwarded to the configuration. { - auto result = RunWslc(std::format( - L"container run -d --stop-timeout -1 --name {} {} sleep infinity", WslcContainerName, DebianImage.NameAndTag())); + auto result = RunWslc( + std::format(L"container run -d --stop-timeout -1 --name {} {} sleep infinity", WslcContainerName, DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); const auto inspect = InspectContainer(WslcContainerName); @@ -1085,8 +1119,12 @@ class WSLCE2EContainerRunTests // Validate that the correct error is displayed if the user passes the exact 'WSLC_STOP_TIMEOUT_DEFAULT' value. { - auto result = RunWslc(std::format( - L"container run --rm --stop-timeout {} --name {} {}", WSLC_STOP_TIMEOUT_DEFAULT, WslcContainerName, DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + L"container run --rm --stop-timeout {} --name {} {}", + WSLC_STOP_TIMEOUT_DEFAULT, + WslcContainerName, + DebianImage.NameAndTag())); result.Verify({.Stderr = L"Invalid stop timeout value: -2147483648\r\nError code: E_INVALIDARG\r\n", .ExitCode = 1}); EnsureContainerDoesNotExist(WslcContainerName); } @@ -1120,10 +1158,11 @@ class WSLCE2EContainerRunTests { // All health-check options are forwarded to the container configuration. { - auto result = RunWslc(std::format( - LR"(container run -d --health-cmd "exit 0" --health-interval 5s --health-timeout 3s --health-retries 2 --health-start-period 1s --name {} {} sleep infinity)", - WslcContainerName, - DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + LR"(container run -d --health-cmd "exit 0" --health-interval 5s --health-timeout 3s --health-retries 2 --health-start-period 1s --name {} {} sleep infinity)", + WslcContainerName, + DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); const auto inspect = InspectContainer(WslcContainerName); @@ -1165,10 +1204,11 @@ class WSLCE2EContainerRunTests WSLC_TEST_METHOD(WSLCE2E_Container_Run_HealthStatus_Healthy) { // A health check that always succeeds should drive the container to the "healthy" state. - auto result = RunWslc(std::format( - LR"(container run -d --health-cmd "exit 0" --health-interval 1s --health-timeout 3s --health-retries 1 --name {} {} sleep infinity)", - WslcContainerName, - DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + LR"(container run -d --health-cmd "exit 0" --health-interval 1s --health-timeout 3s --health-retries 1 --name {} {} sleep infinity)", + WslcContainerName, + DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); const auto health = WaitForContainerHealth(WslcContainerName, "healthy"); @@ -1182,10 +1222,11 @@ class WSLCE2EContainerRunTests WSLC_TEST_METHOD(WSLCE2E_Container_Run_HealthStatus_Unhealthy) { // A health check that always fails should drive the container to the "unhealthy" state. - auto result = RunWslc(std::format( - LR"(container run -d --health-cmd "exit 1" --health-interval 1s --health-timeout 3s --health-retries 1 --name {} {} sleep infinity)", - WslcContainerName, - DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + LR"(container run -d --health-cmd "exit 1" --health-interval 1s --health-timeout 3s --health-retries 1 --name {} {} sleep infinity)", + WslcContainerName, + DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); const auto health = WaitForContainerHealth(WslcContainerName, "unhealthy"); @@ -1198,10 +1239,11 @@ class WSLCE2EContainerRunTests WSLC_TEST_METHOD(WSLCE2E_Container_Run_HealthStatus_Timeout) { - auto result = RunWslc(std::format( - LR"(container run -d --health-cmd "sleep 30" --health-interval 1s --health-timeout 1s --health-retries 1 --name {} {} sleep infinity)", - WslcContainerName, - DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + LR"(container run -d --health-cmd "sleep 30" --health-interval 1s --health-timeout 1s --health-retries 1 --name {} {} sleep infinity)", + WslcContainerName, + DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); const auto health = WaitForContainerHealth(WslcContainerName, "unhealthy"); @@ -1234,8 +1276,9 @@ class WSLCE2EContainerRunTests WSLC_TEST_METHOD(WSLCE2E_Container_Run_Ulimit) { - auto result = RunWslc(std::format( - L"container run --name {} --ulimit nofile=1024:2048 --ulimit nproc=512 {} true", WslcContainerName, DebianImage.NameAndTag())); + auto result = RunWslc( + std::format( + L"container run --name {} --ulimit nofile=1024:2048 --ulimit nproc=512 {} true", WslcContainerName, DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); const auto inspect = InspectContainer(WslcContainerName); diff --git a/test/windows/wslc/e2e/WSLCE2EGlobalTests.cpp b/test/windows/wslc/e2e/WSLCE2EGlobalTests.cpp index 82d529633..abb24bf37 100644 --- a/test/windows/wslc/e2e/WSLCE2EGlobalTests.cpp +++ b/test/windows/wslc/e2e/WSLCE2EGlobalTests.cpp @@ -396,8 +396,8 @@ class WSLCE2EGlobalTests result.Verify({.Stderr = L"", .ExitCode = 0}); // Add a container to the new session. - result = RunWslc(std::format( - L"--session \"{}\" container create --name {} {}", session.Name(), L"test-cont", DebianTestImage().NameAndTag())); + result = RunWslc( + std::format(L"--session \"{}\" container create --name {} {}", session.Name(), L"test-cont", DebianTestImage().NameAndTag())); result.Dump(); // Dump so it is easier to find any potential issues with the pull in the test output. result.Verify({.ExitCode = 0}); diff --git a/test/windows/wslc/e2e/WSLCE2EHelpers.cpp b/test/windows/wslc/e2e/WSLCE2EHelpers.cpp index d460aaa6f..893629e72 100644 --- a/test/windows/wslc/e2e/WSLCE2EHelpers.cpp +++ b/test/windows/wslc/e2e/WSLCE2EHelpers.cpp @@ -306,12 +306,13 @@ wslc_schema::Health WaitForContainerHealth(const std::wstring& containerName, co { const auto inspect = InspectContainer(containerName); const std::string actual = inspect.State.Health.has_value() ? inspect.State.Health->Status : ""; - VERIFY_FAIL(std::format( - L"Container '{}' did not reach health status '{}' (last status: '{}')", - containerName, - wsl::shared::string::MultiByteToWide(std::string(expectedStatus)), - wsl::shared::string::MultiByteToWide(actual)) - .c_str()); + VERIFY_FAIL( + std::format( + L"Container '{}' did not reach health status '{}' (last status: '{}')", + containerName, + wsl::shared::string::MultiByteToWide(std::string(expectedStatus)), + wsl::shared::string::MultiByteToWide(actual)) + .c_str()); throw; } } @@ -696,10 +697,11 @@ namespace { catch (...) { const std::string data = session.GetStdoutData(); - VERIFY_FAIL(std::format( - L"Timed out waiting for tty resize. Captured pseudoconsole output: \"{}\"", - wsl::shared::string::MultiByteToWide(EscapeString(data))) - .c_str()); + VERIFY_FAIL( + std::format( + L"Timed out waiting for tty resize. Captured pseudoconsole output: \"{}\"", + wsl::shared::string::MultiByteToWide(EscapeString(data))) + .c_str()); } } diff --git a/test/windows/wslc/e2e/WSLCE2EImageBuildTests.cpp b/test/windows/wslc/e2e/WSLCE2EImageBuildTests.cpp index 2e2af0fa7..3ef654cf3 100644 --- a/test/windows/wslc/e2e/WSLCE2EImageBuildTests.cpp +++ b/test/windows/wslc/e2e/WSLCE2EImageBuildTests.cpp @@ -94,12 +94,13 @@ class WSLCE2EImageBuildTests "COPY hello.txt /hello.txt\n" "CMD [\"cat\", \"/hello.txt\"]\n"); - auto buildResult = RunWslc(std::format( - L"build \"{}\" -f \"{}\" -t {} -t {} --build-arg TEST_LABEL=wslc_e2e_test", - contextDir.wstring(), - dockerfilePath.wstring(), - BuiltImageTag1.NameAndTag(), - BuiltImageTag2.NameAndTag())); + auto buildResult = RunWslc( + std::format( + L"build \"{}\" -f \"{}\" -t {} -t {} --build-arg TEST_LABEL=wslc_e2e_test", + contextDir.wstring(), + dockerfilePath.wstring(), + BuiltImageTag1.NameAndTag(), + BuiltImageTag2.NameAndTag())); buildResult.Verify({.Stderr = L"", .ExitCode = 0}); // Verify both tags are present by inspecting each one @@ -138,8 +139,9 @@ class WSLCE2EImageBuildTests // Build with --pull --verbose. When --pull causes docker to resolve the base image // from the registry, the FROM step includes a @sha256: digest (e.g. // "FROM docker.io/library/debian:latest@sha256:..."). Without --pull, no digest appears. - auto buildResult = RunWslc(std::format( - L"build \"{}\" -f \"{}\" -t {} --pull --verbose", contextDir.wstring(), dockerfilePath.wstring(), BuiltImagePull.NameAndTag())); + auto buildResult = RunWslc( + std::format( + L"build \"{}\" -f \"{}\" -t {} --pull --verbose", contextDir.wstring(), dockerfilePath.wstring(), BuiltImagePull.NameAndTag())); buildResult.Verify({.Stderr = L"", .ExitCode = 0}); VERIFY_IS_TRUE(buildResult.Stdout.has_value()); @@ -166,8 +168,12 @@ class WSLCE2EImageBuildTests "COPY --from=build-stage /stage.txt /stage.txt\n" "CMD [\"cat\", \"/stage.txt\"]\n"); - auto buildResult = RunWslc(std::format( - L"build \"{}\" -f \"{}\" -t {} --target build-stage", contextDir.wstring(), dockerfilePath.wstring(), BuiltImageTarget.NameAndTag())); + auto buildResult = RunWslc( + std::format( + L"build \"{}\" -f \"{}\" -t {} --target build-stage", + contextDir.wstring(), + dockerfilePath.wstring(), + BuiltImageTarget.NameAndTag())); buildResult.Verify({.Stderr = L"", .ExitCode = 0}); auto inspectData = InspectImage(BuiltImageTarget.NameAndTag()); @@ -196,11 +202,12 @@ class WSLCE2EImageBuildTests WriteTestFileContent(dockerfilePath, "FROM debian:latest\nCMD [\"echo\", \"label-ok\"]\n"); // Use both the short alias (-l) and long form (--label) to confirm both parse paths. - auto buildResult = RunWslc(std::format( - L"build \"{}\" -f \"{}\" -t {} -l first=one --label second=two", - contextDir.wstring(), - dockerfilePath.wstring(), - BuiltImageLabel.NameAndTag())); + auto buildResult = RunWslc( + std::format( + L"build \"{}\" -f \"{}\" -t {} -l first=one --label second=two", + contextDir.wstring(), + dockerfilePath.wstring(), + BuiltImageLabel.NameAndTag())); buildResult.Verify({.Stderr = L"", .ExitCode = 0}); auto inspectData = InspectImage(BuiltImageLabel.NameAndTag()); @@ -231,11 +238,12 @@ class WSLCE2EImageBuildTests WriteTestFileContent( dockerfilePath, "FROM debian:latest\nLABEL conflict=from-dockerfile\nCMD [\"echo\", \"label-override-ok\"]\n"); - auto buildResult = RunWslc(std::format( - L"build \"{}\" -f \"{}\" -t {} --label conflict=from-cli", - contextDir.wstring(), - dockerfilePath.wstring(), - BuiltImageLabelOverride.NameAndTag())); + auto buildResult = RunWslc( + std::format( + L"build \"{}\" -f \"{}\" -t {} --label conflict=from-cli", + contextDir.wstring(), + dockerfilePath.wstring(), + BuiltImageLabelOverride.NameAndTag())); buildResult.Verify({.Stderr = L"", .ExitCode = 0}); auto inspectData = InspectImage(BuiltImageLabelOverride.NameAndTag()); diff --git a/test/windows/wslc/e2e/WSLCE2EImageInspectTests.cpp b/test/windows/wslc/e2e/WSLCE2EImageInspectTests.cpp index 6fb5240c7..0625f42d9 100644 --- a/test/windows/wslc/e2e/WSLCE2EImageInspectTests.cpp +++ b/test/windows/wslc/e2e/WSLCE2EImageInspectTests.cpp @@ -100,8 +100,8 @@ class WSLCE2EImageInspectTests "STOPSIGNAL SIGTERM\n", wsl::shared::string::WideToMultiByte(DebianImage.NameAndTag()))); - auto buildResult = RunWslc(std::format( - L"build \"{}\" -f \"{}\" -t {}", contextDir.wstring(), dockerfilePath.wstring(), BuiltExposeImage.NameAndTag())); + auto buildResult = RunWslc( + std::format(L"build \"{}\" -f \"{}\" -t {}", contextDir.wstring(), dockerfilePath.wstring(), BuiltExposeImage.NameAndTag())); buildResult.Verify({.Stderr = L"", .ExitCode = 0}); auto inspectData = InspectImage(BuiltExposeImage.NameAndTag()); diff --git a/test/windows/wslc/e2e/WSLCE2EImageListTests.cpp b/test/windows/wslc/e2e/WSLCE2EImageListTests.cpp index 10ebe4677..94e48c97d 100644 --- a/test/windows/wslc/e2e/WSLCE2EImageListTests.cpp +++ b/test/windows/wslc/e2e/WSLCE2EImageListTests.cpp @@ -188,10 +188,11 @@ class WSLCE2EImageListTests std::set names; for (const auto& image : images) { - names.insert(std::format( - L"{}:{}", - wsl::shared::string::MultiByteToWide(image.Repository.value_or("")), - wsl::shared::string::MultiByteToWide(image.Tag.value_or("")))); + names.insert( + std::format( + L"{}:{}", + wsl::shared::string::MultiByteToWide(image.Repository.value_or("")), + wsl::shared::string::MultiByteToWide(image.Tag.value_or("")))); } return names; }; diff --git a/test/windows/wslc/e2e/WSLCE2EImageSaveTests.cpp b/test/windows/wslc/e2e/WSLCE2EImageSaveTests.cpp index d1f01f47e..e706590bc 100644 --- a/test/windows/wslc/e2e/WSLCE2EImageSaveTests.cpp +++ b/test/windows/wslc/e2e/WSLCE2EImageSaveTests.cpp @@ -140,8 +140,8 @@ class WSLCE2EImageSaveTests auto restoreDebian = wil::scope_exit([&]() { EnsureImageIsDeleted(DebianImage); }); // Save both images into a single archive. - const auto saveResult = RunWslc(std::format( - L"image save --output \"{}\" {} {}", SavedArchivePath.wstring(), DebianImage.NameAndTag(), AlpineImage.NameAndTag())); + const auto saveResult = RunWslc( + std::format(L"image save --output \"{}\" {} {}", SavedArchivePath.wstring(), DebianImage.NameAndTag(), AlpineImage.NameAndTag())); saveResult.Verify({.Stdout = L"", .Stderr = L"", .ExitCode = 0}); // Delete both source images. @@ -169,8 +169,8 @@ class WSLCE2EImageSaveTests WSLC_TEST_METHOD(WSLCE2E_Image_Save_MultipleImages_InvalidImage) { - const auto result = RunWslc(std::format( - L"image save --output \"{}\" {} {}", SavedArchivePath.wstring(), DebianImage.NameAndTag(), InvalidImage.NameAndTag())); + const auto result = RunWslc( + std::format(L"image save --output \"{}\" {} {}", SavedArchivePath.wstring(), DebianImage.NameAndTag(), InvalidImage.NameAndTag())); VERIFY_IS_TRUE(result.ExitCode.has_value()); VERIFY_ARE_EQUAL(1u, result.ExitCode.value()); VERIFY_IS_TRUE(result.Stderr.has_value()); diff --git a/test/windows/wslc/e2e/WSLCE2ENetworkPruneTests.cpp b/test/windows/wslc/e2e/WSLCE2ENetworkPruneTests.cpp index d73e7affc..8f51b9e75 100644 --- a/test/windows/wslc/e2e/WSLCE2ENetworkPruneTests.cpp +++ b/test/windows/wslc/e2e/WSLCE2ENetworkPruneTests.cpp @@ -104,8 +104,9 @@ class WSLCE2ENetworkPruneTests VerifyNetworkIsListed(TestNetworkName); // Start a container attached to the network so it is considered in use. - RunWslc(std::format( - L"container run -d --name {} --network {} {} sleep infinity", WslcContainerName, TestNetworkName, DebianImage.NameAndTag())) + RunWslc( + std::format( + L"container run -d --name {} --network {} {} sleep infinity", WslcContainerName, TestNetworkName, DebianImage.NameAndTag())) .Verify({.Stderr = L"", .ExitCode = 0}); auto cleanup = wil::scope_exit([&]() { diff --git a/test/windows/wslc/e2e/WSLCE2ENetworkTests.cpp b/test/windows/wslc/e2e/WSLCE2ENetworkTests.cpp index 8f73a5465..23dda31ce 100644 --- a/test/windows/wslc/e2e/WSLCE2ENetworkTests.cpp +++ b/test/windows/wslc/e2e/WSLCE2ENetworkTests.cpp @@ -155,8 +155,9 @@ class WSLCE2ENetworkTests auto result = RunWslc(std::format(L"network create --driver bridge {}", TestNetworkName)); result.Verify({.Stderr = L"", .ExitCode = 0}); - result = RunWslc(std::format( - L"container run -d --network {} --name {} {} sleep infinity", TestNetworkName, WslcContainerName, DebianImage.NameAndTag())); + result = RunWslc( + std::format( + L"container run -d --network {} --name {} {} sleep infinity", TestNetworkName, WslcContainerName, DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); result = RunWslc(std::format(L"network connect {} {}", TestNetworkName, WslcContainerName)); @@ -170,8 +171,9 @@ class WSLCE2ENetworkTests auto result = RunWslc(std::format(L"network create --driver bridge {}", TestNetworkName)); result.Verify({.Stderr = L"", .ExitCode = 0}); - result = RunWslc(std::format( - L"container run -d --network {} --name {} {} sleep infinity", TestNetworkName, WslcContainerName, DebianImage.NameAndTag())); + result = RunWslc( + std::format( + L"container run -d --network {} --name {} {} sleep infinity", TestNetworkName, WslcContainerName, DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); { diff --git a/test/windows/wslc/e2e/WSLCE2ERegistryTests.cpp b/test/windows/wslc/e2e/WSLCE2ERegistryTests.cpp index 061874a48..3c030e366 100644 --- a/test/windows/wslc/e2e/WSLCE2ERegistryTests.cpp +++ b/test/windows/wslc/e2e/WSLCE2ERegistryTests.cpp @@ -74,8 +74,8 @@ class WSLCE2ERegistryTests VerifyAuthFailure(result); // Login and verify that saved credentials are used for push/pull. - result = RunWslc(std::format( - L"login -u {} -p {} {}", string::MultiByteToWide(c_username), string::MultiByteToWide(c_password), registryAddressW)); + result = RunWslc( + std::format(L"login -u {} -p {} {}", string::MultiByteToWide(c_username), string::MultiByteToWide(c_password), registryAddressW)); result.Verify({.Stdout = Localization::WSLCCLI_LoginSucceeded() + L"\r\n", .Stderr = L"", .ExitCode = 0}); registryImageName = TagImageForRegistry(L"debian:latest", registryAddressW); @@ -160,8 +160,8 @@ class WSLCE2ERegistryTests // Login with correct credentials should still succeed after failed attempts. { - auto result = RunWslc(std::format( - L"login -u {} -p {} {}", string::MultiByteToWide(c_username), string::MultiByteToWide(c_password), registryAddressW)); + auto result = RunWslc( + std::format(L"login -u {} -p {} {}", string::MultiByteToWide(c_username), string::MultiByteToWide(c_password), registryAddressW)); result.Verify({.Stdout = Localization::WSLCCLI_LoginSucceeded() + L"\r\n", .Stderr = L"", .ExitCode = 0}); VerifyLogoutSucceeds(registryAddressW); diff --git a/test/windows/wslc/e2e/WSLCE2EVolumePruneTests.cpp b/test/windows/wslc/e2e/WSLCE2EVolumePruneTests.cpp index 02d3b97c8..195e451eb 100644 --- a/test/windows/wslc/e2e/WSLCE2EVolumePruneTests.cpp +++ b/test/windows/wslc/e2e/WSLCE2EVolumePruneTests.cpp @@ -123,8 +123,9 @@ class WSLCE2EVolumePruneTests VerifyVolumeIsListed(TestVolumeName); // Start a container that holds the volume open. - RunWslc(std::format( - L"container run -d --name {} -v {}:/data {} sleep infinity", WslcContainerName, TestVolumeName, DebianImage.NameAndTag())) + RunWslc( + std::format( + L"container run -d --name {} -v {}:/data {} sleep infinity", WslcContainerName, TestVolumeName, DebianImage.NameAndTag())) .Verify({.Stderr = L"", .ExitCode = 0}); auto cleanup = wil::scope_exit([&]() { diff --git a/test/windows/wslc/e2e/WSLCE2EVolumeRemoveTests.cpp b/test/windows/wslc/e2e/WSLCE2EVolumeRemoveTests.cpp index 43b564c7b..2e743d201 100644 --- a/test/windows/wslc/e2e/WSLCE2EVolumeRemoveTests.cpp +++ b/test/windows/wslc/e2e/WSLCE2EVolumeRemoveTests.cpp @@ -113,12 +113,13 @@ class WSLCE2EVolumeRemoveTests VerifyVolumeIsListed(TestVolumeName); // Create a container that uses the volume to ensure it's in use - result = RunWslc(std::format( - L"container run -d --name {} -v {}:/data {} sh -c \"echo -n 'WSLC Volume In Use Test' > /data/test.txt && sleep " - L"infinity\"", - WslcContainerName, - TestVolumeName, - DebianImage.NameAndTag())); + result = RunWslc( + std::format( + L"container run -d --name {} -v {}:/data {} sh -c \"echo -n 'WSLC Volume In Use Test' > /data/test.txt && sleep " + L"infinity\"", + WslcContainerName, + TestVolumeName, + DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); // Attempt to remove the volume while it's in use @@ -168,12 +169,13 @@ class WSLCE2EVolumeRemoveTests VerifyVolumeIsListed(TestVolumeName); // Create a container that uses the volume to ensure it's in use - result = RunWslc(std::format( - L"container run -d --name {} -v {}:/data {} sh -c \"echo -n 'WSLC Volume In Use Test' > /data/test.txt && sleep " - L"infinity\"", - WslcContainerName, - TestVolumeName, - DebianImage.NameAndTag())); + result = RunWslc( + std::format( + L"container run -d --name {} -v {}:/data {} sh -c \"echo -n 'WSLC Volume In Use Test' > /data/test.txt && sleep " + L"infinity\"", + WslcContainerName, + TestVolumeName, + DebianImage.NameAndTag())); result.Verify({.Stderr = L"", .ExitCode = 0}); // --force does not bypass in-use checks, volume should still fail to be removed diff --git a/test/windows/wslc/e2e/WSLCExecutor.cpp b/test/windows/wslc/e2e/WSLCExecutor.cpp index 6d387ddb3..196c72ff8 100644 --- a/test/windows/wslc/e2e/WSLCExecutor.cpp +++ b/test/windows/wslc/e2e/WSLCExecutor.cpp @@ -412,8 +412,9 @@ void WSLCInteractiveSession::ExpectStdout(const std::string& expected) { while (m_stdoutReader->ReadBytes(m_ignoreSequence->size()) == *m_ignoreSequence) { - Log::Comment(std::format(L"Consuming ignored sequence: \"{}\"", wsl::shared::string::MultiByteToWide(EscapeString(*m_ignoreSequence))) - .c_str()); + Log::Comment( + std::format(L"Consuming ignored sequence: \"{}\"", wsl::shared::string::MultiByteToWide(EscapeString(*m_ignoreSequence))) + .c_str()); m_stdoutReader->ConsumeBytes(m_ignoreSequence->size()); } } @@ -564,8 +565,9 @@ void WSLCInteractiveSession::VerifyNoErrors() const auto& stderrContent = m_stderrReader->GetData(); if (!stderrContent.empty()) { - VERIFY_FAIL(std::format(L"Expected no errors but stderr contained: {}", wsl::shared::string::MultiByteToWide(EscapeString(stderrContent))) - .c_str()); + VERIFY_FAIL( + std::format(L"Expected no errors but stderr contained: {}", wsl::shared::string::MultiByteToWide(EscapeString(stderrContent))) + .c_str()); } } From 2be9565127af35531815e53bbb84bd67b15c08c5 Mon Sep 17 00:00:00 2001 From: Ben Hillis Date: Fri, 10 Jul 2026 13:30:42 -0700 Subject: [PATCH 3/5] Fix NuGet restore for VS2026 .slnx solution format The VS2026 CMake generator emits wsl.slnx instead of wsl.sln. The vendored NuGet 5.10 cannot auto-detect a .slnx solution, so 'nuget restore -NonInteractive' failed with 'Cannot determine the packages folder'. Pass -SolutionDirectory . so restore locates ./packages independent of solution format. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d3de59ec-7508-440a-b7e5-1345aad2096a --- .pipelines/build-job.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.pipelines/build-job.yml b/.pipelines/build-job.yml index f883f0b4b..2f3bfd8c9 100644 --- a/.pipelines/build-job.yml +++ b/.pipelines/build-job.yml @@ -126,8 +126,10 @@ jobs: workingDirectory: "." cmakeArgs: . --fresh -A ${{ parameters.platform }} -DCMAKE_BUILD_TYPE=Release -DCMAKE_SYSTEM_VERSION=10.0.26100.0 -DPACKAGE_VERSION=$(version.WSL_PACKAGE_VERSION) -DWSL_NUGET_PACKAGE_VERSION=$(version.WSL_NUGET_PACKAGE_VERSION) -DSKIP_PACKAGE_SIGNING=${{ parameters.isRelease }} -DOFFICIAL_BUILD=${{ parameters.isRelease }} -DINCLUDE_PACKAGE_STAGE=${{ or(parameters.isRelease, parameters.isNightly) }} -DPIPELINE_BUILD_ID=$(Build.BuildId) -DVSO_ORG=${{ parameters.vsoOrg }} -DVSO_PROJECT=${{ parameters.vsoProject }} -DWSL_BUILD_WSL_SETTINGS=true -DWSL_INCLUDE_SDK_CSHARP=true $(packageInputDirArg)\${{ parameters.platform }} - # Workaround for WSL Settings NuGet restore authentication issue - - script: _deps\nuget.exe restore -NonInteractive + # Workaround for WSL Settings NuGet restore authentication issue. + # Pass -SolutionDirectory since the VS2026 generator emits wsl.slnx (not wsl.sln), + # which NuGet 5.10 cannot auto-detect to locate the packages folder. + - script: _deps\nuget.exe restore -SolutionDirectory . -NonInteractive - ${{ each target in parameters.targets }}: - script: cmake --build . --config Release --target ${{ target.target }} -- -m From 1e75ed5f4197fdcf2c88c1a9dd0ed928868025aa Mon Sep 17 00:00:00 2001 From: Ben Hillis Date: Fri, 10 Jul 2026 15:08:55 -0700 Subject: [PATCH 4/5] Require Visual Studio 2026 for build setup Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 742a559b-56fb-4dcc-b795-f03e6a94a37b --- .config/configuration.vsEnterprise.winget | 8 +++---- .config/configuration.vsProfessional.winget | 8 +++---- .config/configuration.winget | 6 ++--- .github/copilot-instructions.md | 6 ++--- .vsconfig | 1 + CMakeLists.txt | 13 +--------- doc/docs/dev-loop.md | 6 ++--- .../WSLC-HelloWorld/WSLCHelloWorld.sln | 4 ++-- .../WSLC-HelloWorld/WSLCHelloWorld.vcxproj | 2 +- doc/samples/WSLC-Neofetch/WSLCNeofetch.sln | 4 ++-- .../WSLC-Neofetch/WSLCNeofetch.vcxproj | 2 +- tools/setup-dev-env.ps1 | 24 +++++++++---------- 12 files changed, 37 insertions(+), 47 deletions(-) diff --git a/.config/configuration.vsEnterprise.winget b/.config/configuration.vsEnterprise.winget index f81df2d5b..534efb1a4 100644 --- a/.config/configuration.vsEnterprise.winget +++ b/.config/configuration.vsEnterprise.winget @@ -3,7 +3,7 @@ # # Usage: winget configure -f .config/configuration.vsEnterprise.winget # -# Visual Studio 2022 Enterprise edition. For other editions use: +# Visual Studio 2026 Enterprise edition. For other editions use: # .config/configuration.winget (Community, default) # .config/configuration.vsProfessional.winget (Professional) properties: @@ -26,10 +26,10 @@ properties: - resource: Microsoft.WinGet.DSC/WinGetPackage id: vsPackage directives: - description: Install Visual Studio 2022 Enterprise + description: Install Visual Studio 2026 Enterprise securityContext: elevated settings: - id: Microsoft.VisualStudio.2022.Enterprise + id: Microsoft.VisualStudio.Enterprise source: winget - resource: Microsoft.VisualStudio.DSC/VSComponents dependsOn: @@ -40,6 +40,6 @@ properties: securityContext: elevated settings: productId: Microsoft.VisualStudio.Product.Enterprise - channelId: VisualStudio.17.Release + channelId: VisualStudio.18.Release vsConfigFile: '${WinGetConfigRoot}\..\.vsconfig' configurationVersion: 0.2.0 diff --git a/.config/configuration.vsProfessional.winget b/.config/configuration.vsProfessional.winget index d9c700b4c..d14aa9a18 100644 --- a/.config/configuration.vsProfessional.winget +++ b/.config/configuration.vsProfessional.winget @@ -3,7 +3,7 @@ # # Usage: winget configure -f .config/configuration.vsProfessional.winget # -# Visual Studio 2022 Professional edition. For other editions use: +# Visual Studio 2026 Professional edition. For other editions use: # .config/configuration.winget (Community, default) # .config/configuration.vsEnterprise.winget (Enterprise) properties: @@ -26,10 +26,10 @@ properties: - resource: Microsoft.WinGet.DSC/WinGetPackage id: vsPackage directives: - description: Install Visual Studio 2022 Professional + description: Install Visual Studio 2026 Professional securityContext: elevated settings: - id: Microsoft.VisualStudio.2022.Professional + id: Microsoft.VisualStudio.Professional source: winget - resource: Microsoft.VisualStudio.DSC/VSComponents dependsOn: @@ -40,6 +40,6 @@ properties: securityContext: elevated settings: productId: Microsoft.VisualStudio.Product.Professional - channelId: VisualStudio.17.Release + channelId: VisualStudio.18.Release vsConfigFile: '${WinGetConfigRoot}\..\.vsconfig' configurationVersion: 0.2.0 diff --git a/.config/configuration.winget b/.config/configuration.winget index 25d1ef1d9..e7f44e270 100644 --- a/.config/configuration.winget +++ b/.config/configuration.winget @@ -26,10 +26,10 @@ properties: - resource: Microsoft.WinGet.DSC/WinGetPackage id: vsPackage directives: - description: Install Visual Studio 2022 Community + description: Install Visual Studio 2026 Community securityContext: elevated settings: - id: Microsoft.VisualStudio.2022.Community + id: Microsoft.VisualStudio.Community source: winget - resource: Microsoft.VisualStudio.DSC/VSComponents dependsOn: @@ -40,6 +40,6 @@ properties: securityContext: elevated settings: productId: Microsoft.VisualStudio.Product.Community - channelId: VisualStudio.17.Release + channelId: VisualStudio.18.Release vsConfigFile: '${WinGetConfigRoot}\..\.vsconfig' configurationVersion: 0.2.0 diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index abf3fbd8f..d12a0c0ec 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -199,10 +199,10 @@ When adding settings to `src/shared/configfile/`: - Visual Studio with these components: - Windows SDK 26100 - MSBuild - - Universal Windows platform support for v143 build tools (X64 and ARM64) - - MSVC v143 - VS 2022 C++ ARM64 build tools (Latest + Spectre) (X64 and ARM64) + - Universal Windows platform support for v145 build tools (X64 and ARM64) + - MSVC v145 - VS 2026 C++ ARM64 build tools (Latest + Spectre) (X64 and ARM64) - C++ core features - - C++ ATL for latest v143 tools (X64 and ARM64) + - C++ ATL for latest v145 tools (X64 and ARM64) - C++ Clang compiler for Windows - .NET desktop development - .NET WinUI app development tools diff --git a/.vsconfig b/.vsconfig index 19229b943..8a9100694 100644 --- a/.vsconfig +++ b/.vsconfig @@ -12,6 +12,7 @@ "Microsoft.VisualStudio.Component.VC.ATL.Spectre", "Microsoft.VisualStudio.Component.VC.ATL.ARM64.Spectre", "Microsoft.VisualStudio.Component.VC.Llvm.Clang", + "Microsoft.VisualStudio.Component.VC.Llvm.ClangToolset", "Microsoft.VisualStudio.Component.Windows11SDK.26100", "Microsoft.VisualStudio.Component.UWP.VC.ARM64", "Microsoft.VisualStudio.Workload.ManagedDesktop", diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c66e8a77..e483a486a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -367,8 +367,7 @@ else() endif() # Determine the Visual Studio installation directory which contains LLVM tools. -# Supported versions: VS2026 and VS2022. -# Prefer VS2026 to keep local clang-format output aligned with pipeline expectations. +# Supported version: VS2026. function(find_vs_install_dir VERSION_RANGE OUTPUT_VAR) execute_process( COMMAND "${VSWHERE_SOURCE_DIR}/vswhere.exe" -version "${VERSION_RANGE}" -products * -requires Microsoft.VisualStudio.Component.VC.Llvm.Clang -property installationPath -prerelease -latest @@ -382,20 +381,10 @@ endfunction() find_vs_install_dir("[18.0,19.0)" VS_INSTALL_DIR) -if (NOT VS_INSTALL_DIR) - find_vs_install_dir("[17.0,18.0)" VS_INSTALL_DIR) - if (VS_INSTALL_DIR) - message(WARNING "Visual Studio 2026 was not found; using Visual Studio 2022 instead. clang-format output may differ from pipeline expectations.") - endif() -endif() - if (NOT VS_INSTALL_DIR) message(FATAL_ERROR "Could not determine Visual Studio installation directory.") endif() -# Pick the first line returned from vswhere, in case multiple versions are returned. -string(REGEX MATCH "([^\n\r]+)" VS_INSTALL_DIR "${VS_INSTALL_DIR}") - if("${CMAKE_HOST_SYSTEM_PROCESSOR}" STREQUAL "AMD64") set(LLVM_INSTALL_DIR "${VS_INSTALL_DIR}/VC/Tools/Llvm/x64/bin") else() diff --git a/doc/docs/dev-loop.md b/doc/docs/dev-loop.md index 6092356b2..55fe8ddb5 100644 --- a/doc/docs/dev-loop.md +++ b/doc/docs/dev-loop.md @@ -8,7 +8,7 @@ All prerequisites can be installed automatically by running: tools\setup-dev-env.ps1 ``` -This uses [WinGet Configuration](https://learn.microsoft.com/windows/package-manager/configuration/) to install Developer Mode, CMake, Visual Studio 2022, and the required workloads from [`.vsconfig`](https://github.com/microsoft/WSL/blob/master/.vsconfig). If VS 2022 is already installed, the script detects your edition (Community, Professional, or Enterprise) and uses the matching configuration. If no VS 2022 is found, it defaults to Community. +This uses [WinGet Configuration](https://learn.microsoft.com/windows/package-manager/configuration/) to install Developer Mode, CMake, Visual Studio 2026, and the required workloads from [`.vsconfig`](https://github.com/microsoft/WSL/blob/master/.vsconfig). If VS 2026 is already installed, the script detects your edition (Community, Professional, or Enterprise) and uses the matching configuration. If no VS 2026 is found, it defaults to Community. You can also run a WinGet configuration directly for your edition: @@ -28,9 +28,9 @@ If you prefer to install prerequisites manually: - CMake >= 3.25 - Can be installed with `winget install Kitware.CMake` -- Visual Studio 2022 with the required components: +- Visual Studio 2026 with the required components: - Use VS Installer → More → Import configuration and select [`.vsconfig`](https://github.com/microsoft/WSL/blob/master/.vsconfig) - - Or: `winget install Microsoft.VisualStudio.2022.Community --override "--wait --quiet --config .vsconfig"` + - Or: `winget install Microsoft.VisualStudio.Community --override "--wait --quiet --config .vsconfig"` - Enable [Developer Mode](https://learn.microsoft.com/en-us/windows/apps/get-started/enable-your-device-for-development) in Windows Settings, or run builds with Administrator privileges (required for symbolic link support) diff --git a/doc/samples/WSLC-HelloWorld/WSLCHelloWorld.sln b/doc/samples/WSLC-HelloWorld/WSLCHelloWorld.sln index 4fc738cdd..d19a21f14 100644 --- a/doc/samples/WSLC-HelloWorld/WSLCHelloWorld.sln +++ b/doc/samples/WSLC-HelloWorld/WSLCHelloWorld.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.14.37027.9 d17.14 +# Visual Studio Version 18 +VisualStudioVersion = 18.7.11903.348 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WSLCHelloWorld", "WSLCHelloWorld.vcxproj", "{2B5C2E11-2C0A-4F1B-9F3D-7E8A1C2D3E4F}" EndProject diff --git a/doc/samples/WSLC-HelloWorld/WSLCHelloWorld.vcxproj b/doc/samples/WSLC-HelloWorld/WSLCHelloWorld.vcxproj index 1033a5f48..5dbaf53b5 100644 --- a/doc/samples/WSLC-HelloWorld/WSLCHelloWorld.vcxproj +++ b/doc/samples/WSLC-HelloWorld/WSLCHelloWorld.vcxproj @@ -19,7 +19,7 @@ - 17.0 + 18.0 Win32Proj {2B5C2E11-2C0A-4F1B-9F3D-7E8A1C2D3E4F} WSLCHelloWorld diff --git a/doc/samples/WSLC-Neofetch/WSLCNeofetch.sln b/doc/samples/WSLC-Neofetch/WSLCNeofetch.sln index 346f8d82e..ce3d58650 100644 --- a/doc/samples/WSLC-Neofetch/WSLCNeofetch.sln +++ b/doc/samples/WSLC-Neofetch/WSLCNeofetch.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.14.37027.9 d17.14 +# Visual Studio Version 18 +VisualStudioVersion = 18.7.11903.348 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WSLCNeofetch", "WSLCNeofetch.vcxproj", "{35158918-896E-42B7-B4E8-CF98816259AA}" EndProject diff --git a/doc/samples/WSLC-Neofetch/WSLCNeofetch.vcxproj b/doc/samples/WSLC-Neofetch/WSLCNeofetch.vcxproj index 56e033662..8d1648767 100644 --- a/doc/samples/WSLC-Neofetch/WSLCNeofetch.vcxproj +++ b/doc/samples/WSLC-Neofetch/WSLCNeofetch.vcxproj @@ -19,7 +19,7 @@ - 17.0 + 18.0 Win32Proj {35158918-896e-42b7-b4e8-cf98816259aa} WSLCNeofetch diff --git a/tools/setup-dev-env.ps1 b/tools/setup-dev-env.ps1 index 6bba3e1c0..743112271 100644 --- a/tools/setup-dev-env.ps1 +++ b/tools/setup-dev-env.ps1 @@ -2,14 +2,14 @@ .SYNOPSIS Sets up the development environment for building WSL. .DESCRIPTION - Detects any existing Visual Studio 2022 installation and runs the + Detects any existing Visual Studio 2026 installation and runs the matching WinGet Configuration to install all prerequisites: - Developer Mode, CMake, Visual Studio 2022, and required workloads + Developer Mode, CMake, Visual Studio 2026, and required workloads from .vsconfig. - If VS 2022 is already installed, the script picks the configuration + If VS 2026 is already installed, the script picks the configuration matching that edition (Community, Professional, or Enterprise). - If no VS 2022 is found, it defaults to Community edition. + If no VS 2026 is found, it defaults to Community edition. .EXAMPLE .\tools\setup-dev-env.ps1 #> @@ -20,13 +20,13 @@ $ErrorActionPreference = "Stop" $repoRoot = (Resolve-Path "$PSScriptRoot\..").Path $configDir = Join-Path $repoRoot ".config" -# ── Detect existing VS 2022 edition ───────────────────────────────── +# ── Detect existing VS 2026 edition ───────────────────────────────── $configFile = "configuration.winget" # default: Community $vswhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" if (Test-Path $vswhere) { - $productId = (& $vswhere -version "[17.0,18.0)" -products * -latest -property productId 2>$null | + $productId = (& $vswhere -version "[18.0,19.0)" -products * -latest -property productId 2>$null | Select-Object -First 1) if ($productId) { $productId = $productId.Trim() } @@ -35,23 +35,23 @@ if (Test-Path $vswhere) { "Microsoft.VisualStudio.Product.Professional" { $configFile = "configuration.vsProfessional.winget" - Write-Host "Detected VS 2022 Professional - using $configFile" -ForegroundColor Green + Write-Host "Detected VS 2026 Professional - using $configFile" -ForegroundColor Green } "Microsoft.VisualStudio.Product.Enterprise" { $configFile = "configuration.vsEnterprise.winget" - Write-Host "Detected VS 2022 Enterprise - using $configFile" -ForegroundColor Green + Write-Host "Detected VS 2026 Enterprise - using $configFile" -ForegroundColor Green } "Microsoft.VisualStudio.Product.Community" { - Write-Host "Detected VS 2022 Community - using $configFile" -ForegroundColor Green + Write-Host "Detected VS 2026 Community - using $configFile" -ForegroundColor Green } default { - Write-Host "No VS 2022 found - will install Community edition" -ForegroundColor Yellow + Write-Host "No VS 2026 found - will install Community edition" -ForegroundColor Yellow } } } else { - Write-Host "No VS 2022 found - will install Community edition" -ForegroundColor Yellow + Write-Host "No VS 2026 found - will install Community edition" -ForegroundColor Yellow } $configPath = Join-Path $configDir $configFile @@ -65,7 +65,7 @@ if (-not (Test-Path -LiteralPath $configPath -PathType Leaf)) # ── Run WinGet Configuration ──────────────────────────────────────── Write-Host "" Write-Host "Running WinGet Configuration ($configFile)..." -ForegroundColor Cyan -Write-Host " This will install: Developer Mode, CMake, VS 2022 + required components" +Write-Host " This will install: Developer Mode, CMake, VS 2026 + required components" Write-Host "" winget configure --enable From 041d8df8888f02ed495594eb558f4d253fd5f3ee Mon Sep 17 00:00:00 2001 From: Ben Hillis Date: Sat, 11 Jul 2026 10:03:47 -0700 Subject: [PATCH 5/5] Remove unreachable break statements after throw in GnsEngine The break statements following unconditional throw in two default switch cases are dead code (flagged in PR #41053 review). Remove them. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d3de59ec-7508-440a-b7e5-1345aad2096a --- src/linux/init/GnsEngine.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/linux/init/GnsEngine.cpp b/src/linux/init/GnsEngine.cpp index d05f1cd32..f3cb53994 100644 --- a/src/linux/init/GnsEngine.cpp +++ b/src/linux/init/GnsEngine.cpp @@ -184,7 +184,6 @@ void GnsEngine::ProcessNotification(const nlohmann::json& payload, Interface& in default: throw RuntimeErrorWithSourceLocation( std::format("Unexpected LxGnsMessageNotification for interfaceName {}: {}", interface.Name(), payload["ResourceType"].get())); - break; } } @@ -709,7 +708,6 @@ std::tuple GnsEngine::ProcessNextMessage(wsl::shared::Transaction& tr default: throw RuntimeErrorWithSourceLocation( std::format("Unexpected Wslcore::Networking::OperationType : {}", static_cast(interfaceNetFilterRequest.operation))); - break; } break; }