Esempio n. 1
0
class TestStrategies(TestWithScenarios, BaseTestCase):

    scenarios = get_scenarios(
        os.path.join(os.path.dirname(__file__), "scenarios"))

    def setUp(self):
        # add description in case parent setup fails.
        self.addDetail('description', text_content(self.desc))

        # builds the tree to be tested
        super(TestStrategies, self).setUp()

        # need the tree built at this point
        self.addDetail(
            'expected-changes',
            text_content(
                pformat(
                    list((c, self.gittree.graph[c].hexsha)
                         for c in self.expected_changes))))

    def test_search_changes(self):

        strategy = LocateChangesWalk(
            branch=self.branches['head'][0],
            search_refs=[self.branches['upstream'][0]])

        self.assertEqual(
            self.gittree._commits_from_nodes(self.expected_changes),
            [c for c in strategy.filtered_iter()])

        self.assertThat(
            self.logger.output,
            matchers.Contains("Searching for most recent merge "
                              "base with upstream branches"))
Esempio n. 2
0
class TestUpstreamMergeBaseSearcher(TestWithScenarios, BaseTestCase):

    scenarios = get_scenarios(
        os.path.join(os.path.dirname(__file__), "scenarios"))

    def setUp(self):
        # add description in case parent setup fails.
        self.addDetail('description', text_content(self.desc))

        # builds the tree to be tested
        super(TestUpstreamMergeBaseSearcher, self).setUp()

        # need the tree built at this point
        self.addDetail(
            'expected-changes',
            text_content(
                pformat(
                    list((c, self.gittree.graph[c].hexsha)
                         for c in self.expected_changes))))

    def test_search_changes(self):
        if getattr(self, 'pattern', None):
            pattern = [self.pattern]
        else:
            pattern = None

        searcher = UpstreamMergeBaseSearcher(branch=self.branches['head'][0],
                                             patterns=pattern,
                                             repo=self.repo)

        self.assertEqual(
            self.gittree._commits_from_nodes(reversed(self.expected_changes)),
            searcher.list(self.branches['upstream'][0]))

        self.assertThat(
            self.logger.output,
            matchers.Contains("Searching for most recent merge "
                              "base with upstream branches"))
Esempio n. 3
0
class TestImportCommand(TestWithScenarios, BaseTestCase):

    scenarios = get_scenarios(os.path.join(os.path.dirname(__file__),
                              "conflict_scenarios"))

    def setUp(self):
        # add description in case parent setup fails.
        self.addDetail('description', text_content(self.desc))

        self.commands, self.parser = main.build_parsers()

        script_cmdline = self.parser.get_default('script_cmdline')
        script_cmdline[-1] = os.path.join(os.getcwd(), main.__file__)
        self.parser.set_defaults(script_cmdline=script_cmdline)

        # builds the tree to be tested
        super(TestImportCommand, self).setUp()

        self.upstream_branch = self.branches['upstream'][0]
        self.target_branch = self.branches['head'][0]

    def test_command(self):
        self.git.tag(inspect.currentframe().f_code.co_name,
                     self.upstream_branch)

        args = self.parser.parse_args(self.parser_args)
        # we should always fail here
        self.assertThat(args.cmd.run(args), Equals(False))

        if hasattr(self, 'post_script'):
            # simulate of manual resolving conflicts and completion of import
            self.run_post_script()

        # assuming non-interactive we should not see the following message
        # from appear in the logged output.
        self.assertThat(self.logger.output,
                        Not(Contains("Successfully rebased and updated")))

        # perform sanity checks on results
        self._check_tree_state()

        # allow disabling of checking the merge commit contents
        # as some tests won't result in an import
        if getattr(self, 'check_merge', True):
            commit_message = self.git.log(self.target_branch, n=1)
            self.assertThat(
                commit_message,
                Contains("of '%s' into '%s'" % (self.upstream_branch,
                                                self.target_branch)))
            # make sure the final state is actually correct
            self.assertThat(
                self.repo.git.rev_parse("%s^{tree}" % self.target_branch),
                Equals(self.repo.git.rev_parse(
                    "%s^2^{tree}" % self.target_branch)),
                "--finish option failed to merge correctly")

        # allow additional test specific verification methods below
        extra_test_func = getattr(self, '_verify_%s' % self.name, None)
        if extra_test_func:
            extra_test_func()

    def _check_tree_state(self):

        expected = getattr(self, 'expect_found', None)
        # even if empty want to confirm that find no changes applied,
        # otherwise confirm we find the expected number of changes.
        if expected is not None:
            if len(list(Commit.new(self.repo,
                                   self.target_branch).parents)) > 1:
                changes = list(Commit.iter_items(
                    self.repo,
                    '%s..%s^2' % (self.upstream_branch, self.target_branch),
                    topo_order=True))
            else:
                # allow checking that nothing was rebased
                changes = []
            self.assertThat(
                len(changes), Equals(len(expected)),
                "should only have seen %s changes, got: %s" %
                (len(expected),
                 ", ".join(["%s:%s" % (commit.hexsha,
                                       commit.message.splitlines()[0])
                           for commit in changes])))

            # expected should be listed in order from oldest to newest, so
            # reverse changes to match as it would be newest to oldest.
            changes.reverse()
            for commit, node in zip(changes, expected):
                if node == "MERGE":
                    continue
                subject = commit.message.splitlines()[0]
                node_subject = self.gittree.graph[node].message.splitlines()[0]
                self.assertThat(subject, Equals(node_subject),
                                "subject '%s' of commit '%s' does not match "
                                "subject '%s' of node '%s'" % (
                                    subject, commit.hexsha, node_subject,
                                    node))
class TestImportInteractiveCommand(TestWithScenarios, BaseTestCase):

    scenarios = get_scenarios(
        os.path.join(os.path.dirname(__file__), "interactive_scenarios"))

    def setUp(self):
        # add description in case parent setup fails.
        self.addDetail('description', text_content(self.desc))

        self.commands, self.parser = main.build_parsers()
        script_cmdline = self.parser.get_default('script_cmdline')
        script_cmdline[-1] = os.path.join(os.getcwd(), main.__file__)
        self.parser.set_defaults(script_cmdline=script_cmdline)

        # builds the tree to be tested
        super(TestImportInteractiveCommand, self).setUp()

    def test_interactive(self):
        upstream_branch = self.branches['upstream'][0]
        target_branch = self.branches['head'][0]

        cmdline = self.parser.get_default('script_cmdline') + self.parser_args

        # ensure interactive mode cannot hang tests
        def kill(proc_pid):
            process = psutil.Process(proc_pid)
            for proc in process.children(recursive=True):
                try:
                    proc.kill()
                except OSError:
                    continue
            try:
                process.kill()
            except OSError:
                pass

        def get_output(proc):
            self.output = proc.communicate()[0]

        proc = subprocess.Popen(cmdline,
                                stdin=open(os.devnull, "r"),
                                stdout=subprocess.PIPE,
                                stderr=subprocess.STDOUT,
                                close_fds=True,
                                cwd=self.testrepo.path)
        proc_thread = threading.Thread(target=get_output, args=[proc])
        proc_thread.start()
        proc_thread.join(getattr(self, 'timeout', 5))
        if proc_thread.is_alive():
            kill(proc.pid)
            proc_thread.join()
            self.addDetail('subprocess-output',
                           text_content(self.output.decode('utf-8')))
            raise Exception('Process #%d killed after timeout' % proc.pid)

        self.addDetail('subprocess-output',
                       text_content(self.output.decode('utf-8')))

        self.assertThat(proc.returncode, Equals(0))

        expected = getattr(self, 'expect_rebased', [])
        if expected:
            changes = list(
                Commit.iter_items(
                    self.repo, '%s..%s^2' % (upstream_branch, target_branch)))
            self.assertThat(
                len(changes), Equals(len(expected)),
                "should only have seen %s changes, got: %s" %
                (len(expected), ", ".join([
                    "%s:%s" % (commit.hexsha, commit.message.splitlines()[0])
                    for commit in changes
                ])))

            # expected should be listed in order from oldest to newest, so
            # reverse changes to match as it would be newest to oldest.
            changes.reverse()
            for commit, node in zip(changes, expected):
                subject = commit.message.splitlines()[0]
                node_subject = self.gittree.graph[node].message.splitlines()[0]
                self.assertThat(
                    subject, Equals(node_subject),
                    "subject '%s' of commit '%s' does not match "
                    "subject '%s' of node '%s'" %
                    (subject, commit.hexsha, node_subject, node))
        import_branch = [
            head for head in self.repo.heads if str(head).startswith("import")
            and not str(head).endswith("-base")
        ]

        self.assertThat(
            self.git.rev_parse(import_branch),
            Not(Equals(self.git.rev_parse(target_branch))),
            "Import branch and target should have identical "
            "contents, but not be the same")

        # allow disabling of checking the merge commit contents
        # as some tests won't result in an import
        if getattr(self, 'check_merge', True):
            commit_message = self.git.log(target_branch, n=1)
            self.assertThat(
                commit_message,
                Contains("of '%s' into '%s'" %
                         (upstream_branch, target_branch)))
            # make sure the final state of merge is correct
            self.assertThat(
                self.repo.git.rev_parse("%s^{tree}" % target_branch),
                Equals(self.repo.git.rev_parse("%s^2^{tree}" % target_branch)),
                "--finish option failed to merge correctly")

        # allow additional test specific verification methods below
        extra_test_func = getattr(self, '_verify_%s' % self.name, None)
        if extra_test_func:
            extra_test_func()

    def _verify_basic(self):
        self.assertThat(
            self.output.decode('utf-8'),
            Contains("Successfully rebased and updated refs/heads/import/"))
Esempio n. 5
0
class TestImportCommand(TestWithScenarios, BaseTestCase):

    scenarios = get_scenarios(
        os.path.join(os.path.dirname(__file__), "scenarios"))

    def setUp(self):
        # add description in case parent setup fails.
        self.addDetail('description', text_content(self.desc))

        self.commands, self.parser = main.build_parsers()

        script_cmdline = self.parser.get_default('script_cmdline')
        script_cmdline[-1] = os.path.join(os.getcwd(), main.__file__)
        self.parser.set_defaults(script_cmdline=script_cmdline)

        # builds the tree to be tested
        super(TestImportCommand, self).setUp()

        self.upstream_branch = self.branches['upstream'][0]
        self.target_branch = self.branches['head'][0]

    def test_command(self):
        self.git.tag(inspect.currentframe().f_code.co_name,
                     self.upstream_branch)

        args = self.parser.parse_args(self.parser_args)
        self.assertThat(args.cmd.run(args), Equals(True),
                        "import command failed to complete successfully")

        # assuming non-interactive we should *NOT* see the following message
        # appear in the logged output.
        self.assertThat(self.logger.output,
                        Not(Contains("Successfully rebased and updated")))

        self.assertThat(self.logger.output,
                        Contains("Starting execution of import command"))

        self.assertThat(
            self.logger.output,
            Not(Contains("Exception occurred during linearisation")))

        # perform sanity checks on results
        self._check_tree_state()

        # allow disabling of checking the merge commit contents
        # as some tests won't result in an import
        if getattr(self, 'check_merge', True):
            commit_message = self.git.log(self.target_branch, n=1)
            self.assertThat(
                commit_message,
                Contains("of '%s' into '%s'" %
                         (self.upstream_branch, self.target_branch)))

            # make sure the final state of merge is correct
            self.assertThat(
                self.repo.git.rev_parse("%s^{tree}" % self.target_branch),
                Equals(
                    self.repo.git.rev_parse("%s^2^{tree}" %
                                            self.target_branch)),
                "--finish option failed to merge correctly")

        # allow additional test specific verification methods below
        extra_test_func = getattr(self, '_verify_%s' % self.name, None)
        if extra_test_func:
            extra_test_func()

    def test_command_with_sha1s(self):
        # convert branches/tags to sha1s and use sha1 instead of branch
        parser_args = [
            arg if (arg.startswith('-') or arg in ("import", )) else
            self.git.rev_parse(arg) for arg in self.parser_args
        ]
        args = self.parser.parse_args(parser_args)
        self.assertThat(args.cmd.run(args), Equals(True),
                        "import command failed to complete successfully")

        self._check_tree_state()

    def test_command_with_tags(self):
        # add tag for each branch/ref and test with added tag
        parser_args = []
        for arg in self.parser_args:
            if (arg.startswith('-') or arg in ("import", )):
                parser_args.append(arg)
                continue

            tag_name = "tag-gu-%s" % arg.replace('~', '-')
            self.git.tag(tag_name, arg)
            parser_args.append(tag_name)

        args = self.parser.parse_args(parser_args)
        self.assertThat(args.cmd.run(args), Equals(True),
                        "import command failed to complete successfully")

        self._check_tree_state()

    def _check_tree_state(self):

        expected = getattr(self, 'expect_found', None)
        # even if empty want to confirm that find no changes applied,
        # otherwise confirm we find the expected number of changes.
        if expected is not None:
            if len(list(Commit.new(self.repo,
                                   self.target_branch).parents)) > 1:
                changes = list(
                    Commit.iter_items(
                        self.repo,
                        '%s..%s^2' %
                        (self.upstream_branch, self.target_branch),
                        topo_order=True))
            else:
                # allow checking that nothing was rebased
                changes = []
            self.assertThat(
                len(changes), Equals(len(expected)),
                "should only have seen %s changes, got: %s" %
                (len(expected), ", ".join([
                    "%s:%s" % (commit.hexsha, commit.message.splitlines()[0])
                    for commit in changes
                ])))

            # expected should be listed in order from oldest to newest, so
            # reverse changes to match as it would be newest to oldest.
            changes.reverse()
            for commit, node in zip(changes, expected):
                if node == "MERGE":
                    continue
                subject = commit.message.splitlines()[0]
                node_subject = self.gittree.graph[node].message.splitlines()[0]
                self.assertThat(
                    subject, Equals(node_subject),
                    "subject '%s' of commit '%s' does not match "
                    "subject '%s' of node '%s'" %
                    (subject, commit.hexsha, node_subject, node))

    def _verify_basic(self):

        self.assertThat(self.git.log(n=1), Contains("Merge branch 'import/"))
        # check we report to the user about the import branch created
        self.assertThat(self.logger.output,
                        Contains("Created import branch 'import/"))

    def _verify_basic_additional_missed(self):
        """Additional verification that test produces a warning"""

        self.assertThat(self.logger.output,
                        Contains("Previous import merged additional"))

    def _verify_import_finish(self):
        """Additional verification for the finished results"""

        commit = self.git.rev_list('master', parents=True, max_count=1).split()
        parents = commit[1:]
        self.assertThat(
            parents,
            Equals([
                self.gittree.graph['D'].hexsha, self.gittree.graph['D1'].hexsha
            ]), "import --finish merge does contain the correct "
            "parents")

    def _verify_import_same_as_previous_upstream(self):
        """Additional verification for the finished results"""
        self.assertThat(self.logger.output,
                        Contains("already at latest upstream commit"))
        self.assertThat(self.logger.output, Contains("Nothing to be imported"))

    def _verify_same_previous_with_same_additional(self):
        """Additional verification for the finished results"""

        self.assertThat(self.logger.output,
                        Contains("already at latest upstream commit"))
        self.assertThat(
            self.logger.output,
            Contains("No updated additional branch given, nothing to be done"))

    def _verify_import_everything_already_upstreamed(self):
        """Additional verification for the finished results"""

        self.assertThat(self.logger.output,
                        Contains("All carried changes gone upstream"))
        self.assertThat(
            self.logger.output,
            Contains("Creating  branch 'import/test_command' from specified "
                     "commit 'upstream/master'"))