diff --git a/tests/functional/test_actions.py b/tests/functional/test_actions.py index d26647e2e..ae6898c4b 100644 --- a/tests/functional/test_actions.py +++ b/tests/functional/test_actions.py @@ -1,13 +1,17 @@ import os from pathlib import Path import tempfile +import unittest from unittest import TestCase from parameterized import parameterized from aws_lambda_builders.actions import CopyDependenciesAction, LinkSinglePathAction, MoveDependenciesAction from aws_lambda_builders.utils import copytree -from tests.testing_utils import read_link_without_junction_prefix +from tests.testing_utils import read_link_without_junction_prefix, symlinks_supported + +SYMLINKS_SUPPORTED = symlinks_supported() +SYMLINKS_UNSUPPORTED_REASON = "Creating symlinks requires Administrator privileges or Developer Mode on this platform" class TestCopyDependenciesAction(TestCase): @@ -32,6 +36,7 @@ def test_copy_dependencies_action(self, source_folder): self.assertEqual(set(os.listdir(test_folder)), set(os.listdir(target))) + @unittest.skipUnless(SYMLINKS_SUPPORTED, SYMLINKS_UNSUPPORTED_REASON) def test_must_maintain_symlinks_if_enabled(self): with tempfile.TemporaryDirectory() as tmpdir: source_dir = os.path.join(tmpdir, "source") @@ -56,6 +61,7 @@ def test_must_maintain_symlinks_if_enabled(self): destination_node_modules_target = read_link_without_junction_prefix(destination_node_modules) self.assertEqual(destination_node_modules_target, source_node_modules) + @unittest.skipUnless(SYMLINKS_SUPPORTED, SYMLINKS_UNSUPPORTED_REASON) def test_must_not_maintain_symlinks_by_default(self): with tempfile.TemporaryDirectory() as tmpdir: source_dir = os.path.join(tmpdir, "source") @@ -78,6 +84,7 @@ def test_must_not_maintain_symlinks_by_default(self): class TestLinkSinglePathAction(TestCase): + @unittest.skipUnless(SYMLINKS_SUPPORTED, SYMLINKS_UNSUPPORTED_REASON) def test_link_directory(self): with tempfile.TemporaryDirectory() as tmpdir: source_dir = os.path.join(tmpdir, "source") diff --git a/tests/functional/test_utils.py b/tests/functional/test_utils.py index a10b57d41..19cc08124 100644 --- a/tests/functional/test_utils.py +++ b/tests/functional/test_utils.py @@ -2,12 +2,16 @@ import tempfile import shutil import platform +import unittest from tarfile import ExtractError from unittest import TestCase from aws_lambda_builders.utils import copytree, get_goarch, extract_tarfile -from tests.testing_utils import read_link_without_junction_prefix +from tests.testing_utils import read_link_without_junction_prefix, symlinks_supported + +SYMLINKS_SUPPORTED = symlinks_supported() +SYMLINKS_UNSUPPORTED_REASON = "Creating symlinks requires Administrator privileges or Developer Mode on this platform" class TestCopyTree(TestCase): @@ -65,6 +69,7 @@ def test_must_return_valid_go_architecture(self): self.assertEqual(get_goarch("x86_64"), "amd64") self.assertEqual(get_goarch(""), "amd64") + @unittest.skipUnless(SYMLINKS_SUPPORTED, SYMLINKS_UNSUPPORTED_REASON) def test_must_maintain_symlinks_if_enabled(self): # set up symlinked file and directory source_target_file_path = file(self.source, "targetfile.txt") @@ -92,6 +97,7 @@ def test_must_maintain_symlinks_if_enabled(self): dest_symlink_dir_target = read_link_without_junction_prefix(dest_symlink_file_path) self.assertEqual(dest_symlink_dir_target, source_target_file_path) + @unittest.skipUnless(SYMLINKS_SUPPORTED, SYMLINKS_UNSUPPORTED_REASON) def test_must_not_maintain_symlinks_by_default(self): # set up symlinked file and directory source_target_file_path = file(self.source, "targetfile.txt") diff --git a/tests/testing_utils.py b/tests/testing_utils.py index 345f62e50..8b1787ff6 100644 --- a/tests/testing_utils.py +++ b/tests/testing_utils.py @@ -1,4 +1,34 @@ import os +import sys +import tempfile + + +def symlinks_supported() -> bool: + """ + Returns True if the current platform and user are able to create symlinks. + + On Windows, os.symlink() requires either Administrator privileges or Developer + Mode to be enabled (Windows 10+). Without either, it raises + ``OSError: [WinError 1314] A required privilege is not held by the client``. + Developer Mode is off by default, so this is the common case for a Windows + contributor running the test suite locally. + + Returns + ------- + bool + True if os.symlink() is expected to succeed on this machine. + """ + if sys.platform != "win32": + return True + with tempfile.TemporaryDirectory() as tmpdir: + target = os.path.join(tmpdir, "target") + link = os.path.join(tmpdir, "link") + open(target, "w").close() + try: + os.symlink(target, link) + except OSError: + return False + return True def read_link_without_junction_prefix(path: str) -> str: