Beispiel #1
0
    def parse_test_cases_from_elf(self, elf_file, app_name):
        """
        parse test cases from elf and save test cases need to be executed to unit test folder
        :param elf_file: elf file path
        :param app_name: built unit test app name
        """
        subprocess.check_output(
            'xtensa-esp32-elf-objdump -t {} | grep \ test_desc > case_address.tmp'
            .format(elf_file),
            shell=True)
        subprocess.check_output(
            'xtensa-esp32-elf-objdump -s {} > section_table.tmp'.format(
                elf_file),
            shell=True)

        table = CreateSectionTable.SectionTable("section_table.tmp")
        test_cases = []
        with open("case_address.tmp", "r") as f:
            for line in f:
                # process symbol table like: "3ffb4310 l     O .dram0.data	00000018 test_desc_33$5010"
                line = line.split()
                test_addr = int(line[0], 16)
                section = line[3]

                name_addr = table.get_unsigned_int(section, test_addr, 4)
                desc_addr = table.get_unsigned_int(section, test_addr + 4, 4)
                file_name_addr = table.get_unsigned_int(
                    section, test_addr + 12, 4)
                name = table.get_string("any", name_addr)
                desc = table.get_string("any", desc_addr)
                file_name = table.get_string("any", file_name_addr)

                tc = self.parse_one_test_case(name, desc, file_name, app_name)

                # check if duplicated case names
                # we need to use it to select case,
                # if duplicated IDs, Unity could select incorrect case to run
                # and we need to check all cases no matter if it's going te be executed by CI
                # also add app_name here, we allow same case for different apps
                if (tc["summary"] + app_name) in self.test_case_names:
                    self.parsing_errors.append("duplicated test case ID: " +
                                               tc["summary"])
                else:
                    self.test_case_names.add(tc["summary"] + app_name)

                if tc["CI ready"] == "Yes":
                    # update test env list and the cases of same env list
                    if tc["test environment"] in self.test_env_tags:
                        self.test_env_tags[tc["test environment"]].append(
                            tc["ID"])
                    else:
                        self.test_env_tags.update(
                            {tc["test environment"]: [tc["ID"]]})
                    # only add cases need to be executed
                    test_cases.append(tc)

        os.remove("section_table.tmp")
        os.remove("case_address.tmp")

        return test_cases
Beispiel #2
0
    def parse_test_cases_from_elf(self, elf_file):
        """
        parse test cases from elf and save test cases to unit test folder
        :param elf_file: elf file path
        """
        subprocess.check_output(
            'xtensa-esp32-elf-objdump -t {} | grep \ test_desc > case_address.tmp'
            .format(elf_file),
            shell=True)
        subprocess.check_output(
            'xtensa-esp32-elf-objdump -s {} > section_table.tmp'.format(
                elf_file),
            shell=True)

        table = CreateSectionTable.SectionTable("section_table.tmp")
        test_cases = []
        with open("case_address.tmp", "r") as f:
            for line in f:
                # process symbol table like: "3ffb4310 l     O .dram0.data	00000018 test_desc_33$5010"
                line = line.split()
                test_addr = int(line[0], 16)
                section = line[3]

                name_addr = table.get_unsigned_int(section, test_addr, 4)
                desc_addr = table.get_unsigned_int(section, test_addr + 4, 4)
                file_name_addr = table.get_unsigned_int(
                    section, test_addr + 12, 4)
                name = table.get_string("any", name_addr)
                desc = table.get_string("any", desc_addr)
                file_name = table.get_string("any", file_name_addr)

                tc = self.parse_one_test_case(name, desc, file_name)
                if tc["CI ready"] == "Yes":
                    # update test env list and the cases of same env list
                    if tc["test environment"] in self.test_env_tags:
                        self.test_env_tags[tc["test environment"]].append(
                            tc["ID"])
                    else:
                        self.test_env_tags.update(
                            {tc["test environment"]: [tc["ID"]]})
                test_cases.append(tc)

        os.remove("section_table.tmp")
        os.remove("case_address.tmp")

        self.dump_test_cases(test_cases)
Beispiel #3
0
def parse_elf_test_cases(elf_file: str, idf_target: str) -> List[Dict]:
    objdump = get_target_objdump(idf_target)

    try:
        subprocess.check_output('{} -s {} > section_table.tmp'.format(
            objdump, elf_file),
                                shell=True)
        table = CreateSectionTable.SectionTable('section_table.tmp')
    except subprocess.CalledProcessError:
        raise Exception('Can\'t resolve elf file. File not found.')
    finally:
        os.remove('section_table.tmp')

    bin_test_cases = []
    try:
        subprocess.check_output(
            '{} -t {} | grep test_desc > case_address.tmp'.format(
                objdump, elf_file),
            shell=True)

        with open('case_address.tmp', 'rb') as input_f:
            for line in input_f:
                # process symbol table like: "3ffb4310 l     O .dram0.data	00000018 test_desc_33$5010"
                sections = line.split()
                test_addr = int(sections[0], 16)
                section = sections[3]

                name_addr = table.get_unsigned_int(section, test_addr, 4)
                desc_addr = table.get_unsigned_int(section, test_addr + 4, 4)
                tc = {
                    'name':
                    table.get_string('any', name_addr),
                    'desc':
                    table.get_string('any', desc_addr),
                    'function_count':
                    table.get_unsigned_int(section, test_addr + 20, 4),
                }
                bin_test_cases.append(tc)
    except subprocess.CalledProcessError:
        raise Exception('Test cases not found')
    finally:
        os.remove('case_address.tmp')

    return bin_test_cases
Beispiel #4
0
    def parse_test_cases_for_one_config(self, configs_folder,
                                        config_output_folder, config_name):
        """
        parse test cases from elf and save test cases need to be executed to unit test folder
        :param configs_folder: folder where per-config sdkconfig framents are located (i.e. tools/unit-test-app/configs)
        :param config_output_folder: build folder of this config
        :param config_name: built unit test config name
        """
        test_groups = self.get_test_groups(
            os.path.join(configs_folder, config_name))

        elf_file = os.path.join(config_output_folder, self.ELF_FILE)
        subprocess.check_output(
            'xtensa-esp32-elf-objdump -t {} | grep test_desc > case_address.tmp'
            .format(elf_file),
            shell=True)
        subprocess.check_output(
            'xtensa-esp32-elf-objdump -s {} > section_table.tmp'.format(
                elf_file),
            shell=True)

        table = CreateSectionTable.SectionTable("section_table.tmp")
        tags = self.parse_tags(
            os.path.join(config_output_folder, self.SDKCONFIG_FILE))
        test_cases = []
        with open("case_address.tmp", "rb") as f:
            for line in f:
                # process symbol table like: "3ffb4310 l     O .dram0.data	00000018 test_desc_33$5010"
                line = line.split()
                test_addr = int(line[0], 16)
                section = line[3]

                name_addr = table.get_unsigned_int(section, test_addr, 4)
                desc_addr = table.get_unsigned_int(section, test_addr + 4, 4)
                file_name_addr = table.get_unsigned_int(
                    section, test_addr + 12, 4)
                function_count = table.get_unsigned_int(
                    section, test_addr + 20, 4)
                name = table.get_string("any", name_addr)
                desc = table.get_string("any", desc_addr)
                file_name = table.get_string("any", file_name_addr)
                tc = self.parse_one_test_case(name, desc, file_name,
                                              config_name, tags)

                # check if duplicated case names
                # we need to use it to select case,
                # if duplicated IDs, Unity could select incorrect case to run
                # and we need to check all cases no matter if it's going te be executed by CI
                # also add app_name here, we allow same case for different apps
                if (tc["summary"] + config_name) in self.test_case_names:
                    self.parsing_errors.append("duplicated test case ID: " +
                                               tc["summary"])
                else:
                    self.test_case_names.add(tc["summary"] + config_name)

                test_group_included = True
                if test_groups is not None and tc["group"] not in test_groups:
                    test_group_included = False

                if tc["CI ready"] == "Yes" and test_group_included:
                    # update test env list and the cases of same env list
                    if tc["test environment"] in self.test_env_tags:
                        self.test_env_tags[tc["test environment"]].append(
                            tc["ID"])
                    else:
                        self.test_env_tags.update(
                            {tc["test environment"]: [tc["ID"]]})

                    if function_count > 1:
                        tc.update({"child case num": function_count})

                    # only add  cases need to be executed
                    test_cases.append(tc)

        os.remove("section_table.tmp")
        os.remove("case_address.tmp")

        return test_cases
Beispiel #5
0
    def parse_test_cases_for_one_config(self, configs_folder,
                                        config_output_folder, config_name):
        """
        parse test cases from elf and save test cases need to be executed to unit test folder
        :param configs_folder: folder where per-config sdkconfig fragments are located (i.e. tools/unit-test-app/configs)
        :param config_output_folder: build folder of this config
        :param config_name: built unit test config name
        """
        tags = self.parse_tags(
            os.path.join(config_output_folder, self.SDKCONFIG_FILE))
        print('Tags of config %s: %s' % (config_name, tags))

        test_groups = self.get_test_groups(
            os.path.join(configs_folder, config_name))

        elf_file = os.path.join(config_output_folder, self.ELF_FILE)
        subprocess.check_output(
            '{} -t {} | grep test_desc > case_address.tmp'.format(
                self.objdump, elf_file),
            shell=True)
        subprocess.check_output('{} -s {} > section_table.tmp'.format(
            self.objdump, elf_file),
                                shell=True)

        table = CreateSectionTable.SectionTable('section_table.tmp')
        test_cases = []

        # we could split cases of same config into multiple binaries as we have limited rom space
        # we should regard those configs like `default` and `default_2` as the same config
        match = self.STRIP_CONFIG_PATTERN.match(config_name)
        stripped_config_name = match.group(1)

        with open('case_address.tmp', 'rb') as f:
            for line in f:
                # process symbol table like: "3ffb4310 l     O .dram0.data	00000018 test_desc_33$5010"
                line = line.split()
                test_addr = int(line[0], 16)
                section = line[3]

                name_addr = table.get_unsigned_int(section, test_addr, 4)
                desc_addr = table.get_unsigned_int(section, test_addr + 4, 4)
                function_count = table.get_unsigned_int(
                    section, test_addr + 20, 4)
                name = table.get_string('any', name_addr)
                desc = table.get_string('any', desc_addr)

                tc = self.parse_one_test_case(name, desc, config_name,
                                              stripped_config_name, tags)

                # check if duplicated case names
                # we need to use it to select case,
                # if duplicated IDs, Unity could select incorrect case to run
                # and we need to check all cases no matter if it's going te be executed by CI
                # also add app_name here, we allow same case for different apps
                if (tc['summary'] +
                        stripped_config_name) in self.test_case_names:
                    self.parsing_errors.append('duplicated test case ID: ' +
                                               tc['summary'])
                else:
                    self.test_case_names.add(tc['summary'] +
                                             stripped_config_name)

                test_group_included = True
                if test_groups is not None and tc['group'] not in test_groups:
                    test_group_included = False

                if tc['CI ready'] == 'Yes' and test_group_included:
                    # update test env list and the cases of same env list
                    if tc['test environment'] in self.test_env_tags:
                        self.test_env_tags[tc['test environment']].append(
                            tc['ID'])
                    else:
                        self.test_env_tags.update(
                            {tc['test environment']: [tc['ID']]})

                    if function_count > 1:
                        tc.update({'child case num': function_count})

                    # only add  cases need to be executed
                    test_cases.append(tc)

        os.remove('section_table.tmp')
        os.remove('case_address.tmp')

        return test_cases
Beispiel #6
0
    def parse_test_cases_for_one_config(self, configs_folder, config_output_folder, config_name):
        """
        parse test cases from elf and save test cases need to be executed to unit test folder
        :param configs_folder: folder where per-config sdkconfig framents are located (i.e. tools/unit-test-app/configs)
        :param config_output_folder: build folder of this config
        :param config_name: built unit test config name
        """
        tags = self.parse_tags(os.path.join(config_output_folder, self.SDKCONFIG_FILE))
        print("Tags of config %s: %s" % (config_name, tags))
        # Search in tags to set the target
        target_tag_dict = {"ESP32_IDF": "esp32", "ESP32S2BETA_IDF": "esp32s2beta"}
        for tag in target_tag_dict:
            if tag in tags:
                target = target_tag_dict[tag]
                break
        else:
            target = "esp32"

        if target == "esp32s2beta":
            # Unit tests temporarily disabled for beta chip
            return []

        test_groups = self.get_test_groups(os.path.join(configs_folder, config_name))

        elf_file = os.path.join(config_output_folder, self.ELF_FILE)
        subprocess.check_output('xtensa-esp32-elf-objdump -t {} | grep test_desc > case_address.tmp'.format(elf_file),
                                shell=True)
        subprocess.check_output('xtensa-esp32-elf-objdump -s {} > section_table.tmp'.format(elf_file), shell=True)

        table = CreateSectionTable.SectionTable("section_table.tmp")
        test_cases = []

        # we could split cases of same config into multiple binaries as we have limited rom space
        # we should regard those configs like `default` and `default_2` as the same config
        match = self.STRIP_CONFIG_PATTERN.match(config_name)
        stripped_config_name = match.group(1)

        with open("case_address.tmp", "rb") as f:
            for line in f:
                # process symbol table like: "3ffb4310 l     O .dram0.data	00000018 test_desc_33$5010"
                line = line.split()
                test_addr = int(line[0], 16)
                section = line[3]

                name_addr = table.get_unsigned_int(section, test_addr, 4)
                desc_addr = table.get_unsigned_int(section, test_addr + 4, 4)
                file_name_addr = table.get_unsigned_int(section, test_addr + 12, 4)
                function_count = table.get_unsigned_int(section, test_addr + 20, 4)
                name = table.get_string("any", name_addr)
                desc = table.get_string("any", desc_addr)
                file_name = table.get_string("any", file_name_addr)

                tc = self.parse_one_test_case(name, desc, file_name, config_name, stripped_config_name, tags, target)

                # check if duplicated case names
                # we need to use it to select case,
                # if duplicated IDs, Unity could select incorrect case to run
                # and we need to check all cases no matter if it's going te be executed by CI
                # also add app_name here, we allow same case for different apps
                if (tc["summary"] + stripped_config_name) in self.test_case_names:
                    self.parsing_errors.append("duplicated test case ID: " + tc["summary"])
                else:
                    self.test_case_names.add(tc["summary"] + stripped_config_name)

                test_group_included = True
                if test_groups is not None and tc["group"] not in test_groups:
                    test_group_included = False

                if tc["CI ready"] == "Yes" and test_group_included:
                    # update test env list and the cases of same env list
                    if tc["test environment"] in self.test_env_tags:
                        self.test_env_tags[tc["test environment"]].append(tc["ID"])
                    else:
                        self.test_env_tags.update({tc["test environment"]: [tc["ID"]]})

                    if function_count > 1:
                        tc.update({"child case num": function_count})

                    # only add  cases need to be executed
                    test_cases.append(tc)

        os.remove("section_table.tmp")
        os.remove("case_address.tmp")

        return test_cases