From dbce33947841f32e5e70e1aaec160d182bc24d47 Mon Sep 17 00:00:00 2001 From: Anthony Nandaa Date: Thu, 16 May 2024 09:23:41 +0300 Subject: [PATCH] test: enabling integration tests on windows Starting off with this one as a POC on the approach, before we proceed to complete the rest under `/frontend/dockerfile`. Tests covered so far: - [x] `/frontend/dockerfile: testEnvEmptyFormatting` - [x] `/frontend/dockerfile: testDockerignoreOverride` - [x] `/frontend/dockerfile: caseEmptyDestDir` Starts addressing #4485 Signed-off-by: Anthony Nandaa --- .github/workflows/test-os.yml | 4 +- client/client_test.go | 1 + frontend/dockerfile/dockerfile_test.go | 80 ++++++++++++++++------- util/testutil/integration/pins.go | 3 + util/testutil/integration/run.go | 31 ++++----- util/testutil/integration/run_unix.go | 26 ++++++++ util/testutil/integration/run_windows.go | 13 ++++ util/testutil/integration/util.go | 4 +- util/testutil/integration/util_windows.go | 6 ++ 9 files changed, 125 insertions(+), 43 deletions(-) create mode 100644 util/testutil/integration/run_unix.go create mode 100644 util/testutil/integration/run_windows.go diff --git a/.github/workflows/test-os.yml b/.github/workflows/test-os.yml index 59afdd4530d66..db93a0f335bd4 100644 --- a/.github/workflows/test-os.yml +++ b/.github/workflows/test-os.yml @@ -77,7 +77,7 @@ jobs: needs: - build env: - TESTFLAGS: "-v --parallel=6 --timeout=30m" + TESTFLAGS: "-v --parallel=6 --timeout=60m" GOTESTSUM_FORMAT: "standard-verbose" strategy: fail-fast: false @@ -102,7 +102,7 @@ jobs: echo "TEST_REPORT_NAME=${{ github.job }}-$(echo "${{ matrix.pkg }}-${{ matrix.skip-integration-tests }}-${{ matrix.worker }}" | tr -dc '[:alnum:]-\n\r' | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV testFlags="${{ env.TESTFLAGS }}" if [ -n "${{ matrix.worker }}" ]; then - testFlags="${testFlags} --run=//worker=${{ matrix.worker }}$" + testFlags="${testFlags} --run=TestIntegration/.*/worker=${{ matrix.worker }}" fi echo "TESTFLAGS=${testFlags}" >> $GITHUB_ENV shell: bash diff --git a/client/client_test.go b/client/client_test.go index eb072132b8893..d3cfabf76cd0b 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -10568,6 +10568,7 @@ func testLayerLimitOnMounts(t *testing.T, sb integration.Sandbox) { } func testClientCustomGRPCOpts(t *testing.T, sb integration.Sandbox) { + integration.SkipOnPlatform(t, "windows") var interceptedMethods []string intercept := func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { interceptedMethods = append(interceptedMethods, method) diff --git a/frontend/dockerfile/dockerfile_test.go b/frontend/dockerfile/dockerfile_test.go index 97c7624ed5aae..c4041ebc0f206 100644 --- a/frontend/dockerfile/dockerfile_test.go +++ b/frontend/dockerfile/dockerfile_test.go @@ -228,8 +228,11 @@ type frontend interface { func init() { frontends := map[string]interface{}{} + images := integration.UnixOrWindows([2][]string{ + {"busybox:latest", "alpine:latest"}, + {"nanoserver:latest"}}) opts = []integration.TestOpt{ - integration.WithMirroredImages(integration.OfficialImages("busybox:latest", "alpine:latest")), + integration.WithMirroredImages(integration.OfficialImages(images...)), integration.WithMatrix("frontend", frontends), } @@ -252,27 +255,34 @@ func init() { func TestIntegration(t *testing.T) { integration.Run(t, allTests, opts...) - integration.Run(t, securityTests, append(append(opts, securityOpts...), - integration.WithMatrix("security.insecure", map[string]interface{}{ - "granted": securityInsecureGranted, - "denied": securityInsecureDenied, - }))...) - integration.Run(t, networkTests, append(opts, - integration.WithMatrix("network.host", map[string]interface{}{ - "granted": networkHostGranted, - "denied": networkHostDenied, - }))...) integration.Run(t, lintTests, opts...) integration.Run(t, heredocTests, opts...) integration.Run(t, outlineTests, opts...) integration.Run(t, targetsTests, opts...) + runLinuxOnlyTests(t) +} + +func runLinuxOnlyTests(t *testing.T) { + integration.SkipOnPlatform(t, "windows") integration.Run(t, reproTests, append(opts, // Only use the amd64 digest, regardless to the host platform integration.WithMirroredImages(map[string]string{ "amd64/bullseye-20230109-slim:latest": "docker.io/amd64/debian:bullseye-20230109-slim@sha256:1acb06a0c31fb467eb8327ad361f1091ab265e0bf26d452dea45dcb0c0ea5e75", }), )...) + + integration.Run(t, securityTests, append(append(opts, securityOpts...), + integration.WithMatrix("security.insecure", map[string]interface{}{ + "granted": securityInsecureGranted, + "denied": securityInsecureDenied, + }))...) + + integration.Run(t, networkTests, append(opts, + integration.WithMatrix("network.host", map[string]interface{}{ + "granted": networkHostGranted, + "denied": networkHostDenied, + }))...) } func testEmptyStringArgInEnv(t *testing.T, sb integration.Sandbox) { @@ -385,14 +395,20 @@ echo -n $my_arg $* > /out } func testEnvEmptyFormatting(t *testing.T, sb integration.Sandbox) { - integration.SkipOnPlatform(t, "windows") f := getFrontend(t, sb) - dockerfile := []byte(` + dockerfile := []byte(integration.UnixOrWindows([2]string{ + ` FROM busybox AS build ENV myenv foo%sbar RUN [ "$myenv" = 'foo%sbar' ] -`) +`, + ` +FROM nanoserver AS build +ENV myenv foo%sbar +RUN if %myenv% NEQ foo%sbar (exit 1) +`, + })) dir := integration.Tmpdir( t, @@ -421,23 +437,36 @@ RUN [ "$myenv" = 'foo%sbar' ] } func testDockerignoreOverride(t *testing.T, sb integration.Sandbox) { - integration.SkipOnPlatform(t, "windows") f := getFrontend(t, sb) - dockerfile := []byte(` + dockerfile := []byte(integration.UnixOrWindows([2]string{ + ` FROM busybox COPY . . RUN [ -f foo ] && [ ! -f bar ] -`) +`, + ` +FROM nanoserver +COPY . . +RUN if exist foo (if not exist bar (exit 0) else (exit 1)) +`, + })) ignore := []byte(` bar `) - dockerfile2 := []byte(` + dockerfile2 := []byte(integration.UnixOrWindows([2]string{ + ` FROM busybox COPY . . RUN [ ! -f foo ] && [ -f bar ] -`) +`, + ` +FROM nanoserver +COPY . . +RUN if not exist foo (if exist bar (exit 0) else (exit 1)) +`, + })) ignore2 := []byte(` foo @@ -478,15 +507,22 @@ foo } func testEmptyDestDir(t *testing.T, sb integration.Sandbox) { - integration.SkipOnPlatform(t, "windows") f := getFrontend(t, sb) - dockerfile := []byte(` + dockerfile := []byte(integration.UnixOrWindows([2]string{ + ` FROM busybox ENV empty="" COPY testfile $empty RUN [ "$(cat testfile)" == "contents0" ] -`) +`, + ` +FROM nanoserver +COPY testfile '' +RUN cmd /V:on /C "set /p tfcontent= sending sigterm %v\n", time.Now()) cmd.Process.Signal(syscall.SIGTERM) + // reduce the wait time for Windows + waitFactor := UnixOrWindows([2]time.Duration{20, 1}) go func() { select { case <-stopped: - case <-time.After(20 * time.Second): + case <-time.After(waitFactor * time.Second): cmd.Process.Kill() } }() diff --git a/util/testutil/integration/util_windows.go b/util/testutil/integration/util_windows.go index 42d6f3fa4110f..a6484fd9729be 100644 --- a/util/testutil/integration/util_windows.go +++ b/util/testutil/integration/util_windows.go @@ -11,6 +11,12 @@ import ( var socketScheme = "npipe://" +var windowsImagesMirrorMap = map[string]string{ + "nanoserver:latest": "mcr.microsoft.com/windows/nanoserver:ltsc2022", + "servercore:latest": "mcr.microsoft.com/windows/servercore:ltsc2022", + "busybox:latest": "registry.k8s.io/e2e-test-images/busybox:1.29-2", +} + // abstracted function to handle pipe dialing on windows. // some simplification has been made to discard timeout param. func dialPipe(address string) (net.Conn, error) {