Fix WSLCTests::ListVms parser for older Windows hcsdiag (#40407)

* Fix WSLCTests::ListVms parser for older Windows hcsdiag The hcsdiag list -raw JSON option is unsupported on the in-box hcsdiag shipped with older Windows builds (e.g. Win10 22H2 / build 19041), where it falls back to printing the help text. With nlohmann::json::parse called in non-throwing mode, this silently produced a discarded value, so ListVms() returned an empty vector and three tests failed in the `vb_release` lab image with "VM with owner 'X' not found": - WSLCTests::VmOwnerMatchesSessionDisplayName - WSLCTests::VmKillTerminatesSession - WSLCTests::VmKillFailsInFlightOperations Switch to parsing the human-readable `hcsdiag list` text output, which is consistent across every supported Windows version (4 comma-separated fields `Type, State, Id, Owner` on the indented detail line). Also log the captured stdout/stderr/exit code via LogInfo so future failures have the raw hcsdiag output captured next to the assertion. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Verify hcsdiag list exit code in WSLCTests::ListVms Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Use HcsEnumerateComputeSystems instead of shelling out to hcsdiag Per PR feedback, call HcsEnumerateComputeSystems directly rather than spawning hcsdiag.exe and parsing its text output. This is what hcsdiag itself does internally, gives us a guaranteed JSON contract from the HCS API (so the previous compatibility issue with older Windows builds and the brittle comma-splitting of the text format both go away), and avoids the extra process launch. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add ExecutionContext and let JSON parse throw in ListVms Code review feedback: - Wrap the HCS call in ExecutionContext(Context::HCS) for consistency with every other helper in src/windows/common/hcs.cpp. - Drop allow_exceptions=false on the JSON parse: HcsEnumerateComputeSystems returns a guaranteed JSON contract, so any parse failure indicates a real schema/platform problem and should fail loudly rather than be silently treated as 'no VMs found'. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix ListVms comment: HcsEnumerateComputeSystems returns all systems Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Ben Hillis committed May 5, 2026 at 14:19 UTC 4fa3cfdd4374419a89fc86e3b5aa4c27d68c2c3d
1 file changed +13 -4
test/windows/WSLCTests.cpp
+13 -4
@@ -18,6 +18,7 @@ Abstract:
18 #include "WSLCProcessLauncher.h"
19 #include "WSLCContainerLauncher.h"
20 #include "WslCoreFilesystem.h"
21 +#include "hcs.hpp"
22 #include <nlohmann/json.hpp>
23
24 using namespace std::literals::chrono_literals;
@@ -444,14 +445,22 @@ class WSLCTests
445 std::wstring Owner;
446 };
447
447 - // Returns VM info (Id + Owner) for all running VMs via hcsdiag.
448 + // Returns VM info (Id + Owner) for all compute systems via the HCS API.
449 static std::vector<VmInfo> ListVms()
450 {
450 - wsl::windows::common::SubProcess process(nullptr, L"hcsdiag list -raw");
451 - auto output = process.RunAndCaptureOutput(10000);
451 + const wsl::windows::common::ExecutionContext context(wsl::windows::common::Context::HCS);
452 +
453 + auto operation = wsl::windows::common::hcs::CreateOperation();
454 + THROW_IF_FAILED(::HcsEnumerateComputeSystems(L"{}", operation.get()));
455 +
456 + wil::unique_cotaskmem_string resultDocument;
457 + const auto result = ::HcsWaitForOperationResult(operation.get(), 10000, &resultDocument);
458 + THROW_IF_FAILED_MSG(result, "HcsEnumerateComputeSystems failed (error: %ls)", resultDocument.get());
459 +
460 + LogInfo("HcsEnumerateComputeSystems result='%ws'", resultDocument.get());
461
462 std::vector<VmInfo> vms;
454 - auto json = nlohmann::json::parse(wsl::shared::string::WideToMultiByte(output.Stdout), nullptr, false);
463 + const auto json = nlohmann::json::parse(wsl::shared::string::WideToMultiByte(resultDocument.get()));
464 if (!json.is_array())
465 {
466 return vms;