--- /dev/null
+# This file is used to process section data generated by `objdump -s`
+import re
+
+
+class SectionTable(object):
+
+ class Section(object):
+ SECTION_START_PATTERN = re.compile("Contents of section (.+?):")
+ DATA_PATTERN = re.compile("([0-9a-f]{4,8})")
+
+ def __init__(self, name, start_address, data):
+ self.name = name
+ self.start_address = start_address
+ self.data = data
+
+ def __contains__(self, item):
+ if (item["region"] == self.name or item["region"] == "any") \
+ and (self.start_address <= item["address"] < (self.start_address + len(self.data))):
+ return True
+ else:
+ return False
+
+ def __getitem__(self, item):
+ if isinstance(item, int):
+ return self.data[item - self.start_address]
+ elif isinstance(item, slice):
+ start = item.start if item.start is None else item.start - self.start_address
+ stop = item.stop if item.stop is None else item.stop - self.start_address
+ return self.data[start:stop]
+ return self.data[item]
+
+ def __str__(self):
+ return "%s [%08x - %08x]" % (self.name, self.start_address, self.start_address+len(self.data))
+
+ __repr__ = __str__
+
+ @classmethod
+ def parse_raw_data(cls, raw_data):
+ name = ""
+ data = ""
+ start_address = 0
+ # first find start line
+ for i, line in enumerate(raw_data):
+ if line.find("Contents of section ") != -1: # do strcmp first to speed up
+ match = cls.SECTION_START_PATTERN.search(line)
+ if match is not None:
+ name = match.group(1)
+ raw_data = raw_data[i+1:]
+ break
+ else:
+ # do some error handling
+ raw_data = [""] # add a dummy first data line
+ pass
+
+ def process_data_line(line_to_process):
+ # first remove the ascii part
+ hex_part = line_to_process.split(" ")[0]
+ # process rest part
+ data_list = cls.DATA_PATTERN.findall(hex_part)
+ try:
+ _address = int(data_list[0], base=16)
+ except IndexError:
+ _address = -1
+
+ def hex_to_str(hex_data):
+ if len(hex_data) % 2 == 1:
+ hex_data = "0" + hex_data # append zero at the beginning
+ _length = len(hex_data)
+ return "".join([chr(int(hex_data[_i:_i+2], base=16))
+ for _i in range(0, _length, 2)])
+ pass
+
+ return _address, "".join([hex_to_str(x) for x in data_list[1:]])
+
+ # handle first line:
+ address, _data = process_data_line(raw_data[0])
+ if address != -1:
+ start_address = address
+ data += _data
+ raw_data = raw_data[1:]
+ for i, line in enumerate(raw_data):
+ address, _data = process_data_line(line)
+ if address == -1:
+ raw_data = raw_data[i:]
+ break
+ else:
+ data += _data
+ else:
+ # do error handling
+ raw_data = []
+ pass
+ return cls(name, start_address, data) if start_address != -1 else None,\
+ None if len(raw_data) == 0 else raw_data
+ pass
+
+ def __init__(self, file_name):
+ with open(file_name, "rb") as f:
+ raw_data = f.readlines()
+ self.table = []
+ while raw_data:
+ section, raw_data = self.Section.parse_raw_data(raw_data)
+ self.table.append(section)
+
+ def get_unsigned_int(self, region, address, size=4, endian="LE"):
+ if address % 4 != 0 or size % 4 != 0:
+ print "warning: try to access without 4 bytes aligned"
+ key = {"address": address, "region": region}
+ for section in self.table:
+ if key in section:
+ tmp = section[address:address+size]
+ value = 0
+ for i in range(size):
+ if endian == "LE":
+ value += ord(tmp[i]) << (i*8)
+ elif endian == "BE":
+ value += ord(tmp[i]) << ((size - i - 1) * 8)
+ else:
+ print "only support LE or BE for parameter endian"
+ assert False
+ break
+ else:
+ value = None
+ return value
+
+ def get_string(self, region, address):
+ value = None
+ key = {"address": address, "region": region}
+ for section in self.table:
+ if key in section:
+ value = section[address:]
+ for i, c in enumerate(value):
+ if c == '\0':
+ value = value[:i]
+ break
+ break
+ return value
+ pass
+
+
+def main():
+ pass
+
+
+if __name__ == '__main__':
+ main()
import yaml
import os
-import os.path
import re
import sys
import shutil
+import CreateSectionTable
MODULE_MAP = yaml.load(open("ModuleDefinition.yml", "r"))
class Parser(object):
@classmethod
- def parse_test_folders(cls):
- test_folder_paths = list()
- os.chdir(os.path.join(IDF_PATH, "components"))
- component_dirs = [d for d in os.listdir(".") if os.path.isdir(d)]
- for dir in component_dirs:
- os.chdir(dir)
- if "test" in os.listdir("."):
- test_folder_paths.append(os.path.join(os.getcwd(), "test"))
- os.chdir("..")
- Parser.parse_test_files(test_folder_paths)
-
- @classmethod
- def parse_test_files(cls, test_folder_paths):
- for path in test_folder_paths:
- os.chdir(path)
- for file_path in os.listdir("."):
- if file_path[-2:] == ".c":
- Parser.read_test_file(os.path.join(os.getcwd(), file_path), len(test_cases)+1)
+ def parse_test_addresses(cls):
+ table = CreateSectionTable.SectionTable(os.path.join(IDF_PATH, "tools", "unit-test-app", "build", "tmp"))
+ file_index = 1
+ test_index = 1
+ with open(os.path.join(IDF_PATH, "tools", "unit-test-app", "build", "tests"), "r") as file:
+ for line in file:
+ line = line.split()
+ test = int(line[0],16)
+ section = line[3]
+ name_addr = table.get_unsigned_int(section, test, 4)
+ desc_addr = table.get_unsigned_int(section, test + 4, 4)
+ name = table.get_string("any", name_addr)
+ desc = table.get_string("any", desc_addr)
+ Parser.parse_test_cases(file_index, test_index, "%s, %s" % (name, desc))
+ file_index += 1
+ test_index += 1
os.chdir(os.path.join("..", ".."))
Parser.dump_test_cases(test_cases)
- @classmethod
- def read_test_file(cls, test_file_path, file_index):
- test_index = 0
- with open(test_file_path, "r") as file:
- for line in file:
- if re.match("TEST_CASE", line):
- test_index += 1
- tags = re.split(r"[\[\]\"]", line)
- Parser.parse_test_cases(file_index, test_index, tags)
-
-
@classmethod
def parse_test_cases(cls, file_index, test_index, tags):
+ tags = re.split(r"[\[\]\"]", tags)
ci_ready = "Yes"
test_env = "UT_T1_1"
for tag in tags:
ci_ready = "No"
if re.match("test_env=", tag):
test_env = tag[9:]
- module_name = tags[4]
+ module_name = tags[1]
try:
MODULE_MAP[module_name]
except KeyError:
test_case = dict(TEST_CASE_PATTERN)
test_case.update({"module": MODULE_MAP[module_name]['module'],
"CI ready": ci_ready,
- "cmd set": ["IDFUnitTest/UnitTest", [tags[1]]],
+ "cmd set": ["IDFUnitTest/UnitTest", [tags[0][:-2]]],
"ID": id,
"test point 2": module_name,
- "steps": tags[1],
- "comment": tags[1],
+ "steps": tags[0][:-2],
+ "comment": tags[0][:-2],
"test environment": test_env,
"sub module": MODULE_MAP[module_name]['sub module'],
- "summary": tags[1]})
+ "summary": tags[0][:-2]})
if test_case["CI ready"] == "Yes":
if test_ids.has_key(test_env):
test_ids[test_env].append(id)
def main():
- Parser.parse_test_folders()
+ os.chdir(os.path.join(IDF_PATH, "tools", "unit-test-app", "build"))
+ os.system('xtensa-esp32-elf-objdump -t unit-test-app.elf | grep test_desc > tests')
+ os.system('xtensa-esp32-elf-objdump -s unit-test-app.elf > tmp')
+ Parser.parse_test_addresses()
Parser.parse_gitlab_ci()
Parser.dump_ci_config()
Parser.copy_module_def_file()