51
} \
52
CATCH_LOG()
53
#define SCOPE_CLEANUP(operation) wil::scope_exit([&]() { IGNORE_ERRORS(operation) })
54
-#define DELETE_CONTAINER_ON_SCOPE_EXIT(container) SCOPE_CLEANUP(container.Delete(WSLCSDK::DeleteContainerFlags::Force))
54
+#define DELETE_CONTAINER_ON_SCOPE_EXIT(container) SCOPE_CLEANUP(container.Delete(WSLCSDK::DeleteContainerOption::Force))
55
#define DELETE_IMAGE_ON_SCOPE_EXIT(imageName) SCOPE_CLEANUP(m_defaultSession.DeleteImage(imageName))
56
57
struct ProcessOutput
152
153
struct RunContainerOptions
154
{
155
- std::vector<winrt::hstring> cmdLine = {};
156
- WSLCSDK::ContainerFlags flags = WSLCSDK::ContainerFlags::None;
155
+ std::vector<winrt::hstring> commandLine = {};
156
+ bool enableGpu = false;
157
std::optional<winrt::hstring> name = std::nullopt;
158
std::chrono::milliseconds timeout = 2min;
159
std::optional<WSLCSDK::ContainerNetworkingMode> networkingMode = std::nullopt;
164
ProcessOutput RunContainerAndWaitForExit(winrt::hstring imageName, RunContainerOptions options = {})
165
{
166
auto procSettings = WSLCSDK::ProcessSettings();
167
- if (!options.cmdLine.empty())
167
+ if (!options.commandLine.empty())
168
{
169
- procSettings.CmdLine(winrt::single_threaded_vector(std::move(options.cmdLine)));
169
+ procSettings.CommandLine(winrt::single_threaded_vector(std::move(options.commandLine)));
170
}
171
172
procSettings.OutputMode(WSLCSDK::ProcessOutputMode::Stream);
173
174
auto containerSettings = WSLCSDK::ContainerSettings(imageName);
175
containerSettings.InitProcess(procSettings);
176
- containerSettings.Flags(options.flags);
176
+ containerSettings.EnableGpu(options.enableGpu);
177
178
if (options.name)
179
{
191
StartContainerAndWaitForInitProcessExit(container, options.timeout);
192
auto output = GetProcessOutput(container.InitProcess());
193
194
- IGNORE_ERRORS(container.Delete(WSLCSDK::DeleteContainerFlags::Force));
194
+ IGNORE_ERRORS(container.Delete(WSLCSDK::DeleteContainerOption::Force));
195
196
return output;
197
}
198
199
bool HasImage(winrt::hstring const& imageName)
200
{
201
- auto images = m_defaultSession.Images();
201
+ auto images = m_defaultSession.GetImages();
202
return std::any_of(images.begin(), images.end(), [&](auto const& img) { return img.Name() == imageName; });
203
}
204
244
// Build session settings using the WinRT API
245
auto settings = WSLCSDK::SessionSettings(c_testSessionName, m_storagePath.wstring());
246
settings.CpuCount(4);
247
- settings.MemoryMB(2048);
247
+ settings.MemorySizeInMB(2048);
248
settings.Timeout(std::chrono::duration_cast<TimeSpan>(30s));
249
settings.VhdRequirements(WSLCSDK::VhdOptions(L"", 4096ull * 1024 * 1024, WSLCSDK::VhdType::Dynamic));
250
293
294
auto settings = WSLCSDK::SessionSettings(L"wslc-winrt-extra-session", extraStorage.wstring());
295
settings.CpuCount(2);
296
- settings.MemoryMB(1024);
296
+ settings.MemorySizeInMB(1024);
297
settings.Timeout(std::chrono::duration_cast<TimeSpan>(30s));
298
settings.VhdRequirements(WSLCSDK::VhdOptions(L"", 1024ull * 1024 * 1024, WSLCSDK::VhdType::Dynamic));
299
306
// Negative: Must throw if used before Start()
307
{
308
auto session = WSLCSDK::Session(settings);
309
- VERIFY_THROWS_HR(std::ignore = session.Images(), E_ILLEGAL_METHOD_CALL);
309
+ VERIFY_THROWS_HR(std::ignore = session.GetImages(), E_ILLEGAL_METHOD_CALL);
310
}
311
312
// Positive: Starting the session must succeed.
350
// drops kill()-sent signals with default disposition when targeting PID 1 in a
351
// PID namespace, so no core dump would be generated if we crash the init process.
352
auto initProcSettings = WSLCSDK::ProcessSettings();
353
- initProcSettings.CmdLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/sleep", L"99"}));
353
+ initProcSettings.CommandLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/sleep", L"99"}));
354
355
auto containerSettings = WSLCSDK::ContainerSettings(L"debian:latest");
356
containerSettings.InitProcess(initProcSettings);
375
});
376
377
auto execSettings = WSLCSDK::ProcessSettings();
378
- execSettings.CmdLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/sh", L"-c", L"kill -SEGV $$"}));
378
+ execSettings.CommandLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/sh", L"-c", L"kill -SEGV $$"}));
379
380
const auto beforeCrash = winrt::clock::now();
381
StartProcessAndWaitForExit(container.CreateProcess(execSettings), 30s);
407
}
408
409
auto execSettings = WSLCSDK::ProcessSettings();
410
- execSettings.CmdLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/sh", L"-c", L"kill -SEGV $$"}));
410
+ execSettings.CommandLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/sh", L"-c", L"kill -SEGV $$"}));
411
412
StartProcessAndWaitForExit(container.CreateProcess(execSettings), 60s);
413
449
WSLC_TEST_METHOD(ImageList)
450
{
451
// Session has images pre-loaded - list must return at least one entry.
452
- const auto images = m_defaultSession.Images();
452
+ const auto images = m_defaultSession.GetImages();
453
VERIFY_IS_TRUE(images.Size() >= 1);
454
455
// At least one image must be non-empty
456
bool foundNonEmpty = false;
457
for (auto const& img : images)
458
{
459
- if (!img.Name().empty() && img.SizeBytes() != 0)
459
+ if (!img.Name().empty() && img.Size() != 0)
460
{
461
foundNonEmpty = true;
462
break;
510
511
VERIFY_IS_TRUE(HasImage(c_importedImageName));
512
513
- auto output = RunContainerAndWaitForExit(c_importedImageName, {.cmdLine = {L"/hello"}});
513
+ auto output = RunContainerAndWaitForExit(c_importedImageName, {.commandLine = {L"/hello"}});
514
VERIFY_ARE_EQUAL(output.ExitCode, 0);
515
VERIFY_IS_TRUE(output.StandardOutput.find(L"Hello from Docker!") != std::string::npos);
516
}
560
{
561
// Positive: stdout is captured correctly.
562
{
563
- auto output = RunContainerAndWaitForExit(L"debian:latest", {.cmdLine = {L"/bin/echo", L"OK"}});
563
+ auto output = RunContainerAndWaitForExit(L"debian:latest", {.commandLine = {L"/bin/echo", L"OK"}});
564
VERIFY_ARE_EQUAL(output.ExitCode, 0);
565
VERIFY_ARE_EQUAL(output.StandardOutput, L"OK\n");
566
VERIFY_ARE_EQUAL(output.StandardError, L"");
568
569
// Positive: stdout and stderr are routed independently.
570
{
571
- auto output =
572
- RunContainerAndWaitForExit(L"debian:latest", {.cmdLine = {L"/bin/sh", L"-c", L"echo stdout && echo stderr >&2"}});
571
+ auto output = RunContainerAndWaitForExit(
572
+ L"debian:latest", {.commandLine = {L"/bin/sh", L"-c", L"echo stdout && echo stderr >&2"}});
573
VERIFY_ARE_EQUAL(output.ExitCode, 0);
574
VERIFY_ARE_EQUAL(output.StandardOutput, L"stdout\n");
575
VERIFY_ARE_EQUAL(output.StandardError, L"stderr\n");
606
WSLC_TEST_METHOD(ContainerGetState)
607
{
608
auto procSettings = WSLCSDK::ProcessSettings();
609
- procSettings.CmdLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/sleep", L"99"}));
609
+ procSettings.CommandLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/sleep", L"99"}));
610
611
auto containerSettings = WSLCSDK::ContainerSettings(L"debian:latest");
612
containerSettings.InitProcess(procSettings);
631
WSLC_TEST_METHOD(ContainerStopAndDelete)
632
{
633
auto procSettings = WSLCSDK::ProcessSettings();
634
- procSettings.CmdLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/sleep", L"999"}));
634
+ procSettings.CommandLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/sleep", L"999"}));
635
636
auto containerSettings = WSLCSDK::ContainerSettings(L"debian:latest");
637
containerSettings.InitProcess(procSettings);
644
VERIFY_NO_THROW(container.Stop(WSLCSDK::Signal::SIGKILL, TimeSpan::zero()));
645
VERIFY_ARE_EQUAL(container.State(), WSLCSDK::ContainerState::Exited);
646
647
- VERIFY_NO_THROW(container.Delete(WSLCSDK::DeleteContainerFlags::None));
647
+ VERIFY_NO_THROW(container.Delete(WSLCSDK::DeleteContainerOption::None));
648
VERIFY_ARE_EQUAL(container.State(), WSLCSDK::ContainerState::Deleted);
649
}
650
651
WSLC_TEST_METHOD(ProcessIOHandles)
652
{
653
auto procSettings = WSLCSDK::ProcessSettings();
654
- procSettings.CmdLine(
654
+ procSettings.CommandLine(
655
winrt::single_threaded_vector<winrt::hstring>({L"/bin/sh", L"-c", L"echo STDOUT_TOKEN; echo STDERR_TOKEN >&2"}));
656
procSettings.OutputMode(WSLCSDK::ProcessOutputMode::Stream);
657
689
{
690
auto output = RunContainerAndWaitForExit(
691
L"debian:latest",
692
- {.cmdLine = {L"/bin/sh", L"-c", L"[ -d /sys/class/net/eth0 ] && echo 'HAS_ETH0' || echo 'NO_ETH0'"},
693
- .flags = WSLCSDK::ContainerFlags::None,
692
+ {.commandLine = {L"/bin/sh", L"-c", L"[ -d /sys/class/net/eth0 ] && echo 'HAS_ETH0' || echo 'NO_ETH0'"},
693
.networkingMode = WSLCSDK::ContainerNetworkingMode::Bridged});
694
695
VERIFY_ARE_EQUAL(output.StandardOutput, L"HAS_ETH0\n");
699
{
700
auto output = RunContainerAndWaitForExit(
701
L"debian:latest",
703
- {.cmdLine = {L"/bin/sh", L"-c", L"[ -d /sys/class/net/eth0 ] && echo 'HAS_ETH0' || echo 'NO_ETH0'"},
704
- .flags = WSLCSDK::ContainerFlags::None,
702
+ {.commandLine = {L"/bin/sh", L"-c", L"[ -d /sys/class/net/eth0 ] && echo 'HAS_ETH0' || echo 'NO_ETH0'"},
703
.networkingMode = WSLCSDK::ContainerNetworkingMode::None});
704
705
VERIFY_ARE_EQUAL(output.StandardOutput, L"NO_ETH0\n");
727
// Functional: BRIDGED networking with port mapping; HTTP server must be reachable.
728
{
729
auto procSettings = WSLCSDK::ProcessSettings();
732
- procSettings.CmdLine(winrt::single_threaded_vector<winrt::hstring>({L"python3", L"-m", L"http.server", L"8000"}));
730
+ procSettings.CommandLine(winrt::single_threaded_vector<winrt::hstring>({L"python3", L"-m", L"http.server", L"8000"}));
731
procSettings.EnvironmentVariables(
732
winrt::single_threaded_map(std::map<winrt::hstring, winrt::hstring>{{L"PYTHONUNBUFFERED", L"1"}}));
733
procSettings.OutputMode(WSLCSDK::ProcessOutputMode::Stream);
752
// Functional: port mapping with explicit IPv4 WindowsAddress.
753
{
754
auto procSettings = WSLCSDK::ProcessSettings();
757
- procSettings.CmdLine(winrt::single_threaded_vector<winrt::hstring>({L"python3", L"-m", L"http.server", L"8000"}));
755
+ procSettings.CommandLine(winrt::single_threaded_vector<winrt::hstring>({L"python3", L"-m", L"http.server", L"8000"}));
756
procSettings.EnvironmentVariables(
757
winrt::single_threaded_map(std::map<winrt::hstring, winrt::hstring>{{L"PYTHONUNBUFFERED", L"1"}}));
758
procSettings.OutputMode(WSLCSDK::ProcessOutputMode::Stream);
779
// Functional: port mapping with explicit IPv6 WindowsAddress.
780
{
781
auto procSettings = WSLCSDK::ProcessSettings();
784
- procSettings.CmdLine(
782
+ procSettings.CommandLine(
783
winrt::single_threaded_vector<winrt::hstring>({L"python3", L"-m", L"http.server", L"--bind", L"::", L"8000"}));
784
procSettings.EnvironmentVariables(
785
winrt::single_threaded_map(std::map<winrt::hstring, winrt::hstring>{{L"PYTHONUNBUFFERED", L"1"}}));
835
containerSettings.Volumes(winrt::single_threaded_vector<WSLCSDK::ContainerVolume>(
836
{WSLCSDK::ContainerVolume(currentDirectory, L"/mnt/path", false)}));
837
auto container = m_defaultSession.CreateContainer(containerSettings);
840
- container.Delete(WSLCSDK::DeleteContainerFlags::None);
838
+ container.Delete(WSLCSDK::DeleteContainerOption::None);
839
}
840
}
841
867
"! touch /mnt/ro/probe 2>/dev/null";
868
869
auto procSettings = WSLCSDK::ProcessSettings();
872
- procSettings.CmdLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/sh", L"-c", winrt::to_hstring(c_script)}));
870
+ procSettings.CommandLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/sh", L"-c", winrt::to_hstring(c_script)}));
871
872
auto containerSettings = WSLCSDK::ContainerSettings(L"debian:latest");
873
containerSettings.InitProcess(procSettings);
880
StartContainerAndWaitForInitProcessExit(container);
881
882
VERIFY_ARE_EQUAL(container.InitProcess().ExitCode(), 0);
885
- container.Delete(WSLCSDK::DeleteContainerFlags::Force);
883
+ container.Delete(WSLCSDK::DeleteContainerOption::Force);
884
885
// Verify the file written by the container is visible on the host.
886
std::ifstream written(hostRwDir / "written.txt");
903
// The inspect JSON must contain the container ID.
904
VERIFY_IS_TRUE(winrt::to_string(inspectJson).find(winrt::to_string(id)) != std::string::npos);
905
908
- container.Delete(WSLCSDK::DeleteContainerFlags::None);
906
+ container.Delete(WSLCSDK::DeleteContainerOption::None);
907
cleanup.release();
908
}
909
911
{
912
// Start a long-running container so we can exec into it.
913
auto initProcSettings = WSLCSDK::ProcessSettings();
916
- initProcSettings.CmdLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/sleep", L"99"}));
914
+ initProcSettings.CommandLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/sleep", L"99"}));
915
916
auto containerSettings = WSLCSDK::ContainerSettings(L"debian:latest");
917
containerSettings.InitProcess(initProcSettings);
924
// Positive: exec a command that exits 0.
925
{
926
auto execSettings = WSLCSDK::ProcessSettings();
929
- execSettings.CmdLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/true"}));
927
+ execSettings.CommandLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/true"}));
928
929
auto execProcess = container.CreateProcess(execSettings);
930
StartProcessAndWaitForExit(execProcess);
946
// Functional: container process should see the configured hostname.
947
{
948
auto procSettings = WSLCSDK::ProcessSettings();
951
- procSettings.CmdLine(
949
+ procSettings.CommandLine(
950
winrt::single_threaded_vector<winrt::hstring>({L"/bin/sh", L"-c", L"test \"$(hostname)\" = my-test-host"}));
951
952
auto containerSettings = WSLCSDK::ContainerSettings(L"debian:latest");
956
auto container = m_defaultSession.CreateContainer(containerSettings);
957
StartContainerAndWaitForInitProcessExit(container);
958
VERIFY_ARE_EQUAL(container.InitProcess().ExitCode(), 0);
961
- container.Delete(WSLCSDK::DeleteContainerFlags::Force);
959
+ container.Delete(WSLCSDK::DeleteContainerOption::Force);
960
}
961
}
962
963
WSLC_TEST_METHOD(ContainerDomainName)
964
{
965
auto procSettings = WSLCSDK::ProcessSettings();
968
- procSettings.CmdLine(
966
+ procSettings.CommandLine(
967
winrt::single_threaded_vector<winrt::hstring>({L"/bin/sh", L"-c", L"test \"$(domainname)\" = test.local"}));
968
969
auto containerSettings = WSLCSDK::ContainerSettings(L"debian:latest");
973
auto container = m_defaultSession.CreateContainer(containerSettings);
974
StartContainerAndWaitForInitProcessExit(container);
975
VERIFY_ARE_EQUAL(container.InitProcess().ExitCode(), 0);
978
- container.Delete(WSLCSDK::DeleteContainerFlags::Force);
976
+ container.Delete(WSLCSDK::DeleteContainerOption::Force);
977
}
978
979
// -----------------------------------------------------------------------
983
WSLC_TEST_METHOD(ProcessEnvVariables)
984
{
985
auto procSettings = WSLCSDK::ProcessSettings();
988
- procSettings.CmdLine(
986
+ procSettings.CommandLine(
987
winrt::single_threaded_vector<winrt::hstring>({L"/bin/sh", L"-c", L"test \"$MY_TEST_VAR\" = hello-from-test"}));
988
procSettings.EnvironmentVariables(
989
winrt::single_threaded_map(std::map<winrt::hstring, winrt::hstring>{{L"MY_TEST_VAR", L"hello-from-test"}}));
994
auto container = m_defaultSession.CreateContainer(containerSettings);
995
StartContainerAndWaitForInitProcessExit(container);
996
VERIFY_ARE_EQUAL(container.InitProcess().ExitCode(), 0);
999
- container.Delete(WSLCSDK::DeleteContainerFlags::Force);
997
+ container.Delete(WSLCSDK::DeleteContainerOption::Force);
998
}
999
1000
WSLC_TEST_METHOD(ProcessSignal)
1006
}
1007
1008
auto procSettings = WSLCSDK::ProcessSettings();
1011
- procSettings.CmdLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/sleep", L"99"}));
1009
+ procSettings.CommandLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/sleep", L"99"}));
1010
1011
auto containerSettings = WSLCSDK::ContainerSettings(L"debian:latest");
1012
containerSettings.InitProcess(procSettings);
1039
}
1040
1041
auto procSettings = WSLCSDK::ProcessSettings();
1044
- procSettings.CmdLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/sleep", L"99"}));
1042
+ procSettings.CommandLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/sleep", L"99"}));
1043
1044
auto containerSettings = WSLCSDK::ContainerSettings(L"debian:latest");
1045
containerSettings.InitProcess(procSettings);
1057
{
1058
auto runAndGetExitCode = [&](int code) -> int32_t {
1059
auto procSettings = WSLCSDK::ProcessSettings();
1062
- procSettings.CmdLine(
1060
+ procSettings.CommandLine(
1061
winrt::single_threaded_vector<winrt::hstring>({L"/bin/sh", L"-c", winrt::to_hstring(std::format("exit {}", code))}));
1062
1063
auto containerSettings = WSLCSDK::ContainerSettings(L"debian:latest");
1067
StartContainerAndWaitForInitProcessExit(container);
1068
auto exitCode = container.InitProcess().ExitCode();
1069
1072
- container.Delete(WSLCSDK::DeleteContainerFlags::Force);
1070
+ container.Delete(WSLCSDK::DeleteContainerOption::Force);
1071
return exitCode;
1072
};
1073
1077
// Negative: querying ExitCode while process is still running must throw.
1078
{
1079
auto procSettings = WSLCSDK::ProcessSettings();
1082
- procSettings.CmdLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/sleep", L"99"}));
1080
+ procSettings.CommandLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/sleep", L"99"}));
1081
1082
auto containerSettings = WSLCSDK::ContainerSettings(L"debian:latest");
1083
containerSettings.InitProcess(procSettings);
1097
WSLC_TEST_METHOD(ProcessGetState)
1098
{
1099
auto procSettings = WSLCSDK::ProcessSettings();
1102
- procSettings.CmdLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/sleep", L"99"}));
1100
+ procSettings.CommandLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/sleep", L"99"}));
1101
1102
auto containerSettings = WSLCSDK::ContainerSettings(L"debian:latest");
1103
containerSettings.InitProcess(procSettings);
1134
{
1135
// Functional: container should see the configured working directory.
1136
auto procSettings = WSLCSDK::ProcessSettings();
1139
- procSettings.CmdLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/sh", L"-c", L"test \"$(pwd)\" = /tmp"}));
1137
+ procSettings.CommandLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/sh", L"-c", L"test \"$(pwd)\" = /tmp"}));
1138
procSettings.WorkingDirectory(L"/tmp");
1139
1140
auto containerSettings = WSLCSDK::ContainerSettings(L"debian:latest");
1143
auto container = m_defaultSession.CreateContainer(containerSettings);
1144
StartContainerAndWaitForInitProcessExit(container);
1145
VERIFY_ARE_EQUAL(container.InitProcess().ExitCode(), 0);
1148
- container.Delete(WSLCSDK::DeleteContainerFlags::Force);
1146
+ container.Delete(WSLCSDK::DeleteContainerOption::Force);
1147
}
1148
1149
// -----------------------------------------------------------------------
1159
WSLC_TEST_METHOD(GetMissingComponents)
1160
{
1161
const auto missing = WSLCSDK::WslcService::GetMissingComponents();
1164
- VERIFY_ARE_EQUAL(missing, WSLCSDK::ComponentFlags::None);
1162
+ VERIFY_ARE_EQUAL(missing.Size(), 0u);
1163
}
1164
1165
WSLC_TEST_METHOD(InstallWithDependencies)
1166
{
1167
WSLCSDK::WslcService::InstallWithDependenciesAsync().get();
1170
- VERIFY_ARE_EQUAL(WSLCSDK::WslcService::GetMissingComponents(), WSLCSDK::ComponentFlags::None);
1168
+ VERIFY_ARE_EQUAL(WSLCSDK::WslcService::GetMissingComponents().Size(), 0u);
1169
}
1170
1171
// -----------------------------------------------------------------------
1177
// Negative: registering OutputReceived/ErrorReceived without OutputMode::Event must throw.
1178
{
1179
auto procSettings = WSLCSDK::ProcessSettings();
1182
- procSettings.CmdLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/sleep", L"1"}));
1180
+ procSettings.CommandLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/sleep", L"1"}));
1181
1182
auto containerSettings = WSLCSDK::ContainerSettings(L"debian:latest");
1183
containerSettings.InitProcess(procSettings);
1197
// Positive: with OutputMode::Event, registering and revoking event handlers must succeed.
1198
{
1199
auto procSettings = WSLCSDK::ProcessSettings();
1202
- procSettings.CmdLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/sleep", L"1"}));
1200
+ procSettings.CommandLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/sleep", L"1"}));
1201
procSettings.OutputMode(WSLCSDK::ProcessOutputMode::Event);
1202
1203
auto containerSettings = WSLCSDK::ContainerSettings(L"debian:latest");
1224
// Negative: OutputReceived/ErrorReceived with OutputMode::Stream must throw.
1225
{
1226
auto procSettings = WSLCSDK::ProcessSettings();
1229
- procSettings.CmdLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/sleep", L"1"}));
1227
+ procSettings.CommandLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/sleep", L"1"}));
1228
procSettings.OutputMode(WSLCSDK::ProcessOutputMode::Stream);
1229
1230
auto containerSettings = WSLCSDK::ContainerSettings(L"debian:latest");
1244
std::string stdoutData, stderrData;
1245
1246
auto procSettings = WSLCSDK::ProcessSettings();
1249
- procSettings.CmdLine(
1247
+ procSettings.CommandLine(
1248
winrt::single_threaded_vector<winrt::hstring>({L"/bin/sh", L"-c", L"echo STDOUT && echo STDERR >&2"}));
1249
procSettings.OutputMode(WSLCSDK::ProcessOutputMode::Event);
1250
1272
{
1273
// Long-running init process to keep the container alive.
1274
auto initProcSettings = WSLCSDK::ProcessSettings();
1277
- initProcSettings.CmdLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/sleep", L"99"}));
1275
+ initProcSettings.CommandLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/sleep", L"99"}));
1276
1277
auto containerSettings = WSLCSDK::ContainerSettings(L"debian:latest");
1278
containerSettings.InitProcess(initProcSettings);
1285
std::string stdoutData, stderrData;
1286
1287
auto execProcSettings = WSLCSDK::ProcessSettings();
1290
- execProcSettings.CmdLine(
1288
+ execProcSettings.CommandLine(
1289
winrt::single_threaded_vector<winrt::hstring>({L"/bin/sh", L"-c", L"echo EXEC_OUT && echo EXEC_ERR >&2"}));
1290
execProcSettings.OutputMode(WSLCSDK::ProcessOutputMode::Event);
1291
1310
// (draining uncallbacked streams to prevent deadlock), so both stdout and stderr
1311
// handles are consumed and neither can be obtained via GetOutputStream.
1312
auto procSettings = WSLCSDK::ProcessSettings();
1315
- procSettings.CmdLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/sleep", L"99"}));
1313
+ procSettings.CommandLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/sleep", L"99"}));
1314
procSettings.OutputMode(WSLCSDK::ProcessOutputMode::Event);
1315
1316
auto containerSettings = WSLCSDK::ContainerSettings(L"debian:latest");
1339
std::promise<int32_t> exitPromise;
1340
1341
auto procSettings = WSLCSDK::ProcessSettings();
1344
- procSettings.CmdLine(winrt::single_threaded_vector<winrt::hstring>(
1342
+ procSettings.CommandLine(winrt::single_threaded_vector<winrt::hstring>(
1343
{L"/bin/sh", L"-c", winrt::hstring(std::format(L"echo HELLO && exit {}", exitCodeArg))}));
1344
procSettings.OutputMode(WSLCSDK::ProcessOutputMode::Event);
1345
1386
1387
// Long-running init process to keep the container alive.
1388
auto initProcSettings = WSLCSDK::ProcessSettings();
1391
- initProcSettings.CmdLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/sleep", L"999"}));
1389
+ initProcSettings.CommandLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/sleep", L"999"}));
1390
1391
auto containerSettings = WSLCSDK::ContainerSettings(L"debian:latest");
1392
containerSettings.InitProcess(initProcSettings);
1400
std::atomic<bool> exitFired{false};
1401
1402
auto execProcSettings = WSLCSDK::ProcessSettings();
1405
- execProcSettings.CmdLine(
1403
+ execProcSettings.CommandLine(
1404
winrt::single_threaded_vector<winrt::hstring>({L"/bin/sh", L"-c", L"while true; do echo LINE; sleep 0.05; done"}));
1405
execProcSettings.OutputMode(WSLCSDK::ProcessOutputMode::Event);
1406
1439
stdoutData.reserve(c_expectedBytes + 4096);
1440
1441
auto procSettings = WSLCSDK::ProcessSettings();
1444
- procSettings.CmdLine(winrt::single_threaded_vector<winrt::hstring>(
1442
+ procSettings.CommandLine(winrt::single_threaded_vector<winrt::hstring>(
1443
{L"/bin/sh", L"-c", L"dd if=/dev/zero bs=1024 count=1024 2>/dev/null | base64 -w 0"}));
1444
procSettings.OutputMode(WSLCSDK::ProcessOutputMode::Event);
1445
1493
// Positive: write a marker via a container that mounts the named volume.
1494
{
1495
auto procSettings = WSLCSDK::ProcessSettings();
1498
- procSettings.CmdLine(winrt::single_threaded_vector<winrt::hstring>(
1496
+ procSettings.CommandLine(winrt::single_threaded_vector<winrt::hstring>(
1497
{L"/bin/sh", L"-c", L"echo wslc-winrt-vhd-test > /data/marker.txt"}));
1498
1499
auto containerSettings = WSLCSDK::ContainerSettings(L"debian:latest");
1504
auto container = session.CreateContainer(containerSettings);
1505
StartContainerAndWaitForInitProcessExit(container);
1506
VERIFY_ARE_EQUAL(container.InitProcess().ExitCode(), 0);
1509
- container.Delete(WSLCSDK::DeleteContainerFlags::Force);
1507
+ container.Delete(WSLCSDK::DeleteContainerOption::Force);
1508
}
1509
1510
// Positive: read back the marker in a second container (read-only mount).
1511
{
1512
auto procSettings = WSLCSDK::ProcessSettings();
1515
- procSettings.CmdLine(winrt::single_threaded_vector<winrt::hstring>(
1513
+ procSettings.CommandLine(winrt::single_threaded_vector<winrt::hstring>(
1514
{L"/bin/sh", L"-c", L"test \"$(cat /data/marker.txt)\" = wslc-winrt-vhd-test"}));
1515
1516
auto containerSettings = WSLCSDK::ContainerSettings(L"debian:latest");
1521
auto container = session.CreateContainer(containerSettings);
1522
StartContainerAndWaitForInitProcessExit(container);
1523
VERIFY_ARE_EQUAL(container.InitProcess().ExitCode(), 0);
1526
- container.Delete(WSLCSDK::DeleteContainerFlags::Force);
1524
+ container.Delete(WSLCSDK::DeleteContainerOption::Force);
1525
}
1526
1527
// Positive: delete the volume.
1531
// Negative: zero size must fail.
1532
VERIFY_THROWS_HR(session.CreateVhdVolume(WSLCSDK::VhdOptions(c_volumeName, 0, WSLCSDK::VhdType::Dynamic)), E_INVALIDARG);
1533
1536
- // Positive: fixed-allocation VHD; on-disk file size must be >= SizeBytes.
1534
+ // Positive: fixed-allocation VHD; on-disk file size must be >= Size.
1535
{
1536
constexpr auto c_fixedVolumeName = L"wslc-sdk-vhd-fixed";
1537
constexpr auto c_fixedSizeBytes = 64ull * _1MB;
1544
VERIFY_IS_GREATER_THAN_OR_EQUAL(std::filesystem::file_size(expectedVhdPath), c_fixedSizeBytes);
1545
}
1546
1549
- // Positive: SetOwner() bakes uid/gid into the volume root inode at mkfs time.
1547
+ // Positive: Owner() bakes uid/gid into the volume root inode at mkfs time.
1548
// Verify by stat-ing the mount inside a container.
1549
{
1550
constexpr auto c_ownedVolumeName = L"wslc-sdk-vhd-owned";
1551
auto vhdOptions = WSLCSDK::VhdOptions(c_ownedVolumeName, c_vhdSizeBytes, WSLCSDK::VhdType::Dynamic);
1554
- vhdOptions.SetOwner(65534, 65534); // nobody:nogroup
1552
+ vhdOptions.Owner(WSLCSDK::VhdOwner{65534, 65534}); // nobody:nogroup
1553
session.CreateVhdVolume(vhdOptions);
1554
1555
auto deleteVolume = SCOPE_CLEANUP(session.DeleteVhdVolume(c_ownedVolumeName));
1556
1557
auto procSettings = WSLCSDK::ProcessSettings();
1560
- procSettings.CmdLine(winrt::single_threaded_vector<winrt::hstring>({L"/usr/bin/stat", L"-c", L"%u %g", L"/data"}));
1558
+ procSettings.CommandLine(winrt::single_threaded_vector<winrt::hstring>({L"/usr/bin/stat", L"-c", L"%u %g", L"/data"}));
1559
procSettings.OutputMode(WSLCSDK::ProcessOutputMode::Stream);
1560
1561
auto containerSettings = WSLCSDK::ContainerSettings(L"debian:latest");
1568
auto output = GetProcessOutput(container.InitProcess());
1569
VERIFY_ARE_EQUAL(container.InitProcess().ExitCode(), 0);
1570
VERIFY_ARE_EQUAL(output.StandardOutput, L"65534 65534\n");
1573
- container.Delete(WSLCSDK::DeleteContainerFlags::Force);
1571
+ container.Delete(WSLCSDK::DeleteContainerOption::Force);
1572
}
1573
}
1574
1693
WSLC_TEST_METHOD(ExecOnStoppedContainer)
1694
{
1695
auto procSettings = WSLCSDK::ProcessSettings();
1698
- procSettings.CmdLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/sleep", L"10"}));
1696
+ procSettings.CommandLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/sleep", L"10"}));
1697
1698
auto containerSettings = WSLCSDK::ContainerSettings(L"debian:latest");
1699
containerSettings.InitProcess(procSettings);
1705
1706
// The init process has now exited. Attempting to exec on a stopped container must fail.
1707
auto execSettings = WSLCSDK::ProcessSettings();
1710
- execSettings.CmdLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/echo", L"should-fail"}));
1708
+ execSettings.CommandLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/echo", L"should-fail"}));
1709
1710
VERIFY_THROWS_HR(container.CreateProcess(execSettings).Start(), static_cast<HRESULT>(WSLC_E_CONTAINER_NOT_RUNNING));
1711
}
1713
WSLC_TEST_METHOD(DuplicateContainerName)
1714
{
1715
auto procSettings = WSLCSDK::ProcessSettings();
1718
- procSettings.CmdLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/sleep", L"10"}));
1716
+ procSettings.CommandLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/sleep", L"10"}));
1717
1718
auto containerSettings = WSLCSDK::ContainerSettings(L"debian:latest");
1719
containerSettings.InitProcess(procSettings);
1731
WSLC_TEST_METHOD(DeleteRunningContainerWithoutForce)
1732
{
1733
auto procSettings = WSLCSDK::ProcessSettings();
1736
- procSettings.CmdLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/sleep", L"10"}));
1734
+ procSettings.CommandLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/sleep", L"10"}));
1735
1736
auto containerSettings = WSLCSDK::ContainerSettings(L"debian:latest");
1737
containerSettings.InitProcess(procSettings);
1742
auto cleanup = DELETE_CONTAINER_ON_SCOPE_EXIT(container);
1743
1744
// Deleting a running container without Force must fail.
1747
- VERIFY_THROWS_HR(container.Delete(WSLCSDK::DeleteContainerFlags::None), static_cast<HRESULT>(WSLC_E_CONTAINER_IS_RUNNING));
1745
+ VERIFY_THROWS_HR(container.Delete(WSLCSDK::DeleteContainerOption::None), static_cast<HRESULT>(WSLC_E_CONTAINER_IS_RUNNING));
1746
}
1747
1748
WSLC_TEST_METHOD(DeleteNonExistentImage)
1760
// Negative: creating a GPU container on a session without GPU support must fail.
1761
{
1762
auto containerSettings = WSLCSDK::ContainerSettings(L"debian:latest");
1765
- containerSettings.Flags(WSLCSDK::ContainerFlags::EnableGpu);
1763
+ containerSettings.EnableGpu(true);
1764
1765
VERIFY_THROWS_HR(m_defaultSession.CreateContainer(containerSettings).Start(), HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED));
1766
}
1773
});
1774
1775
auto settings = WSLCSDK::SessionSettings(L"wslc-winrt-gpu-test", gpuStorage.wstring());
1778
- settings.FeatureFlags(WSLCSDK::SessionFeatureFlags::EnableGpu);
1776
+ settings.EnableGpu(true);
1777
settings.VhdRequirements(WSLCSDK::VhdOptions(L"", 4096ull * 1024 * 1024, WSLCSDK::VhdType::Dynamic));
1778
1779
auto gpuSession = WSLCSDK::Session(settings);
1786
// the WSL GPU libraries inside a GPU container.
1787
{
1788
auto procSettings = WSLCSDK::ProcessSettings();
1791
- procSettings.CmdLine(winrt::single_threaded_vector<winrt::hstring>(
1789
+ procSettings.CommandLine(winrt::single_threaded_vector<winrt::hstring>(
1790
{L"/bin/sh",
1791
L"-c",
1792
L"test -c /dev/dxg && test -r /dev/dxg && test -w /dev/dxg && cat /etc/ld.so.conf.d/ld.wsl.conf"}));
1794
1795
auto containerSettings = WSLCSDK::ContainerSettings(L"debian:latest");
1796
containerSettings.InitProcess(procSettings);
1799
- containerSettings.Flags(WSLCSDK::ContainerFlags::EnableGpu);
1797
+ containerSettings.EnableGpu(true);
1798
1799
auto container = gpuSession.CreateContainer(containerSettings);
1800
auto cleanup = DELETE_CONTAINER_ON_SCOPE_EXIT(container);