Improve wslc sdk test coverage (#40761)
Add wslc sdk tests: WslcSdkTests::ContainerAutoRemove WslcSdkTests::DeleteRunningContainerWithForce WslcSdkTests::ImageProgressCallback WslcSdkTests::StopContainerTimeout
Feng Wang committed
Jun 12, 2026 at 10:30 UTC
e6e8f1e8296f2177de018a0e4ad87aa57699aa2c
1 file changed
+162
test/windows/WslcSdkTests.cpp
+162
@@ -2651,4 +2651,166 @@ class WslcSdkTests
2651
VERIFY_ARE_EQUAL(output.stdoutOutput, "/usr/lib/wsl/lib\n");
2652
}
2653
}
2654
+
2655
+ WSLC_TEST_METHOD(ContainerAutoRemove)
2656
+ {
2657
+ WslcProcessSettings procSettings;
2658
+ VERIFY_SUCCEEDED(WslcInitProcessSettings(&procSettings));
2659
+ const char* argv[] = {"/bin/sh", "-c", "echo wslc-auto-remove"};
2660
+ VERIFY_SUCCEEDED(WslcSetProcessSettingsCmdLine(&procSettings, argv, ARRAYSIZE(argv)));
2661
+
2662
+ WslcContainerSettings containerSettings;
2663
+ VERIFY_SUCCEEDED(WslcInitContainerSettings("debian:latest", &containerSettings));
2664
+ VERIFY_SUCCEEDED(WslcSetContainerSettingsInitProcess(&containerSettings, &procSettings));
2665
+ VERIFY_SUCCEEDED(WslcSetContainerSettingsFlags(&containerSettings, WSLC_CONTAINER_FLAG_AUTO_REMOVE));
2666
+
2667
+ UniqueContainer container;
2668
+ VERIFY_SUCCEEDED(WslcCreateContainer(m_defaultSession, &containerSettings, &container, nullptr));
2669
+ VERIFY_SUCCEEDED(WslcStartContainer(container.get(), WSLC_CONTAINER_START_FLAG_ATTACH, nullptr));
2670
+
2671
+ UniqueProcess process;
2672
+ VERIFY_SUCCEEDED(WslcGetContainerInitProcess(container.get(), &process));
2673
+ auto output = WaitForProcessOutput(process.get());
2674
+ VERIFY_ARE_EQUAL(output.stdoutOutput, "wslc-auto-remove\n");
2675
+
2676
+ VERIFY_NO_THROW(wsl::shared::retry::RetryWithTimeout<void>(
2677
+ [&]() {
2678
+ WslcContainerState state{};
2679
+ THROW_IF_FAILED(WslcGetContainerState(container.get(), &state));
2680
+ THROW_WIN32_IF(ERROR_RETRY, state != WSLC_CONTAINER_STATE_DELETED);
2681
+ },
2682
+ std::chrono::milliseconds{100},
2683
+ std::chrono::seconds{30}));
2684
+ }
2685
+
2686
+ WSLC_TEST_METHOD(DeleteRunningContainerWithForce)
2687
+ {
2688
+ WslcProcessSettings procSettings;
2689
+ VERIFY_SUCCEEDED(WslcInitProcessSettings(&procSettings));
2690
+ const char* argv[] = {"/bin/sleep", "99"};
2691
+ VERIFY_SUCCEEDED(WslcSetProcessSettingsCmdLine(&procSettings, argv, ARRAYSIZE(argv)));
2692
+
2693
+ WslcContainerSettings containerSettings;
2694
+ VERIFY_SUCCEEDED(WslcInitContainerSettings("debian:latest", &containerSettings));
2695
+ VERIFY_SUCCEEDED(WslcSetContainerSettingsInitProcess(&containerSettings, &procSettings));
2696
+
2697
+ UniqueContainer container;
2698
+ VERIFY_SUCCEEDED(WslcCreateContainer(m_defaultSession, &containerSettings, &container, nullptr));
2699
+ VERIFY_SUCCEEDED(WslcStartContainer(container.get(), WSLC_CONTAINER_START_FLAG_NONE, nullptr));
2700
+
2701
+ {
2702
+ WslcContainerState state{};
2703
+ VERIFY_SUCCEEDED(WslcGetContainerState(container.get(), &state));
2704
+ VERIFY_ARE_EQUAL(state, WSLC_CONTAINER_STATE_RUNNING);
2705
+ }
2706
+
2707
+ VERIFY_SUCCEEDED(WslcDeleteContainer(container.get(), WSLC_DELETE_CONTAINER_FLAG_FORCE, nullptr));
2708
+
2709
+ {
2710
+ WslcContainerState state{};
2711
+ VERIFY_SUCCEEDED(WslcGetContainerState(container.get(), &state));
2712
+ VERIFY_ARE_EQUAL(state, WSLC_CONTAINER_STATE_DELETED);
2713
+ }
2714
+ }
2715
+
2716
+ WSLC_TEST_METHOD(ImageProgressCallback)
2717
+ {
2718
+ auto [registryContainer, registryAddress] = StartLocalRegistry();
2719
+ auto registryAuth = wsl::windows::common::wslutil::BuildRegistryAuthHeader("", "");
2720
+
2721
+ struct ProgressContext
2722
+ {
2723
+ bool invoked = false;
2724
+ bool sawKnownStatus = false;
2725
+ };
2726
+
2727
+ auto progressCb = [](const WslcImageProgressMessage* progress, PVOID context) -> HRESULT {
2728
+ auto* ctx = static_cast<ProgressContext*>(context);
2729
+ ctx->invoked = true;
2730
+ if (progress != nullptr && progress->status != WSLC_IMAGE_PROGRESS_STATUS_UNKNOWN)
2731
+ {
2732
+ ctx->sawKnownStatus = true;
2733
+ }
2734
+ return S_OK;
2735
+ };
2736
+
2737
+ const auto registryImage = std::format("{}/hello-world:latest", registryAddress);
2738
+ const auto registryRepo = std::format("{}/hello-world", registryAddress);
2739
+
2740
+ WslcTagImageOptions tagOptions{};
2741
+ tagOptions.image = "hello-world:latest";
2742
+ tagOptions.repo = registryRepo.c_str();
2743
+ tagOptions.tag = "latest";
2744
+ VERIFY_SUCCEEDED(WslcTagSessionImage(m_defaultSession, &tagOptions, nullptr));
2745
+
2746
+ auto cleanup = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [&]() {
2747
+ LOG_IF_FAILED(WslcDeleteSessionImage(m_defaultSession, registryImage.c_str(), nullptr));
2748
+ LOG_IF_FAILED(WslcLoadSessionImageFromFile(m_defaultSession, GetTestImagePath("hello-world:latest").c_str(), nullptr, nullptr));
2749
+ });
2750
+
2751
+ {
2752
+ ProgressContext ctx;
2753
+ WslcPushImageOptions opts{};
2754
+ opts.image = registryImage.c_str();
2755
+ opts.registryAuth = registryAuth.c_str();
2756
+ opts.progressCallback = progressCb;
2757
+ opts.progressCallbackContext = &ctx;
2758
+
2759
+ VERIFY_SUCCEEDED(WslcPushSessionImage(m_defaultSession, &opts, nullptr));
2760
+ VERIFY_IS_TRUE(ctx.invoked);
2761
+ }
2762
+
2763
+ VERIFY_SUCCEEDED(WslcDeleteSessionImage(m_defaultSession, registryImage.c_str(), nullptr));
2764
+ VERIFY_SUCCEEDED(WslcDeleteSessionImage(m_defaultSession, "hello-world:latest", nullptr));
2765
+
2766
+ {
2767
+ ProgressContext ctx;
2768
+ WslcPullImageOptions opts{};
2769
+ opts.uri = registryImage.c_str();
2770
+ opts.registryAuth = registryAuth.c_str();
2771
+ opts.progressCallback = progressCb;
2772
+ opts.progressCallbackContext = &ctx;
2773
+
2774
+ VERIFY_SUCCEEDED(WslcPullSessionImage(m_defaultSession, &opts, nullptr));
2775
+ VERIFY_IS_TRUE(HasImage(registryImage));
2776
+ VERIFY_IS_TRUE(ctx.sawKnownStatus);
2777
+ }
2778
+ }
2779
+
2780
+ WSLC_TEST_METHOD(StopContainerTimeout)
2781
+ {
2782
+ WslcProcessSettings procSettings;
2783
+ VERIFY_SUCCEEDED(WslcInitProcessSettings(&procSettings));
2784
+ const char* argv[] = {"/bin/sh", "-c", "trap '' TERM; sleep 60"};
2785
+ VERIFY_SUCCEEDED(WslcSetProcessSettingsCmdLine(&procSettings, argv, ARRAYSIZE(argv)));
2786
+
2787
+ WslcContainerSettings containerSettings;
2788
+ VERIFY_SUCCEEDED(WslcInitContainerSettings("debian:latest", &containerSettings));
2789
+ VERIFY_SUCCEEDED(WslcSetContainerSettingsInitProcess(&containerSettings, &procSettings));
2790
+
2791
+ UniqueContainer container;
2792
+ VERIFY_SUCCEEDED(WslcCreateContainer(m_defaultSession, &containerSettings, &container, nullptr));
2793
+ VERIFY_SUCCEEDED(WslcStartContainer(container.get(), WSLC_CONTAINER_START_FLAG_NONE, nullptr));
2794
+
2795
+ {
2796
+ WslcContainerState state{};
2797
+ VERIFY_SUCCEEDED(WslcGetContainerState(container.get(), &state));
2798
+ VERIFY_ARE_EQUAL(state, WSLC_CONTAINER_STATE_RUNNING);
2799
+ }
2800
+
2801
+ constexpr uint32_t c_timeoutSeconds = 1;
2802
+ const auto start = std::chrono::steady_clock::now();
2803
+ VERIFY_SUCCEEDED(WslcStopContainer(container.get(), WSLC_SIGNAL_SIGTERM, c_timeoutSeconds, nullptr));
2804
+ const auto elapsedMs = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start).count();
2805
+
2806
+ VERIFY_IS_GREATER_THAN_OR_EQUAL(elapsedMs, 1000LL);
2807
+ // Ensure it's not because of the sleep running out.
2808
+ VERIFY_IS_LESS_THAN(elapsedMs, 30000LL);
2809
+
2810
+ {
2811
+ WslcContainerState state{};
2812
+ VERIFY_SUCCEEDED(WslcGetContainerState(container.get(), &state));
2813
+ VERIFY_ARE_EQUAL(state, WSLC_CONTAINER_STATE_EXITED);
2814
+ }
2815
+ }
2816
};