Add github issue suggestion in user visible error (#41432)
This PR adds a "search or file issue on github" suggestion in all user visible errors to: Help users find solutions faster. Collect more user reported issues to help reliability improvements. This PR also updates all tests checking the error message to use a unified function for creating the expected error message.
Feng Wang committed
Aug 26, 2026 at 11:05 UTC
00df65ad829adcdcbe0cb82af5179f67f6234464
27 files changed
+368
-273
localization/strings/en-US/Resources.resw
+3
-2
@@ -1169,8 +1169,9 @@ This prompt will time out in 60 seconds.</value>
1169
</data>
1170
<data name="MessageErrorCode" xml:space="preserve">
1171
<value>{}
1172
-Error code: {}</value>
1173
- <comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
1172
+Error code: {}
1173
+If this error was unexpected, please consider searching for existing issues or filing a new issue at https://github.com/microsoft/WSL/issues.</value>
1174
+ <comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated{Locked="https://github.com/microsoft/WSL/issues"}</comment>
1175
</data>
1176
<data name="MessageInvalidJson" xml:space="preserve">
1177
<value>Invalid JSON document. Parse error: {}</value>
test/windows/Common.cpp
+10
@@ -3149,3 +3149,13 @@ void ValidateCOMErrorMessageContains(const std::wstring& ExpectedSubstring)
3149
VERIFY_FAIL();
3150
}
3151
}
3152
+
3153
+std::wstring FormatErrorMessage(std::wstring_view message, std::wstring_view errorCode)
3154
+{
3155
+ return std::format(
3156
+ L"{}\r\nError code: {}\r\n"
3157
+ L"If this error was unexpected, please consider searching for existing issues or filing a new issue at "
3158
+ L"https://github.com/microsoft/WSL/issues.\r\n",
3159
+ message,
3160
+ errorCode);
3161
+}
test/windows/Common.h
+2
@@ -723,3 +723,5 @@ void WriteSocket(SOCKET Socket, const void* data, size_t size);
723
void ValidateCOMErrorMessage(const std::optional<std::wstring>& Expected, const std::source_location& Source = std::source_location::current());
724
725
void ValidateCOMErrorMessageContains(const std::wstring& ExpectedSubstring);
726
+
727
+std::wstring FormatErrorMessage(std::wstring_view message, std::wstring_view errorCode);
test/windows/InstallerTests.cpp
+4
-4
@@ -721,10 +721,10 @@ class InstallerTests
721
// Validate that calling wsl.exe triggers the install.
722
auto [output, warnings] = LxsstuLaunchWslAndCaptureOutput(L"echo ok", -1, nulDevice.get());
723
VERIFY_ARE_EQUAL(
724
- L"\r\nAnother application has exclusive access to the file 'C:\\Program Files\\WSL\\wsl.exe'. Please shut down all "
725
- L"other applications, then click Retry.\r\n"
726
- L"Update failed (exit code: 1603).\r\n"
727
- L"Error code: Wsl/CallMsi/Install/ERROR_INSTALL_FAILURE\r\n",
724
+ FormatErrorMessage(
725
+ L"\r\nAnother application has exclusive access to the file 'C:\\Program Files\\WSL\\wsl.exe'. Please shut "
726
+ L"down all other applications, then click Retry.\r\nUpdate failed (exit code: 1603).",
727
+ L"Wsl/CallMsi/Install/ERROR_INSTALL_FAILURE"),
728
output);
729
}
730
test/windows/MountTests.cpp
+3
-2
@@ -353,8 +353,9 @@ class MountTests
353
const auto [output, error] = LxsstuLaunchWslAndCaptureOutput(mountCommand, -1);
354
VERIFY_ARE_EQUAL(
355
output,
356
- L"The mount name cannot be empty, '.', '..', or contain '/'. Please retry with a valid mount name.\r\n"
357
- L"Error code: Wsl/Service/MountDisk/WSL_E_VM_MODE_INVALID_MOUNT_NAME\r\n",
356
+ FormatErrorMessage(
357
+ L"The mount name cannot be empty, '.', '..', or contain '/'. Please retry with a valid mount name.",
358
+ L"Wsl/Service/MountDisk/WSL_E_VM_MODE_INVALID_MOUNT_NAME"),
359
name);
360
VERIFY_ARE_EQUAL(error, L"", name);
361
}
test/windows/PluginTests.cpp
+31
-26
@@ -109,7 +109,7 @@ class PluginTests
109
RestartWslService();
110
}
111
112
- static void StartWsl(int expectedExitCode, LPCWSTR ExpectedOutput = nullptr)
112
+ static void StartWsl(int expectedExitCode, const std::wstring& expectedOutput = {})
113
{
114
auto [output, error] = LxsstuLaunchWslAndCaptureOutput(L"echo -n OK", expectedExitCode);
115
if (expectedExitCode == 0)
@@ -118,7 +118,7 @@ class PluginTests
118
}
119
else
120
{
121
- VERIFY_ARE_EQUAL(output, ExpectedOutput);
121
+ VERIFY_ARE_EQUAL(output, expectedOutput);
122
}
123
}
124
@@ -299,8 +299,9 @@ class PluginTests
299
ConfigurePlugin(PluginTestType::Success);
300
StartWsl(
301
-1,
302
- L"A fatal error was returned by plugin 'TestPlugin'\r\nError code: "
303
- L"Wsl/Service/CreateInstance/CreateVm/Plugin/E_ACCESSDENIED\r\n");
302
+ FormatErrorMessage(
303
+ L"A fatal error was returned by plugin 'TestPlugin'",
304
+ L"Wsl/Service/CreateInstance/CreateVm/Plugin/E_ACCESSDENIED"));
305
306
ValidateLogFile(ExpectedOutput);
307
}
@@ -374,8 +375,9 @@ class PluginTests
375
ConfigurePlugin(PluginTestType::PluginRequiresUpdate);
376
StartWsl(
377
-1,
377
- L"The plugin 'TestPlugin' requires a newer version of WSL. Please run: wsl.exe --update\r\nError code: "
378
- L"Wsl/Service/CreateInstance/CreateVm/Plugin/WSL_E_PLUGIN_REQUIRES_UPDATE\r\n");
378
+ FormatErrorMessage(
379
+ L"The plugin 'TestPlugin' requires a newer version of WSL. Please run: wsl.exe --update",
380
+ L"Wsl/Service/CreateInstance/CreateVm/Plugin/WSL_E_PLUGIN_REQUIRES_UPDATE"));
381
382
ValidateLogFile(ExpectedOutput);
383
}
@@ -413,8 +415,8 @@ class PluginTests
415
ConfigurePlugin(PluginTestType::FailToLoad);
416
StartWsl(
417
-1,
416
- L"A fatal error was returned by plugin 'TestPlugin'\r\nError code: "
417
- L"Wsl/Service/CreateInstance/CreateVm/Plugin/E_UNEXPECTED\r\n");
418
+ FormatErrorMessage(
419
+ L"A fatal error was returned by plugin 'TestPlugin'", L"Wsl/Service/CreateInstance/CreateVm/Plugin/E_UNEXPECTED"));
420
ValidateLogFile(ExpectedOutput);
421
}
422
@@ -440,8 +442,8 @@ class PluginTests
442
ConfigurePlugin(PluginTestType::FailToStartVm);
443
StartWsl(
444
-1,
443
- L"A fatal error was returned by plugin 'TestPlugin'\r\nError code: "
444
- L"Wsl/Service/CreateInstance/CreateVm/Plugin/E_UNEXPECTED\r\n");
445
+ FormatErrorMessage(
446
+ L"A fatal error was returned by plugin 'TestPlugin'", L"Wsl/Service/CreateInstance/CreateVm/Plugin/E_UNEXPECTED"));
447
ValidateLogFile(ExpectedOutput);
448
}
449
@@ -460,13 +462,15 @@ class PluginTests
462
463
StartWsl(
464
-1,
463
- L"A fatal error was returned by plugin 'TestPlugin'. Error message: 'Plugin error message'\r\nError code: "
464
- L"Wsl/Service/CreateInstance/CreateVm/Plugin/E_UNEXPECTED\r\n");
465
+ FormatErrorMessage(
466
+ L"A fatal error was returned by plugin 'TestPlugin'. Error message: 'Plugin error message'",
467
+ L"Wsl/Service/CreateInstance/CreateVm/Plugin/E_UNEXPECTED"));
468
469
StartWsl(
470
-1,
468
- L"A fatal error was returned by plugin 'TestPlugin'. Error message: 'Plugin error message'\r\nError code: "
469
- L"Wsl/Service/CreateInstance/CreateVm/Plugin/E_UNEXPECTED\r\n");
471
+ FormatErrorMessage(
472
+ L"A fatal error was returned by plugin 'TestPlugin'. Error message: 'Plugin error message'",
473
+ L"Wsl/Service/CreateInstance/CreateVm/Plugin/E_UNEXPECTED"));
474
475
ValidateLogFile(ExpectedOutput);
476
}
@@ -495,12 +499,11 @@ class PluginTests
499
OnDistroStarted: E_UNEXPECTED
500
VM Stopping)";
501
498
- constexpr auto ExpectedError =
499
- L"A fatal error was returned by plugin 'TestPlugin'\r\nError code: "
500
- L"Wsl/Service/CreateInstance/Plugin/E_UNEXPECTED\r\n";
501
-
502
ConfigurePlugin(PluginTestType::FailToStartDistro);
503
- StartWsl(-1, ExpectedError);
503
+ StartWsl(
504
+ -1,
505
+ FormatErrorMessage(
506
+ L"A fatal error was returned by plugin 'TestPlugin'", L"Wsl/Service/CreateInstance/Plugin/E_UNEXPECTED"));
507
ValidateLogFile(ExpectedOutput);
508
}
509
@@ -530,8 +533,9 @@ class PluginTests
533
ConfigurePlugin(PluginTestType::ErrorMessageStartVm);
534
StartWsl(
535
-1,
533
- L"A fatal error was returned by plugin 'TestPlugin'. Error message: 'StartVm plugin error message'\r\nError code: "
534
- L"Wsl/Service/CreateInstance/CreateVm/Plugin/E_FAIL\r\n");
536
+ FormatErrorMessage(
537
+ L"A fatal error was returned by plugin 'TestPlugin'. Error message: 'StartVm plugin error message'",
538
+ L"Wsl/Service/CreateInstance/CreateVm/Plugin/E_FAIL"));
539
540
ValidateLogFile(ExpectedOutput);
541
}
@@ -548,9 +552,9 @@ class PluginTests
552
ConfigurePlugin(PluginTestType::ErrorMessageStartDistro);
553
StartWsl(
554
-1,
551
- L"A fatal error was returned by plugin 'TestPlugin'. Error message: 'StartDistro plugin error message'\r\nError "
552
- L"code: "
553
- L"Wsl/Service/CreateInstance/Plugin/E_FAIL\r\n");
555
+ FormatErrorMessage(
556
+ L"A fatal error was returned by plugin 'TestPlugin'. Error message: 'StartDistro plugin error message'",
557
+ L"Wsl/Service/CreateInstance/Plugin/E_FAIL"));
558
559
ValidateLogFile(ExpectedOutput);
560
}
@@ -1006,7 +1010,8 @@ class PluginTests
1010
ConfigurePlugin(PluginTestType::ErrorMessageStartDistro);
1011
StartWsl(
1012
-1,
1009
- L"A fatal error was returned by plugin 'TestPlugin'\r\nError code: "
1010
- L"Wsl/Service/CreateInstance/CreateVm/Plugin/TRUST_E_NOSIGNATURE\r\n");
1013
+ FormatErrorMessage(
1014
+ L"A fatal error was returned by plugin 'TestPlugin'",
1015
+ L"Wsl/Service/CreateInstance/CreateVm/Plugin/TRUST_E_NOSIGNATURE"));
1016
}
1017
};
test/windows/PolicyTests.cpp
+23
-19
@@ -110,8 +110,9 @@ class PolicyTest
110
auto revert = SetPolicy(c_allowDiskMount, 1);
111
ValidateOutput(
112
L"--mount DoesNotExist",
113
- L"Failed to attach disk 'DoesNotExist' to WSL2: The system cannot find the file specified. \r\n"
114
- L"Error code: Wsl/Service/AttachDisk/MountDisk/HCS/ERROR_FILE_NOT_FOUND\r\n");
113
+ FormatErrorMessage(
114
+ L"Failed to attach disk 'DoesNotExist' to WSL2: The system cannot find the file specified. ",
115
+ L"Wsl/Service/AttachDisk/MountDisk/HCS/ERROR_FILE_NOT_FOUND"));
116
}
117
118
WSL2_TEST_METHOD(MountPolicyDisabled)
@@ -120,7 +121,7 @@ class PolicyTest
121
auto revert = SetPolicy(c_allowDiskMount, 0);
122
ValidateOutput(
123
L"--mount DoesNotExist",
123
- L"wsl.exe --mount is disabled by the computer policy.\r\nError code: Wsl/Service/WSL_E_DISK_MOUNT_DISABLED\r\n");
124
+ FormatErrorMessage(L"wsl.exe --mount is disabled by the computer policy.", L"Wsl/Service/WSL_E_DISK_MOUNT_DISABLED"));
125
}
126
127
void ValidatePolicy(LPCWSTR Name, LPCWSTR Config, LPCWSTR ExpectedWarnings, const std::function<void(DWORD)>& Validate = [](auto) {})
@@ -210,9 +211,9 @@ class PolicyTest
211
212
ValidateOutput(
213
L"echo ok",
213
- std::format(
214
- L"{}\r\nError code: Wsl/Service/CreateInstance/CreateVm/WSL_E_CUSTOM_KERNEL_NOT_FOUND\r\n",
215
- wsl::shared::Localization::MessageCustomKernelNotFound(wslConfigPath, nonExistentFile)));
214
+ FormatErrorMessage(
215
+ wsl::shared::Localization::MessageCustomKernelNotFound(wslConfigPath, nonExistentFile),
216
+ L"Wsl/Service/CreateInstance/CreateVm/WSL_E_CUSTOM_KERNEL_NOT_FOUND"));
217
}
218
219
// Disable the custom kernel policy and validate that the expected warnings are shown.
@@ -246,9 +247,9 @@ class PolicyTest
247
248
ValidateOutput(
249
L"echo ok",
249
- L"The custom system distribution specified in " + wslConfigPath +
250
- L" was not found or is not the correct format.\r\nError code: "
251
- L"Wsl/Service/CreateInstance/CreateVm/WSL_E_CUSTOM_SYSTEM_DISTRO_ERROR\r\n");
250
+ FormatErrorMessage(
251
+ L"The custom system distribution specified in " + wslConfigPath + L" was not found or is not the correct format.",
252
+ L"Wsl/Service/CreateInstance/CreateVm/WSL_E_CUSTOM_SYSTEM_DISTRO_ERROR"));
253
}
254
255
{
@@ -321,13 +322,16 @@ class PolicyTest
322
{
323
ValidateOutput(
324
L"--set-version " LXSS_DISTRO_NAME_TEST_L L" 1",
324
- L"WSL1 is disabled by the computer policy.\r\nError code: Wsl/Service/WSL_E_WSL1_DISABLED\r\n");
325
+ FormatErrorMessage(L"WSL1 is disabled by the computer policy.", L"Wsl/Service/WSL_E_WSL1_DISABLED"));
326
}
327
else
328
{
329
ValidateOutput(
329
- L"echo ok",
330
- L"WSL1 is disabled by the computer policy.\r\nPlease run 'wsl.exe --set-version " LXSS_DISTRO_NAME_TEST_L L" 2' to upgrade to WSL2.\r\nError code: Wsl/Service/CreateInstance/WSL_E_WSL1_DISABLED\r\n");
330
+ L"echo ok",
331
+ FormatErrorMessage(
332
+ L"WSL1 is disabled by the computer policy.\r\nPlease run 'wsl.exe "
333
+ L"--set-version " LXSS_DISTRO_NAME_TEST_L L" 2' to upgrade to WSL2.",
334
+ L"Wsl/Service/CreateInstance/WSL_E_WSL1_DISABLED"));
335
}
336
}
337
}
@@ -361,9 +365,9 @@ class PolicyTest
365
auto [output, _] = LxsstuLaunchWslAndCaptureOutput(L"/bin/true", -1);
366
VERIFY_ARE_EQUAL(
367
output,
364
- L"This program is blocked by group policy. For more information, contact your system administrator. "
365
- L"\r\nError "
366
- L"code: Wsl/ERROR_ACCESS_DISABLED_BY_POLICY\r\n");
368
+ FormatErrorMessage(
369
+ L"This program is blocked by group policy. For more information, contact your system administrator. ",
370
+ L"Wsl/ERROR_ACCESS_DISABLED_BY_POLICY"));
371
}
372
};
373
@@ -456,10 +460,10 @@ class PolicyTest
460
// The disabled message must go to stderr only -- never to stdout.
461
VERIFY_ARE_EQUAL(L"", stdoutText);
462
459
- // The wslc CLI renders failures via MessageErrorCode("{}\nError code: {}") and
463
+ // The wslc CLI renders failures via MessageErrorCode and
464
// PrintMessage adds a trailing newline; line endings are \r\n through console pipes.
465
const auto expected =
462
- wsl::shared::Localization::MessageWSLContainerDisabled() + L"\r\nError code: WSLC_E_CONTAINER_DISABLED\r\n";
466
+ FormatErrorMessage(wsl::shared::Localization::MessageWSLContainerDisabled(), L"WSLC_E_CONTAINER_DISABLED");
467
VERIFY_ARE_EQUAL(expected, stderrText);
468
}
469
@@ -476,8 +480,8 @@ class PolicyTest
480
VERIFY_ARE_NOT_EQUAL(0, exitCode);
481
VERIFY_ARE_EQUAL(L"", stdoutText);
482
479
- const auto expected = wsl::shared::Localization::MessageRegistryBlockedByPolicy(L"docker.io") +
480
- L"\r\nError code: WSLC_E_REGISTRY_BLOCKED_BY_POLICY\r\n";
483
+ const auto expected = FormatErrorMessage(
484
+ wsl::shared::Localization::MessageRegistryBlockedByPolicy(L"docker.io"), L"WSLC_E_REGISTRY_BLOCKED_BY_POLICY");
485
VERIFY_ARE_EQUAL(expected, stderrText);
486
}
487
test/windows/SimpleTests.cpp
+5
-3
@@ -119,9 +119,11 @@ class SimpleTests
119
// Setting a distro VHD to sparse requires the allow unsafe flag.
120
ValidateOutput(
121
std::format(L"{} {} {} {}", WSL_MANAGE_ARG, tempDistro, WSL_MANAGE_ARG_SET_SPARSE_OPTION_LONG, L"true").c_str(),
122
- L"Sparse VHD support is currently disabled due to potential data corruption.\r\n"
123
- L"To force a distribution to use a sparse VHD, please run:\r\n"
124
- L"wsl.exe --manage <DistributionName> --set-sparse true --allow-unsafe\r\nError code: Wsl/Service/E_INVALIDARG\r\n",
122
+ FormatErrorMessage(
123
+ L"Sparse VHD support is currently disabled due to potential data corruption.\r\n"
124
+ L"To force a distribution to use a sparse VHD, please run:\r\n"
125
+ L"wsl.exe --manage <DistributionName> --set-sparse true --allow-unsafe",
126
+ L"Wsl/Service/E_INVALIDARG"),
127
L"",
128
-1);
129
test/windows/UnitTests.cpp
+140
-124
@@ -166,7 +166,8 @@ class UnitTests
166
auto [out, err] =
167
LxsstuLaunchWslAndCaptureOutput(std::format(L"--export {} {} --format vhd", LXSS_DISTRO_NAME_TEST_L, vhdPath), -1);
168
169
- VERIFY_ARE_EQUAL(out, L"This operation is only supported by WSL2.\r\nError code: Wsl/Service/WSL_E_WSL2_NEEDED\r\n");
169
+ VERIFY_ARE_EQUAL(
170
+ out, FormatErrorMessage(L"This operation is only supported by WSL2.", L"Wsl/Service/WSL_E_WSL2_NEEDED"));
171
VERIFY_ARE_EQUAL(err, L"");
172
}
173
@@ -1195,17 +1196,14 @@ class UnitTests
1196
{
1197
validateOutput(
1198
commandLine.c_str(),
1198
- std::format(
1199
- L"Failed to create disk '{}ext4.vhdx': The file exists. \r\n"
1200
- L"Error code: Wsl/Service/RegisterDistro/ERROR_FILE_EXISTS\r\n",
1201
- LXSST_IMPORT_DISTRO_TEST_DIR));
1199
+ FormatErrorMessage(
1200
+ std::format(L"Failed to create disk '{}ext4.vhdx': The file exists. ", LXSST_IMPORT_DISTRO_TEST_DIR),
1201
+ L"Wsl/Service/RegisterDistro/ERROR_FILE_EXISTS"));
1202
}
1203
else
1204
{
1205
validateOutput(
1206
- commandLine.c_str(),
1207
- L"The file exists. \r\n"
1208
- L"Error code: Wsl/Service/RegisterDistro/ERROR_FILE_EXISTS\r\n");
1206
+ commandLine.c_str(), FormatErrorMessage(L"The file exists. ", L"Wsl/Service/RegisterDistro/ERROR_FILE_EXISTS"));
1207
}
1208
1209
commandLine = std::format(L"--import dummy {} {} --version {}", LXSST_IMPORT_DISTRO_TEST_DIR, vhdFileName, version);
@@ -1216,8 +1214,7 @@ class UnitTests
1214
commandLine = std::format(L"--import dummy {} {} --vhd --version 1", LXSST_IMPORT_DISTRO_TEST_DIR, vhdFileName);
1215
validateOutput(
1216
commandLine.c_str(),
1219
- L"This operation is only supported by WSL2.\r\n"
1220
- L"Error code: Wsl/Service/RegisterDistro/WSL_E_WSL2_NEEDED\r\n");
1217
+ FormatErrorMessage(L"This operation is only supported by WSL2.", L"Wsl/Service/RegisterDistro/WSL_E_WSL2_NEEDED"));
1218
}
1219
1220
//
@@ -1235,8 +1232,8 @@ class UnitTests
1232
commandLine = std::format(L"--import path-conflict-distro \"{}\" \"{}\" --version {}", basePath, tarFileName, version);
1233
validateOutput(
1234
commandLine.c_str(),
1238
- L"The supplied install location is already in use.\r\n"
1239
- L"Error code: Wsl/Service/RegisterDistro/ERROR_FILE_EXISTS\r\n");
1235
+ FormatErrorMessage(
1236
+ L"The supplied install location is already in use.", L"Wsl/Service/RegisterDistro/ERROR_FILE_EXISTS"));
1237
}
1238
1239
//
@@ -1277,7 +1274,7 @@ class UnitTests
1274
auto [out, err] = LxsstuLaunchWslAndCaptureOutput(commandLine.c_str(), -1);
1275
1276
VERIFY_ARE_EQUAL(
1280
- out, L"Importing the distribution failed.\r\nError code: Wsl/Service/RegisterDistro/WSL_E_IMPORT_FAILED\r\n");
1277
+ out, FormatErrorMessage(L"Importing the distribution failed.", L"Wsl/Service/RegisterDistro/WSL_E_IMPORT_FAILED"));
1278
VERIFY_ARE_EQUAL(err, L"bsdtar: Error opening archive: Unrecognized archive format\n");
1279
}
1280
@@ -1422,7 +1419,7 @@ class UnitTests
1419
auto [output, _] = LxsstuLaunchWslAndCaptureOutput(
1420
Cmd.c_str(), wcscmp(EntryPoint, L"bash.exe") == 0 ? 1 : -1, nullptr, nullptr, EXTENDED_STARTUPINFO_PRESENT | CREATE_UNICODE_ENVIRONMENT, EntryPoint);
1421
1425
- const auto expectedOutput = Message + L"\r\nError code: " + Code + L"\r\n";
1422
+ const auto expectedOutput = FormatErrorMessage(Message, Code);
1423
1424
if (!wsl::shared::string::IsEqual(output, expectedOutput, ignoreCasing))
1425
{
@@ -1519,9 +1516,7 @@ class UnitTests
1516
L"-d DummyBrokenDistro",
1517
L"An error occurred accessing the registry. Path: '\\REGISTRY\\USER\\" + Sid +
1518
L"\\Software\\Microsoft\\Windows\\CurrentVersion\\Lxss\\{baa405ef-1822-4bbe-84e2-30e4c6330d42}"
1522
- L"\\Version'."
1523
- L" "
1524
- L"Error: Data of this type is not supported. ",
1519
+ L"\\Version'. Error: Data of this type is not supported. ",
1520
L"Wsl/Service/ReadDistroConfig/ERROR_UNSUPPORTED_TYPE",
1521
{},
1522
L"wsl.exe",
@@ -1932,12 +1927,6 @@ Usage:
1927
Unregisters the distribution and deletes the root filesystem.
1928
)""";
1929
1935
- const std::wstring WslInstallHelpMessage =
1936
- LR"""(Invalid distribution name: 'foo'.
1937
-To get a list of valid distributions, use 'wsl.exe --list --online'.
1938
-Error code: Wsl/InstallDistro/WSL_E_DISTRO_NOT_FOUND
1939
-)""";
1940
-
1930
auto AddCrlf = [](const std::wstring& Input) {
1931
std::wstring MessageWithCrlf;
1932
@@ -1963,7 +1952,12 @@ Error code: Wsl/InstallDistro/WSL_E_DISTRO_NOT_FOUND
1952
RegistryKeyChange<std::wstring> keyChange(
1953
HKEY_LOCAL_MACHINE, LXSS_REGISTRY_PATH, wsl::windows::common::distribution::c_distroUrlRegistryValue, c_testDistributionEndpoint);
1954
1966
- VerifyOutput(L"--install foo", AddCrlf(WslInstallHelpMessage), -1);
1955
+ VerifyOutput(
1956
+ L"--install foo",
1957
+ FormatErrorMessage(
1958
+ L"Invalid distribution name: 'foo'.\r\nTo get a list of valid distributions, use 'wsl.exe --list --online'.",
1959
+ L"Wsl/InstallDistro/WSL_E_DISTRO_NOT_FOUND"),
1960
+ -1);
1961
}
1962
1963
WSL2_TEST_METHOD(TestExistingSwapVhd)
@@ -2288,16 +2282,20 @@ Error code: Wsl/InstallDistro/WSL_E_DISTRO_NOT_FOUND
2282
2283
validateWarnings(
2284
L"networkingMode=bridged",
2291
- L"wsl: Bridged networking requires wsl2.vmSwitch to be set.\r\n"
2292
- L"Error code: CreateInstance/CreateVm/ConfigureNetworking/WSL_E_VMSWITCH_NOT_SET\r\n"
2293
- L"wsl: Failed to configure network (networkingMode Bridged), falling back to networkingMode None.\r\n",
2285
+ L"wsl: " +
2286
+ FormatErrorMessage(
2287
+ L"Bridged networking requires wsl2.vmSwitch to be set.",
2288
+ L"CreateInstance/CreateVm/ConfigureNetworking/WSL_E_VMSWITCH_NOT_SET") +
2289
+ L"wsl: Failed to configure network (networkingMode Bridged), falling back to networkingMode None.\r\n",
2290
L"[wsl2]\n");
2291
2292
validateWarnings(
2293
L"networkingMode=bridged\nvmSwitch=DoesNotExist",
2298
- L"wsl: The VmSwitch 'DoesNotExist' was not found. Available switches:*\r\n"
2299
- L"Error code: CreateInstance/CreateVm/ConfigureNetworking/WSL_E_VMSWITCH_NOT_FOUND\r\n"
2300
- L"wsl: Failed to configure network (networkingMode Bridged), falling back to networkingMode None.\r\n",
2294
+ L"wsl: " +
2295
+ FormatErrorMessage(
2296
+ L"The VmSwitch 'DoesNotExist' was not found. Available switches:*",
2297
+ L"CreateInstance/CreateVm/ConfigureNetworking/WSL_E_VMSWITCH_NOT_FOUND") +
2298
+ L"wsl: Failed to configure network (networkingMode Bridged), falling back to networkingMode None.\r\n",
2299
L"[wsl2]\n",
2300
true);
2301
@@ -2511,9 +2509,9 @@ Error code: Wsl/InstallDistro/WSL_E_DISTRO_NOT_FOUND
2509
std::tie(output, warnings) = LxsstuLaunchWslAndCaptureOutput(L"--system echo not ok", -1);
2510
2511
const std::wstring configPath = wsl::windows::common::helpers::GetWslConfigPath();
2514
- const auto expectedOutput =
2515
- L"GUI application support is disabled via " + configPath +
2516
- L" or /etc/wsl.conf.\r\nError code: Wsl/Service/CreateInstance/WSL_E_GUI_APPLICATIONS_DISABLED\r\n";
2512
+ const auto expectedOutput = FormatErrorMessage(
2513
+ L"GUI application support is disabled via " + configPath + L" or /etc/wsl.conf.",
2514
+ L"Wsl/Service/CreateInstance/WSL_E_GUI_APPLICATIONS_DISABLED");
2515
2516
VERIFY_ARE_EQUAL(output, expectedOutput);
2517
VERIFY_ARE_EQUAL(L"", warnings);
@@ -2678,11 +2676,12 @@ Error code: Wsl/InstallDistro/WSL_E_DISTRO_NOT_FOUND
2676
// Attempt to import a vhd with an open handle.
2677
validateOutput(
2678
std::format(L"--import-in-place test-distro-corrupted \"{}\"", vhdPath.wstring()),
2681
- std::format(
2682
- L"Failed to attach disk '\\\\?\\{}' to WSL2: The process cannot access the file because it is being used by "
2683
- L"another process. \r\n"
2684
- L"Error code: Wsl/Service/RegisterDistro/MountDisk/HCS/ERROR_SHARING_VIOLATION\r\n",
2685
- vhdPath.wstring()));
2679
+ FormatErrorMessage(
2680
+ std::format(
2681
+ L"Failed to attach disk '\\\\?\\{}' to WSL2: The process cannot access the file because it is being used by "
2682
+ L"another process. ",
2683
+ vhdPath.wstring()),
2684
+ L"Wsl/Service/RegisterDistro/MountDisk/HCS/ERROR_SHARING_VIOLATION"));
2685
2686
vhd.reset();
2687
@@ -2707,14 +2706,16 @@ Error code: Wsl/InstallDistro/WSL_E_DISTRO_NOT_FOUND
2706
// Validate that starting the distribution fails with the correct error code.
2707
validateOutput(
2708
L"-d BrokenDistro echo ok",
2710
- L"The distribution failed to start because its virtual disk is corrupted.\r\n"
2711
- L"Error code: Wsl/Service/CreateInstance/WSL_E_DISK_CORRUPTED\r\n");
2709
+ FormatErrorMessage(
2710
+ L"The distribution failed to start because its virtual disk is corrupted.",
2711
+ L"Wsl/Service/CreateInstance/WSL_E_DISK_CORRUPTED"));
2712
2713
// Validate that trying to export the distribution fails with the correct error code.
2714
validateOutput(
2715
L"--export BrokenDistro dummy.tar",
2716
- L"The distribution failed to start because its virtual disk is corrupted.\r\n"
2717
- L"Error code: Wsl/Service/WSL_E_DISK_CORRUPTED\r\n");
2716
+ FormatErrorMessage(
2717
+ L"The distribution failed to start because its virtual disk is corrupted.",
2718
+ L"Wsl/Service/WSL_E_DISK_CORRUPTED"));
2719
2720
// Shutdown WSL to force the disk to detach.
2721
VERIFY_ARE_EQUAL(LxsstuLaunchWsl(L"--shutdown"), 0L);
@@ -2723,8 +2724,9 @@ Error code: Wsl/InstallDistro/WSL_E_DISTRO_NOT_FOUND
2724
// Import a corrupted vhd.
2725
validateOutput(
2726
std::format(L"--import-in-place test-distro-corrupted \"{}\"", vhdPath.wstring()),
2726
- L"The distribution failed to start because its virtual disk is corrupted.\r\n"
2727
- L"Error code: Wsl/Service/RegisterDistro/WSL_E_DISK_CORRUPTED\r\n");
2727
+ FormatErrorMessage(
2728
+ L"The distribution failed to start because its virtual disk is corrupted.",
2729
+ L"Wsl/Service/RegisterDistro/WSL_E_DISK_CORRUPTED"));
2730
2731
// Ensure the VHD can be deleted to make sure it was properly ejected from the VM.
2732
VERIFY_ARE_EQUAL(DeleteFileW(vhdPath.c_str()), TRUE);
@@ -2941,17 +2943,17 @@ Error code: Wsl/InstallDistro/WSL_E_DISTRO_NOT_FOUND
2943
WslConfigChange configChange(LxssGenerateTestConfig({.kernel = nonExistentFile.c_str()}));
2944
ValidateOutput(
2945
L"echo ok",
2944
- std::format(
2945
- L"{}\r\nError code: Wsl/Service/CreateInstance/CreateVm/WSL_E_CUSTOM_KERNEL_NOT_FOUND\r\n",
2946
- wsl::shared::Localization::MessageCustomKernelNotFound(wslConfigPath, nonExistentFile)),
2946
+ FormatErrorMessage(
2947
+ wsl::shared::Localization::MessageCustomKernelNotFound(wslConfigPath, nonExistentFile),
2948
+ L"Wsl/Service/CreateInstance/CreateVm/WSL_E_CUSTOM_KERNEL_NOT_FOUND"),
2949
L"");
2950
2951
configChange.Update(LxssGenerateTestConfig({.kernelModules = nonExistentFile.c_str()}));
2952
ValidateOutput(
2953
L"echo ok",
2952
- std::format(
2953
- L"{}\r\nError code: Wsl/Service/CreateInstance/CreateVm/WSL_E_CUSTOM_KERNEL_NOT_FOUND\r\n",
2954
- wsl::shared::Localization::MessageCustomKernelModulesNotFound(wslConfigPath, nonExistentFile)),
2954
+ FormatErrorMessage(
2955
+ wsl::shared::Localization::MessageCustomKernelModulesNotFound(wslConfigPath, nonExistentFile),
2956
+ L"Wsl/Service/CreateInstance/CreateVm/WSL_E_CUSTOM_KERNEL_NOT_FOUND"),
2957
L"");
2958
2959
#ifdef WSL_DEV_INSTALL_PATH
@@ -2981,9 +2983,9 @@ Error code: Wsl/InstallDistro/WSL_E_DISTRO_NOT_FOUND
2983
configChange.Update(LxssGenerateTestConfig({.kernelModules = kernelModulesPath.c_str()}));
2984
ValidateOutput(
2985
L"echo ok",
2984
- std::format(
2985
- L"{}\r\nError code: Wsl/Service/CreateInstance/CreateVm/WSL_E_CUSTOM_KERNEL_NOT_FOUND\r\n",
2986
- wsl::shared::Localization::MessageMismatchedKernelModulesError()),
2986
+ FormatErrorMessage(
2987
+ wsl::shared::Localization::MessageMismatchedKernelModulesError(),
2988
+ L"Wsl/Service/CreateInstance/CreateVm/WSL_E_CUSTOM_KERNEL_NOT_FOUND"),
2989
L"");
2990
2991
configChange.Update(LxssGenerateTestConfig());
@@ -3132,8 +3134,8 @@ Error code: Wsl/InstallDistro/WSL_E_DISTRO_NOT_FOUND
3134
3135
VERIFY_ARE_EQUAL(
3136
out,
3135
- L"The supplied install location is already in use.\r\nError code: "
3136
- L"Wsl/Service/MoveDistro/ERROR_FILE_EXISTS\r\n");
3137
+ FormatErrorMessage(
3138
+ L"The supplied install location is already in use.", L"Wsl/Service/MoveDistro/ERROR_FILE_EXISTS"));
3139
// Validate that the distribution still starts and that the vhd hasn't moved.
3140
validateDistro();
3141
VERIFY_IS_TRUE(std::filesystem::exists(std::format(L"{}\\ext4.vhdx", absolutePath)));
@@ -3147,8 +3149,9 @@ Error code: Wsl/InstallDistro/WSL_E_DISTRO_NOT_FOUND
3149
3150
VERIFY_ARE_EQUAL(
3151
out,
3150
- L"The filename, directory name, or volume label syntax is incorrect. \r\nError code: "
3151
- L"Wsl/Service/MoveDistro/ERROR_INVALID_NAME\r\n");
3152
+ FormatErrorMessage(
3153
+ L"The filename, directory name, or volume label syntax is incorrect. ",
3154
+ L"Wsl/Service/MoveDistro/ERROR_INVALID_NAME"));
3155
// Validate that the distribution still starts and that the vhd hasn't moved.
3156
validateDistro();
3157
VERIFY_IS_TRUE(std::filesystem::exists(std::format(L"{}\\ext4.vhdx", absolutePath)));
@@ -3309,9 +3312,10 @@ Error code: Wsl/InstallDistro/WSL_E_DISTRO_NOT_FOUND
3312
auto cleanupName =
3313
wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [name]() { LxsstuLaunchWsl(std::format(L"--unregister {}", name)); });
3314
3312
- auto validateDistro = [name](LPCWSTR size, LPCWSTR expectedSize, LPCWSTR expectedError = nullptr) {
3313
- auto [out, _] = LxsstuLaunchWslAndCaptureOutput(std::format(L"--manage {} --resize {}", name, size), expectedError ? -1 : 0);
3314
- if (expectedError)
3315
+ auto validateDistro = [name](LPCWSTR size, LPCWSTR expectedSize, const std::wstring& expectedError = {}) {
3316
+ auto [out, _] =
3317
+ LxsstuLaunchWslAndCaptureOutput(std::format(L"--manage {} --resize {}", name, size), expectedError.empty() ? 0 : -1);
3318
+ if (!expectedError.empty())
3319
{
3320
VERIFY_ARE_EQUAL(expectedError, out);
3321
return;
@@ -3324,14 +3328,16 @@ Error code: Wsl/InstallDistro/WSL_E_DISTRO_NOT_FOUND
3328
3329
validateDistro(L"1500G", L"1.5T");
3330
validateDistro(L"500G", L"492G");
3327
- validateDistro(L"1M", nullptr, L"Failed to resize disk.\r\nError code: Wsl/Service/E_FAIL\r\n");
3331
+ validateDistro(L"1M", nullptr, FormatErrorMessage(L"Failed to resize disk.", L"Wsl/Service/E_FAIL"));
3332
3333
{
3334
WslKeepAlive keepAlive;
3335
auto [out, _] = LxsstuLaunchWslAndCaptureOutput(L"--manage test_distro --resize 1500GB", -1);
3336
VERIFY_ARE_EQUAL(
3333
- L"The operation could not be completed because the VHD is currently in use. To force WSL to stop use: wsl.exe "
3334
- L"--shutdown\r\nError code: Wsl/Service/WSL_E_DISTRO_NOT_STOPPED\r\n",
3337
+ FormatErrorMessage(
3338
+ L"The operation could not be completed because the VHD is currently in use. To force WSL "
3339
+ L"to stop use: wsl.exe --shutdown",
3340
+ L"Wsl/Service/WSL_E_DISTRO_NOT_STOPPED"),
3341
out);
3342
}
3343
}
@@ -4368,7 +4374,7 @@ localhostForwarding=true
4374
auto [out, _] = LxsstuLaunchWslAndCaptureOutput(L"--manage nonexistent --set-default-user root", -1);
4375
4376
VERIFY_ARE_EQUAL(
4371
- out, L"There is no distribution with the supplied name.\r\nError code: Wsl/Service/WSL_E_DISTRO_NOT_FOUND\r\n");
4377
+ out, FormatErrorMessage(L"There is no distribution with the supplied name.", L"Wsl/Service/WSL_E_DISTRO_NOT_FOUND"));
4378
4379
constexpr auto injectionMarker = L"/tmp/wsl-manage-default-user-injection";
4380
LxsstuLaunchWsl(std::format(L"-u root -e /usr/bin/rm -f {}", injectionMarker));
@@ -4615,7 +4621,7 @@ VERSION_ID="Invalid|Format"
4621
const auto testDistroId = GetDistributionId(LXSS_DISTRO_NAME_TEST_L);
4622
VERIFY_IS_TRUE(testDistroId.has_value());
4623
4618
- auto validateOutput = [](const std::wstring& Cmd, LPCWSTR ExpectedOutput, int ExitCode = 0) {
4624
+ auto validateOutput = [](const std::wstring& Cmd, const std::wstring& ExpectedOutput, int ExitCode = 0) {
4625
auto [out, _] = LxsstuLaunchWslAndCaptureOutput(Cmd, ExitCode);
4626
4627
VERIFY_ARE_EQUAL(out, ExpectedOutput);
@@ -4639,11 +4645,12 @@ VERSION_ID="Invalid|Format"
4645
wsl::shared::string::GuidToString<wchar_t>(testDistroId.value(), wsl::shared::string::GuidToStringFlags::Uppercase)),
4646
L"OK");
4647
4642
- validateOutput(L"--distribution-id InvalidGuid", L"The parameter is incorrect. \r\nError code: Wsl/E_INVALIDARG\r\n", -1);
4648
+ validateOutput(L"--distribution-id InvalidGuid", FormatErrorMessage(L"The parameter is incorrect. ", L"Wsl/E_INVALIDARG"), -1);
4649
validateOutput(
4650
L"--distribution-id {C13B2B63-F9D5-4840-8105-F6ABECCF46CA}",
4645
- L"There is no distribution with the supplied name.\r\nError code: "
4646
- L"Wsl/Service/CreateInstance/ReadDistroConfig/WSL_E_DISTRO_NOT_FOUND\r\n",
4651
+ FormatErrorMessage(
4652
+ L"There is no distribution with the supplied name.",
4653
+ L"Wsl/Service/CreateInstance/ReadDistroConfig/WSL_E_DISTRO_NOT_FOUND"),
4654
-1);
4655
}
4656
@@ -4953,12 +4960,13 @@ VERSION_ID="Invalid|Format"
4960
CreateTarFromManifest(L"", L"distro-no-default-name.tar");
4961
4962
// Import should fail without --name
4956
- constexpr auto expectedOutput =
4957
- L"Installing: distro-no-default-name.tar\r\n\
4958
-This distribution doesn't contain a default name. Use --name to choose the distribution name.\r\n\
4959
-Error code: Wsl/Service/RegisterDistro/WSL_E_DISTRIBUTION_NAME_NEEDED\r\n";
4963
+ const auto expectedOutput = L"Installing: distro-no-default-name.tar\r\n" +
4964
+ FormatErrorMessage(
4965
+ L"This distribution doesn't contain a default name. Use --name to choose the "
4966
+ L"distribution name.",
4967
+ L"Wsl/Service/RegisterDistro/WSL_E_DISTRIBUTION_NAME_NEEDED");
4968
4961
- InstallFromTar(L"distro-no-default-name.tar", L"", -1, expectedOutput);
4969
+ InstallFromTar(L"distro-no-default-name.tar", L"", -1, expectedOutput.c_str());
4970
4971
// And succeed with --name
4972
InstallFromTar(L"distro-no-default-name.tar", L"--name test-distro-no-default-name");
@@ -5212,12 +5220,13 @@ Error code: Wsl/Service/RegisterDistro/WSL_E_DISTRIBUTION_NAME_NEEDED\r\n";
5220
5221
CreateTarFromManifest(L"[oobe]\ndefaultName = test_distro", L"conflict.tar");
5222
5215
- constexpr auto expectedOutput =
5216
- L"Installing: conflict.tar\r\n\
5217
-A distribution with the supplied name already exists. Use --name to choose a different name.\r\n\
5218
-Error code: Wsl/Service/RegisterDistro/ERROR_ALREADY_EXISTS\r\n";
5223
+ const auto expectedOutput = L"Installing: conflict.tar\r\n" +
5224
+ FormatErrorMessage(
5225
+ L"A distribution with the supplied name already exists. Use --name to choose a "
5226
+ L"different name.",
5227
+ L"Wsl/Service/RegisterDistro/ERROR_ALREADY_EXISTS");
5228
5220
- InstallFromTar(L"conflict.tar", L"", -1, expectedOutput);
5229
+ InstallFromTar(L"conflict.tar", L"", -1, expectedOutput.c_str());
5230
}
5231
5232
// Distribution default name is invalid
@@ -5226,12 +5235,11 @@ Error code: Wsl/Service/RegisterDistro/ERROR_ALREADY_EXISTS\r\n";
5235
5236
CreateTarFromManifest(L"[oobe]\ndefaultName = invalid!", L"invalid.tar");
5237
5229
- constexpr auto expectedOutput =
5230
- L"Installing: invalid.tar\r\n\
5231
-Invalid distribution name: \"invalid!\".\r\n\
5232
-Error code: Wsl/Service/RegisterDistro/E_INVALIDARG\r\n";
5238
+ const auto expectedOutput =
5239
+ L"Installing: invalid.tar\r\n" +
5240
+ FormatErrorMessage(L"Invalid distribution name: \"invalid!\".", L"Wsl/Service/RegisterDistro/E_INVALIDARG");
5241
5234
- InstallFromTar(L"invalid.tar", L"", -1, expectedOutput);
5242
+ InstallFromTar(L"invalid.tar", L"", -1, expectedOutput.c_str());
5243
}
5244
5245
// Distribution icon file is too big
@@ -5604,9 +5612,10 @@ Error code: Wsl/Service/RegisterDistro/E_INVALIDARG\r\n";
5612
5613
ValidateInstallError(
5614
L"--install DoesNotExists",
5607
- L"Invalid distribution name: 'DoesNotExists'.\r\n\
5608
-To get a list of valid distributions, use 'wsl.exe --list --online'.\r\n\
5609
-Error code: Wsl/InstallDistro/WSL_E_DISTRO_NOT_FOUND\r\n");
5615
+ FormatErrorMessage(
5616
+ L"Invalid distribution name: 'DoesNotExists'.\r\nTo get a list of valid distributions, use 'wsl.exe "
5617
+ L"--list --online'.",
5618
+ L"Wsl/InstallDistro/WSL_E_DISTRO_NOT_FOUND"));
5619
5620
VERIFY_ARE_EQUAL(LxsstuLaunchWsl(L"--unregister debian-12"), 0L);
5621
@@ -5750,16 +5759,16 @@ Distribution successfully installed. It can be launched via 'wsl.exe -d ubuntu-d
5759
// There's no easy way to automate the appx package installation, but verify that we take the legacy path
5760
ValidateInstallError(
5761
L"--install legacy --no-launch --web-download",
5753
- L"Downloading: legacy\r\n\
5754
-A connection with the server could not be established \r\n\
5755
-Error code: Wsl/InstallDistro/WININET_E_CANNOT_CONNECT\r\n",
5762
+ L"Downloading: legacy\r\n" +
5763
+ FormatErrorMessage(
5764
+ L"A connection with the server could not be established ", L"Wsl/InstallDistro/WININET_E_CANNOT_CONNECT"),
5765
L"wsl: Using legacy distribution registration. Consider using a tar based distribution instead.\r\n");
5766
5767
ValidateInstallError(
5768
L"--install legacy --no-launch --web-download --legacy",
5760
- L"Downloading: legacy\r\n\
5761
-A connection with the server could not be established \r\n\
5762
-Error code: Wsl/InstallDistro/WININET_E_CANNOT_CONNECT\r\n",
5769
+ L"Downloading: legacy\r\n" +
5770
+ FormatErrorMessage(
5771
+ L"A connection with the server could not be established ", L"Wsl/InstallDistro/WININET_E_CANNOT_CONNECT"),
5772
L"wsl: Using legacy distribution registration. Consider using a tar based distribution instead.\r\n");
5773
}
5774
@@ -5801,9 +5810,9 @@ Error code: Wsl/InstallDistro/WININET_E_CANNOT_CONNECT\r\n",
5810
// Validate that --legacy takes the appx path.
5811
ValidateInstallError(
5812
L"--install debian-12 --no-launch --web-download --legacy",
5804
- L"Downloading: debian-12\r\n\
5805
-A connection with the server could not be established \r\n\
5806
-Error code: Wsl/InstallDistro/WININET_E_CANNOT_CONNECT\r\n",
5813
+ L"Downloading: debian-12\r\n" +
5814
+ FormatErrorMessage(
5815
+ L"A connection with the server could not be established ", L"Wsl/InstallDistro/WININET_E_CANNOT_CONNECT"),
5816
L"wsl: Using legacy distribution registration. Consider using a tar based distribution instead.\r\n");
5817
}
5818
@@ -5921,11 +5930,10 @@ Error code: Wsl/InstallDistro/WININET_E_CANNOT_CONNECT\r\n",
5930
5931
ValidateInstallError(
5932
L"--install debian-12",
5924
- std::format(
5925
- L"Installing: DebianFriendlyName\r\n\
5926
-The distribution hash doesn't match. Expected: 0x12, actual hash: {}\r\n\
5927
-Error code: Wsl/InstallDistro/VerifyChecksum/TRUST_E_BAD_DIGEST\r\n",
5928
- wsl::shared::string::MultiByteToWide(tarHash)),
5933
+ L"Installing: DebianFriendlyName\r\n" +
5934
+ FormatErrorMessage(
5935
+ std::format(L"The distribution hash doesn't match. Expected: 0x12, actual hash: {}", wsl::shared::string::MultiByteToWide(tarHash)),
5936
+ L"Wsl/InstallDistro/VerifyChecksum/TRUST_E_BAD_DIGEST"),
5937
L"");
5938
}
5939
@@ -5952,9 +5960,8 @@ Error code: Wsl/InstallDistro/VerifyChecksum/TRUST_E_BAD_DIGEST\r\n",
5960
5961
ValidateInstallError(
5962
L"--install debian-12",
5955
- L"Installing: DebianFriendlyName\r\n\
5956
-Invalid hex string: wrongformat\r\n\
5957
-Error code: Wsl/InstallDistro/VerifyChecksum/E_INVALIDARG\r\n",
5963
+ L"Installing: DebianFriendlyName\r\n" +
5964
+ FormatErrorMessage(L"Invalid hex string: wrongformat", L"Wsl/InstallDistro/VerifyChecksum/E_INVALIDARG"),
5965
L"");
5966
}
5967
@@ -5989,9 +5996,10 @@ Error code: Wsl/InstallDistro/VerifyChecksum/E_INVALIDARG\r\n",
5996
5997
ValidateInstallError(
5998
L"--install invalid",
5992
- L"Invalid distribution name: 'invalid'.\r\n\
5993
-To get a list of valid distributions, use 'wsl.exe --list --online'.\r\n\
5994
-Error code: Wsl/InstallDistro/WSL_E_DISTRO_NOT_FOUND\r\n",
5999
+ FormatErrorMessage(
6000
+ L"Invalid distribution name: 'invalid'.\r\nTo get a list of valid distributions, use 'wsl.exe --list "
6001
+ L"--online'.",
6002
+ L"Wsl/InstallDistro/WSL_E_DISTRO_NOT_FOUND"),
6003
L"");
6004
}
6005
@@ -6029,8 +6037,8 @@ Error code: Wsl/InstallDistro/WSL_E_DISTRO_NOT_FOUND\r\n",
6037
6038
VERIFY_ARE_EQUAL(
6039
out,
6032
- L"Cannot create a file when that file already exists. \r\n"
6033
- L"Error code: Wsl/InstallDistro/ERROR_ALREADY_EXISTS\r\n");
6040
+ FormatErrorMessage(
6041
+ L"Cannot create a file when that file already exists. ", L"Wsl/InstallDistro/ERROR_ALREADY_EXISTS"));
6042
6043
VERIFY_ARE_EQUAL(err, L"");
6044
}
@@ -6040,8 +6048,8 @@ Error code: Wsl/InstallDistro/WSL_E_DISTRO_NOT_FOUND\r\n",
6048
6049
VERIFY_ARE_EQUAL(
6050
out,
6043
- L"Cannot create a file when that file already exists. \r\n"
6044
- L"Error code: Wsl/InstallDistro/ERROR_ALREADY_EXISTS\r\n");
6051
+ FormatErrorMessage(
6052
+ L"Cannot create a file when that file already exists. ", L"Wsl/InstallDistro/ERROR_ALREADY_EXISTS"));
6053
6054
VERIFY_ARE_EQUAL(err, L"");
6055
}
@@ -6068,8 +6076,9 @@ Error code: Wsl/InstallDistro/WSL_E_DISTRO_NOT_FOUND\r\n",
6076
auto restore = SetManifest(manifest);
6077
ValidateInstallError(
6078
L"--install",
6071
- L"No default distribution has been configured. Please provide a distribution to install.\r\n\
6072
-Error code: Wsl/InstallDistro/E_UNEXPECTED\r\n",
6079
+ FormatErrorMessage(
6080
+ L"No default distribution has been configured. Please provide a distribution to install.",
6081
+ L"Wsl/InstallDistro/E_UNEXPECTED"),
6082
L"");
6083
}
6084
@@ -6079,8 +6088,10 @@ Error code: Wsl/InstallDistro/E_UNEXPECTED\r\n",
6088
6089
ValidateInstallError(
6090
L"--install debian",
6082
- L"Invalid JSON document. Parse error: [json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - invalid literal; last read: 'B'\r\n\
6083
-Error code: Wsl/InstallDistro/WSL_E_INVALID_JSON\r\n",
6091
+ FormatErrorMessage(
6092
+ L"Invalid JSON document. Parse error: [json.exception.parse_error.101] parse error at line 1, column 1: "
6093
+ L"syntax error while parsing value - invalid literal; last read: 'B'",
6094
+ L"Wsl/InstallDistro/WSL_E_INVALID_JSON"),
6095
L"");
6096
}
6097
@@ -6910,8 +6921,9 @@ Error code: Wsl/InstallDistro/WSL_E_INVALID_JSON\r\n",
6921
6922
VERIFY_ARE_EQUAL(
6923
out,
6913
- L"The imported file is not a valid Linux distribution.\r\nError code: "
6914
- L"Wsl/Service/RegisterDistro/WSL_E_NOT_A_LINUX_DISTRO\r\n");
6924
+ FormatErrorMessage(
6925
+ L"The imported file is not a valid Linux distribution.",
6926
+ L"Wsl/Service/RegisterDistro/WSL_E_NOT_A_LINUX_DISTRO"));
6927
6928
// TODO: Uncomment once SetVersionDebug is removed from the tests .wslconfig.
6929
// VERIFY_ARE_EQUAL(err, L"");
@@ -6923,8 +6935,9 @@ Error code: Wsl/InstallDistro/WSL_E_INVALID_JSON\r\n",
6935
6936
VERIFY_ARE_EQUAL(
6937
out,
6926
- L"Installing: NUL\r\nThe imported file is not a valid Linux distribution.\r\nError code: "
6927
- L"Wsl/Service/RegisterDistro/WSL_E_NOT_A_LINUX_DISTRO\r\n");
6938
+ L"Installing: NUL\r\n" + FormatErrorMessage(
6939
+ L"The imported file is not a valid Linux distribution.",
6940
+ L"Wsl/Service/RegisterDistro/WSL_E_NOT_A_LINUX_DISTRO"));
6941
// TODO: Uncomment once SetVersionDebug is removed from the tests .wslconfig.
6942
// VERIFY_ARE_EQUAL(err, L"");
6943
}
@@ -6946,8 +6959,9 @@ Error code: Wsl/InstallDistro/WSL_E_INVALID_JSON\r\n",
6959
6960
VERIFY_ARE_EQUAL(
6961
out,
6949
- L"The imported file is not a valid Linux distribution.\r\nError code: "
6950
- L"Wsl/Service/RegisterDistro/WSL_E_NOT_A_LINUX_DISTRO\r\n");
6962
+ FormatErrorMessage(
6963
+ L"The imported file is not a valid Linux distribution.",
6964
+ L"Wsl/Service/RegisterDistro/WSL_E_NOT_A_LINUX_DISTRO"));
6965
// TODO: Uncomment once SetVersionDebug is removed from the tests .wslconfig.
6966
// VERIFY_ARE_EQUAL(err, L"");
6967
}
@@ -7113,7 +7127,8 @@ Error code: Wsl/InstallDistro/WSL_E_INVALID_JSON\r\n",
7127
auto [out, err] =
7128
LxsstuLaunchWslAndCaptureOutput(std::format(L"--export {} {} --format vhd", LXSS_DISTRO_NAME_TEST_L, vhdPath), -1);
7129
VERIFY_ARE_EQUAL(
7116
- out, L"The specified file must have the .vhdx file extension.\r\nError code: Wsl/Service/WSL_E_EXPORT_FAILED\r\n");
7130
+ out,
7131
+ FormatErrorMessage(L"The specified file must have the .vhdx file extension.", L"Wsl/Service/WSL_E_EXPORT_FAILED"));
7132
VERIFY_ARE_EQUAL(err, L"");
7133
7134
// Export the distribution to a .vhdx.
@@ -7139,7 +7154,7 @@ Error code: Wsl/InstallDistro/WSL_E_INVALID_JSON\r\n",
7154
// Attempt to export to a .vhdx (should fail).
7155
std::tie(out, err) = LxsstuLaunchWslAndCaptureOutput(std::format(L"--export {} {} --format vhd", newDistroName, vhdxPath), -1);
7156
VERIFY_ARE_EQUAL(
7142
- out, L"The specified file must have the .vhd file extension.\r\nError code: Wsl/Service/WSL_E_EXPORT_FAILED\r\n");
7157
+ out, FormatErrorMessage(L"The specified file must have the .vhd file extension.", L"Wsl/Service/WSL_E_EXPORT_FAILED"));
7158
VERIFY_ARE_EQUAL(err, L"");
7159
7160
// Attempt to import to a non VHD file.
@@ -7153,8 +7168,9 @@ Error code: Wsl/InstallDistro/WSL_E_INVALID_JSON\r\n",
7168
std::format(L"--import {} {} {} --vhd", negativeVariationDistro, negativeVariationDistro, tempFile.Path), -1);
7169
VERIFY_ARE_EQUAL(
7170
out,
7156
- L"The specified file must have the .vhd or .vhdx file extension.\r\nError code: "
7157
- L"Wsl/Service/RegisterDistro/WSL_E_IMPORT_FAILED\r\n");
7171
+ FormatErrorMessage(
7172
+ L"The specified file must have the .vhd or .vhdx file extension.",
7173
+ L"Wsl/Service/RegisterDistro/WSL_E_IMPORT_FAILED"));
7174
VERIFY_ARE_EQUAL(err, L"");
7175
}
7176
test/windows/wslc/e2e/WSLCE2EContainerAttachTests.cpp
+2
-1
@@ -116,7 +116,8 @@ class WSLCE2EContainerAttachTests
116
{
117
auto result = RunWslc(std::format(L"container attach {}", WslcContainerName));
118
result.Verify(
119
- {.Stderr = std::format(L"Container '{}' not found.\r\nError code: WSLC_E_CONTAINER_NOT_FOUND\r\n", WslcContainerName),
119
+ {.Stderr =
120
+ FormatErrorMessage(std::format(L"Container '{}' not found.", WslcContainerName), L"WSLC_E_CONTAINER_NOT_FOUND"),
121
.ExitCode = 1});
122
}
123
test/windows/wslc/e2e/WSLCE2EContainerCreateTests.cpp
+36
-20
@@ -97,11 +97,11 @@ class WSLCE2EContainerCreateTests
97
98
auto result = RunWslc(std::format(L"container create --name {} {}", WslcContainerName, reference));
99
100
- std::wstringstream expectedError;
101
- expectedError << L"Image '" << reference << L"' not found, pulling\r\n"
102
- << L"manifest for " << reference << L" not found: manifest unknown: manifest unknown\r\n"
103
- << L"Error code: WSLC_E_IMAGE_NOT_FOUND\r\n";
104
- result.Verify({.Stderr = expectedError.str(), .ExitCode = 1});
100
+ const auto expectedError = std::format(L"Image '{}' not found, pulling\r\n", reference) +
101
+ FormatErrorMessage(
102
+ std::format(L"manifest for {} not found: manifest unknown: manifest unknown", reference),
103
+ L"WSLC_E_IMAGE_NOT_FOUND");
104
+ result.Verify({.Stderr = expectedError, .ExitCode = 1});
105
}
106
107
WSLC_TEST_METHOD(WSLCE2E_Container_Create_PullPolicy)
@@ -120,8 +120,9 @@ class WSLCE2EContainerCreateTests
120
EnsureContainerDoesNotExist(WslcContainerName);
121
122
result = RunWslc(std::format(L"container create --pull=always --name {} {}", WslcContainerName, registryImage));
123
- const auto errorMessage = std::format(
124
- L"manifest for {} not found: manifest unknown: manifest unknown\r\nError code: WSLC_E_IMAGE_NOT_FOUND\r\n", registryImage);
123
+ const auto errorMessage = FormatErrorMessage(
124
+ std::format(L"manifest for {} not found: manifest unknown: manifest unknown", registryImage),
125
+ L"WSLC_E_IMAGE_NOT_FOUND");
126
result.Verify({.Stdout = L"", .Stderr = errorMessage, .ExitCode = 1});
127
VerifyContainerIsNotListed(WslcContainerName);
128
@@ -171,7 +172,8 @@ class WSLCE2EContainerCreateTests
172
auto result = RunWslc(std::format(
173
L"container create --cidfile \"{}\" --name {} {}", EscapePath(cidFilePath.wstring()), WslcContainerName, DebianImage.NameAndTag()));
174
result.Verify(
174
- {.Stderr = std::format(L"CID file '{}' already exists\r\nError code: ERROR_FILE_EXISTS\r\n", EscapePath(cidFilePath.wstring())),
175
+ {.Stderr = FormatErrorMessage(
176
+ std::format(L"CID file '{}' already exists", EscapePath(cidFilePath.wstring())), L"ERROR_FILE_EXISTS"),
177
.ExitCode = 1});
178
179
VerifyContainerIsNotListed(WslcContainerName);
@@ -189,7 +191,13 @@ class WSLCE2EContainerCreateTests
191
// Attempt to create another container with the same name
192
result = RunWslc(std::format(L"container create --name {} {}", WslcContainerName, DebianImage.NameAndTag()));
193
result.Verify(
192
- {.Stderr = std::format(L"Conflict. The container name \"/{}\" is already in use by container \"{}\". You have to remove (or rename) that container to be able to reuse that name.\r\nError code: ERROR_ALREADY_EXISTS\r\n", WslcContainerName, containerId),
194
+ {.Stderr = FormatErrorMessage(
195
+ std::format(
196
+ L"Conflict. The container name \"/{}\" is already in use by container \"{}\". You have to remove "
197
+ L"(or rename) that container to be able to reuse that name.",
198
+ WslcContainerName,
199
+ containerId),
200
+ L"ERROR_ALREADY_EXISTS"),
201
.ExitCode = 1});
202
}
203
@@ -632,7 +640,9 @@ class WSLCE2EContainerCreateTests
640
641
result = RunWslc(std::format(L"container start -a {}", WslcContainerName));
642
result.Verify(
635
- {.Stderr = L"unable to find user user_does_not_exist: no matching entries in passwd file\r\nError code: E_FAIL\r\n", .ExitCode = 1});
643
+ {.Stderr =
644
+ FormatErrorMessage(L"unable to find user user_does_not_exist: no matching entries in passwd file", L"E_FAIL"),
645
+ .ExitCode = 1});
646
}
647
648
WSLC_TEST_METHOD(WSLCE2E_Container_Create_Tmpfs)
@@ -778,7 +788,10 @@ class WSLCE2EContainerCreateTests
788
WslcContainerName,
789
source.wstring(),
790
AlpineImage.NameAndTag()));
781
- result.Verify({.Stdout = L"", .Stderr = FormatWslcError(Localization::MessageWslcBindSourcePathNotFound(source.wstring())), .ExitCode = 1});
791
+ result.Verify(
792
+ {.Stdout = L"",
793
+ .Stderr = FormatErrorMessage(Localization::MessageWslcBindSourcePathNotFound(source.wstring()), L"E_INVALIDARG"),
794
+ .ExitCode = 1});
795
VERIFY_IS_FALSE(std::filesystem::exists(source));
796
EnsureContainerDoesNotExist(WslcContainerName);
797
}
@@ -922,7 +935,10 @@ class WSLCE2EContainerCreateTests
935
{
936
const auto result =
937
RunWslc(std::format(L"container create --name {} {} {} true", WslcContainerName, arguments, DebianImage.NameAndTag()));
925
- result.Verify({.Stdout = L"", .Stderr = FormatWslcError(Localization::WSLCCLI_DuplicateMountDestinationError(L"/data")), .ExitCode = 1});
938
+ result.Verify(
939
+ {.Stdout = L"",
940
+ .Stderr = FormatErrorMessage(Localization::WSLCCLI_DuplicateMountDestinationError(L"/data"), L"E_INVALIDARG"),
941
+ .ExitCode = 1});
942
EnsureContainerDoesNotExist(WslcContainerName);
943
}
944
}
@@ -1094,7 +1110,7 @@ class WSLCE2EContainerCreateTests
1110
{
1111
auto result =
1112
RunWslc(std::format(L"container create --stop-timeout -2 --name {} {}", WslcContainerName, DebianImage.NameAndTag()));
1097
- result.Verify({.Stderr = L"Invalid stop timeout value: -2\r\nError code: E_INVALIDARG\r\n", .ExitCode = 1});
1113
+ result.Verify({.Stderr = FormatErrorMessage(L"Invalid stop timeout value: -2", L"E_INVALIDARG"), .ExitCode = 1});
1114
VerifyContainerIsNotListed(WslcContainerName);
1115
}
1116
}
@@ -1310,7 +1326,7 @@ class WSLCE2EContainerCreateTests
1326
{
1327
auto result = RunWslc(
1328
std::format(L"container create --network does-not-exist --name {} {} true", WslcContainerName, DebianImage.NameAndTag()));
1313
- result.Verify({.Stderr = L"Network not found: 'does-not-exist'\r\nError code: WSLC_E_NETWORK_NOT_FOUND\r\n", .ExitCode = 1});
1329
+ result.Verify({.Stderr = FormatErrorMessage(L"Network not found: 'does-not-exist'", L"WSLC_E_NETWORK_NOT_FOUND"), .ExitCode = 1});
1330
VerifyContainerIsNotListed(WslcContainerName);
1331
}
1332
@@ -1369,8 +1385,8 @@ class WSLCE2EContainerCreateTests
1385
auto result =
1386
RunWslc(std::format(L"container create --network-alias db --name {} {} true", WslcContainerName, DebianImage.NameAndTag()));
1387
result.Verify(
1372
- {.Stderr =
1373
- L"Network aliases require a user-defined network. Use --network to specify one.\r\nError code: E_INVALIDARG\r\n",
1388
+ {.Stderr = FormatErrorMessage(
1389
+ L"Network aliases require a user-defined network. Use --network to specify one.", L"E_INVALIDARG"),
1390
.ExitCode = 1});
1391
VerifyContainerIsNotListed(WslcContainerName);
1392
}
@@ -1380,8 +1396,8 @@ class WSLCE2EContainerCreateTests
1396
auto result = RunWslc(std::format(
1397
L"container create --network none --network-alias db --name {} {} true", WslcContainerName, DebianImage.NameAndTag()));
1398
result.Verify(
1383
- {.Stderr =
1384
- L"Network aliases require a user-defined network. Use --network to specify one.\r\nError code: E_INVALIDARG\r\n",
1399
+ {.Stderr = FormatErrorMessage(
1400
+ L"Network aliases require a user-defined network. Use --network to specify one.", L"E_INVALIDARG"),
1401
.ExitCode = 1});
1402
VerifyContainerIsNotListed(WslcContainerName);
1403
}
@@ -1437,7 +1453,7 @@ class WSLCE2EContainerCreateTests
1453
auto result =
1454
RunWslc(std::format(L"container create --ip {} --name {} {} true", ipAddress, WslcContainerName, DebianImage.NameAndTag()));
1455
result.Verify(
1440
- {.Stderr = std::format(L"{}\r\nError code: E_INVALIDARG\r\n", wsl::shared::Localization::MessageWslcIpRequiresUserDefinedNetwork()),
1456
+ {.Stderr = FormatErrorMessage(wsl::shared::Localization::MessageWslcIpRequiresUserDefinedNetwork(), L"E_INVALIDARG"),
1457
.ExitCode = 1});
1458
VerifyContainerIsNotListed(WslcContainerName);
1459
}
@@ -1449,7 +1465,7 @@ class WSLCE2EContainerCreateTests
1465
auto result = RunWslc(std::format(
1466
L"container create --network bridge --ip {} --name {} {} true", ipAddress, WslcContainerName, DebianImage.NameAndTag()));
1467
result.Verify(
1452
- {.Stderr = std::format(L"{}\r\nError code: E_INVALIDARG\r\n", wsl::shared::Localization::MessageWslcIpRequiresUserDefinedNetwork()),
1468
+ {.Stderr = FormatErrorMessage(wsl::shared::Localization::MessageWslcIpRequiresUserDefinedNetwork(), L"E_INVALIDARG"),
1469
.ExitCode = 1});
1470
VerifyContainerIsNotListed(WslcContainerName);
1471
}
test/windows/wslc/e2e/WSLCE2EContainerExecTests.cpp
+4
-2
@@ -86,7 +86,8 @@ class WSLCE2EContainerExecTests
86
{
87
auto result = RunWslc(std::format(L"container exec {} echo hello", WslcContainerName));
88
result.Verify(
89
- {.Stderr = std::format(L"Container '{}' not found.\r\nError code: WSLC_E_CONTAINER_NOT_FOUND\r\n", WslcContainerName),
89
+ {.Stderr =
90
+ FormatErrorMessage(std::format(L"Container '{}' not found.", WslcContainerName), L"WSLC_E_CONTAINER_NOT_FOUND"),
91
.ExitCode = 1});
92
}
93
@@ -425,7 +426,8 @@ class WSLCE2EContainerExecTests
426
427
auto inspect = InspectContainer(WslcContainerName);
428
result = RunWslc(std::format(L"container exec {} echo should-fail", WslcContainerName));
428
- auto errorMessage = std::format(L"Container '{}' is not running.\r\nError code: WSLC_E_CONTAINER_NOT_RUNNING\r\n", inspect.Id);
429
+ auto errorMessage =
430
+ FormatErrorMessage(std::format(L"Container '{}' is not running.", inspect.Id), L"WSLC_E_CONTAINER_NOT_RUNNING");
431
result.Verify({.Stderr = errorMessage, .ExitCode = 1});
432
}
433
test/windows/wslc/e2e/WSLCE2EContainerKillTests.cpp
+2
-1
@@ -95,7 +95,8 @@ class WSLCE2EContainerKillTests
95
96
auto result = RunWslc(std::format(L"container kill {}", WslcContainerName));
97
result.Verify(
98
- {.Stderr = std::format(L"Container '{}' not found.\r\nError code: WSLC_E_CONTAINER_NOT_FOUND\r\n", WslcContainerName),
98
+ {.Stderr =
99
+ FormatErrorMessage(std::format(L"Container '{}' not found.", WslcContainerName), L"WSLC_E_CONTAINER_NOT_FOUND"),
100
.ExitCode = 1});
101
}
102
test/windows/wslc/e2e/WSLCE2EContainerRemoveTests.cpp
+2
-1
@@ -62,7 +62,8 @@ class WSLCE2EContainerRemoveTests
62
auto result = RunWslc(std::format(L"container remove {}", WslcContainerName));
63
result.Verify(
64
{.Stdout = L"",
65
- .Stderr = std::format(L"Container '{}' not found.\r\nError code: WSLC_E_CONTAINER_NOT_FOUND\r\n", WslcContainerName),
65
+ .Stderr =
66
+ FormatErrorMessage(std::format(L"Container '{}' not found.", WslcContainerName), L"WSLC_E_CONTAINER_NOT_FOUND"),
67
.ExitCode = 1});
68
}
69
test/windows/wslc/e2e/WSLCE2EContainerRunTests.cpp
+41
-24
@@ -108,8 +108,9 @@ class WSLCE2EContainerRunTests
108
VERIFY_IS_FALSE(result.Stdout->empty());
109
110
result = RunWslc(std::format(L"container run --pull=always --rm --name {} {}", WslcContainerName, registryImage));
111
- const auto errorMessage = std::format(
112
- L"manifest for {} not found: manifest unknown: manifest unknown\r\nError code: WSLC_E_IMAGE_NOT_FOUND\r\n", registryImage);
111
+ const auto errorMessage = FormatErrorMessage(
112
+ std::format(L"manifest for {} not found: manifest unknown: manifest unknown", registryImage),
113
+ L"WSLC_E_IMAGE_NOT_FOUND");
114
result.Verify({.Stdout = L"", .Stderr = errorMessage, .ExitCode = 1});
115
VerifyContainerIsNotListed(WslcContainerName);
116
@@ -149,7 +150,8 @@ class WSLCE2EContainerRunTests
150
auto result = RunWslc(std::format(
151
L"container run --cidfile \"{}\" --name {} {}", EscapePath(cidFilePath.wstring()), WslcContainerName, DebianImage.NameAndTag()));
152
result.Verify(
152
- {.Stderr = std::format(L"CID file '{}' already exists\r\nError code: ERROR_FILE_EXISTS\r\n", EscapePath(cidFilePath.wstring())),
153
+ {.Stderr = FormatErrorMessage(
154
+ std::format(L"CID file '{}' already exists", EscapePath(cidFilePath.wstring())), L"ERROR_FILE_EXISTS"),
155
.ExitCode = 1});
156
157
VerifyContainerIsNotListed(WslcContainerName);
@@ -172,7 +174,13 @@ class WSLCE2EContainerRunTests
174
{
175
auto result = RunWslc(std::format(L"container run --rm --entrypoint /bin/does-not-exist {}", DebianImage.NameAndTag()));
176
result.Verify(
175
- {.Stdout = L"", .Stderr = L"failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: exec: \"/bin/does-not-exist\": stat /bin/does-not-exist: no such file or directory: unknown\r\nError code: E_INVALIDARG\r\n", .ExitCode = 1});
177
+ {.Stdout = L"",
178
+ .Stderr = FormatErrorMessage(
179
+ L"failed to create task for container: failed to create shim task: OCI runtime create failed: runc create "
180
+ L"failed: unable to start container process: error during container init: exec: \"/bin/does-not-exist\": stat "
181
+ L"/bin/does-not-exist: no such file or directory: unknown",
182
+ L"E_INVALIDARG"),
183
+ .ExitCode = 1});
184
}
185
186
WSLC_TEST_METHOD(WSLCE2E_Container_Run_Entrypoint_Detach_Lifecycle)
@@ -414,13 +422,15 @@ class WSLCE2EContainerRunTests
422
{
423
auto result = RunWslc(std::format(L"container run --rm -u user_does_not_exist {} id -u", DebianImage.NameAndTag()));
424
result.Verify(
417
- {.Stderr = L"unable to find user user_does_not_exist: no matching entries in passwd file\r\nError code: E_FAIL\r\n", .ExitCode = 1});
425
+ {.Stderr =
426
+ FormatErrorMessage(L"unable to find user user_does_not_exist: no matching entries in passwd file", L"E_FAIL"),
427
+ .ExitCode = 1});
428
}
429
430
WSLC_TEST_METHOD(WSLCE2E_Container_Run_UserOption_UnknownGroup_Fails)
431
{
432
auto result = RunWslc(std::format(L"container run --rm -u root:badgid {} id -u", DebianImage.NameAndTag()));
423
- result.Verify({.Stderr = L"unable to find group badgid: no matching entries in group file\r\nError code: E_FAIL\r\n", .ExitCode = 1});
433
+ result.Verify({.Stderr = FormatErrorMessage(L"unable to find group badgid: no matching entries in group file", L"E_FAIL"), .ExitCode = 1});
434
}
435
436
WSLC_TEST_METHOD(WSLCE2E_Container_Run_UserOption_NameGroupRoot)
@@ -479,10 +489,12 @@ class WSLCE2EContainerRunTests
489
// Attempt to start — should fail with port conflict
490
auto startResult = RunWslc(std::format(L"container start {}", containerId));
491
startResult.Verify(
482
- {.Stderr = std::format(
483
- L"Failed to map port '127.0.0.1:{}/tcp', Only one usage of each socket address (protocol/network "
484
- L"address/port) is normally permitted. \r\nError code: WSAEADDRINUSE\r\n",
485
- HostTestPort1),
492
+ {.Stderr = FormatErrorMessage(
493
+ std::format(
494
+ L"Failed to map port '127.0.0.1:{}/tcp', Only one usage of each socket address (protocol/network "
495
+ L"address/port) is normally permitted. ",
496
+ HostTestPort1),
497
+ L"WSAEADDRINUSE"),
498
.ExitCode = 1});
499
500
// Clean up the created container
@@ -518,10 +530,12 @@ class WSLCE2EContainerRunTests
530
// Attempt to start — should fail with a port conflict, with the IPv6 address bracketed in the message.
531
auto ipv6StartResult = RunWslc(std::format(L"container start {}", ipv6ContainerId));
532
ipv6StartResult.Verify(
521
- {.Stderr = std::format(
522
- L"Failed to map port '[::1]:{}/tcp', Only one usage of each socket address (protocol/network "
523
- L"address/port) is normally permitted. \r\nError code: WSAEADDRINUSE\r\n",
524
- HostTestPort2),
533
+ {.Stderr = FormatErrorMessage(
534
+ std::format(
535
+ L"Failed to map port '[::1]:{}/tcp', Only one usage of each socket address (protocol/network "
536
+ L"address/port) is normally permitted. ",
537
+ HostTestPort2),
538
+ L"WSAEADDRINUSE"),
539
.ExitCode = 1});
540
}
541
@@ -944,7 +958,7 @@ class WSLCE2EContainerRunTests
958
{
959
auto result = RunWslc(std::format(
960
L"container run --rm --network does-not-exist --name {} {} true", WslcContainerName, DebianImage.NameAndTag()));
947
- result.Verify({.Stderr = L"Network not found: 'does-not-exist'\r\nError code: WSLC_E_NETWORK_NOT_FOUND\r\n", .ExitCode = 1});
961
+ result.Verify({.Stderr = FormatErrorMessage(L"Network not found: 'does-not-exist'", L"WSLC_E_NETWORK_NOT_FOUND"), .ExitCode = 1});
962
}
963
964
WSLC_TEST_METHOD(WSLCE2E_Container_Run_NetworkAlias_Success)
@@ -1004,8 +1018,8 @@ class WSLCE2EContainerRunTests
1018
auto result =
1019
RunWslc(std::format(L"container run --rm --network-alias db --name {} {} true", WslcContainerName, DebianImage.NameAndTag()));
1020
result.Verify(
1007
- {.Stderr =
1008
- L"Network aliases require a user-defined network. Use --network to specify one.\r\nError code: E_INVALIDARG\r\n",
1021
+ {.Stderr = FormatErrorMessage(
1022
+ L"Network aliases require a user-defined network. Use --network to specify one.", L"E_INVALIDARG"),
1023
.ExitCode = 1});
1024
}
1025
@@ -1014,8 +1028,8 @@ class WSLCE2EContainerRunTests
1028
auto result = RunWslc(std::format(
1029
L"container run --rm --network none --network-alias db --name {} {} true", WslcContainerName, DebianImage.NameAndTag()));
1030
result.Verify(
1017
- {.Stderr =
1018
- L"Network aliases require a user-defined network. Use --network to specify one.\r\nError code: E_INVALIDARG\r\n",
1031
+ {.Stderr = FormatErrorMessage(
1032
+ L"Network aliases require a user-defined network. Use --network to specify one.", L"E_INVALIDARG"),
1033
.ExitCode = 1});
1034
}
1035
@@ -1075,7 +1089,7 @@ class WSLCE2EContainerRunTests
1089
auto result =
1090
RunWslc(std::format(L"container run --rm --ip {} --name {} {} true", ipAddress, WslcContainerName, DebianImage.NameAndTag()));
1091
result.Verify(
1078
- {.Stderr = std::format(L"{}\r\nError code: E_INVALIDARG\r\n", wsl::shared::Localization::MessageWslcIpRequiresUserDefinedNetwork()),
1092
+ {.Stderr = FormatErrorMessage(wsl::shared::Localization::MessageWslcIpRequiresUserDefinedNetwork(), L"E_INVALIDARG"),
1093
.ExitCode = 1});
1094
}
1095
@@ -1086,7 +1100,7 @@ class WSLCE2EContainerRunTests
1100
auto result = RunWslc(std::format(
1101
L"container run --rm --network bridge --ip {} --name {} {} true", ipAddress, WslcContainerName, DebianImage.NameAndTag()));
1102
result.Verify(
1089
- {.Stderr = std::format(L"{}\r\nError code: E_INVALIDARG\r\n", wsl::shared::Localization::MessageWslcIpRequiresUserDefinedNetwork()),
1103
+ {.Stderr = FormatErrorMessage(wsl::shared::Localization::MessageWslcIpRequiresUserDefinedNetwork(), L"E_INVALIDARG"),
1104
.ExitCode = 1});
1105
}
1106
@@ -1257,7 +1271,10 @@ with mmap.mmap(fd, 32 * 1024, flags=mmap.MAP_SHARED, prot=mmap.PROT_READ | mmap.
1271
L"container run --rm --name {} --mount type=tmpfs,target=/data --mount type=tmpfs,target=/data/ {} true",
1272
WslcContainerName,
1273
DebianImage.NameAndTag()));
1260
- result.Verify({.Stdout = L"", .Stderr = FormatWslcError(Localization::WSLCCLI_DuplicateMountDestinationError(L"/data")), .ExitCode = 1});
1274
+ result.Verify(
1275
+ {.Stdout = L"",
1276
+ .Stderr = FormatErrorMessage(Localization::WSLCCLI_DuplicateMountDestinationError(L"/data"), L"E_INVALIDARG"),
1277
+ .ExitCode = 1});
1278
EnsureContainerDoesNotExist(WslcContainerName);
1279
}
1280
@@ -1358,7 +1375,7 @@ with mmap.mmap(fd, 32 * 1024, flags=mmap.MAP_SHARED, prot=mmap.PROT_READ | mmap.
1375
{
1376
auto result =
1377
RunWslc(std::format(L"container run --rm --stop-timeout -2 --name {} {}", WslcContainerName, DebianImage.NameAndTag()));
1361
- result.Verify({.Stderr = L"Invalid stop timeout value: -2\r\nError code: E_INVALIDARG\r\n", .ExitCode = 1});
1378
+ result.Verify({.Stderr = FormatErrorMessage(L"Invalid stop timeout value: -2", L"E_INVALIDARG"), .ExitCode = 1});
1379
EnsureContainerDoesNotExist(WslcContainerName);
1380
}
1381
@@ -1366,7 +1383,7 @@ with mmap.mmap(fd, 32 * 1024, flags=mmap.MAP_SHARED, prot=mmap.PROT_READ | mmap.
1383
{
1384
auto result = RunWslc(std::format(
1385
L"container run --rm --stop-timeout {} --name {} {}", WSLC_STOP_TIMEOUT_DEFAULT, WslcContainerName, DebianImage.NameAndTag()));
1369
- result.Verify({.Stderr = L"Invalid stop timeout value: -2147483648\r\nError code: E_INVALIDARG\r\n", .ExitCode = 1});
1386
+ result.Verify({.Stderr = FormatErrorMessage(L"Invalid stop timeout value: -2147483648", L"E_INVALIDARG"), .ExitCode = 1});
1387
EnsureContainerDoesNotExist(WslcContainerName);
1388
}
1389
}
test/windows/wslc/e2e/WSLCE2EContainerStopTests.cpp
+2
-1
@@ -132,7 +132,8 @@ class WSLCE2EContainerStopTests
132
133
auto result = RunWslc(std::format(L"container stop {} -t 0", WslcContainerName));
134
result.Verify(
135
- {.Stderr = std::format(L"Container '{}' not found.\r\nError code: WSLC_E_CONTAINER_NOT_FOUND\r\n", WslcContainerName),
135
+ {.Stderr =
136
+ FormatErrorMessage(std::format(L"Container '{}' not found.", WslcContainerName), L"WSLC_E_CONTAINER_NOT_FOUND"),
137
.ExitCode = 1});
138
}
139
test/windows/wslc/e2e/WSLCE2EGlobalTests.cpp
+12
-7
@@ -230,7 +230,7 @@ class WSLCE2EGlobalTests
230
result = RunWslc(std::format(L"--session \"{}\" container list", adminName), ElevationType::NonElevated);
231
232
// Should fail with access denied.
233
- result.Verify({.Stderr = L"The requested operation requires elevation. \r\nError code: ERROR_ELEVATION_REQUIRED\r\n", .ExitCode = 1});
233
+ result.Verify({.Stderr = FormatErrorMessage(L"The requested operation requires elevation. ", L"ERROR_ELEVATION_REQUIRED"), .ExitCode = 1});
234
}
235
236
WSLC_TEST_METHOD(WSLCE2E_Session_ElevatedCanAccessNonElevatedSession)
@@ -256,11 +256,13 @@ class WSLCE2EGlobalTests
256
auto nonAdminName = GetExpectedDefaultSessionName(false);
257
auto adminName = GetExpectedDefaultSessionName(true);
258
auto result = RunWslc(std::format(L"--session \"{}\" container list", nonAdminName), ElevationType::Elevated);
259
- result.Verify({.Stderr = std::format(L"Session not found: '{}'\r\nError code: WSLC_E_SESSION_NOT_FOUND\r\n", nonAdminName), .ExitCode = 1});
259
+ result.Verify(
260
+ {.Stderr = FormatErrorMessage(std::format(L"Session not found: '{}'", nonAdminName), L"WSLC_E_SESSION_NOT_FOUND"), .ExitCode = 1});
261
262
// Ensure non-elevated cannot create the elevated session.
263
result = RunWslc(std::format(L"--session \"{}\" container list", adminName), ElevationType::NonElevated);
263
- result.Verify({.Stderr = std::format(L"Session not found: '{}'\r\nError code: WSLC_E_SESSION_NOT_FOUND\r\n", adminName), .ExitCode = 1});
264
+ result.Verify(
265
+ {.Stderr = FormatErrorMessage(std::format(L"Session not found: '{}'", adminName), L"WSLC_E_SESSION_NOT_FOUND"), .ExitCode = 1});
266
}
267
268
// Regression test for session name squatting vulnerability.
@@ -461,7 +463,7 @@ class WSLCE2EGlobalTests
463
464
// Attempt to terminate the admin session from the non-elevated process and fail.
465
result = RunWslc(std::format(L"--session \"{}\" system session terminate", adminName), ElevationType::NonElevated);
464
- result.Verify({.Stderr = L"The requested operation requires elevation. \r\nError code: ERROR_ELEVATION_REQUIRED\r\n", .ExitCode = 1});
466
+ result.Verify({.Stderr = FormatErrorMessage(L"The requested operation requires elevation. ", L"ERROR_ELEVATION_REQUIRED"), .ExitCode = 1});
467
468
// Terminate the non-elevated session from the elevated process.
469
result = RunWslc(std::format(L"--session \"{}\" system session terminate", nonAdminName), ElevationType::Elevated);
@@ -491,7 +493,9 @@ class WSLCE2EGlobalTests
493
// Verify targeting a non-existent session fails.
494
auto result = RunWslc(L"--session INVALID_SESSION_NAME container list");
495
result.Verify(
494
- {.Stdout = L"", .Stderr = L"Session not found: 'INVALID_SESSION_NAME'\r\nError code: WSLC_E_SESSION_NOT_FOUND\r\n", .ExitCode = 1});
496
+ {.Stdout = L"",
497
+ .Stderr = FormatErrorMessage(L"Session not found: 'INVALID_SESSION_NAME'", L"WSLC_E_SESSION_NOT_FOUND"),
498
+ .ExitCode = 1});
499
500
// Verify session list
501
result = RunWslc(L"system session list");
@@ -621,12 +625,13 @@ class WSLCE2EGlobalTests
625
626
{
627
auto result = RunWslc(L"--session not-found system session run echo OK");
624
- result.Verify({.Stderr = L"Session not found: 'not-found'\r\nError code: WSLC_E_SESSION_NOT_FOUND\r\n", .ExitCode = 1});
628
+ result.Verify({.Stderr = FormatErrorMessage(L"Session not found: 'not-found'", L"WSLC_E_SESSION_NOT_FOUND"), .ExitCode = 1});
629
}
630
631
{
632
auto result = RunWslc(L"system session run not-found");
629
- result.Verify({.Stdout = L"", .Stderr = L"Failed to launch command not-found. Errno = 2\r\nError code: E_FAIL\r\n", .ExitCode = 1});
633
+ result.Verify(
634
+ {.Stdout = L"", .Stderr = FormatErrorMessage(L"Failed to launch command not-found. Errno = 2", L"E_FAIL"), .ExitCode = 1});
635
}
636
}
637
test/windows/wslc/e2e/WSLCE2EHelpers.h
-5
@@ -23,11 +23,6 @@ Abstract:
23
24
namespace WSLCE2ETests {
25
26
-inline std::wstring FormatWslcError(const std::wstring& message, std::wstring_view errorCode = L"E_INVALIDARG")
27
-{
28
- return std::format(L"{}\r\nError code: {}\r\n", message, errorCode);
29
-}
30
-
26
// VT sequence constants and helpers for TTY testing.
27
// Sequences are sourced from wsl::windows::common::vt (VTSupport.h).
28
namespace VT {
test/windows/wslc/e2e/WSLCE2EImageBuildTests.cpp
+5
-4
@@ -1205,7 +1205,7 @@ class WSLCE2EImageBuildTests
1205
auto buildResult = RunWslc(std::format(L"build \"{}\"", testRoot.wstring()));
1206
buildResult.Verify(
1207
{.Stderr =
1208
- L"Both Dockerfile and Containerfile found. Use -f to select the file to use\r\nError code: E_INVALIDARG\r\n",
1208
+ FormatErrorMessage(L"Both Dockerfile and Containerfile found. Use -f to select the file to use", L"E_INVALIDARG"),
1209
.ExitCode = 1});
1210
}
1211
@@ -1217,7 +1217,8 @@ class WSLCE2EImageBuildTests
1217
auto absolutePath = std::filesystem::absolute(testRoot);
1218
auto buildResult = RunWslc(std::format(L"build \"{}\"", testRoot.wstring()));
1219
buildResult.Verify(
1220
- {.Stderr = std::format(L"No Containerfile or Dockerfile found in '{}'\r\nError code: E_INVALIDARG\r\n", absolutePath.wstring()),
1220
+ {.Stderr = FormatErrorMessage(
1221
+ std::format(L"No Containerfile or Dockerfile found in '{}'", absolutePath.wstring()), L"E_INVALIDARG"),
1222
.ExitCode = 1});
1223
}
1224
@@ -1237,8 +1238,8 @@ class WSLCE2EImageBuildTests
1238
auto absoluteContainerfilePath = std::filesystem::absolute(containerfilePath);
1239
auto buildResult = RunWslc(std::format(L"build \"{}\"", testRoot.wstring()));
1240
buildResult.Verify(
1240
- {.Stderr = std::format(
1241
- L"Failed to open '{}': Access is denied. \r\nError code: E_ACCESSDENIED\r\n", absoluteContainerfilePath.wstring()),
1241
+ {.Stderr = FormatErrorMessage(
1242
+ std::format(L"Failed to open '{}': Access is denied. ", absoluteContainerfilePath.wstring()), L"E_ACCESSDENIED"),
1243
.ExitCode = 1});
1244
}
1245
test/windows/wslc/e2e/WSLCE2EImageDeleteTests.cpp
+10
-7
@@ -52,7 +52,8 @@ class WSLCE2EImageDeleteTests
52
WSLC_TEST_METHOD(WSLCE2E_Image_Delete_ImageNotFound)
53
{
54
auto result = RunWslc(std::format(L"image delete {}", InvalidImage.Name));
55
- auto errorMessage = std::format(L"No such image: {}\r\nError code: WSLC_E_IMAGE_NOT_FOUND\r\n", InvalidImage.NameAndTag());
55
+ auto errorMessage =
56
+ FormatErrorMessage(std::format(L"No such image: {}", InvalidImage.NameAndTag()), L"WSLC_E_IMAGE_NOT_FOUND");
57
result.Verify({.Stdout = L"", .Stderr = errorMessage, .ExitCode = 1});
58
}
59
@@ -99,12 +100,14 @@ class WSLCE2EImageDeleteTests
100
auto imageId = GetHashId(inspectImage.Id);
101
102
auto result = RunWslc(std::format(L"image delete {}", DebianImage.Name));
102
- auto errorMessage = std::format(
103
- L"conflict: unable to remove repository reference \"{}\" (must force) - container {} is using its referenced image "
104
- L"{}\r\nError code: ERROR_SHARING_VIOLATION\r\n",
105
- DebianImage.Name,
106
- containerId,
107
- imageId);
103
+ auto errorMessage = FormatErrorMessage(
104
+ std::format(
105
+ L"conflict: unable to remove repository reference \"{}\" (must force) - container {} is using its referenced "
106
+ L"image {}",
107
+ DebianImage.Name,
108
+ containerId,
109
+ imageId),
110
+ L"ERROR_SHARING_VIOLATION");
111
result.Verify({.Stdout = L"", .Stderr = errorMessage, .ExitCode = 1});
112
}
113
test/windows/wslc/e2e/WSLCE2EImageSaveTests.cpp
+1
-1
@@ -61,7 +61,7 @@ class WSLCE2EImageSaveTests
61
WSLC_TEST_METHOD(WSLCE2E_Image_Save_ImageNotFound)
62
{
63
const auto result = RunWslc(std::format(L"image save --output \"{}\" {}", SavedArchivePath.wstring(), InvalidImage.NameAndTag()));
64
- result.Verify({.Stdout = L"", .Stderr = L"reference does not exist\r\nError code: WSLC_E_IMAGE_NOT_FOUND\r\n", .ExitCode = 1});
64
+ result.Verify({.Stdout = L"", .Stderr = FormatErrorMessage(L"reference does not exist", L"WSLC_E_IMAGE_NOT_FOUND"), .ExitCode = 1});
65
}
66
67
WSLC_TEST_METHOD(WSLCE2E_Image_Save_Success)
test/windows/wslc/e2e/WSLCE2EImageTagTests.cpp
+4
-3
@@ -63,7 +63,8 @@ class WSLCE2EImageTagTests
63
WSLC_TEST_METHOD(WSLCE2E_Image_Tag_SourceImageNotFound)
64
{
65
auto result = RunWslc(std::format(L"image tag {} {}", InvalidImage.NameAndTag(), DebianTaggedImage.NameAndTag()));
66
- auto errorMessage = std::format(L"No such image: {}\r\nError code: WSLC_E_IMAGE_NOT_FOUND\r\n", InvalidImage.NameAndTag());
66
+ auto errorMessage =
67
+ FormatErrorMessage(std::format(L"No such image: {}", InvalidImage.NameAndTag()), L"WSLC_E_IMAGE_NOT_FOUND");
68
result.Verify({.Stdout = L"", .Stderr = errorMessage, .ExitCode = 1});
69
}
70
@@ -71,8 +72,8 @@ class WSLCE2EImageTagTests
72
{
73
auto imageWithDigest = L"debian-mock:tag@sha256:11111111111111111111111111111111";
74
auto result = RunWslc(std::format(L"image tag {} {}", DebianImage.NameAndTag(), imageWithDigest));
74
- auto errorMessage =
75
- std::format(L"Invalid image tag format: '{}'. Expected format is 'name:tag'\r\nError code: E_INVALIDARG\r\n", imageWithDigest);
75
+ auto errorMessage = FormatErrorMessage(
76
+ std::format(L"Invalid image tag format: '{}'. Expected format is 'name:tag'", imageWithDigest), L"E_INVALIDARG");
77
result.Verify({.Stdout = L"", .Stderr = errorMessage, .ExitCode = 1});
78
}
79
test/windows/wslc/e2e/WSLCE2ENetworkCreateTests.cpp
+5
-3
@@ -110,7 +110,9 @@ class WSLCE2ENetworkCreateTests
110
111
result = RunWslc(std::format(L"network create --driver bridge {}", TestNetworkName));
112
result.Verify(
113
- {.Stdout = L"", .Stderr = L"Cannot create a file when that file already exists. \r\nError code: ERROR_ALREADY_EXISTS\r\n", .ExitCode = 1});
113
+ {.Stdout = L"",
114
+ .Stderr = FormatErrorMessage(L"Cannot create a file when that file already exists. ", L"ERROR_ALREADY_EXISTS"),
115
+ .ExitCode = 1});
116
}
117
118
WSLC_TEST_METHOD(WSLCE2E_Network_Create_Internal_Success)
@@ -162,7 +164,7 @@ class WSLCE2ENetworkCreateTests
164
auto result = RunWslc(std::format(L"network create --gateway 172.47.0.1 {}", TestNetworkName));
165
result.Verify(
166
{.Stdout = L"",
165
- .Stderr = L"The '--gateway' option requires '--subnet' to also be specified.\r\nError code: E_INVALIDARG\r\n",
167
+ .Stderr = FormatErrorMessage(L"The '--gateway' option requires '--subnet' to also be specified.", L"E_INVALIDARG"),
168
.ExitCode = 1});
169
170
VerifyNetworkIsNotListed(TestNetworkName);
@@ -190,7 +192,7 @@ class WSLCE2ENetworkCreateTests
192
auto result = RunWslc(std::format(L"network create --ip-range 172.52.10.0/24 {}", TestNetworkName));
193
result.Verify(
194
{.Stdout = L"",
193
- .Stderr = L"The '--ip-range' option requires '--subnet' to also be specified.\r\nError code: E_INVALIDARG\r\n",
195
+ .Stderr = FormatErrorMessage(L"The '--ip-range' option requires '--subnet' to also be specified.", L"E_INVALIDARG"),
196
.ExitCode = 1});
197
198
VerifyNetworkIsNotListed(TestNetworkName);
test/windows/wslc/e2e/WSLCE2ENetworkTests.cpp
+13
-6
@@ -132,7 +132,8 @@ class WSLCE2ENetworkTests
132
133
result = RunWslc(std::format(L"network connect {} {}", TestNetworkName, WslcContainerName));
134
result.Verify(
135
- {.Stderr = std::format(L"Network not found: '{}'\r\nError code: WSLC_E_NETWORK_NOT_FOUND\r\n", TestNetworkName), .ExitCode = 1});
135
+ {.Stderr = FormatErrorMessage(std::format(L"Network not found: '{}'", TestNetworkName), L"WSLC_E_NETWORK_NOT_FOUND"),
136
+ .ExitCode = 1});
137
}
138
139
WSLC_TEST_METHOD(WSLCE2E_Network_Connect_UnknownContainer)
@@ -142,7 +143,8 @@ class WSLCE2ENetworkTests
143
144
result = RunWslc(std::format(L"network connect {} {}", TestNetworkName, WslcContainerName));
145
result.Verify(
145
- {.Stderr = std::format(L"Container '{}' not found.\r\nError code: WSLC_E_CONTAINER_NOT_FOUND\r\n", WslcContainerName),
146
+ {.Stderr =
147
+ FormatErrorMessage(std::format(L"Container '{}' not found.", WslcContainerName), L"WSLC_E_CONTAINER_NOT_FOUND"),
148
.ExitCode = 1});
149
}
150
@@ -160,7 +162,8 @@ class WSLCE2ENetworkTests
162
VERIFY_IS_TRUE(result.Stderr.has_value());
163
VerifyPatternMatch(
164
string::WideToMultiByte(result.Stderr.value()),
163
- "*does not support connecting or disconnecting additional networks*Error code: *\r\n");
165
+ string::WideToMultiByte(
166
+ FormatErrorMessage(L"*does not support connecting or disconnecting additional networks*", L"*")));
167
}
168
169
WSLC_TEST_METHOD(WSLCE2E_Network_Connect_AlreadyConnected_DockerErrorPropagated)
@@ -175,7 +178,9 @@ class WSLCE2ENetworkTests
178
result = RunWslc(std::format(L"network connect {} {}", TestNetworkName, WslcContainerName));
179
VERIFY_ARE_EQUAL(1u, result.ExitCode.value());
180
VERIFY_IS_TRUE(result.Stderr.has_value());
178
- VerifyPatternMatch(string::WideToMultiByte(result.Stderr.value()), "*already exists*Error code: *\r\n");
181
+ VerifyPatternMatch(
182
+ string::WideToMultiByte(result.Stderr.value()),
183
+ string::WideToMultiByte(FormatErrorMessage(L"*already exists*", L"*")));
184
}
185
186
WSLC_TEST_METHOD(WSLCE2E_Network_Connect_WithEndpointFlags_RoundTrips)
@@ -310,7 +315,8 @@ class WSLCE2ENetworkTests
315
316
result = RunWslc(std::format(L"network disconnect {} {}", TestNetworkName, WslcContainerName));
317
result.Verify(
313
- {.Stderr = std::format(L"Network not found: '{}'\r\nError code: WSLC_E_NETWORK_NOT_FOUND\r\n", TestNetworkName), .ExitCode = 1});
318
+ {.Stderr = FormatErrorMessage(std::format(L"Network not found: '{}'", TestNetworkName), L"WSLC_E_NETWORK_NOT_FOUND"),
319
+ .ExitCode = 1});
320
}
321
322
WSLC_TEST_METHOD(WSLCE2E_Network_Disconnect_UnknownContainer)
@@ -320,7 +326,8 @@ class WSLCE2ENetworkTests
326
327
result = RunWslc(std::format(L"network disconnect {} {}", TestNetworkName, WslcContainerName));
328
result.Verify(
323
- {.Stderr = std::format(L"Container '{}' not found.\r\nError code: WSLC_E_CONTAINER_NOT_FOUND\r\n", WslcContainerName),
329
+ {.Stderr =
330
+ FormatErrorMessage(std::format(L"Container '{}' not found.", WslcContainerName), L"WSLC_E_CONTAINER_NOT_FOUND"),
331
.ExitCode = 1});
332
}
333
test/windows/wslc/e2e/WSLCE2EPushPullTests.cpp
+4
-3
@@ -126,16 +126,17 @@ class WSLCE2EPushPullTests
126
WSLC_TEST_METHOD(WSLCE2E_Image_Push_NonExistentImage)
127
{
128
auto result = RunWslc(L"push does-not-exist:latest");
129
- auto errorMessage = L"An image does not exist locally with the tag: does-not-exist\r\nError code: E_FAIL\r\n";
129
+ auto errorMessage = FormatErrorMessage(L"An image does not exist locally with the tag: does-not-exist", L"E_FAIL");
130
result.Verify({.Stderr = errorMessage, .ExitCode = 1});
131
}
132
133
WSLC_TEST_METHOD(WSLCE2E_Image_Pull_NonExistentImage)
134
{
135
auto result = RunWslc(L"pull does-not-exist:latest");
136
- auto errorMessage =
136
+ auto errorMessage = FormatErrorMessage(
137
L"pull access denied for does-not-exist, repository does not exist or may require 'docker login': denied: requested "
138
- L"access to the resource is denied\r\nError code: WSLC_E_IMAGE_NOT_FOUND\r\n";
138
+ L"access to the resource is denied",
139
+ L"WSLC_E_IMAGE_NOT_FOUND");
140
result.Verify({.Stdout = L"", .Stderr = errorMessage, .ExitCode = 1});
141
}
142
test/windows/wslc/e2e/WSLCE2ESessionEnterTests.cpp
+2
-2
@@ -115,8 +115,8 @@ class WSLCE2ESessionEnterTests
115
// found in '<path>'" message rather than a bare system error.
116
const auto storagePath = std::filesystem::absolute(L"does-not-exist").wstring();
117
result.Verify({
118
- .Stderr = wsl::shared::Localization::MessageWslcSessionStorageNotFound(storagePath) +
119
- L"\r\nError code: ERROR_PATH_NOT_FOUND\r\n",
118
+ .Stderr = FormatErrorMessage(
119
+ wsl::shared::Localization::MessageWslcSessionStorageNotFound(storagePath), L"ERROR_PATH_NOT_FOUND"),
120
.ExitCode = 1,
121
});
122
}
test/windows/wslc/e2e/WSLCE2EVolumeRemoveTests.cpp
+2
-2
@@ -127,7 +127,7 @@ class WSLCE2EVolumeRemoveTests
127
result = RunWslc(std::format(L"volume remove {}", TestVolumeName));
128
result.Verify(
129
{.Stdout = L"",
130
- .Stderr = std::format(L"Volume '{}' is in use.\r\nError code: ERROR_SHARING_VIOLATION\r\n", TestVolumeName),
130
+ .Stderr = FormatErrorMessage(std::format(L"Volume '{}' is in use.", TestVolumeName), L"ERROR_SHARING_VIOLATION"),
131
.ExitCode = 1});
132
133
VerifyVolumeIsListed(TestVolumeName);
@@ -182,7 +182,7 @@ class WSLCE2EVolumeRemoveTests
182
result = RunWslc(std::format(L"volume remove --force {}", TestVolumeName));
183
result.Verify(
184
{.Stdout = L"",
185
- .Stderr = std::format(L"Volume '{}' is in use.\r\nError code: ERROR_SHARING_VIOLATION\r\n", TestVolumeName),
185
+ .Stderr = FormatErrorMessage(std::format(L"Volume '{}' is in use.", TestVolumeName), L"ERROR_SHARING_VIOLATION"),
186
.ExitCode = 1});
187
188
VerifyVolumeIsListed(TestVolumeName);