3331
}
3332
}
3333
3334
+ WSLC_TEST_METHOD(ContainerGpu)
3335
+ {
3336
+
3337
+ // Validate that setting the GPU flag on a non-GPU session fails.
3338
+ {
3339
+ WSLCContainerLauncher launcher("debian:latest", "test-container-gpu-fail");
3340
+ launcher.SetContainerFlags(WSLCContainerFlagsGpu);
3341
+
3342
+ auto [hr, _] = launcher.LaunchNoThrow(*m_defaultSession);
3343
+ VERIFY_ARE_EQUAL(hr, HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED));
3344
+ }
3345
+
3346
+ auto restore = ResetTestSession();
3347
+
3348
+ auto settings = GetDefaultSessionSettings(L"container-gpu-test", true);
3349
+ WI_SetFlag(settings.FeatureFlags, WslcFeatureFlagsGPU);
3350
+
3351
+ auto session = CreateSession(settings);
3352
+
3353
+ // Validate that the GPU is correctly configured for containers init process.
3354
+ {
3355
+ WSLCContainerLauncher launcher(
3356
+ "debian:latest", "test-container-init-gpu", {"/bin/sh", "-c", "test -c /dev/dxg && echo $LD_LIBRARY_PATH"});
3357
+ launcher.SetContainerFlags(WSLCContainerFlagsGpu);
3358
+
3359
+ auto container = launcher.Launch(*session);
3360
+
3361
+ ValidateContainerOutput(container, {{1, "/usr/lib/wsl/lib\n"}}, 0);
3362
+ }
3363
+
3364
+ // Validate that GPU resources are available inside a container when WSLCContainerFlagsGpu is set.
3365
+ {
3366
+ WSLCContainerLauncher launcher("debian:latest", "test-container-gpu", {"sleep", "99999"});
3367
+ launcher.SetContainerFlags(WSLCContainerFlagsGpu);
3368
+
3369
+ auto container = launcher.Launch(*session);
3370
+
3371
+ auto expect = [&](const std::vector<std::string> command,
3372
+ int exitCode,
3373
+ const std::map<int, std::string>& expectedOutput = {},
3374
+ const std::vector<std::string>& env = {}) {
3375
+ auto process = WSLCProcessLauncher({}, command, env).Launch(container.Get());
3376
+ ValidateProcessOutput(process, expectedOutput, exitCode);
3377
+ };
3378
+
3379
+ // Validate that /dev/dxg is available as a character device.
3380
+ expect({"/bin/sh", "-c", "test -c /dev/dxg"}, 0);
3381
+
3382
+ // Validate that the GPU library directory is mounted and contains libraries.
3383
+ expect({"/bin/sh", "-c", "test -d /usr/lib/wsl/lib && ls /usr/lib/wsl/lib | grep -q ."}, 0);
3384
+
3385
+ // Validate that the GPU drivers directory is mounted and accessible.
3386
+ expect({"/bin/sh", "-c", "test -d /usr/lib/wsl/drivers"}, 0);
3387
+
3388
+ // Validate that the GPU mount points are read-only.
3389
+ expect({"/usr/bin/touch", "/usr/lib/wsl/lib/test"}, 1);
3390
+ expect({"/usr/bin/touch", "/usr/lib/wsl/drivers/test"}, 1);
3391
+
3392
+ // Validate that LD_LIBRARY_PATH is set to include the GPU library path.
3393
+ expect({"/bin/sh", "-c", "echo $LD_LIBRARY_PATH"}, 0, {{1, "/usr/lib/wsl/lib\n"}});
3394
+
3395
+ // Validate that exec with a pre-existing LD_LIBRARY_PATH appends the GPU path.
3396
+ expect({"/bin/sh", "-c", "echo $LD_LIBRARY_PATH"}, 0, {{1, "/custom/path:/usr/lib/wsl/lib\n"}}, {"LD_LIBRARY_PATH=/custom/path"});
3397
+
3398
+ // Validate that exec with a trailing colon in LD_LIBRARY_PATH doesn't produce a double colon.
3399
+ expect({"/bin/sh", "-c", "echo $LD_LIBRARY_PATH"}, 0, {{1, "/custom/path:/usr/lib/wsl/lib\n"}}, {"LD_LIBRARY_PATH=/custom/path:"});
3400
+ expect({"/bin/sh", "-c", "echo $LD_LIBRARY_PATH"}, 0, {{1, "/usr/lib/wsl/lib\n"}}, {"LD_LIBRARY_PATH="});
3401
+ }
3402
+
3403
+ // Validate that containers without the GPU flag do not have GPU resources.
3404
+ {
3405
+ WSLCContainerLauncher launcher("debian:latest", "test-container-no-gpu", {"/bin/sh", "-c", "test -c /dev/dxg"});
3406
+ auto container = launcher.Launch(*session);
3407
+
3408
+ ValidateContainerOutput(container, {{1, ""}}, 1);
3409
+ }
3410
+ }
3411
+
3412
WSLC_TEST_METHOD(Modules)
3413
{
3414
// Sanity check.