Esempio n. 1
0
    def setUp(self):
        super(SSHTestCase, self).setUp()
        self.disable_directory_isolation()
        tac_handler = SSHServerLayer.getTacHandler()
        self.server = SSHCodeHostingServer(self.scheme, tac_handler)
        self.server.start_server()
        self.addCleanup(self.server.stop_server)

        # Prevent creation of in-process sftp:// and bzr+ssh:// transports --
        # such connections tend to leak threads and occasionally create
        # uncollectable garbage.
        ssh_denier = DenyingServer(['bzr+ssh://', 'sftp://'])
        ssh_denier.start_server()
        self.addCleanup(ssh_denier.stop_server)

        # Create a local branch with one revision
        tree = self.make_branch_and_tree('local')
        self.local_branch = tree.branch
        self.local_branch_path = local_path_from_url(self.local_branch.base)
        self.build_tree(['local/foo'])
        tree.add('foo')
        self.revid = tree.commit('Added foo')
    def setUp(self):
        super(SSHTestCase, self).setUp()
        self.disable_directory_isolation()
        tac_handler = SSHServerLayer.getTacHandler()
        self.server = SSHCodeHostingServer(self.scheme, tac_handler)
        self.server.start_server()
        self.addCleanup(self.server.stop_server)

        # Prevent creation of in-process sftp:// and bzr+ssh:// transports --
        # such connections tend to leak threads and occasionally create
        # uncollectable garbage.
        ssh_denier = DenyingServer(['bzr+ssh://', 'sftp://'])
        ssh_denier.start_server()
        self.addCleanup(ssh_denier.stop_server)

        # Create a local branch with one revision
        tree = self.make_branch_and_tree('local')
        self.local_branch = tree.branch
        self.local_branch_path = local_path_from_url(self.local_branch.base)
        self.build_tree(['local/foo'])
        tree.add('foo')
        self.revid = tree.commit('Added foo')
Esempio n. 3
0
class SSHTestCase(TestCaseWithTransport, LoomTestMixin, TestCaseWithFactory):
    """TestCase class that runs an SSH server as well as the app server."""

    layer = SSHServerLayer
    scheme = None

    def setUp(self):
        super(SSHTestCase, self).setUp()
        self.disable_directory_isolation()
        tac_handler = SSHServerLayer.getTacHandler()
        self.server = SSHCodeHostingServer(self.scheme, tac_handler)
        self.server.start_server()
        self.addCleanup(self.server.stop_server)

        # Prevent creation of in-process sftp:// and bzr+ssh:// transports --
        # such connections tend to leak threads and occasionally create
        # uncollectable garbage.
        ssh_denier = DenyingServer(['bzr+ssh://', 'sftp://'])
        ssh_denier.start_server()
        self.addCleanup(ssh_denier.stop_server)

        # Create a local branch with one revision
        tree = self.make_branch_and_tree('local')
        self.local_branch = tree.branch
        self.local_branch_path = local_path_from_url(self.local_branch.base)
        self.build_tree(['local/foo'])
        tree.add('foo')
        self.revid = tree.commit('Added foo')

    def __str__(self):
        return self.id()

    def getTransport(self, relpath=None):
        return self.server.getTransport(relpath)

    def assertBranchesMatch(self, local_url, remote_url):
        """Assert that two branches have the same last revision."""
        local_revision = self.getLastRevision(local_url)
        remote_revision = self.getLastRevision(remote_url)
        self.assertEqual(local_revision, remote_revision)

    def _run_bzr(self, args, retcode=0):
        """Call run_bzr_subprocess with some common options.

        We always want to force the subprocess to do its ssh communication
        with paramiko (because OpenSSH doesn't respect the $HOME environment
        variable) and we want to load the plugins that are in rocketfuel
        (mainly so we can test the loom support).
        """
        return self.run_bzr_subprocess(
            args,
            env_changes={
                'BZR_SSH': 'paramiko',
                'BZR_PLUGIN_PATH': get_BZR_PLUGIN_PATH_for_subprocess()
            },
            allow_plugins=True,
            retcode=retcode)

    def _run_bzr_error(self, args):
        """Run bzr expecting an error, returning the error message.
        """
        output, error = self._run_bzr(args, retcode=3)
        for line in error.splitlines():
            if line.startswith("bzr: ERROR"):
                return line
        raise AssertionError("Didn't find error line in output:\n\n%s\n" %
                             error)

    def branch(self, remote_url, local_directory):
        """Branch from the given URL to a local directory."""
        self._run_bzr(['branch', remote_url, local_directory])

    def get_bzr_path(self):
        """See `bzrlib.tests.TestCase.get_bzr_path`.

        We override this to return the 'bzr' executable from sourcecode.
        """
        return get_bzr_path()

    def push(self, local_directory, remote_url, extra_args=None):
        """Push the local branch to the given URL."""
        args = ['push', '-d', local_directory, remote_url]
        if extra_args is not None:
            args.extend(extra_args)
        self._run_bzr(args)

    def assertCantPush(self, local_directory, remote_url, error_messages=()):
        """Check that we cannot push from 'local_directory' to 'remote_url'.

        In addition, if a list of messages is supplied as the error_messages
        argument, check that the bzr client printed one of these messages
        which shouldn't include the 'bzr: ERROR:' part of the message.

        :return: The last line of the stderr from the subprocess, which will
            be the 'bzr: ERROR: <repr of Exception>' line.
        """
        error_line = self._run_bzr_error(
            ['push', '-d', local_directory, remote_url])
        # This will be the will be the 'bzr: ERROR: <repr of Exception>' line.
        if not error_messages:
            return error_line
        for msg in error_messages:
            if error_line.startswith('bzr: ERROR: ' + msg):
                return error_line
        self.fail("Error message %r didn't match any of those supplied." %
                  error_line)

    def getLastRevision(self, remote_url):
        """Get the last revision ID at the given URL."""
        output, error = self._run_bzr(['revision-info', '-d', remote_url])
        return output.split()[1]

    def getTransportURL(self, relpath=None, username=None):
        """Return the base URL for the tests."""
        if relpath is None:
            relpath = ''
        return self.server.get_url(username) + relpath

    def getDatabaseBranch(self, personName, productName, branchName):
        """Look up and return the specified branch from the database."""
        owner = Person.byName(personName)
        if productName is None:
            product = None
        else:
            product = Product.selectOneBy(name=productName)
        namespace = get_branch_namespace(owner, product)
        return namespace.getByName(branchName)

    def createBazaarBranch(self,
                           user,
                           product,
                           branch,
                           creator=None,
                           branch_root=None):
        """Create a new branch in the database and push our test branch there.

        Used to create branches that the test user is not able to create, and
        might not even be able to view.
        """
        authserver = xmlrpclib.ServerProxy(
            config.codehosting.authentication_endpoint)
        codehosting_api = xmlrpclib.ServerProxy(
            config.codehosting.codehosting_endpoint)
        if creator is None:
            creator_id = authserver.getUserAndSSHKeys(user)['id']
        else:
            creator_id = authserver.getUserAndSSHKeys(creator)['id']
        if branch_root is None:
            branch_root = self.server._mirror_root
        branch_id = codehosting_api.createBranch(
            creator_id, '/~%s/%s/%s' % (user, product, branch))
        branch_url = 'file://' + os.path.abspath(
            os.path.join(branch_root, branch_id_to_path(branch_id)))
        self.push(self.local_branch_path, branch_url, ['--create-prefix'])
        return branch_url
class SSHTestCase(TestCaseWithTransport, LoomTestMixin, TestCaseWithFactory):
    """TestCase class that runs an SSH server as well as the app server."""

    layer = SSHServerLayer
    scheme = None

    def setUp(self):
        super(SSHTestCase, self).setUp()
        self.disable_directory_isolation()
        tac_handler = SSHServerLayer.getTacHandler()
        self.server = SSHCodeHostingServer(self.scheme, tac_handler)
        self.server.start_server()
        self.addCleanup(self.server.stop_server)

        # Prevent creation of in-process sftp:// and bzr+ssh:// transports --
        # such connections tend to leak threads and occasionally create
        # uncollectable garbage.
        ssh_denier = DenyingServer(['bzr+ssh://', 'sftp://'])
        ssh_denier.start_server()
        self.addCleanup(ssh_denier.stop_server)

        # Create a local branch with one revision
        tree = self.make_branch_and_tree('local')
        self.local_branch = tree.branch
        self.local_branch_path = local_path_from_url(self.local_branch.base)
        self.build_tree(['local/foo'])
        tree.add('foo')
        self.revid = tree.commit('Added foo')

    def __str__(self):
        return self.id()

    def getTransport(self, relpath=None):
        return self.server.getTransport(relpath)

    def assertBranchesMatch(self, local_url, remote_url):
        """Assert that two branches have the same last revision."""
        local_revision = self.getLastRevision(local_url)
        remote_revision = self.getLastRevision(remote_url)
        self.assertEqual(local_revision, remote_revision)

    def runInChdir(self, directory, func, *args, **kwargs):
        old_dir = os.getcwdu()
        os.chdir(directory)
        try:
            return func(*args, **kwargs)
        finally:
            os.chdir(old_dir)

    def _run_bzr(self, args, retcode=0):
        """Call run_bzr_subprocess with some common options.

        We always want to force the subprocess to do its ssh communication
        with paramiko (because OpenSSH doesn't respect the $HOME environment
        variable) and we want to load the plugins that are in rocketfuel
        (mainly so we can test the loom support).
        """
        return self.run_bzr_subprocess(
            args, env_changes={
                'BZR_SSH': 'paramiko',
                'BZR_PLUGIN_PATH': get_BZR_PLUGIN_PATH_for_subprocess()
            },
            allow_plugins=True, retcode=retcode)

    def _run_bzr_error(self, args):
        """Run bzr expecting an error, returning the error message.
        """
        output, error = self._run_bzr(args, retcode=3)
        for line in error.splitlines():
            if line.startswith("bzr: ERROR"):
                return line
        raise AssertionError(
            "Didn't find error line in output:\n\n%s\n" % error)

    def branch(self, remote_url, local_directory):
        """Branch from the given URL to a local directory."""
        self._run_bzr(['branch', remote_url, local_directory])

    def get_bzr_path(self):
        """See `bzrlib.tests.TestCase.get_bzr_path`.

        We override this to return the 'bzr' executable from sourcecode.
        """
        return get_bzr_path()

    def push(self, local_directory, remote_url, extra_args=None):
        """Push the local branch to the given URL."""
        args = ['push', '-d', local_directory, remote_url]
        if extra_args is not None:
            args.extend(extra_args)
        self._run_bzr(args)

    def assertCantPush(self, local_directory, remote_url, error_messages=()):
        """Check that we cannot push from 'local_directory' to 'remote_url'.

        In addition, if a list of messages is supplied as the error_messages
        argument, check that the bzr client printed one of these messages
        which shouldn't include the 'bzr: ERROR:' part of the message.

        :return: The last line of the stderr from the subprocess, which will
            be the 'bzr: ERROR: <repr of Exception>' line.
        """
        error_line = self._run_bzr_error(
            ['push', '-d', local_directory, remote_url])
        # This will be the will be the 'bzr: ERROR: <repr of Exception>' line.
        if not error_messages:
            return error_line
        for msg in error_messages:
            if error_line.startswith('bzr: ERROR: ' + msg):
                return error_line
        self.fail(
            "Error message %r didn't match any of those supplied."
            % error_line)

    def getLastRevision(self, remote_url):
        """Get the last revision ID at the given URL."""
        output, error = self._run_bzr(
            ['revision-info', '-d', remote_url])
        return output.split()[1]

    def getTransportURL(self, relpath=None, username=None):
        """Return the base URL for the tests."""
        if relpath is None:
            relpath = ''
        return self.server.get_url(username) + relpath

    def getDatabaseBranch(self, personName, productName, branchName):
        """Look up and return the specified branch from the database."""
        owner = Person.byName(personName)
        if productName is None:
            product = None
        else:
            product = Product.selectOneBy(name=productName)
        namespace = get_branch_namespace(owner, product)
        return namespace.getByName(branchName)

    def createBazaarBranch(self, user, product, branch, creator=None,
                           branch_root=None):
        """Create a new branch in the database and push our test branch there.

        Used to create branches that the test user is not able to create, and
        might not even be able to view.
        """
        authserver = xmlrpclib.ServerProxy(
            config.codehosting.authentication_endpoint)
        codehosting_api = xmlrpclib.ServerProxy(
            config.codehosting.codehosting_endpoint)
        if creator is None:
            creator_id = authserver.getUserAndSSHKeys(user)['id']
        else:
            creator_id = authserver.getUserAndSSHKeys(creator)['id']
        if branch_root is None:
            branch_root = self.server._mirror_root
        branch_id = codehosting_api.createBranch(
            creator_id, '/~%s/%s/%s' % (user, product, branch))
        branch_url = 'file://' + os.path.abspath(
            os.path.join(branch_root, branch_id_to_path(branch_id)))
        self.push(self.local_branch_path, branch_url, ['--create-prefix'])
        return branch_url