def updateStats(self, log):
        """
        Parse test results out of common test harnesses.

        Currently supported are:

         * Plone
         * Nose
         * Trial
         * Something mitchell wrote in Java
        """
        stdio = log.getText()

        total = passed = skipped = fails = warnings = errors = 0
        hastests = False

        # Plone? That has lines starting "Ran" and "Total". Total is missing if there is only a single layer.
        # For this reason, we total ourselves which lets us work even if someone runes 2 batches of plone tests
        # from a single target

        # Example::
        #     Ran 24 tests with 0 failures and 0 errors in 0.009 seconds

        if not hastests:
            outputs = re.findall(
                "Ran (?P<count>[\d]+) tests with (?P<fail>[\d]+) failures and (?P<error>[\d]+) errors",
                stdio)
            for output in outputs:
                total += int(output[0])
                fails += int(output[1])
                errors += int(output[2])
                hastests = True

        # Twisted

        # Example::
        #    FAILED (errors=5, successes=11)
        #    PASSED (successes=16)
        if not hastests:
            for line in stdio.split("\n"):
                if line.startswith("FAILED (") or line.startswith("PASSED ("):
                    hastests = True

                    line = line[8:][:-1]
                    stats = line.split(", ")
                    data = {}

                    for stat in stats:
                        k, v = stat.split("=")
                        data[k] = int(v)

                    if "successes" not in data:
                        total = 0
                        for number in re.findall(
                                "Ran (?P<count>[\d]+) tests in ", stdio):
                            total += int(number)
                        data["successes"] = total - sum(data.values())

        # This matches Nose and Django output

        # Example::
        #     Ran 424 tests in 152.927s
        #     FAILED (failures=1)
        #     FAILED (errors=3)

        if not hastests:
            fails += len(re.findall('FAIL:', stdio))
            errors += len(
                re.findall(
                    '======================================================================\nERROR:',
                    stdio))
            for number in re.findall("Ran (?P<count>[\d]+)", stdio):
                total += int(number)
                hastests = True

        # We work out passed at the end because most test runners dont tell us
        # and we can't distinguish between different test systems easily so we
        # might double count.
        passed = total - (skipped + fails + errors + warnings)

        # Update the step statistics with out shiny new totals
        if hastests:
            self.setStatistic('total', total)
            self.setStatistic('fails', fails)
            self.setStatistic('errors', errors)
            self.setStatistic('warnings', warnings)
            self.setStatistic('skipped', skipped)
            self.setStatistic('passed', passed)
Parse test results out of common test harnesses.

        Currently supported are:

         * Plone
         * Nose
         * Trial
         * Something mitchell wrote in Java