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__copy_to_hosted_location(self):
        """
        Test the operation of _copy_to_hosted_location().
        """
        repo = MagicMock(spec=Repository)
        repo.id = "lebowski"
        repo.working_dir = self.temp_dir
        progress_report = progress.PublishProgressReport(self.publish_conduit)
        config = distributor_mocks.get_basic_config(
            **{constants.CONFIG_SERVE_HTTP: True, constants.CONFIG_SERVE_HTTPS: True}
        )

        # Let's put a dummy file and a dummy symlink in the build_dir, so we can make sure they get
        # copied to the right places.
        build_dir = publish._get_or_create_build_dir(repo)
        with open(os.path.join(build_dir, "the_dude.txt"), "w") as the_dude:
            the_dude.write("Let's go bowling.")
        os.symlink("/symlink/path", os.path.join(build_dir, "symlink"))

        # This should copy our dummy file to the monkey patched folders from our setUp() method.
        publish._copy_to_hosted_location(repo, config, progress_report)

        # Make sure that the_dude.txt got copied to the right places
        expected_http_path = os.path.join(constants.ISO_HTTP_DIR, "lebowski", "the_dude.txt")
        expected_https_path = os.path.join(constants.ISO_HTTPS_DIR, "lebowski", "the_dude.txt")
        self.assertTrue(os.path.exists(expected_http_path))
        self.assertTrue(os.path.exists(expected_https_path))
        # Now make sure our symlink is also in place, and points to the correct location
        expected_http_symlink_path = os.path.join(constants.ISO_HTTP_DIR, "lebowski", "symlink")
        expected_https_symlink_path = os.path.join(constants.ISO_HTTPS_DIR, "lebowski", "symlink")
        self.assertTrue(os.path.islink(expected_http_symlink_path))
        self.assertTrue(os.path.islink(expected_https_symlink_path))
        self.assertEqual(os.path.realpath(expected_http_symlink_path), "/symlink/path")
        self.assertEqual(os.path.realpath(expected_https_symlink_path), "/symlink/path")
    def test__get_or_create_build_dir_oserror(self, makedirs):
        """
        Let's raise the OSError that this method tries to catch to make sure we raise it appropriately.
        """
        os_error = OSError()
        os_error.errno = errno.ENOSPC
        makedirs.side_effect = os_error

        repo = MagicMock(spec=Repository)
        repo.working_dir = self.temp_dir

        # Assert that the build dir does not exist
        expected_build_dir = os.path.join(self.temp_dir, publish.BUILD_DIRNAME)
        self.assertFalse(os.path.exists(expected_build_dir))

        try:
            publish._get_or_create_build_dir(repo)
            self.fail("An OSError should have been raised but was not.")
        except OSError, e:
            self.assertEqual(e.errno, errno.ENOSPC)
    def test__get_or_create_build_dir(self):
        """
        _get_or_create_build_dir() should create the directory the first time it is called, and
        should return the path to it both times it is called.
        """
        repo = MagicMock(spec=Repository)
        repo.working_dir = self.temp_dir

        # Assert that the build dir does not exist
        expected_build_dir = os.path.join(self.temp_dir, publish.BUILD_DIRNAME)
        self.assertFalse(os.path.exists(expected_build_dir))

        build_dir = publish._get_or_create_build_dir(repo)

        # Assert that the build dir is correct and has been created
        self.assertEqual(build_dir, expected_build_dir)
        self.assertTrue(os.path.exists(build_dir))

        # It should not blow up if we call it again
        build_dir = publish._get_or_create_build_dir(repo)
        self.assertEqual(build_dir, expected_build_dir)
    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)
    def test__get_or_create_build_dir_already_exists(self):
        """
        _get_or_create_build_dir() should correctly handle the situation when the build_dir already exists.
        """
        repo = MagicMock(spec=Repository)
        repo.working_dir = self.temp_dir

        # Assert that the build dir does not exist
        expected_build_dir = os.path.join(self.temp_dir, publish.BUILD_DIRNAME)
        os.makedirs(expected_build_dir)
        self.assertTrue(os.path.exists(expected_build_dir))

        build_dir = publish._get_or_create_build_dir(repo)

        # Assert that the build dir is correct and has been created
        self.assertEqual(build_dir, expected_build_dir)
        self.assertTrue(os.path.exists(build_dir))