components: Correct the Python coding style

This commit is contained in:
Roland Dobai 2018-12-04 13:06:46 +01:00
parent c69907a54b
commit e1e6c1ae0a
6 changed files with 326 additions and 300 deletions

13
.flake8
View file

@ -150,22 +150,15 @@ exclude =
components/unity/unity,
examples/build_system/cmake/import_lib/main/lib/tinyxml2
# autogenerated scripts
examples/provisioning/custom_config/components/custom_provisioning/python/custom_config_pb2.py,
# temporary list (should be empty)
components/app_update/dump_otadata.py,
components/app_update/gen_empty_partition.py,
components/espcoredump/espcoredump.py,
components/espcoredump/test/test_espcoredump.py,
components/nvs_flash/nvs_partition_generator/nvs_partition_gen.py,
components/partition_table/gen_esp32part.py,
components/partition_table/test_gen_esp32part_host/gen_esp32part_tests.py,
components/protocomm/python/constants_pb2.py,
components/protocomm/python/sec0_pb2.py,
components/protocomm/python/sec1_pb2.py,
components/protocomm/python/session_pb2.py,
components/ulp/esp32ulp_mapgen.py,
components/wifi_provisioning/python/wifi_config_pb2.py,
components/wifi_provisioning/python/wifi_constants_pb2.py,
examples/provisioning/custom_config/components/custom_provisioning/python/custom_config_pb2.py,
# temporary list (should be empty)
components/nvs_flash/nvs_partition_generator/nvs_partition_gen.py,
tools/ci/apply_bot_filter.py,
tools/cmake/convert_to_cmake.py,
tools/esp_app_trace/apptrace_proc.py,

View file

@ -5,6 +5,7 @@
from __future__ import print_function
from __future__ import unicode_literals
from __future__ import division
import sys
try:
from builtins import zip
from builtins import str
@ -15,13 +16,11 @@ except ImportError:
print('Import has failed probably because of the missing "future" package. Please install all the packages for '
'interpreter {} from the $IDF_PATH/requirements.txt file.'.format(sys.executable))
sys.exit(1)
import sys
import os
import argparse
import subprocess
import tempfile
import struct
import array
import errno
import base64
import binascii
@ -53,6 +52,7 @@ class ESPCoreDumpError(RuntimeError):
"""
super(ESPCoreDumpError, self).__init__(message)
class BinStruct(object):
"""Binary structure representation
@ -359,8 +359,8 @@ class ESPCoreDumpElfFile(esptool.ELFFile):
f.seek(offs)
return f.read(size)
prog_sections = [ESPCoreDumpSection(lookup_string(n_offs), lma, read_data(offs, size), flags) for (n_offs, _type, flags, lma, size, offs) in prog_sections
if lma != 0]
prog_sections = [ESPCoreDumpSection(lookup_string(n_offs), lma, read_data(offs, size), flags)
for (n_offs, _type, flags, lma, size, offs) in prog_sections if lma != 0]
self.sections = prog_sections
def _read_program_segments(self, f, seg_table_offs, entsz, num):
@ -387,8 +387,8 @@ class ESPCoreDumpElfFile(esptool.ELFFile):
f.seek(offs)
return f.read(size)
self.program_segments = [ESPCoreDumpSegment(vaddr, read_data(offset, filesz), type, flags) for (type, offset, vaddr, filesz,flags) in prog_segments
if vaddr != 0]
self.program_segments = [ESPCoreDumpSegment(vaddr, read_data(offset, filesz), type, flags)
for (type, offset, vaddr, filesz,flags) in prog_segments if vaddr != 0]
def add_program_segment(self, addr, data, type, flags):
"""Adds new program segment
@ -492,21 +492,21 @@ class ESPCoreDumpLoader(object):
REG_LE_IDX = 3
REG_LC_IDX = 4
REG_SAR_IDX = 5
REG_WS_IDX=6
REG_WB_IDX=7
# REG_WS_IDX = 6
# REG_WB_IDX = 7
REG_AR_START_IDX = 64
REG_AR_NUM=64
# REG_AR_NUM = 64
# FIXME: acc to xtensa_elf_gregset_t number of regs must be 128,
# but gdb complanis when it less then 129
REG_NUM = 129
XT_SOL_EXIT=0
# XT_SOL_EXIT = 0
XT_SOL_PC = 1
XT_SOL_PS = 2
XT_SOL_NEXT=3
# XT_SOL_NEXT = 3
XT_SOL_AR_START = 4
XT_SOL_AR_NUM = 4
XT_SOL_FRMSZ=8
# XT_SOL_FRMSZ = 8
XT_STK_EXIT = 0
XT_STK_PC = 1
@ -514,8 +514,8 @@ class ESPCoreDumpLoader(object):
XT_STK_AR_START = 3
XT_STK_AR_NUM = 16
XT_STK_SAR = 19
XT_STK_EXCCAUSE=20
XT_STK_EXCVADDR=21
# XT_STK_EXCCAUSE = 20
# XT_STK_EXCVADDR = 21
XT_STK_LBEG = 22
XT_STK_LEND = 23
XT_STK_LCOUNT = 24
@ -550,14 +550,14 @@ class ESPCoreDumpLoader(object):
regs[REG_PS_IDX] = stack[XT_SOL_PS]
for i in range(XT_SOL_AR_NUM):
regs[REG_AR_START_IDX + i] = stack[XT_SOL_AR_START + i]
nxt = stack[XT_SOL_NEXT]
# nxt = stack[XT_SOL_NEXT]
# TODO: remove magic hack with saved PC to get proper value
regs[REG_PC_IDX] = ((regs[REG_PC_IDX] & 0x3FFFFFFF) | 0x40000000)
if regs[REG_PC_IDX] & 0x80000000:
regs[REG_PC_IDX] = (regs[REG_PC_IDX] & 0x3fffffff) | 0x40000000;
regs[REG_PC_IDX] = (regs[REG_PC_IDX] & 0x3fffffff) | 0x40000000
if regs[REG_AR_START_IDX + 0] & 0x80000000:
regs[REG_AR_START_IDX + 0] = (regs[REG_AR_START_IDX + 0] & 0x3fffffff) | 0x40000000;
regs[REG_AR_START_IDX + 0] = (regs[REG_AR_START_IDX + 0] & 0x3fffffff) | 0x40000000
return regs
def remove_tmp_file(self, fname):
@ -610,7 +610,8 @@ class ESPCoreDumpLoader(object):
data = self.read_data(core_off, tcbsz_aligned)
try:
if tcbsz != tcbsz_aligned:
core_elf.add_program_segment(tcb_addr, data[:tcbsz - tcbsz_aligned], ESPCoreDumpElfFile.PT_LOAD, ESPCoreDumpSegment.PF_R | ESPCoreDumpSegment.PF_W)
core_elf.add_program_segment(tcb_addr, data[:tcbsz - tcbsz_aligned],
ESPCoreDumpElfFile.PT_LOAD, ESPCoreDumpSegment.PF_R | ESPCoreDumpSegment.PF_W)
else:
core_elf.add_program_segment(tcb_addr, data, ESPCoreDumpElfFile.PT_LOAD, ESPCoreDumpSegment.PF_R | ESPCoreDumpSegment.PF_W)
except ESPCoreDumpError as e:
@ -876,6 +877,7 @@ class GDBMIStreamConsoleHandler(GDBMIOutStreamHandler):
"""
TAG = '~'
def load_aux_elf(elf_path):
""" Loads auxilary ELF file and composes GDB command to read its symbols
"""
@ -888,6 +890,7 @@ def load_aux_elf(elf_path):
sym_cmd = 'add-symbol-file %s 0x%x' % (elf_path, s.addr)
return (elf, sym_cmd)
def dbg_corefile(args):
""" Command to load core dump from file or flash and run GDB debug session with it
"""
@ -911,13 +914,13 @@ def dbg_corefile(args):
loader.cleanup()
return
p = subprocess.Popen(
bufsize = 0,
p = subprocess.Popen(bufsize=0,
args=[args.gdb,
'--nw', # ignore .gdbinit
'--core=%s' % core_fname, # core file,
'-ex', rom_sym_cmd,
args.prog],
args.prog
],
stdin=None, stdout=None, stderr=None,
close_fds=CLOSE_FDS
)
@ -934,6 +937,7 @@ def info_corefile(args):
""" Command to load core dump from file or flash and print it's data in user friendly form
"""
global CLOSE_FDS
def gdbmi_console_stream_handler(ln):
sys.stdout.write(ln)
sys.stdout.flush()
@ -961,12 +965,10 @@ def info_corefile(args):
for c in gdb_cmds:
gdb_args += ['-ex', c]
gdb_args.append(args.prog)
p = subprocess.Popen(
bufsize = 0,
p = subprocess.Popen(bufsize=0,
args=gdb_args,
stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
close_fds = CLOSE_FDS
)
close_fds=CLOSE_FDS)
gdbmi_read2prompt(p.stdout, handlers)
return p
@ -1130,9 +1132,12 @@ def main():
parser_debug_coredump.add_argument('--debug', '-d', help='Log level (0..3)', type=int, default=2)
parser_debug_coredump.add_argument('--gdb', '-g', help='Path to gdb', default='xtensa-esp32-elf-gdb')
parser_debug_coredump.add_argument('--core', '-c', help='Path to core dump file (if skipped core dump will be read from flash)', type=str)
parser_debug_coredump.add_argument('--core-format', '-t', help='(elf, raw or b64). File specified with "-c" is an ELF ("elf"), raw (raw) or base64-encoded (b64) binary', type=str, default='elf')
parser_debug_coredump.add_argument('--off', '-o', help='Ofsset of coredump partition in flash (type "make partition_table" to see).', type=int, default=0x110000)
parser_debug_coredump.add_argument('--save-core', '-s', help='Save core to file. Othwerwise temporary core file will be deleted. Ignored with "-c"', type=str)
parser_debug_coredump.add_argument('--core-format', '-t', help='(elf, raw or b64). File specified with "-c" is an ELF ("elf"), '
'raw (raw) or base64-encoded (b64) binary', type=str, default='elf')
parser_debug_coredump.add_argument('--off', '-o', help='Ofsset of coredump partition in flash '
'(type "make partition_table" to see).', type=int, default=0x110000)
parser_debug_coredump.add_argument('--save-core', '-s', help='Save core to file. Othwerwise temporary core file will be deleted. '
'Ignored with "-c"', type=str)
parser_debug_coredump.add_argument('--rom-elf', '-r', help='Path to ROM ELF file.', type=str, default='esp32_rom.elf')
parser_debug_coredump.add_argument('prog', help='Path to program\'s ELF binary', type=str)
@ -1142,9 +1147,12 @@ def main():
parser_info_coredump.add_argument('--debug', '-d', help='Log level (0..3)', type=int, default=0)
parser_info_coredump.add_argument('--gdb', '-g', help='Path to gdb', default='xtensa-esp32-elf-gdb')
parser_info_coredump.add_argument('--core', '-c', help='Path to core dump file (if skipped core dump will be read from flash)', type=str)
parser_info_coredump.add_argument('--core-format', '-t', help='(elf, raw or b64). File specified with "-c" is an ELF ("elf"), raw (raw) or base64-encoded (b64) binary', type=str, default='elf')
parser_info_coredump.add_argument('--off', '-o', help='Ofsset of coredump partition in flash (type "make partition_table" to see).', type=int, default=0x110000)
parser_info_coredump.add_argument('--save-core', '-s', help='Save core to file. Othwerwise temporary core file will be deleted. Does not work with "-c"', type=str)
parser_info_coredump.add_argument('--core-format', '-t', help='(elf, raw or b64). File specified with "-c" is an ELF ("elf"), '
'raw (raw) or base64-encoded (b64) binary', type=str, default='elf')
parser_info_coredump.add_argument('--off', '-o', help='Offset of coredump partition in flash (type '
'"make partition_table" to see).', type=int, default=0x110000)
parser_info_coredump.add_argument('--save-core', '-s', help='Save core to file. Othwerwise temporary core file will be deleted. '
'Does not work with "-c"', type=str)
parser_info_coredump.add_argument('--rom-elf', '-r', help='Path to ROM ELF file.', type=str, default='esp32_rom.elf')
parser_info_coredump.add_argument('--print-mem', '-m', help='Print memory dump', action='store_true')
parser_info_coredump.add_argument('prog', help='Path to program\'s ELF binary', type=str)

View file

@ -18,11 +18,15 @@ import sys
import os
import unittest
try:
import espcoredump
except ImportError:
idf_path = os.getenv('IDF_PATH')
if idf_path:
sys.path.insert(0, os.path.join(idf_path, 'components', 'espcoredump'))
import espcoredump
class TestESPCoreDumpFileLoader(unittest.TestCase):
def setUp(self):
self.tmp_file = 'tmp'
@ -43,6 +47,7 @@ class TestESPCoreDumpFileLoader(unittest.TestCase):
def test_create_corefile(self):
self.assertEqual(self.dloader.create_corefile(core_fname=self.tmp_file, off=0, rom_elf=None), self.tmp_file)
if __name__ == '__main__':
# The purpose of these tests is to increase the code coverage at places which are sensitive to issues related to
# Python 2&3 compatibility.

View file

@ -71,16 +71,19 @@ md5sum = True
secure = False
offset_part_table = 0
def status(msg):
""" Print status message to stderr """
if not quiet:
critical(msg)
def critical(msg):
""" Print critical message to stderr """
sys.stderr.write(msg)
sys.stderr.write('\n')
class PartitionTable(list):
def __init__(self):
super(PartitionTable, self).__init__(self)
@ -149,14 +152,14 @@ class PartitionTable(list):
ptype = TYPES[ptype]
except KeyError:
try:
ptypes = int(ptype, 0)
ptype = int(ptype, 0)
except TypeError:
pass
try:
subtype = SUBTYPES[int(ptype)][subtype]
except KeyError:
try:
ptypes = int(ptype, 0)
ptype = int(ptype, 0)
except TypeError:
pass
@ -209,7 +212,7 @@ class PartitionTable(list):
@classmethod
def from_binary(cls, b):
md5 = hashlib.md5();
md5 = hashlib.md5()
result = cls()
for o in range(0,len(b),32):
data = b[o:o + 32]
@ -242,6 +245,7 @@ class PartitionTable(list):
rows += [x.to_csv(simple_formatting) for x in self]
return "\n".join(rows) + "\n"
class PartitionDefinition(object):
MAGIC_BYTES = b"\xAA\x50"
@ -353,12 +357,14 @@ class PartitionDefinition(object):
raise ValidationError(self, "Size field is not set")
if self.name in TYPES and TYPES.get(self.name, "") != self.type:
critical("WARNING: Partition has name '%s' which is a partition type, but does not match this partition's type (0x%x). Mistake in partition table?" % (self.name, self.type))
critical("WARNING: Partition has name '%s' which is a partition type, but does not match this partition's "
"type (0x%x). Mistake in partition table?" % (self.name, self.type))
all_subtype_names = []
for names in (t.keys() for t in SUBTYPES.values()):
all_subtype_names += names
if self.name in all_subtype_names and SUBTYPES.get(self.type, {}).get(self.name, "") != self.subtype:
critical("WARNING: Partition has name '%s' which is a partition subtype, but this partition has non-matching type 0x%x and subtype 0x%x. Mistake in partition table?" % (self.name, self.type, self.subtype))
critical("WARNING: Partition has name '%s' which is a partition subtype, but this partition has "
"non-matching type 0x%x and subtype 0x%x. Mistake in partition table?" % (self.name, self.type, self.subtype))
STRUCT_FORMAT = b"<2sBBLL16sL"
@ -404,7 +410,7 @@ class PartitionDefinition(object):
def lookup_keyword(t, keywords):
for k,v in keywords.items():
if simple_formatting == False and t == v:
if simple_formatting is False and t == v:
return k
return "%d" % t
@ -437,6 +443,7 @@ def parse_int(v, keywords={}):
except KeyError:
raise InputError("Value '%s' is not valid. Known keywords: %s" % (v, ", ".join(keywords)))
def main():
global quiet
global md5sum
@ -448,7 +455,8 @@ def main():
nargs='?', choices=['1MB', '2MB', '4MB', '8MB', '16MB'])
parser.add_argument('--disable-md5sum', help='Disable md5 checksum for the partition table', default=False, action='store_true')
parser.add_argument('--no-verify', help="Don't verify partition table fields", action='store_true')
parser.add_argument('--verify', '-v', help="Verify partition table fields (deprecated, this behaviour is enabled by default and this flag does nothing.", action='store_true')
parser.add_argument('--verify', '-v', help="Verify partition table fields (deprecated, this behaviour is "
"enabled by default and this flag does nothing.", action='store_true')
parser.add_argument('--quiet', '-q', help="Don't print non-critical status messages to stderr", action='store_true')
parser.add_argument('--offset', '-o', help='Set offset partition table', default='0x8000')
parser.add_argument('--secure', help="Require app partitions to be suitable for secure boot", action='store_true')
@ -481,7 +489,8 @@ def main():
size = size_mb * 1024 * 1024 # flash memory uses honest megabytes!
table_size = table.flash_size()
if size < table_size:
raise InputError("Partitions defined in '%s' occupy %.1fMB of flash (%d bytes) which does not fit in configured flash size %dMB. Change the flash size in menuconfig under the 'Serial Flasher Config' menu." %
raise InputError("Partitions defined in '%s' occupy %.1fMB of flash (%d bytes) which does not fit in configured "
"flash size %dMB. Change the flash size in menuconfig under the 'Serial Flasher Config' menu." %
(args.input.name, table_size / 1024.0 / 1024.0, table_size, size_mb))
# Make sure that the output directory is created

View file

@ -8,8 +8,13 @@ import subprocess
import tempfile
import os
import io
import re
try:
import gen_esp32part
except ImportError:
sys.path.append("..")
from gen_esp32part import *
import gen_esp32part
SIMPLE_CSV = """
# Name,Type,SubType,Offset,Size,Flags
@ -53,6 +58,7 @@ def _strip_trailing_ffs(binary_table):
binary_table = binary_table[0:len(binary_table) - 32]
return binary_table
class Py23TestCase(unittest.TestCase):
def __init__(self, *args, **kwargs):
@ -64,10 +70,11 @@ class Py23TestCase(unittest.TestCase):
# This fix is used in order to avoid using the alias from the six library
self.assertRaisesRegex = self.assertRaisesRegexp
class CSVParserTests(Py23TestCase):
def test_simple_partition(self):
table = PartitionTable.from_csv(SIMPLE_CSV)
table = gen_esp32part.PartitionTable.from_csv(SIMPLE_CSV)
self.assertEqual(len(table), 1)
self.assertEqual(table[0].name, "factory")
self.assertEqual(table[0].type, 0)
@ -75,15 +82,13 @@ class CSVParserTests(Py23TestCase):
self.assertEqual(table[0].offset, 65536)
self.assertEqual(table[0].size, 1048576)
def test_require_type(self):
csv = """
# Name,Type, SubType,Offset,Size
ihavenotype,
"""
with self.assertRaisesRegex(InputError, "type"):
PartitionTable.from_csv(csv)
with self.assertRaisesRegex(gen_esp32part.InputError, "type"):
gen_esp32part.PartitionTable.from_csv(csv)
def test_type_subtype_names(self):
csv_magicnumbers = """
@ -106,9 +111,9 @@ myota_status, data, ota,, 0x100000
"""
# make two equivalent partition tables, one using
# magic numbers and one using shortcuts. Ensure they match
magic = PartitionTable.from_csv(csv_magicnumbers)
magic = gen_esp32part.PartitionTable.from_csv(csv_magicnumbers)
magic.verify()
nomagic = PartitionTable.from_csv(csv_nomagicnumbers)
nomagic = gen_esp32part.PartitionTable.from_csv(csv_nomagicnumbers)
nomagic.verify()
self.assertEqual(nomagic["myapp"].type, 0)
@ -128,7 +133,7 @@ myota_status, data, ota,, 0x100000
# Name, Type, Subtype, Offset, Size
one_megabyte, app, factory, 64k, 1M
"""
t = PartitionTable.from_csv(csv)
t = gen_esp32part.PartitionTable.from_csv(csv)
t.verify()
self.assertEqual(t[0].offset, 64 * 1024)
self.assertEqual(t[0].size, 1 * 1024 * 1024)
@ -141,7 +146,7 @@ second, data, 0x15,, 1M
minidata, data, 0x40,, 32K
otherapp, app, factory,, 1M
"""
t = PartitionTable.from_csv(csv)
t = gen_esp32part.PartitionTable.from_csv(csv)
# 'first'
self.assertEqual(t[0].offset, 0x010000) # 64KB boundary as it's an app image
self.assertEqual(t[0].size, 0x100000) # Size specified in CSV
@ -159,7 +164,7 @@ otherapp, app, factory,, 1M
first, app, factory, 0x10000, -2M
second, data, 0x15, , 1M
"""
t = PartitionTable.from_csv(csv)
t = gen_esp32part.PartitionTable.from_csv(csv)
t.verify()
# 'first'
self.assertEqual(t[0].offset, 0x10000) # in CSV
@ -172,8 +177,8 @@ second, data, 0x15, , 1M
first, app, factory, 0x100000, 2M
second, app, ota_0, 0x200000, 1M
"""
with self.assertRaisesRegex(InputError, "overlap"):
t = PartitionTable.from_csv(csv)
with self.assertRaisesRegex(gen_esp32part.InputError, "overlap"):
t = gen_esp32part.PartitionTable.from_csv(csv)
t.verify()
def test_unique_name_fail(self):
@ -181,16 +186,17 @@ second, app, ota_0, 0x200000, 1M
first, app, factory, 0x100000, 1M
first, app, ota_0, 0x200000, 1M
"""
with self.assertRaisesRegex(InputError, "Partition names must be unique"):
t = PartitionTable.from_csv(csv)
with self.assertRaisesRegex(gen_esp32part.InputError, "Partition names must be unique"):
t = gen_esp32part.PartitionTable.from_csv(csv)
t.verify()
class BinaryOutputTests(Py23TestCase):
def test_binary_entry(self):
csv = """
first, 0x30, 0xEE, 0x100400, 0x300000
"""
t = PartitionTable.from_csv(csv)
t = gen_esp32part.PartitionTable.from_csv(csv)
tb = _strip_trailing_ffs(t.to_binary())
self.assertEqual(len(tb), 64 + 32)
self.assertEqual(b'\xAA\x50', tb[0:2]) # magic
@ -206,22 +212,21 @@ first, 0x30, 0xEE, 0x100400, 0x300000
first, 0x30, 0xEE, 0x100400, 0x300000
second,0x31, 0xEF, , 0x100000
"""
t = PartitionTable.from_csv(csv)
t = gen_esp32part.PartitionTable.from_csv(csv)
tb = _strip_trailing_ffs(t.to_binary())
self.assertEqual(len(tb), 96 + 32)
self.assertEqual(b'\xAA\x50', tb[0:2])
self.assertEqual(b'\xAA\x50', tb[32:34])
def test_encrypted_flag(self):
csv = """
# Name, Type, Subtype, Offset, Size, Flags
first, app, factory,, 1M, encrypted
"""
t = PartitionTable.from_csv(csv)
t = gen_esp32part.PartitionTable.from_csv(csv)
self.assertTrue(t[0].encrypted)
tb = _strip_trailing_ffs(t.to_binary())
tr = PartitionTable.from_binary(tb)
tr = gen_esp32part.PartitionTable.from_binary(tb)
self.assertTrue(tr[0].encrypted)
@ -237,11 +242,11 @@ class BinaryParserTests(Py23TestCase):
b"\xFF" * 32
# verify that parsing 32 bytes as a table
# or as a single Definition are the same thing
t = PartitionTable.from_binary(entry)
t = gen_esp32part.PartitionTable.from_binary(entry)
self.assertEqual(len(t), 1)
t[0].verify()
e = PartitionDefinition.from_binary(entry[:32])
e = gen_esp32part.PartitionDefinition.from_binary(entry[:32])
self.assertEqual(t[0], e)
e.verify()
@ -252,14 +257,14 @@ class BinaryParserTests(Py23TestCase):
self.assertEqual(e.name, "0123456789abc")
def test_multiple_entries(self):
t = PartitionTable.from_binary(LONGER_BINARY_TABLE)
t = gen_esp32part.PartitionTable.from_binary(LONGER_BINARY_TABLE)
t.verify()
self.assertEqual(3, len(t))
self.assertEqual(t[0].type, APP_TYPE)
self.assertEqual(t[0].type, gen_esp32part.APP_TYPE)
self.assertEqual(t[0].name, "factory")
self.assertEqual(t[1].type, DATA_TYPE)
self.assertEqual(t[1].type, gen_esp32part.DATA_TYPE)
self.assertEqual(t[1].name, "data")
self.assertEqual(t[2].type, 0x10)
@ -274,16 +279,16 @@ class BinaryParserTests(Py23TestCase):
b"\x00\x00\x20\x00" + \
b"0123456789abc\0\0\0" + \
b"\x00\x00\x00\x00"
with self.assertRaisesRegex(InputError, "Invalid magic bytes"):
PartitionTable.from_binary(bad_magic)
with self.assertRaisesRegex(gen_esp32part.InputError, "Invalid magic bytes"):
gen_esp32part.PartitionTable.from_binary(bad_magic)
def test_bad_length(self):
bad_length = b"OHAI" + \
b"\x00\x00\x10\x00" + \
b"\x00\x00\x20\x00" + \
b"0123456789"
with self.assertRaisesRegex(InputError, "32 bytes"):
PartitionTable.from_binary(bad_length)
with self.assertRaisesRegex(gen_esp32part.InputError, "32 bytes"):
gen_esp32part.PartitionTable.from_binary(bad_length)
class CSVOutputTests(Py23TestCase):
@ -292,7 +297,7 @@ class CSVOutputTests(Py23TestCase):
return list(csv.reader(source_str.split("\n")))
def test_output_simple_formatting(self):
table = PartitionTable.from_csv(SIMPLE_CSV)
table = gen_esp32part.PartitionTable.from_csv(SIMPLE_CSV)
as_csv = table.to_csv(True)
c = self._readcsv(as_csv)
# first two lines should start with comments
@ -306,11 +311,11 @@ class CSVOutputTests(Py23TestCase):
self.assertEqual(row[4], "0x100000") # also hex
# round trip back to a PartitionTable and check is identical
roundtrip = PartitionTable.from_csv(as_csv)
roundtrip = gen_esp32part.PartitionTable.from_csv(as_csv)
self.assertEqual(roundtrip, table)
def test_output_smart_formatting(self):
table = PartitionTable.from_csv(SIMPLE_CSV)
table = gen_esp32part.PartitionTable.from_csv(SIMPLE_CSV)
as_csv = table.to_csv(False)
c = self._readcsv(as_csv)
# first two lines should start with comments
@ -324,9 +329,10 @@ class CSVOutputTests(Py23TestCase):
self.assertEqual(row[4], "1M")
# round trip back to a PartitionTable and check is identical
roundtrip = PartitionTable.from_csv(as_csv)
roundtrip = gen_esp32part.PartitionTable.from_csv(as_csv)
self.assertEqual(roundtrip, table)
class CommandLineTests(Py23TestCase):
def test_basic_cmdline(self):
@ -344,7 +350,7 @@ class CommandLineTests(Py23TestCase):
# reopen the CSV and check the generated binary is identical
self.assertNotIn(b"WARNING", output)
with open(csvpath, 'r') as f:
from_csv = PartitionTable.from_csv(f.read())
from_csv = gen_esp32part.PartitionTable.from_csv(f.read())
self.assertEqual(_strip_trailing_ffs(from_csv.to_binary()), LONGER_BINARY_TABLE)
# run gen_esp32part.py to conver the CSV to binary again
@ -372,30 +378,29 @@ class VerificationTests(Py23TestCase):
# Name,Type, SubType,Offset,Size
app,app, factory, 32K, 1M
"""
with self.assertRaisesRegex(ValidationError,
r"Offset.+not aligned"):
t = PartitionTable.from_csv(csv)
with self.assertRaisesRegex(gen_esp32part.ValidationError, r"Offset.+not aligned"):
t = gen_esp32part.PartitionTable.from_csv(csv)
t.verify()
def test_warnings(self):
try:
sys.stderr = io.StringIO() # capture stderr
csv_1 = "app, 1, 2, 32K, 1M\n"
PartitionTable.from_csv(csv_1).verify()
gen_esp32part.PartitionTable.from_csv(csv_1).verify()
self.assertIn("WARNING", sys.stderr.getvalue())
self.assertIn("partition type", sys.stderr.getvalue())
sys.stderr = io.StringIO()
csv_2 = "ota_0, app, ota_1, , 1M\n"
PartitionTable.from_csv(csv_2).verify()
gen_esp32part.PartitionTable.from_csv(csv_2).verify()
self.assertIn("WARNING", sys.stderr.getvalue())
self.assertIn("partition subtype", sys.stderr.getvalue())
finally:
sys.stderr = sys.__stderr__
class PartToolTests(Py23TestCase):
def _run_parttool(self, csvcontents, args, info):
@ -404,7 +409,8 @@ class PartToolTests(Py23TestCase):
f.write(csvcontents)
try:
output = subprocess.check_output([sys.executable, "../parttool.py"] + args.split(" ")
+ ["--partition-table-file", csvpath , "get_partition_info", "--info", info], stderr=subprocess.STDOUT)
+ ["--partition-table-file", csvpath, "get_partition_info", "--info", info],
stderr=subprocess.STDOUT)
self.assertNotIn(b"WARNING", output)
m = re.search(b"0x[0-9a-fA-F]+", output)
return m.group(0) if m else ""
@ -418,7 +424,9 @@ otadata, data, ota, 0xd000, 0x2000
phy_init, data, phy, 0xf000, 0x1000
factory, app, factory, 0x10000, 1M
"""
rpt = lambda args, info: self._run_parttool(csv, args, info)
def rpt(args, info):
return self._run_parttool(csv, args, info)
self.assertEqual(
rpt("--partition-type=data --partition-subtype=nvs -q", "offset"), b"0x9000")
@ -437,7 +445,9 @@ phy_init, data, phy, 0xf000, 0x1000
ota_0, app, ota_0, 0x30000, 1M
ota_1, app, ota_1, , 1M
"""
rpt = lambda args, info: self._run_parttool(csv, args, info)
def rpt(args, info):
return self._run_parttool(csv, args, info)
self.assertEqual(
rpt("--partition-type=app --partition-subtype=ota_1 -q", "offset"), b"0x130000")
@ -448,5 +458,6 @@ ota_1, app, ota_1, , 1M
self._run_parttool(csv_mod, "--partition-boot-default -q", "offset"),
b"0x130000") # now default is ota_1
if __name__ == "__main__":
unittest.main()

View file

@ -7,27 +7,28 @@
from optparse import OptionParser
BASE_ADDR = 0x50000000;
BASE_ADDR = 0x50000000
def gen_ld_h_from_sym(f_sym, f_ld, f_h):
f_ld.write("/* Variable definitions for ESP32ULP linker\n");
f_ld.write(" * This file is generated automatically by esp32ulp_mapgen.py utility.\n");
f_ld.write(" */\n\n");
f_h.write("// Variable definitions for ESP32ULP\n");
f_h.write("// This file is generated automatically by esp32ulp_mapgen.py utility\n\n");
f_h.write("#pragma once\n\n");
f_ld.write("/* Variable definitions for ESP32ULP linker\n")
f_ld.write(" * This file is generated automatically by esp32ulp_mapgen.py utility.\n")
f_ld.write(" */\n\n")
f_h.write("// Variable definitions for ESP32ULP\n")
f_h.write("// This file is generated automatically by esp32ulp_mapgen.py utility\n\n")
f_h.write("#pragma once\n\n")
for line in f_sym:
name, _, addr_str = line.split()
addr = int(addr_str, 16) + BASE_ADDR;
f_h.write("extern uint32_t ulp_{0};\n".format(name));
addr = int(addr_str, 16) + BASE_ADDR
f_h.write("extern uint32_t ulp_{0};\n".format(name))
f_ld.write("PROVIDE ( ulp_{0} = 0x{1:08x} );\n".format(name, addr))
def main():
description = ("This application generates .h and .ld files for symbols defined in input file. "
"The input symbols file can be generated using nm utility like this: "
"esp32-ulp-nm -g -f posix <elf_file> > <symbols_file>" );
"esp32-ulp-nm -g -f posix <elf_file> > <symbols_file>")
parser = OptionParser(description=description)
parser.add_option("-s", "--symfile", dest="symfile",
@ -44,11 +45,10 @@ def main():
parser.print_help()
return 1
with open(options.outputfile + ".h", 'w') as f_h, \
open(options.outputfile + ".ld", 'w') as f_ld, \
open(options.symfile) as f_sym: \
with open(options.outputfile + ".h", 'w') as f_h, open(options.outputfile + ".ld", 'w') as f_ld, open(options.symfile) as f_sym:
gen_ld_h_from_sym(f_sym, f_ld, f_h)
return 0
if __name__ == "__main__":
exit(main());
exit(main())