def main():
    parser = argparse.ArgumentParser(description='run_memory_map')
    parser.add_argument('--toolchain', type=str, help='GCC toolchain path', default='')
    parser.add_argument('--binutils_prefix', type=str, help='GNU binutils prefix', default='')
    parser.add_argument('--file', type=str, help='Binary file')
    parser.add_argument('--key_name', type=str, help='TeamCity buildStatisticValue key name suffix', default='none')
    args = parser.parse_args()

    tsm = TeamcityServiceMessages()

    sections = parse_size(args.toolchain, args.binutils_prefix, args.file)
    if sections:
        flash_size = 0
        ram_size = 0
        other_size = 0
        for section in sections:
            if section.name in ['.text', '.ARM.exidx', '.relocate']:
                flash_size += section.size
            elif section.name in ['.bss', '.stack']:
                ram_size += section.size
            else:
                other_size += section.size
        tsm.message('buildStatisticValue', key='FLASH ({0})'.format(args.key_name), value=str(flash_size))
        tsm.message('buildStatisticValue', key='RAM ({0})'.format(args.key_name), value=str(ram_size))
        # tsm.message('buildStatisticValue', key='OTHER ({0})'.format(args.key_name), value=str(other_size))
    else:
        tsm.buildProblem('Unable to detect sections', '')
def test_build_problem():
    stream = StreamStub()
    messages = TeamcityServiceMessages(output=stream, now=lambda: fixed_date)
    messages.buildProblem(description='something is wrong', identity='me')
    assert stream.observed_output.strip() == textwrap.dedent("""\
        ##teamcity[buildProblem timestamp='2000-11-02T10:23:01.556' description='something is wrong' identity='me']
        """).strip().encode('utf-8')
def test_build_problem():
    stream = StreamStub()
    messages = TeamcityServiceMessages(output=stream, now=lambda: fixed_date)
    messages.buildProblem(description='something is wrong', identity='me')
    assert stream.observed_output.strip() == textwrap.dedent("""\
        ##teamcity[buildProblem timestamp='2000-11-02T10:23:01.556' description='something is wrong' identity='me']
        """).strip().encode('utf-8')
class TeamcityBuild(UserBuild):
    def __init__(self, configuration):
        super().__init__(configuration)

        # This accounts for the volume mapping from the container.
        # Our local /results is mapped to some relative ./results on the host,
        # so we use /results/artifacts to copy our files but results/artifacts as
        # an artifact path for teamcity.
        # TODO abstract out the volume mapping
        self.artifact_dir = Path("/results/artifacts")

        self.teamcity_messages = TeamcityServiceMessages()

    def copy_artifacts(self, artifacts):
        super().copy_artifacts(artifacts)

        # Start loading the junit reports.
        junit_reports_pattern = "{}/junit/*.xml".format(
            str(self.artifact_dir.relative_to("/")))
        self.teamcity_messages.importData("junit", junit_reports_pattern)

        # Instruct teamcity to upload our artifact directory
        artifact_path_pattern = "+:{}=>artifacts.tar.gz".format(
            str(self.artifact_dir.relative_to("/")))
        self.teamcity_messages.publishArtifacts(artifact_path_pattern)

    def run(self, args=None):
        args = args if args is not None else []

        # Let the user know what build is being run.
        # This makes it easier to retrieve the info from the logs.
        self.teamcity_messages.customMessage("Starting build {}".format(
            self.configuration.name),
                                             status="NORMAL")

        return_code, message = super().run()

        # Since we are aborting the build, make sure to flush everything first
        os.sync()

        if return_code != 0:
            # Add a build problem to the report
            self.teamcity_messages.buildProblem(
                message,
                # Let Teamcity calculate an ID from our message
                None)
            # Change the final build message
            self.teamcity_messages.buildStatus(
                # Don't change the status, let Teamcity set it to failure
                None,
                message)
        else:
            # Change the final build message but keep the original one as well
            self.teamcity_messages.buildStatus(
                # Don't change the status, let Teamcity set it to success
                None,
                "{} ({{build.status.text}})".format(message))

        return (return_code, message)