From cd10d508e20a4964586b46f7edea8a6dc900157c Mon Sep 17 00:00:00 2001
From: Fabian Meumertzheim <fabian@meumertzhe.im>
Date: Tue, 13 Dec 2022 01:34:02 -0800
Subject: [PATCH] Fix `--nozip_undeclared_test_outputs` on Windows

Without this change, testing with `--nozip_undeclared_test_outputs` always fails with this error:

```
FATAL: MappedOutputFile(): CreateFileW() failed: (error: 3): The system cannot find the path specified.
```

Closes #16973.

PiperOrigin-RevId: 494953454
Change-Id: I8338e897a9e4f4fdcd6dad511ee8e777182fefcd
---
 src/test/py/bazel/bazel_windows_test.py | 54 +++++++++++++++++++++++++
 tools/test/windows/tw.cc                |  6 ++-
 2 files changed, 58 insertions(+), 2 deletions(-)

diff --git a/src/test/py/bazel/bazel_windows_test.py b/src/test/py/bazel/bazel_windows_test.py
index 77013297a806a3..d9dc71e8c31aad 100644
--- a/src/test/py/bazel/bazel_windows_test.py
+++ b/src/test/py/bazel/bazel_windows_test.py
@@ -397,6 +397,60 @@ def testRunWithScriptPath(self):
     self.AssertExitCode(exit_code, 0, stderr)
     self.assertIn('Hello from test!', '\n'.join(stdout))
 
+  def testZipUndeclaredTestOutputs(self):
+    self.CreateWorkspaceWithDefaultRepos('WORKSPACE')
+    self.ScratchFile(
+        'BUILD',
+        [
+            'sh_test(',
+            '  name = "foo_test",',
+            '  srcs = ["foo.sh"],',
+            ')',
+            '',
+        ],
+    )
+    self.ScratchFile(
+        'foo.sh',
+        [
+            'touch "$TEST_UNDECLARED_OUTPUTS_DIR/foo.txt"',
+        ],
+    )
+
+    exit_code, stdout, stderr = self.RunBazel(['info', 'bazel-testlogs'])
+    self.AssertExitCode(exit_code, 0, stderr)
+    bazel_testlogs = stdout[0]
+
+    output_file = os.path.join(bazel_testlogs, 'foo_test/test.outputs/foo.txt')
+    output_zip = os.path.join(
+        bazel_testlogs, 'foo_test/test.outputs/outputs.zip'
+    )
+
+    # Run the test with undeclared outputs zipping.
+    exit_code, _, stderr = self.RunBazel(
+        [
+            'test',
+            '--zip_undeclared_test_outputs',
+            '//:foo_test',
+        ],
+    )
+    self.AssertExitCode(exit_code, 0, stderr)
+    # FIXME: The Windows test runner does not delete the undeclared outputs
+    #  after zipping, which differs from the behavior on other platforms.
+    self.assertTrue(os.path.exists(output_file))
+    self.assertTrue(os.path.exists(output_zip))
+
+    # Run the test without undeclared outputs zipping.
+    exit_code, _, stderr = self.RunBazel(
+        [
+            'test',
+            '--nozip_undeclared_test_outputs',
+            '//:foo_test',
+        ],
+    )
+    self.AssertExitCode(exit_code, 0, stderr)
+    self.assertTrue(os.path.exists(output_file))
+    self.assertFalse(os.path.exists(output_zip))
+
 
 if __name__ == '__main__':
   unittest.main()
diff --git a/tools/test/windows/tw.cc b/tools/test/windows/tw.cc
index d20d5c52168b60..8d5f61c4a3d915 100644
--- a/tools/test/windows/tw.cc
+++ b/tools/test/windows/tw.cc
@@ -1298,8 +1298,10 @@ bool StartSubprocess(const Path& path, const std::wstring& args,
 }
 
 bool ArchiveUndeclaredOutputs(const UndeclaredOutputs& undecl) {
-  if (undecl.root.Get().empty()) {
-    // TEST_UNDECLARED_OUTPUTS_DIR was undefined, there's nothing to archive.
+  if (undecl.root.Get().empty() || undecl.zip.Get().empty()) {
+    // TEST_UNDECLARED_OUTPUTS_DIR was undefined, so there's nothing to archive,
+    // or TEST_UNDECLARED_OUTPUTS_ZIP was undefined as
+    // --nozip_undeclared_test_outputs was specified.
     return true;
   }