From 5f1830a0e2ce1a684d598bcdf5d1fa4adcfaab07 Mon Sep 17 00:00:00 2001 From: Beena352 Date: Tue, 23 Dec 2025 12:59:51 -0800 Subject: [PATCH 1/9] WIP: local test changes --- test/windows/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/windows/CMakeLists.txt b/test/windows/CMakeLists.txt index c700d66f4..1abe54e68 100644 --- a/test/windows/CMakeLists.txt +++ b/test/windows/CMakeLists.txt @@ -9,7 +9,8 @@ set(SOURCES PluginTests.cpp PolicyTests.cpp InstallerTests.cpp - WSLATests.cpp) + WSLATests.cpp + WsladiagTests.cpp) set(HEADERS Common.h From b466c8f0f2deedd8b0dc30bf8eee20d002241cd3 Mon Sep 17 00:00:00 2001 From: Beena352 Date: Tue, 23 Dec 2025 14:55:52 -0800 Subject: [PATCH 2/9] Add argument and error-handling tests for wsladiag --- test/windows/WsladiagTests.cpp | 134 +++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 test/windows/WsladiagTests.cpp diff --git a/test/windows/WsladiagTests.cpp b/test/windows/WsladiagTests.cpp new file mode 100644 index 000000000..bd3f6801f --- /dev/null +++ b/test/windows/WsladiagTests.cpp @@ -0,0 +1,134 @@ +/*++ + +Copyright (c) Microsoft. All rights reserved. + +Module Name: + + WsladiagTests.cpp + +Abstract: + + This file contains smoke tests for wsladiag. + +--*/ + +#include "precomp.h" +#include "Common.h" +#include + +namespace WsladiagTests { +class WsladiagTests +{ + WSL_TEST_CLASS(WsladiagTests) + + TEST_CLASS_SETUP(TestClassSetup) + { + VERIFY_ARE_EQUAL(LxsstuInitialize(FALSE), TRUE); + return true; + } + + TEST_CLASS_CLEANUP(TestClassCleanup) + { + LxsstuUninitialize(FALSE); + return true; + } + + static std::wstring BuildWsladiagCmd(const std::wstring& args) + { + const auto exePath = wsl::windows::common::wslutil::GetBasePath() / L"wsladiag.exe"; + VERIFY_IS_TRUE(std::filesystem::exists(exePath)); + + const auto exe = exePath.wstring(); + return args.empty() ? std::format(L"\"{}\"", exe) : std::format(L"\"{}\" {}", exe, args); + } + + static std::tuple RunWsladiag(const std::wstring& args) + { + auto cmd = BuildWsladiagCmd(args); + return LxsstuLaunchCommandAndCaptureOutputWithResult(cmd.data()); + } + + TEST_METHOD(List_ShowsSessionsOrNoSessions) + { + auto [out, err, code] = RunWsladiag(L"list"); + VERIFY_ARE_EQUAL(0, code); + VERIFY_ARE_EQUAL(L"", err); + + const bool noSessions = (out.find(L"No WSLA sessions found.") != std::wstring::npos); + + const bool hasTable = (out.find(L"WSLA session") != std::wstring::npos) && (out.find(L"ID") != std::wstring::npos) && + (out.find(L"Display Name") != std::wstring::npos); + + VERIFY_IS_TRUE(noSessions || hasTable); + } + + TEST_METHOD(Help_ShowsUsage) + { + auto [out, err, code] = RunWsladiag(L"--help"); + VERIFY_ARE_EQUAL(0, code); + VERIFY_ARE_EQUAL(L"", out); + + VERIFY_IS_TRUE(err.find(L"Usage:") != std::wstring::npos); + VERIFY_IS_TRUE(err.find(L"wsladiag list") != std::wstring::npos); + VERIFY_IS_TRUE(err.find(L"wsladiag shell [--verbose]") != std::wstring::npos); + } + + TEST_METHOD(Shell_MissingName_ShowsUsage) + { + auto [out, err, code] = RunWsladiag(L"shell"); + VERIFY_ARE_NOT_EQUAL(0, code); + VERIFY_ARE_EQUAL(L"", out); + + VERIFY_IS_TRUE(err.find(L"Usage:") != std::wstring::npos); + VERIFY_IS_TRUE(err.find(L"wsladiag shell [--verbose]") != std::wstring::npos); + } + + TEST_METHOD(Shell_InvalidSessionName_Verbose) + { + auto [out, err, code] = RunWsladiag(L"shell DefinitelyNotARealSession --verbose"); + VERIFY_ARE_NOT_EQUAL(0, code); + + VERIFY_IS_TRUE(out.find(L"[diag] shell='DefinitelyNotARealSession'") != std::wstring::npos); + VERIFY_IS_TRUE(err.find(L"Session not found: 'DefinitelyNotARealSession'") != std::wstring::npos); + } + + TEST_METHOD(UnknownCommand_ShowsUsage) + { + auto [out, err, code] = RunWsladiag(L"blah"); + VERIFY_ARE_NOT_EQUAL(0, code); + VERIFY_ARE_EQUAL(L"", out); + + VERIFY_IS_TRUE(err.find(L"Unknown command: 'blah'") != std::wstring::npos); + VERIFY_IS_TRUE(err.find(L"Usage:") != std::wstring::npos); + } + + TEST_METHOD(EmptyCommand_ShowsUsage) + { + auto [out, err, code] = RunWsladiag(L""); + VERIFY_ARE_EQUAL(0, code); + VERIFY_ARE_EQUAL(L"", out); + + VERIFY_IS_TRUE(err.find(L"Usage:") != std::wstring::npos); + VERIFY_IS_TRUE(err.find(L"wsladiag list") != std::wstring::npos); + VERIFY_IS_TRUE(err.find(L"wsladiag shell [--verbose]") != std::wstring::npos); + } + + TEST_METHOD(Shell_InvalidSessionName_Silent) + { + auto [out, err, code] = RunWsladiag(L"shell DefinitelyNotARealSession"); + VERIFY_ARE_NOT_EQUAL(0, code); + VERIFY_ARE_EQUAL(L"", out); + + VERIFY_IS_TRUE(err.find(L"Session not found: 'DefinitelyNotARealSession'") != std::wstring::npos); + } + + TEST_METHOD(Help_ShortFlag_ShowsUsage) + { + auto [out, err, code] = RunWsladiag(L"-h"); + VERIFY_ARE_EQUAL(0, code); + VERIFY_ARE_EQUAL(L"", out); + + VERIFY_IS_TRUE(err.find(L"Usage:") != std::wstring::npos); + } +}; +} // namespace WsladiagTests \ No newline at end of file From a46a738ea3c6cf31f73e2d879c7d42deb013d792 Mon Sep 17 00:00:00 2001 From: Beena352 Date: Tue, 23 Dec 2025 15:05:12 -0800 Subject: [PATCH 3/9] test/windows/WsladiagTests.cpp --- test/windows/WsladiagTests.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/windows/WsladiagTests.cpp b/test/windows/WsladiagTests.cpp index bd3f6801f..5628798ee 100644 --- a/test/windows/WsladiagTests.cpp +++ b/test/windows/WsladiagTests.cpp @@ -130,5 +130,23 @@ class WsladiagTests VERIFY_IS_TRUE(err.find(L"Usage:") != std::wstring::npos); } + + TEST_METHOD(Help_ShortAndLongFlags_Match) + { + auto [outH, errH, codeH] = RunWsladiag(L"-h"); + auto [outLong, errLong, codeLong] = RunWsladiag(L"--help"); + + VERIFY_ARE_EQUAL(0, codeH); + VERIFY_ARE_EQUAL(0, codeLong); + + VERIFY_ARE_EQUAL(L"", outH); + VERIFY_ARE_EQUAL(L"", outLong); + + VERIFY_ARE_EQUAL(errH, errLong); + + VERIFY_IS_TRUE(errH.find(L"Usage:") != std::wstring::npos); + VERIFY_IS_TRUE(errH.find(L"wsladiag list") != std::wstring::npos); + VERIFY_IS_TRUE(errH.find(L"wsladiag shell [--verbose]") != std::wstring::npos); + } }; } // namespace WsladiagTests \ No newline at end of file From 4e9676a7c0148c617300c4b384bc54190bf26ffd Mon Sep 17 00:00:00 2001 From: Beena352 Date: Tue, 23 Dec 2025 15:34:57 -0800 Subject: [PATCH 4/9] Remove duplicate help flag test --- test/windows/WsladiagTests.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/test/windows/WsladiagTests.cpp b/test/windows/WsladiagTests.cpp index 5628798ee..e6287d1f1 100644 --- a/test/windows/WsladiagTests.cpp +++ b/test/windows/WsladiagTests.cpp @@ -122,15 +122,6 @@ class WsladiagTests VERIFY_IS_TRUE(err.find(L"Session not found: 'DefinitelyNotARealSession'") != std::wstring::npos); } - TEST_METHOD(Help_ShortFlag_ShowsUsage) - { - auto [out, err, code] = RunWsladiag(L"-h"); - VERIFY_ARE_EQUAL(0, code); - VERIFY_ARE_EQUAL(L"", out); - - VERIFY_IS_TRUE(err.find(L"Usage:") != std::wstring::npos); - } - TEST_METHOD(Help_ShortAndLongFlags_Match) { auto [outH, errH, codeH] = RunWsladiag(L"-h"); From e1771da323bc50143635d7e0970668410d18a93c Mon Sep 17 00:00:00 2001 From: Beena352 Date: Thu, 25 Dec 2025 13:05:29 -0800 Subject: [PATCH 5/9] Use GetMsiPackagePath() for wsladiag.exe location lookup --- test/windows/WSLATests.cpp | 2 +- test/windows/WsladiagTests.cpp | 139 +++++++++++++++++++-------------- 2 files changed, 82 insertions(+), 59 deletions(-) diff --git a/test/windows/WSLATests.cpp b/test/windows/WSLATests.cpp index e78b49a59..587465b35 100644 --- a/test/windows/WSLATests.cpp +++ b/test/windows/WSLATests.cpp @@ -150,7 +150,7 @@ class WSLATests if (result.Code != expectedResult) { LogError( - "Comman didn't return expected code (%i). ExitCode: %i, Stdout: '%hs', Stderr: '%hs'", + "Command didn't return expected code (%i). ExitCode: %i, Stdout: '%hs', Stderr: '%hs'", expectedResult, result.Code, result.Output[1].c_str(), diff --git a/test/windows/WsladiagTests.cpp b/test/windows/WsladiagTests.cpp index e6287d1f1..15c9d1cc8 100644 --- a/test/windows/WsladiagTests.cpp +++ b/test/windows/WsladiagTests.cpp @@ -21,6 +21,7 @@ class WsladiagTests { WSL_TEST_CLASS(WsladiagTests) + // Initialize the tests TEST_CLASS_SETUP(TestClassSetup) { VERIFY_ARE_EQUAL(LxsstuInitialize(FALSE), TRUE); @@ -32,66 +33,51 @@ class WsladiagTests LxsstuUninitialize(FALSE); return true; } - - static std::wstring BuildWsladiagCmd(const std::wstring& args) - { - const auto exePath = wsl::windows::common::wslutil::GetBasePath() / L"wsladiag.exe"; - VERIFY_IS_TRUE(std::filesystem::exists(exePath)); - - const auto exe = exePath.wstring(); - return args.empty() ? std::format(L"\"{}\"", exe) : std::format(L"\"{}\" {}", exe, args); - } - - static std::tuple RunWsladiag(const std::wstring& args) - { - auto cmd = BuildWsladiagCmd(args); - return LxsstuLaunchCommandAndCaptureOutputWithResult(cmd.data()); - } - + // Test that wsladiag list command shows either sessions or "no sessions" message TEST_METHOD(List_ShowsSessionsOrNoSessions) { auto [out, err, code] = RunWsladiag(L"list"); VERIFY_ARE_EQUAL(0, code); VERIFY_ARE_EQUAL(L"", err); - const bool noSessions = (out.find(L"No WSLA sessions found.") != std::wstring::npos); - - const bool hasTable = (out.find(L"WSLA session") != std::wstring::npos) && (out.find(L"ID") != std::wstring::npos) && - (out.find(L"Display Name") != std::wstring::npos); - - VERIFY_IS_TRUE(noSessions || hasTable); + ValidateListOutput(out); } + // Test that wsladiag --help shows usage information TEST_METHOD(Help_ShowsUsage) { auto [out, err, code] = RunWsladiag(L"--help"); VERIFY_ARE_EQUAL(0, code); VERIFY_ARE_EQUAL(L"", out); - - VERIFY_IS_TRUE(err.find(L"Usage:") != std::wstring::npos); - VERIFY_IS_TRUE(err.find(L"wsladiag list") != std::wstring::npos); - VERIFY_IS_TRUE(err.find(L"wsladiag shell [--verbose]") != std::wstring::npos); + ValidateUsage(err); } - TEST_METHOD(Shell_MissingName_ShowsUsage) + // Test that wsladiag with no arguments shows usage information + TEST_METHOD(EmptyCommand_ShowsUsage) { - auto [out, err, code] = RunWsladiag(L"shell"); - VERIFY_ARE_NOT_EQUAL(0, code); + auto [out, err, code] = RunWsladiag(L""); + VERIFY_ARE_EQUAL(0, code); VERIFY_ARE_EQUAL(L"", out); - - VERIFY_IS_TRUE(err.find(L"Usage:") != std::wstring::npos); - VERIFY_IS_TRUE(err.find(L"wsladiag shell [--verbose]") != std::wstring::npos); + ValidateUsage(err); } - TEST_METHOD(Shell_InvalidSessionName_Verbose) + // Test that -h and --help flags produce identical output + TEST_METHOD(Help_ShortAndLongFlags_Match) { - auto [out, err, code] = RunWsladiag(L"shell DefinitelyNotARealSession --verbose"); - VERIFY_ARE_NOT_EQUAL(0, code); + auto [outH, errH, codeH] = RunWsladiag(L"-h"); + auto [outLong, errLong, codeLong] = RunWsladiag(L"--help"); + + VERIFY_ARE_EQUAL(0, codeH); + VERIFY_ARE_EQUAL(0, codeLong); - VERIFY_IS_TRUE(out.find(L"[diag] shell='DefinitelyNotARealSession'") != std::wstring::npos); - VERIFY_IS_TRUE(err.find(L"Session not found: 'DefinitelyNotARealSession'") != std::wstring::npos); + VERIFY_ARE_EQUAL(L"", outH); + VERIFY_ARE_EQUAL(L"", outLong); + + VERIFY_ARE_EQUAL(errH, errLong); + ValidateUsage(errH); } + // Test that unknown commands show error message and usage TEST_METHOD(UnknownCommand_ShowsUsage) { auto [out, err, code] = RunWsladiag(L"blah"); @@ -99,45 +85,82 @@ class WsladiagTests VERIFY_ARE_EQUAL(L"", out); VERIFY_IS_TRUE(err.find(L"Unknown command: 'blah'") != std::wstring::npos); - VERIFY_IS_TRUE(err.find(L"Usage:") != std::wstring::npos); + ValidateUsage(err); } - TEST_METHOD(EmptyCommand_ShowsUsage) + // Test that shell command without session name shows usage + TEST_METHOD(Shell_MissingName_ShowsUsage) { - auto [out, err, code] = RunWsladiag(L""); - VERIFY_ARE_EQUAL(0, code); + auto [out, err, code] = RunWsladiag(L"shell"); + VERIFY_ARE_NOT_EQUAL(0, code); VERIFY_ARE_EQUAL(L"", out); - - VERIFY_IS_TRUE(err.find(L"Usage:") != std::wstring::npos); - VERIFY_IS_TRUE(err.find(L"wsladiag list") != std::wstring::npos); - VERIFY_IS_TRUE(err.find(L"wsladiag shell [--verbose]") != std::wstring::npos); + ValidateUsage(err); } + // Test shell command with invalid session name (silent mode) TEST_METHOD(Shell_InvalidSessionName_Silent) { - auto [out, err, code] = RunWsladiag(L"shell DefinitelyNotARealSession"); + const std::wstring name = L"DefinitelyNotARealSession"; + auto [out, err, code] = RunWsladiag(std::format(L"shell {}", name)); VERIFY_ARE_NOT_EQUAL(0, code); VERIFY_ARE_EQUAL(L"", out); - VERIFY_IS_TRUE(err.find(L"Session not found: 'DefinitelyNotARealSession'") != std::wstring::npos); + ValidateSessionNotFound(err, name); } - TEST_METHOD(Help_ShortAndLongFlags_Match) + // Test shell command with invalid session name (verbose mode) + TEST_METHOD(Shell_InvalidSessionName_Verbose) { - auto [outH, errH, codeH] = RunWsladiag(L"-h"); - auto [outLong, errLong, codeLong] = RunWsladiag(L"--help"); + const std::wstring name = L"DefinitelyNotARealSession"; + auto [out, err, code] = RunWsladiag(std::format(L"shell {} --verbose", name)); + VERIFY_ARE_NOT_EQUAL(0, code); - VERIFY_ARE_EQUAL(0, codeH); - VERIFY_ARE_EQUAL(0, codeLong); + VERIFY_IS_TRUE(out.find(std::format(L"[diag] shell='{}'", name)) != std::wstring::npos); + ValidateSessionNotFound(err, name); + } - VERIFY_ARE_EQUAL(L"", outH); - VERIFY_ARE_EQUAL(L"", outLong); + // Build command line for wsladiag.exe with given arguments + static std::wstring BuildWsladiagCmd(const std::wstring& args) + { + const auto msiPathOpt = wsl::windows::common::wslutil::GetMsiPackagePath(); + VERIFY_IS_TRUE(msiPathOpt.has_value()); - VERIFY_ARE_EQUAL(errH, errLong); + const auto exePath = std::filesystem::path(*msiPathOpt) / L"wsladiag.exe"; + const auto exe = exePath.wstring(); - VERIFY_IS_TRUE(errH.find(L"Usage:") != std::wstring::npos); - VERIFY_IS_TRUE(errH.find(L"wsladiag list") != std::wstring::npos); - VERIFY_IS_TRUE(errH.find(L"wsladiag shell [--verbose]") != std::wstring::npos); + return args.empty() ? std::format(L"\"{}\"", exe) : std::format(L"\"{}\" {}", exe, args); + } + + // Execute wsladiag with given arguments and return output, error, and exit code + static std::tuple RunWsladiag(const std::wstring& args) + { + auto cmd = BuildWsladiagCmd(args); + return LxsstuLaunchCommandAndCaptureOutputWithResult(cmd.data()); + } + + // Validate that list command output shows either no sessions message or session table + static void ValidateListOutput(const std::wstring& out) + { + const bool noSessions = out.find(L"No WSLA sessions found.") != std::wstring::npos; + + const bool hasTable = out.find(L"WSLA session") != std::wstring::npos && out.find(L"ID") != std::wstring::npos && + out.find(L"Creator PID") != std::wstring::npos && out.find(L"Display Name") != std::wstring::npos; + + VERIFY_IS_TRUE(noSessions || hasTable); + } + + // Validate that usage information contains expected command descriptions + static void ValidateUsage(const std::wstring& err) + { + VERIFY_IS_TRUE(err.find(L"Usage:") != std::wstring::npos); + VERIFY_IS_TRUE(err.find(L"wsladiag list") != std::wstring::npos); + VERIFY_IS_TRUE(err.find(L"wsladiag shell [--verbose]") != std::wstring::npos); + } + + // Validate that session not found error contains the expected session name + static void ValidateSessionNotFound(const std::wstring& err, const std::wstring& name) + { + VERIFY_IS_TRUE(err.find(std::format(L"Session not found: '{}'", name)) != std::wstring::npos); } }; } // namespace WsladiagTests \ No newline at end of file From bfff64657ca2c34fe372b8d133b998ca4890e320 Mon Sep 17 00:00:00 2001 From: Beena352 Date: Sat, 3 Jan 2026 17:43:45 -0800 Subject: [PATCH 6/9] tests: validate wsladiag stdout/stderr --- src/windows/wsladiag/wsladiag.cpp | 1 + test/windows/WsladiagTests.cpp | 13 ++++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/windows/wsladiag/wsladiag.cpp b/src/windows/wsladiag/wsladiag.cpp index 8c11c0022..28b7c0c21 100644 --- a/src/windows/wsladiag/wsladiag.cpp +++ b/src/windows/wsladiag/wsladiag.cpp @@ -727,6 +727,7 @@ int wmain(int, wchar_t**) wsl::windows::common::EnableContextualizedErrors(false); ExecutionContext context{Context::WslaDiag}; + int exitCode = 1; HRESULT result = S_OK; diff --git a/test/windows/WsladiagTests.cpp b/test/windows/WsladiagTests.cpp index 15c9d1cc8..6581ab09d 100644 --- a/test/windows/WsladiagTests.cpp +++ b/test/windows/WsladiagTests.cpp @@ -16,6 +16,13 @@ Module Name: #include "Common.h" #include +static const std::wstring c_usageText = + L"wsladiag - WSLA diagnostics tool\r\n" + L"Usage:\r\n" + L" wsladiag list\r\n" + L" wsladiag shell [--verbose]\r\n" + L" wsladiag --help\r\n"; + namespace WsladiagTests { class WsladiagTests { @@ -50,6 +57,7 @@ class WsladiagTests VERIFY_ARE_EQUAL(0, code); VERIFY_ARE_EQUAL(L"", out); ValidateUsage(err); + } // Test that wsladiag with no arguments shows usage information @@ -80,12 +88,14 @@ class WsladiagTests // Test that unknown commands show error message and usage TEST_METHOD(UnknownCommand_ShowsUsage) { + auto [out, err, code] = RunWsladiag(L"blah"); VERIFY_ARE_NOT_EQUAL(0, code); VERIFY_ARE_EQUAL(L"", out); VERIFY_IS_TRUE(err.find(L"Unknown command: 'blah'") != std::wstring::npos); ValidateUsage(err); + } // Test that shell command without session name shows usage @@ -95,6 +105,7 @@ class WsladiagTests VERIFY_ARE_NOT_EQUAL(0, code); VERIFY_ARE_EQUAL(L"", out); ValidateUsage(err); + } // Test shell command with invalid session name (silent mode) @@ -143,7 +154,7 @@ class WsladiagTests { const bool noSessions = out.find(L"No WSLA sessions found.") != std::wstring::npos; - const bool hasTable = out.find(L"WSLA session") != std::wstring::npos && out.find(L"ID") != std::wstring::npos && + const bool hasTable = out.find(L"Found") != std::wstring::npos && out.find(L"ID") != std::wstring::npos && out.find(L"Creator PID") != std::wstring::npos && out.find(L"Display Name") != std::wstring::npos; VERIFY_IS_TRUE(noSessions || hasTable); From 365b15d2d5273517b82b03b654c10b01c4a3959f Mon Sep 17 00:00:00 2001 From: Beena352 Date: Mon, 12 Jan 2026 16:59:14 -0800 Subject: [PATCH 7/9] Localize Wsladiag tests --- src/shared/inc/CommandLine.h | 10 +++++ src/windows/wsladiag/wsladiag.cpp | 5 ++- test/windows/WsladiagTests.cpp | 68 ++++++++++++++++++++++++++----- 3 files changed, 71 insertions(+), 12 deletions(-) diff --git a/src/shared/inc/CommandLine.h b/src/shared/inc/CommandLine.h index cde97e622..1af2c1ee6 100644 --- a/src/shared/inc/CommandLine.h +++ b/src/shared/inc/CommandLine.h @@ -307,8 +307,13 @@ class ArgumentParser public: #ifdef WIN32 +<<<<<<< HEAD ArgumentParser(const std::wstring& CommandLine, LPCWSTR Name, int StartIndex = 1, bool ignoreUnknownArgs = false) : m_parseIndex(StartIndex), m_name(Name), m_ignoreUnknownArgs(ignoreUnknownArgs) +======= + ArgumentParser(const std::wstring& CommandLine, LPCWSTR Name, int StartIndex = 1, bool IgnoreUnknownArgs = false) : + m_startIndex(StartIndex), m_name(Name), m_ignoreUnknownArgs(IgnoreUnknownArgs) +>>>>>>> ea162030 (Localize Wsladiag tests) { m_argv.reset(CommandLineToArgvW(std::wstring(CommandLine).c_str(), &m_argc)); THROW_LAST_ERROR_IF(!m_argv); @@ -316,8 +321,13 @@ class ArgumentParser #else +<<<<<<< HEAD ArgumentParser(int argc, const char* const* argv, bool ignoreUnknownArgs = false) : m_argc(argc), m_argv(argv), m_parseIndex(1), m_ignoreUnknownArgs(ignoreUnknownArgs) +======= + ArgumentParser(int argc, const char* const* argv, bool IgnoreUnknownArgs = false) : + m_argc(argc), m_argv(argv), m_startIndex(1), m_ignoreUnknownArgs(IgnoreUnknownArgs) +>>>>>>> ea162030 (Localize Wsladiag tests) { } diff --git a/src/windows/wsladiag/wsladiag.cpp b/src/windows/wsladiag/wsladiag.cpp index 28b7c0c21..486d2b206 100644 --- a/src/windows/wsladiag/wsladiag.cpp +++ b/src/windows/wsladiag/wsladiag.cpp @@ -65,7 +65,11 @@ static int ReportError(const std::wstring& context, HRESULT hr) return 1; } +<<<<<<< HEAD // Handler for `wsladiag shell ` command. +======= +// Handler for `wsladiag shell [--verbose]` command - launches TTY-backed interactive shell. +>>>>>>> ea162030 (Localize Wsladiag tests) static int RunShellCommand(std::wstring_view commandLine) { std::wstring sessionName; @@ -727,7 +731,6 @@ int wmain(int, wchar_t**) wsl::windows::common::EnableContextualizedErrors(false); ExecutionContext context{Context::WslaDiag}; - int exitCode = 1; HRESULT result = S_OK; diff --git a/test/windows/WsladiagTests.cpp b/test/windows/WsladiagTests.cpp index 6581ab09d..e25177caf 100644 --- a/test/windows/WsladiagTests.cpp +++ b/test/windows/WsladiagTests.cpp @@ -14,20 +14,15 @@ Module Name: #include "precomp.h" #include "Common.h" +#include "Localization.h" #include -static const std::wstring c_usageText = - L"wsladiag - WSLA diagnostics tool\r\n" - L"Usage:\r\n" - L" wsladiag list\r\n" - L" wsladiag shell [--verbose]\r\n" - L" wsladiag --help\r\n"; - namespace WsladiagTests { class WsladiagTests { WSL_TEST_CLASS(WsladiagTests) +<<<<<<< HEAD // Initialize the tests TEST_CLASS_SETUP(TestClassSetup) { @@ -40,6 +35,14 @@ class WsladiagTests LxsstuUninitialize(FALSE); return true; } +======= + // Use localized usage text at runtime + static std::wstring GetUsageText() + { + return std::wstring(wsl::shared::Localization::MessageWsladiagUsage()); + } + +>>>>>>> ea162030 (Localize Wsladiag tests) // Test that wsladiag list command shows either sessions or "no sessions" message TEST_METHOD(List_ShowsSessionsOrNoSessions) { @@ -53,20 +56,28 @@ class WsladiagTests // Test that wsladiag --help shows usage information TEST_METHOD(Help_ShowsUsage) { +<<<<<<< HEAD auto [out, err, code] = RunWsladiag(L"--help"); VERIFY_ARE_EQUAL(0, code); VERIFY_ARE_EQUAL(L"", out); ValidateUsage(err); +======= + ValidateWsladiagOutput(L"--help", 0, L"", GetUsageText()); +>>>>>>> ea162030 (Localize Wsladiag tests) } // Test that wsladiag with no arguments shows usage information TEST_METHOD(EmptyCommand_ShowsUsage) { +<<<<<<< HEAD auto [out, err, code] = RunWsladiag(L""); VERIFY_ARE_EQUAL(0, code); VERIFY_ARE_EQUAL(L"", out); ValidateUsage(err); +======= + ValidateWsladiagOutput(L"", 0, L"", GetUsageText()); +>>>>>>> ea162030 (Localize Wsladiag tests) } // Test that -h and --help flags produce identical output @@ -88,6 +99,7 @@ class WsladiagTests // Test that unknown commands show error message and usage TEST_METHOD(UnknownCommand_ShowsUsage) { +<<<<<<< HEAD auto [out, err, code] = RunWsladiag(L"blah"); VERIFY_ARE_NOT_EQUAL(0, code); @@ -96,38 +108,63 @@ class WsladiagTests VERIFY_IS_TRUE(err.find(L"Unknown command: 'blah'") != std::wstring::npos); ValidateUsage(err); +======= + const std::wstring verb = L"blah"; + const std::wstring errorMsg = std::wstring(wsl::shared::Localization::MessageWslaUnknownCommand(verb.c_str())); + const std::wstring expected = errorMsg + GetUsageText(); + ValidateWsladiagOutput(verb, 1, L"", expected); +>>>>>>> ea162030 (Localize Wsladiag tests) } // Test that shell command without session name shows usage TEST_METHOD(Shell_MissingName_ShowsUsage) { auto [out, err, code] = RunWsladiag(L"shell"); +<<<<<<< HEAD VERIFY_ARE_NOT_EQUAL(0, code); VERIFY_ARE_EQUAL(L"", out); ValidateUsage(err); +======= + VERIFY_ARE_EQUAL(1, code); + VERIFY_ARE_EQUAL(L"", out); + const std::wstring missingArgMsg = + std::wstring(wsl::shared::Localization::MessageMissingArgument(L"", L"wsladiag shell")); + VERIFY_IS_TRUE(NormalizeForCompare(err).find(NormalizeForCompare(missingArgMsg)) != std::wstring::npos); +>>>>>>> ea162030 (Localize Wsladiag tests) } // Test shell command with invalid session name (silent mode) TEST_METHOD(Shell_InvalidSessionName_Silent) { +<<<<<<< HEAD const std::wstring name = L"DefinitelyNotARealSession"; auto [out, err, code] = RunWsladiag(std::format(L"shell {}", name)); VERIFY_ARE_NOT_EQUAL(0, code); VERIFY_ARE_EQUAL(L"", out); ValidateSessionNotFound(err, name); +======= + const auto expectedErr = + std::wstring(wsl::shared::Localization::MessageWslaSessionNotFound(L"DefinitelyNotARealSession")); + ValidateWsladiagOutput(L"shell DefinitelyNotARealSession", 1, L"", expectedErr); +>>>>>>> ea162030 (Localize Wsladiag tests) } // Test shell command with invalid session name (verbose mode) TEST_METHOD(Shell_InvalidSessionName_Verbose) { const std::wstring name = L"DefinitelyNotARealSession"; +<<<<<<< HEAD auto [out, err, code] = RunWsladiag(std::format(L"shell {} --verbose", name)); VERIFY_ARE_NOT_EQUAL(0, code); VERIFY_IS_TRUE(out.find(std::format(L"[diag] shell='{}'", name)) != std::wstring::npos); ValidateSessionNotFound(err, name); +======= + const auto expectedErr = std::wstring(wsl::shared::Localization::MessageWslaSessionNotFound(name.c_str())); + ValidateWsladiagOutput(std::format(L"shell {} --verbose", name), 1, L"", expectedErr); +>>>>>>> ea162030 (Localize Wsladiag tests) } // Build command line for wsladiag.exe with given arguments @@ -145,17 +182,20 @@ class WsladiagTests // Execute wsladiag with given arguments and return output, error, and exit code static std::tuple RunWsladiag(const std::wstring& args) { - auto cmd = BuildWsladiagCmd(args); + std::wstring cmd = BuildWsladiagCmd(args); return LxsstuLaunchCommandAndCaptureOutputWithResult(cmd.data()); } // Validate that list command output shows either no sessions message or session table static void ValidateListOutput(const std::wstring& out) { - const bool noSessions = out.find(L"No WSLA sessions found.") != std::wstring::npos; + const bool noSessions = out.find(std::wstring(wsl::shared::Localization::MessageWslaNoSessionsFound())) != std::wstring::npos; + const auto idHeader = std::wstring(wsl::shared::Localization::MessageWslaHeaderId()); + const auto pidHeader = std::wstring(wsl::shared::Localization::MessageWslaHeaderCreatorPid()); + const auto nameHeader = std::wstring(wsl::shared::Localization::MessageWslaHeaderDisplayName()); - const bool hasTable = out.find(L"Found") != std::wstring::npos && out.find(L"ID") != std::wstring::npos && - out.find(L"Creator PID") != std::wstring::npos && out.find(L"Display Name") != std::wstring::npos; + const bool hasTable = (out.find(idHeader) != std::wstring::npos) && (out.find(pidHeader) != std::wstring::npos) && + (out.find(nameHeader) != std::wstring::npos); VERIFY_IS_TRUE(noSessions || hasTable); } @@ -163,6 +203,7 @@ class WsladiagTests // Validate that usage information contains expected command descriptions static void ValidateUsage(const std::wstring& err) { +<<<<<<< HEAD VERIFY_IS_TRUE(err.find(L"Usage:") != std::wstring::npos); VERIFY_IS_TRUE(err.find(L"wsladiag list") != std::wstring::npos); VERIFY_IS_TRUE(err.find(L"wsladiag shell [--verbose]") != std::wstring::npos); @@ -172,6 +213,11 @@ class WsladiagTests static void ValidateSessionNotFound(const std::wstring& err, const std::wstring& name) { VERIFY_IS_TRUE(err.find(std::format(L"Session not found: '{}'", name)) != std::wstring::npos); +======= + const std::wstring nerr = NormalizeForCompare(err); + const std::wstring usage = NormalizeForCompare(GetUsageText()); + VERIFY_IS_TRUE(nerr.find(usage) != std::wstring::npos); +>>>>>>> ea162030 (Localize Wsladiag tests) } }; } // namespace WsladiagTests \ No newline at end of file From f3b8b06a2c4d192dcb4795f6f4e1df2cb460bd0a Mon Sep 17 00:00:00 2001 From: Beena352 Date: Fri, 16 Jan 2026 05:45:08 -0800 Subject: [PATCH 8/9] update tests --- src/shared/inc/CommandLine.h | 12 +- src/windows/wsladiag/wsladiag.cpp | 5 +- test/windows/WsladiagTests.cpp | 200 +++++++++++------------------- 3 files changed, 72 insertions(+), 145 deletions(-) diff --git a/src/shared/inc/CommandLine.h b/src/shared/inc/CommandLine.h index 1af2c1ee6..40aef627a 100644 --- a/src/shared/inc/CommandLine.h +++ b/src/shared/inc/CommandLine.h @@ -307,13 +307,9 @@ class ArgumentParser public: #ifdef WIN32 -<<<<<<< HEAD ArgumentParser(const std::wstring& CommandLine, LPCWSTR Name, int StartIndex = 1, bool ignoreUnknownArgs = false) : m_parseIndex(StartIndex), m_name(Name), m_ignoreUnknownArgs(ignoreUnknownArgs) -======= - ArgumentParser(const std::wstring& CommandLine, LPCWSTR Name, int StartIndex = 1, bool IgnoreUnknownArgs = false) : - m_startIndex(StartIndex), m_name(Name), m_ignoreUnknownArgs(IgnoreUnknownArgs) ->>>>>>> ea162030 (Localize Wsladiag tests) + { m_argv.reset(CommandLineToArgvW(std::wstring(CommandLine).c_str(), &m_argc)); THROW_LAST_ERROR_IF(!m_argv); @@ -321,13 +317,9 @@ class ArgumentParser #else -<<<<<<< HEAD ArgumentParser(int argc, const char* const* argv, bool ignoreUnknownArgs = false) : m_argc(argc), m_argv(argv), m_parseIndex(1), m_ignoreUnknownArgs(ignoreUnknownArgs) -======= - ArgumentParser(int argc, const char* const* argv, bool IgnoreUnknownArgs = false) : - m_argc(argc), m_argv(argv), m_startIndex(1), m_ignoreUnknownArgs(IgnoreUnknownArgs) ->>>>>>> ea162030 (Localize Wsladiag tests) + { } diff --git a/src/windows/wsladiag/wsladiag.cpp b/src/windows/wsladiag/wsladiag.cpp index 486d2b206..abe120cbc 100644 --- a/src/windows/wsladiag/wsladiag.cpp +++ b/src/windows/wsladiag/wsladiag.cpp @@ -65,11 +65,8 @@ static int ReportError(const std::wstring& context, HRESULT hr) return 1; } -<<<<<<< HEAD // Handler for `wsladiag shell ` command. -======= -// Handler for `wsladiag shell [--verbose]` command - launches TTY-backed interactive shell. ->>>>>>> ea162030 (Localize Wsladiag tests) + static int RunShellCommand(std::wstring_view commandLine) { std::wstring sessionName; diff --git a/test/windows/WsladiagTests.cpp b/test/windows/WsladiagTests.cpp index e25177caf..15b7c86db 100644 --- a/test/windows/WsladiagTests.cpp +++ b/test/windows/WsladiagTests.cpp @@ -22,202 +22,140 @@ class WsladiagTests { WSL_TEST_CLASS(WsladiagTests) -<<<<<<< HEAD - // Initialize the tests - TEST_CLASS_SETUP(TestClassSetup) - { - VERIFY_ARE_EQUAL(LxsstuInitialize(FALSE), TRUE); - return true; - } - - TEST_CLASS_CLEANUP(TestClassCleanup) - { - LxsstuUninitialize(FALSE); - return true; - } -======= // Use localized usage text at runtime static std::wstring GetUsageText() { return std::wstring(wsl::shared::Localization::MessageWsladiagUsage()); } ->>>>>>> ea162030 (Localize Wsladiag tests) - // Test that wsladiag list command shows either sessions or "no sessions" message - TEST_METHOD(List_ShowsSessionsOrNoSessions) + // Test that wsladiag list command "no sessions" message + TEST_METHOD(List_NoSessions) { - auto [out, err, code] = RunWsladiag(L"list"); - VERIFY_ARE_EQUAL(0, code); - VERIFY_ARE_EQUAL(L"", err); + auto [stdOut, stdErr, exitCode] = RunWsladiag(L"list"); - ValidateListOutput(out); + VERIFY_ARE_EQUAL(0, exitCode); + VERIFY_ARE_EQUAL(L"", stdErr); + VERIFY_ARE_EQUAL(std::wstring(wsl::shared::Localization::MessageWslaNoSessionsFound()) + L"\r\n", stdOut); } - // Test that wsladiag --help shows usage information - TEST_METHOD(Help_ShowsUsage) + TEST_METHOD(List_ShowsSessions) { -<<<<<<< HEAD - auto [out, err, code] = RunWsladiag(L"--help"); - VERIFY_ARE_EQUAL(0, code); - VERIFY_ARE_EQUAL(L"", out); - ValidateUsage(err); + auto [stdOut, stdErr, exitCode] = RunWsladiag(L"list"); + + VERIFY_ARE_EQUAL(0, exitCode); + VERIFY_ARE_EQUAL(L"", stdErr); -======= - ValidateWsladiagOutput(L"--help", 0, L"", GetUsageText()); ->>>>>>> ea162030 (Localize Wsladiag tests) + ValidateListShowsSessionTable(stdOut); } - // Test that wsladiag with no arguments shows usage information - TEST_METHOD(EmptyCommand_ShowsUsage) + // Test that wsladiag --help shows usage information + TEST_METHOD(Help_ShowsUsage) { -<<<<<<< HEAD - auto [out, err, code] = RunWsladiag(L""); - VERIFY_ARE_EQUAL(0, code); - VERIFY_ARE_EQUAL(L"", out); - ValidateUsage(err); -======= - ValidateWsladiagOutput(L"", 0, L"", GetUsageText()); ->>>>>>> ea162030 (Localize Wsladiag tests) + ValidateWsladiagOutput(L"--help", 0, L"", GetUsageText() + L"\r\n"); } - // Test that -h and --help flags produce identical output - TEST_METHOD(Help_ShortAndLongFlags_Match) + // Test that -h shows usage information + TEST_METHOD(Help_ShortFlag_ShowsUsage) { - auto [outH, errH, codeH] = RunWsladiag(L"-h"); - auto [outLong, errLong, codeLong] = RunWsladiag(L"--help"); - - VERIFY_ARE_EQUAL(0, codeH); - VERIFY_ARE_EQUAL(0, codeLong); - - VERIFY_ARE_EQUAL(L"", outH); - VERIFY_ARE_EQUAL(L"", outLong); + ValidateWsladiagOutput(L"-h", 0, L"", GetUsageText() + L"\r\n"); + } - VERIFY_ARE_EQUAL(errH, errLong); - ValidateUsage(errH); + // Test that wsladiag with no arguments shows usage information + TEST_METHOD(EmptyCommand_ShowsUsage) + { + ValidateWsladiagOutput(L"", 0, L"", GetUsageText() + L"\r\n"); } // Test that unknown commands show error message and usage - TEST_METHOD(UnknownCommand_ShowsUsage) + TEST_METHOD(UnknownCommand_ShowsError) { -<<<<<<< HEAD + const std::wstring verb = L"blah"; + const std::wstring errorMsg = std::wstring(wsl::shared::Localization::MessageWslaUnknownCommand(verb.c_str())); + const std::wstring usage = GetUsageText(); - auto [out, err, code] = RunWsladiag(L"blah"); - VERIFY_ARE_NOT_EQUAL(0, code); - VERIFY_ARE_EQUAL(L"", out); + auto [stdOut, stdErr, exitCode] = RunWsladiag(verb); - VERIFY_IS_TRUE(err.find(L"Unknown command: 'blah'") != std::wstring::npos); - ValidateUsage(err); + VERIFY_ARE_EQUAL(1, exitCode); + VERIFY_ARE_EQUAL(L"", stdOut); -======= - const std::wstring verb = L"blah"; - const std::wstring errorMsg = std::wstring(wsl::shared::Localization::MessageWslaUnknownCommand(verb.c_str())); - const std::wstring expected = errorMsg + GetUsageText(); - ValidateWsladiagOutput(verb, 1, L"", expected); ->>>>>>> ea162030 (Localize Wsladiag tests) + VERIFY_IS_TRUE(stdErr.find(errorMsg) != std::wstring::npos); + VERIFY_IS_TRUE(stdErr.find(usage) != std::wstring::npos); } - // Test that shell command without session name shows usage - TEST_METHOD(Shell_MissingName_ShowsUsage) + // Test that shell command without session name shows error + TEST_METHOD(Shell_MissingName_ShowsError) { auto [out, err, code] = RunWsladiag(L"shell"); -<<<<<<< HEAD - VERIFY_ARE_NOT_EQUAL(0, code); - VERIFY_ARE_EQUAL(L"", out); - ValidateUsage(err); - -======= VERIFY_ARE_EQUAL(1, code); VERIFY_ARE_EQUAL(L"", out); + const std::wstring missingArgMsg = std::wstring(wsl::shared::Localization::MessageMissingArgument(L"", L"wsladiag shell")); - VERIFY_IS_TRUE(NormalizeForCompare(err).find(NormalizeForCompare(missingArgMsg)) != std::wstring::npos); ->>>>>>> ea162030 (Localize Wsladiag tests) + VERIFY_IS_TRUE(err.find(missingArgMsg) != std::wstring::npos); } - // Test shell command with invalid session name (silent mode) - TEST_METHOD(Shell_InvalidSessionName_Silent) + // Test shell command with invalid session name (non verbose mode) + TEST_METHOD(Shell_InvalidSessionName_NonVerbose) { -<<<<<<< HEAD const std::wstring name = L"DefinitelyNotARealSession"; - auto [out, err, code] = RunWsladiag(std::format(L"shell {}", name)); - VERIFY_ARE_NOT_EQUAL(0, code); - VERIFY_ARE_EQUAL(L"", out); + auto [stdOut, stdErr, exitCode] = RunWsladiag(L"shell " + name); + + VERIFY_ARE_EQUAL(1, exitCode); + VERIFY_ARE_EQUAL(L"", stdOut); - ValidateSessionNotFound(err, name); -======= - const auto expectedErr = - std::wstring(wsl::shared::Localization::MessageWslaSessionNotFound(L"DefinitelyNotARealSession")); - ValidateWsladiagOutput(L"shell DefinitelyNotARealSession", 1, L"", expectedErr); ->>>>>>> ea162030 (Localize Wsladiag tests) + const auto expected = std::wstring(wsl::shared::Localization::MessageWslaSessionNotFound(name.c_str())); + VERIFY_IS_TRUE(stdErr.find(expected) != std::wstring::npos); } // Test shell command with invalid session name (verbose mode) TEST_METHOD(Shell_InvalidSessionName_Verbose) { const std::wstring name = L"DefinitelyNotARealSession"; -<<<<<<< HEAD - auto [out, err, code] = RunWsladiag(std::format(L"shell {} --verbose", name)); - VERIFY_ARE_NOT_EQUAL(0, code); - - VERIFY_IS_TRUE(out.find(std::format(L"[diag] shell='{}'", name)) != std::wstring::npos); - ValidateSessionNotFound(err, name); -======= - const auto expectedErr = std::wstring(wsl::shared::Localization::MessageWslaSessionNotFound(name.c_str())); - ValidateWsladiagOutput(std::format(L"shell {} --verbose", name), 1, L"", expectedErr); ->>>>>>> ea162030 (Localize Wsladiag tests) - } + auto [stdOut, stdErr, exitCode] = RunWsladiag(std::format(L"shell {} --verbose", name)); - // Build command line for wsladiag.exe with given arguments - static std::wstring BuildWsladiagCmd(const std::wstring& args) - { - const auto msiPathOpt = wsl::windows::common::wslutil::GetMsiPackagePath(); - VERIFY_IS_TRUE(msiPathOpt.has_value()); - - const auto exePath = std::filesystem::path(*msiPathOpt) / L"wsladiag.exe"; - const auto exe = exePath.wstring(); + VERIFY_ARE_EQUAL(1, exitCode); + VERIFY_ARE_EQUAL(L"", stdOut); - return args.empty() ? std::format(L"\"{}\"", exe) : std::format(L"\"{}\" {}", exe, args); + const auto expected = std::wstring(wsl::shared::Localization::MessageWslaSessionNotFound(name.c_str())); + VERIFY_IS_TRUE(stdErr.find(expected) != std::wstring::npos); } // Execute wsladiag with given arguments and return output, error, and exit code static std::tuple RunWsladiag(const std::wstring& args) { - std::wstring cmd = BuildWsladiagCmd(args); - return LxsstuLaunchCommandAndCaptureOutputWithResult(cmd.data()); + std::wstring commandLine = BuildWsladiagCmd(args); + return LxsstuLaunchCommandAndCaptureOutputWithResult(commandLine.data()); } - // Validate that list command output shows either no sessions message or session table - static void ValidateListOutput(const std::wstring& out) + // Validate that list command output shows a session table + static void ValidateListShowsSessionTable(const std::wstring& out) { - const bool noSessions = out.find(std::wstring(wsl::shared::Localization::MessageWslaNoSessionsFound())) != std::wstring::npos; const auto idHeader = std::wstring(wsl::shared::Localization::MessageWslaHeaderId()); const auto pidHeader = std::wstring(wsl::shared::Localization::MessageWslaHeaderCreatorPid()); const auto nameHeader = std::wstring(wsl::shared::Localization::MessageWslaHeaderDisplayName()); - const bool hasTable = (out.find(idHeader) != std::wstring::npos) && (out.find(pidHeader) != std::wstring::npos) && - (out.find(nameHeader) != std::wstring::npos); - - VERIFY_IS_TRUE(noSessions || hasTable); + VERIFY_IS_TRUE(out.find(idHeader) != std::wstring::npos); + VERIFY_IS_TRUE(out.find(pidHeader) != std::wstring::npos); + VERIFY_IS_TRUE(out.find(nameHeader) != std::wstring::npos); } - // Validate that usage information contains expected command descriptions - static void ValidateUsage(const std::wstring& err) + static std::wstring BuildWsladiagCmd(const std::wstring& args) { -<<<<<<< HEAD - VERIFY_IS_TRUE(err.find(L"Usage:") != std::wstring::npos); - VERIFY_IS_TRUE(err.find(L"wsladiag list") != std::wstring::npos); - VERIFY_IS_TRUE(err.find(L"wsladiag shell [--verbose]") != std::wstring::npos); + const auto installPath = wsl::windows::common::wslutil::GetMsiPackagePath(); + VERIFY_IS_TRUE(installPath.has_value()); + + const auto exePath = std::filesystem::path(*installPath) / L"wsladiag.exe"; + const auto exe = exePath.wstring(); + + return args.empty() ? std::format(L"\"{}\"", exe) : std::format(L"\"{}\" {}", exe, args); } - // Validate that session not found error contains the expected session name - static void ValidateSessionNotFound(const std::wstring& err, const std::wstring& name) + static void ValidateWsladiagOutput(const std::wstring& args, int expectedExitCode, const std::wstring& expectedStdout, const std::wstring& expectedStderr) { - VERIFY_IS_TRUE(err.find(std::format(L"Session not found: '{}'", name)) != std::wstring::npos); -======= - const std::wstring nerr = NormalizeForCompare(err); - const std::wstring usage = NormalizeForCompare(GetUsageText()); - VERIFY_IS_TRUE(nerr.find(usage) != std::wstring::npos); ->>>>>>> ea162030 (Localize Wsladiag tests) + auto [stdOut, stdErr, exitCode] = RunWsladiag(args); + VERIFY_ARE_EQUAL(expectedExitCode, exitCode); + VERIFY_ARE_EQUAL(expectedStdout, stdOut); + VERIFY_ARE_EQUAL(expectedStderr, stdErr); } }; } // namespace WsladiagTests \ No newline at end of file From dc5b0b374f3d656ea33e0c24746502be1d787cb1 Mon Sep 17 00:00:00 2001 From: Beena352 Date: Tue, 20 Jan 2026 12:55:03 -0800 Subject: [PATCH 9/9] update tests --- test/windows/WsladiagTests.cpp | 127 +++++++++++++++++++-------------- 1 file changed, 75 insertions(+), 52 deletions(-) diff --git a/test/windows/WsladiagTests.cpp b/test/windows/WsladiagTests.cpp index 15b7c86db..cf5c89096 100644 --- a/test/windows/WsladiagTests.cpp +++ b/test/windows/WsladiagTests.cpp @@ -15,17 +15,65 @@ Module Name: #include "precomp.h" #include "Common.h" #include "Localization.h" + #include +#include namespace WsladiagTests { class WsladiagTests { WSL_TEST_CLASS(WsladiagTests) - // Use localized usage text at runtime + // Add CRLFs for exact-string comparisons + static std::wstring AddCrlf(const std::wstring& input) + { + std::wstring messageWithCrlf; + + for (const auto ch : input) + { + if (ch == L'\n') + { + messageWithCrlf += L'\r'; + } + messageWithCrlf += ch; + } + + return messageWithCrlf; + } + static std::wstring GetUsageText() { - return std::wstring(wsl::shared::Localization::MessageWsladiagUsage()); + auto usage = AddCrlf(std::wstring(wsl::shared::Localization::MessageWsladiagUsage())); + if (usage.empty() || usage.back() != L'\n') + { + usage += L"\r\n"; + } + return usage; + } + + static std::wstring BuildWsladiagCmd(const std::wstring& args) + { + const auto installPath = wsl::windows::common::wslutil::GetMsiPackagePath(); + VERIFY_IS_TRUE(installPath.has_value()); + + const auto exePath = std::filesystem::path(*installPath) / L"wsladiag.exe"; + const auto exe = exePath.wstring(); + + return args.empty() ? std::format(L"\"{}\"", exe) : std::format(L"\"{}\" {}", exe, args); + } + // Execute wsladiag with given arguments and return output, error, and exit code + static std::tuple RunWsladiag(const std::wstring& args) + { + std::wstring commandLine = BuildWsladiagCmd(args); + return LxsstuLaunchCommandAndCaptureOutputWithResult(commandLine.data()); + } + + static void ValidateWsladiagOutput(const std::wstring& args, int expectedExitCode, const std::wstring& expectedStdout, const std::wstring& expectedStderr) + { + auto [stdOut, stdErr, exitCode] = RunWsladiag(args); + VERIFY_ARE_EQUAL(expectedExitCode, exitCode); + VERIFY_ARE_EQUAL(expectedStdout, stdOut); + VERIFY_ARE_EQUAL(expectedStderr, stdErr); } // Test that wsladiag list command "no sessions" message @@ -45,25 +93,34 @@ class WsladiagTests VERIFY_ARE_EQUAL(0, exitCode); VERIFY_ARE_EQUAL(L"", stdErr); - ValidateListShowsSessionTable(stdOut); + const std::wstring noSessions = std::wstring(wsl::shared::Localization::MessageWslaNoSessionsFound()) + L"\r\n"; + + if (stdOut == noSessions) + { + return; + } + + VERIFY_IS_TRUE(stdOut.find(L"ID") != std::wstring::npos); + VERIFY_IS_TRUE(stdOut.find(L"Creator PID") != std::wstring::npos); + VERIFY_IS_TRUE(stdOut.find(L"Display Name") != std::wstring::npos); } // Test that wsladiag --help shows usage information TEST_METHOD(Help_ShowsUsage) { - ValidateWsladiagOutput(L"--help", 0, L"", GetUsageText() + L"\r\n"); + ValidateWsladiagOutput(L"--help", 0, L"", GetUsageText()); } // Test that -h shows usage information TEST_METHOD(Help_ShortFlag_ShowsUsage) { - ValidateWsladiagOutput(L"-h", 0, L"", GetUsageText() + L"\r\n"); + ValidateWsladiagOutput(L"-h", 0, L"", GetUsageText()); } // Test that wsladiag with no arguments shows usage information TEST_METHOD(EmptyCommand_ShowsUsage) { - ValidateWsladiagOutput(L"", 0, L"", GetUsageText() + L"\r\n"); + ValidateWsladiagOutput(L"", 0, L"", GetUsageText()); } // Test that unknown commands show error message and usage @@ -78,20 +135,24 @@ class WsladiagTests VERIFY_ARE_EQUAL(1, exitCode); VERIFY_ARE_EQUAL(L"", stdOut); - VERIFY_IS_TRUE(stdErr.find(errorMsg) != std::wstring::npos); - VERIFY_IS_TRUE(stdErr.find(usage) != std::wstring::npos); + const std::wstring expected = errorMsg + L"\r\n" + usage; + VERIFY_ARE_EQUAL(expected, stdErr); } // Test that shell command without session name shows error TEST_METHOD(Shell_MissingName_ShowsError) { - auto [out, err, code] = RunWsladiag(L"shell"); - VERIFY_ARE_EQUAL(1, code); - VERIFY_ARE_EQUAL(L"", out); + auto [stdOut, stdErr, exitCode] = RunWsladiag(L"shell"); - const std::wstring missingArgMsg = - std::wstring(wsl::shared::Localization::MessageMissingArgument(L"", L"wsladiag shell")); - VERIFY_IS_TRUE(err.find(missingArgMsg) != std::wstring::npos); + VERIFY_ARE_EQUAL(1, exitCode); + VERIFY_ARE_EQUAL(L"", stdOut); + + const std::wstring errorLine = L"Command line argument requires a value."; + const std::wstring helpHint = L"Please use 'wsladiag shell --help' to get a list of supported arguments."; + const std::wstring errorCode = L"Error code: E_INVALIDARG"; + + const std::wstring expected = errorLine + L"\r\n" + helpHint + L"\r\n" + errorCode + L"\r\n"; + VERIFY_ARE_EQUAL(expected, stdErr); } // Test shell command with invalid session name (non verbose mode) @@ -119,43 +180,5 @@ class WsladiagTests const auto expected = std::wstring(wsl::shared::Localization::MessageWslaSessionNotFound(name.c_str())); VERIFY_IS_TRUE(stdErr.find(expected) != std::wstring::npos); } - - // Execute wsladiag with given arguments and return output, error, and exit code - static std::tuple RunWsladiag(const std::wstring& args) - { - std::wstring commandLine = BuildWsladiagCmd(args); - return LxsstuLaunchCommandAndCaptureOutputWithResult(commandLine.data()); - } - - // Validate that list command output shows a session table - static void ValidateListShowsSessionTable(const std::wstring& out) - { - const auto idHeader = std::wstring(wsl::shared::Localization::MessageWslaHeaderId()); - const auto pidHeader = std::wstring(wsl::shared::Localization::MessageWslaHeaderCreatorPid()); - const auto nameHeader = std::wstring(wsl::shared::Localization::MessageWslaHeaderDisplayName()); - - VERIFY_IS_TRUE(out.find(idHeader) != std::wstring::npos); - VERIFY_IS_TRUE(out.find(pidHeader) != std::wstring::npos); - VERIFY_IS_TRUE(out.find(nameHeader) != std::wstring::npos); - } - - static std::wstring BuildWsladiagCmd(const std::wstring& args) - { - const auto installPath = wsl::windows::common::wslutil::GetMsiPackagePath(); - VERIFY_IS_TRUE(installPath.has_value()); - - const auto exePath = std::filesystem::path(*installPath) / L"wsladiag.exe"; - const auto exe = exePath.wstring(); - - return args.empty() ? std::format(L"\"{}\"", exe) : std::format(L"\"{}\" {}", exe, args); - } - - static void ValidateWsladiagOutput(const std::wstring& args, int expectedExitCode, const std::wstring& expectedStdout, const std::wstring& expectedStderr) - { - auto [stdOut, stdErr, exitCode] = RunWsladiag(args); - VERIFY_ARE_EQUAL(expectedExitCode, exitCode); - VERIFY_ARE_EQUAL(expectedStdout, stdOut); - VERIFY_ARE_EQUAL(expectedStderr, stdErr); - } }; } // namespace WsladiagTests \ No newline at end of file