From 151231358af5aede5ba4535f26e747e748cded91 Mon Sep 17 00:00:00 2001 From: Ben Hillis Date: Fri, 8 May 2026 12:07:38 -0700 Subject: [PATCH 1/3] Fix ListImages test flaky Before/Since filter ordering The test hardcoded the assumption that debian:latest was created before python:3.12-alpine, but Docker image Created timestamps come from when the image was built in the registry, not when it was pulled or saved. The arm64 test data tars have debian (Mar 16) newer than python (Mar 3), causing the since filter to not return python. Fix by dynamically determining which image is older/newer based on actual Created timestamps, making the test robust against independently updated test data tars. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- test/windows/WSLCTests.cpp | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/test/windows/WSLCTests.cpp b/test/windows/WSLCTests.cpp index c8a095bb9..c0c0e03f7 100644 --- a/test/windows/WSLCTests.cpp +++ b/test/windows/WSLCTests.cpp @@ -898,69 +898,81 @@ class WSLCTests LogInfo("Test: Before/Since filters"); { - // Get all images to find their IDs + // Get all images to find their IDs and creation times wil::unique_cotaskmem_array_ptr allImages; VERIFY_SUCCEEDED(m_defaultSession->ListImages(nullptr, allImages.addressof(), allImages.size_address())); std::string debianId, pythonId; + LONGLONG debianCreated = 0, pythonCreated = 0; for (const auto& image : allImages) { std::string imageName = image.Image; if (imageName == "debian:latest") { debianId = image.Hash; + debianCreated = image.Created; } else if (imageName == "python:3.12-alpine") { pythonId = image.Hash; + pythonCreated = image.Created; } } VERIFY_IS_FALSE(debianId.empty()); VERIFY_IS_FALSE(pythonId.empty()); - // Test 'since' filter - images created after debian + // Determine which image is older/newer based on actual creation timestamps. + // Image creation times come from the registry and can change independently. + const auto& olderId = (debianCreated <= pythonCreated) ? debianId : pythonId; + const auto& newerId = (debianCreated <= pythonCreated) ? pythonId : debianId; + const auto* newerName = (debianCreated <= pythonCreated) ? "python:3.12-alpine" : "debian:latest"; + const auto* olderName = (debianCreated <= pythonCreated) ? "debian:latest" : "python:3.12-alpine"; + + LogInfo("Older image: %hs (Created: %lld), Newer image: %hs (Created: %lld)", olderName, std::min(debianCreated, pythonCreated), newerName, std::max(debianCreated, pythonCreated)); + + // Test 'since' filter - images created after the older image { WSLCListImageOptions options{}; options.Flags = WSLCListImagesFlagsNone; - options.Since = debianId.c_str(); + options.Since = olderId.c_str(); wil::unique_cotaskmem_array_ptr images; VERIFY_SUCCEEDED(m_defaultSession->ListImages(&options, images.addressof(), images.size_address())); VERIFY_IS_TRUE(images.size() > 0); - bool foundPython = false; + bool foundNewer = false; for (const auto& image : images) { LogInfo("Image: %hs, Hash: %hs, Created: %lld", image.Image, image.Hash, image.Created); - if (std::string{image.Image} == "python:3.12-alpine") + if (std::string{image.Image} == newerName) { - foundPython = true; + foundNewer = true; } } - VERIFY_IS_TRUE(foundPython); + VERIFY_IS_TRUE(foundNewer); } - // Test 'before' filter - images created before python + // Test 'before' filter - images created before the newer image { WSLCListImageOptions options{}; options.Flags = WSLCListImagesFlagsNone; - options.Before = pythonId.c_str(); + options.Before = newerId.c_str(); wil::unique_cotaskmem_array_ptr images; VERIFY_SUCCEEDED(m_defaultSession->ListImages(&options, images.addressof(), images.size_address())); VERIFY_IS_TRUE(images.size() > 0); - bool foundDebian = false; + bool foundOlder = false; for (const auto& image : images) { - if (std::string{image.Image} == "debian:latest") + if (std::string{image.Image} == olderName) { - foundDebian = true; + foundOlder = true; } } - VERIFY_IS_TRUE(foundDebian); + VERIFY_IS_TRUE(foundOlder); } } From d39f5547656e9f45b43ffec1c708b742ac2e9bd5 Mon Sep 17 00:00:00 2001 From: Ben Hillis Date: Fri, 8 May 2026 13:00:06 -0700 Subject: [PATCH 2/3] format --- test/windows/WSLCTests.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/windows/WSLCTests.cpp b/test/windows/WSLCTests.cpp index c0c0e03f7..64153584a 100644 --- a/test/windows/WSLCTests.cpp +++ b/test/windows/WSLCTests.cpp @@ -929,7 +929,12 @@ class WSLCTests const auto* newerName = (debianCreated <= pythonCreated) ? "python:3.12-alpine" : "debian:latest"; const auto* olderName = (debianCreated <= pythonCreated) ? "debian:latest" : "python:3.12-alpine"; - LogInfo("Older image: %hs (Created: %lld), Newer image: %hs (Created: %lld)", olderName, std::min(debianCreated, pythonCreated), newerName, std::max(debianCreated, pythonCreated)); + LogInfo( + "Older image: %hs (Created: %lld), Newer image: %hs (Created: %lld)", + olderName, + std::min(debianCreated, pythonCreated), + newerName, + std::max(debianCreated, pythonCreated)); // Test 'since' filter - images created after the older image { From 5457b5766b7d2a664ac9bd8012939f0b1d46d92d Mon Sep 17 00:00:00 2001 From: Ben Hillis Date: Fri, 8 May 2026 14:00:49 -0700 Subject: [PATCH 3/3] Address PR feedback: assert Created timestamps are populated and distinct Adds explicit VERIFY checks that debianCreated/pythonCreated are > 0 and not equal before using them to choose the since/before boundary, preventing silent fallthrough or ambiguous Docker filter behavior when both images share a Created timestamp. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- test/windows/WSLCTests.cpp | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/test/windows/WSLCTests.cpp b/test/windows/WSLCTests.cpp index 64153584a..4215be1a0 100644 --- a/test/windows/WSLCTests.cpp +++ b/test/windows/WSLCTests.cpp @@ -922,19 +922,27 @@ class WSLCTests VERIFY_IS_FALSE(debianId.empty()); VERIFY_IS_FALSE(pythonId.empty()); + // Both Created timestamps must be populated and distinct so that the since/before + // boundaries are unambiguous. Equal timestamps would make Docker's filter behavior + // ambiguous and could reintroduce flakiness. + VERIFY_IS_GREATER_THAN(debianCreated, 0LL); + VERIFY_IS_GREATER_THAN(pythonCreated, 0LL); + VERIFY_ARE_NOT_EQUAL(debianCreated, pythonCreated); + // Determine which image is older/newer based on actual creation timestamps. // Image creation times come from the registry and can change independently. - const auto& olderId = (debianCreated <= pythonCreated) ? debianId : pythonId; - const auto& newerId = (debianCreated <= pythonCreated) ? pythonId : debianId; - const auto* newerName = (debianCreated <= pythonCreated) ? "python:3.12-alpine" : "debian:latest"; - const auto* olderName = (debianCreated <= pythonCreated) ? "debian:latest" : "python:3.12-alpine"; + const bool debianIsOlder = debianCreated < pythonCreated; + const auto& olderId = debianIsOlder ? debianId : pythonId; + const auto& newerId = debianIsOlder ? pythonId : debianId; + const auto* olderName = debianIsOlder ? "debian:latest" : "python:3.12-alpine"; + const auto* newerName = debianIsOlder ? "python:3.12-alpine" : "debian:latest"; LogInfo( "Older image: %hs (Created: %lld), Newer image: %hs (Created: %lld)", olderName, - std::min(debianCreated, pythonCreated), + debianIsOlder ? debianCreated : pythonCreated, newerName, - std::max(debianCreated, pythonCreated)); + debianIsOlder ? pythonCreated : debianCreated); // Test 'since' filter - images created after the older image {