def test__symlink_units_existing_correct_link(self, symlink):
        """
        Make sure that the _symlink_units handles an existing correct link well.
        """
        repo = MagicMock(spec=Repository)
        repo.working_dir = self.temp_dir
        progress_report = progress.PublishProgressReport(self.publish_conduit)

        # There's some logic in _symlink_units to handle preexisting files and symlinks, so let's
        # create some fakes to see if it does the right thing
        build_dir = publish._get_or_create_build_dir(repo)
        unit = self.existing_units[0]
        expected_symlink_destination = os.path.join("/", "path", unit.unit_key["name"])
        os.symlink(expected_symlink_destination, os.path.join(build_dir, unit.unit_key["name"]))
        # Now let's reset the Mock so that we can make sure it doesn't get called during _symlink
        symlink.reset_mock()

        publish._symlink_units(repo, [unit], progress_report)

        # The call count for symlink should be 0, because the _symlink_units call should have noticed that the
        # symlink was already correct and thus should have skipped it
        self.assertEqual(symlink.call_count, 0)
        expected_symlink_path = os.path.join(build_dir, unit.unit_key["name"])
        self.assertTrue(os.path.islink(expected_symlink_path))
        self.assertEqual(os.path.realpath(expected_symlink_path), expected_symlink_destination)
    def test__symlink_units_os_error(self, readlink):
        """
        Make sure that the _symlink_units handles an OSError correctly, for the case where it doesn't raise
        EINVAL. We already have a test that raises EINVAL (test__symlink_units places an ordinary file there.)
        """
        os_error = OSError()
        # This would be an unexpected error for reading a symlink!
        os_error.errno = errno.ENOSPC
        readlink.side_effect = os_error

        repo = MagicMock(spec=Repository)
        repo.working_dir = self.temp_dir
        progress_report = progress.PublishProgressReport(self.publish_conduit)

        # There's some logic in _symlink_units to handle preexisting files and symlinks, so let's
        # create some fakes to see if it does the right thing
        build_dir = publish._get_or_create_build_dir(repo)
        unit = self.existing_units[0]
        expected_symlink_destination = os.path.join("/", "path", unit.unit_key["name"])
        os.symlink(expected_symlink_destination, os.path.join(build_dir, unit.unit_key["name"]))

        try:
            publish._symlink_units(repo, [unit], progress_report)
            self.fail("An OSError should have been raised, but was not!")
        except OSError, e:
            self.assertEqual(e.errno, errno.ENOSPC)
    def test__symlink_units(self):
        """
        Make sure that the _symlink_units creates all the correct symlinks.
        """
        repo = MagicMock(spec=Repository)
        repo.working_dir = self.temp_dir
        progress_report = progress.PublishProgressReport(self.publish_conduit)

        # There's some logic in _symlink_units to handle preexisting files and symlinks, so let's
        # create some fakes to see if it does the right thing
        build_dir = publish._get_or_create_build_dir(repo)
        os.symlink("/some/weird/path", os.path.join(build_dir, self.existing_units[0].unit_key["name"]))
        with open(os.path.join(build_dir, self.existing_units[1].unit_key["name"]), "w") as wrong:
            wrong.write("This is wrong.")

        publish._symlink_units(repo, self.existing_units, progress_report)

        build_dir = publish._get_or_create_build_dir(repo)
        for unit in self.existing_units:
            expected_symlink_path = os.path.join(build_dir, unit.unit_key["name"])
            self.assertTrue(os.path.islink(expected_symlink_path))
            expected_symlink_destination = os.path.join("/", "path", unit.unit_key["name"])
            self.assertEqual(os.path.realpath(expected_symlink_path), expected_symlink_destination)