mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-11 00:24:34 +02:00
ldgen: additional tests for generation support classes
This commit is contained in:
@@ -72,8 +72,10 @@ test_ldgen_on_host:
|
|||||||
extends: .host_test_template
|
extends: .host_test_template
|
||||||
script:
|
script:
|
||||||
- cd tools/ldgen/test
|
- cd tools/ldgen/test
|
||||||
- ./test_fragments.py
|
- ${IDF_PATH}/tools/ci/multirun_with_pyenv.sh ./test_fragments.py
|
||||||
- ./test_generation.py
|
- ${IDF_PATH}/tools/ci/multirun_with_pyenv.sh ./test_generation.py
|
||||||
|
- ${IDF_PATH}/tools/ci/multirun_with_pyenv.sh ./test_entity.py
|
||||||
|
- ${IDF_PATH}/tools/ci/multirun_with_pyenv.sh ./test_output_commands.py
|
||||||
variables:
|
variables:
|
||||||
LC_ALL: C.UTF-8
|
LC_ALL: C.UTF-8
|
||||||
|
|
||||||
|
@@ -88,8 +88,10 @@ tools/kconfig_new/test/confserver/test_confserver.py
|
|||||||
tools/kconfig_new/test/gen_kconfig_doc/test_kconfig_out.py
|
tools/kconfig_new/test/gen_kconfig_doc/test_kconfig_out.py
|
||||||
tools/kconfig_new/test/gen_kconfig_doc/test_target_visibility.py
|
tools/kconfig_new/test/gen_kconfig_doc/test_target_visibility.py
|
||||||
tools/ldgen/ldgen.py
|
tools/ldgen/ldgen.py
|
||||||
|
tools/ldgen/test/test_entity.py
|
||||||
tools/ldgen/test/test_fragments.py
|
tools/ldgen/test/test_fragments.py
|
||||||
tools/ldgen/test/test_generation.py
|
tools/ldgen/test/test_generation.py
|
||||||
|
tools/ldgen/test/test_output_commands.py
|
||||||
tools/mass_mfg/mfg_gen.py
|
tools/mass_mfg/mfg_gen.py
|
||||||
tools/mkdfu.py
|
tools/mkdfu.py
|
||||||
tools/mkuf2.py
|
tools/mkuf2.py
|
||||||
|
78
tools/ldgen/output_commands.py
Normal file
78
tools/ldgen/output_commands.py
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
#
|
||||||
|
# Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
|
||||||
|
from entity import Entity
|
||||||
|
|
||||||
|
|
||||||
|
class InputSectionDesc():
|
||||||
|
|
||||||
|
def __init__(self, entity, sections, exclusions=None):
|
||||||
|
assert(entity.specificity != Entity.Specificity.SYMBOL)
|
||||||
|
|
||||||
|
self.entity = entity
|
||||||
|
self.sections = set(sections)
|
||||||
|
|
||||||
|
self.exclusions = set()
|
||||||
|
|
||||||
|
if exclusions:
|
||||||
|
assert(not [e for e in exclusions if e.specificity == Entity.Specificity.SYMBOL or
|
||||||
|
e.specificity == Entity.Specificity.NONE])
|
||||||
|
self.exclusions = set(exclusions)
|
||||||
|
else:
|
||||||
|
self.exclusions = set()
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
if self.sections:
|
||||||
|
exclusion_strings = []
|
||||||
|
|
||||||
|
for exc in sorted(self.exclusions):
|
||||||
|
if exc.specificity == Entity.Specificity.ARCHIVE:
|
||||||
|
exc_string = '*%s' % (exc.archive)
|
||||||
|
else:
|
||||||
|
exc_string = '*%s:%s.*' % (exc.archive, exc.obj)
|
||||||
|
|
||||||
|
exclusion_strings.append(exc_string)
|
||||||
|
|
||||||
|
section_strings = []
|
||||||
|
|
||||||
|
if exclusion_strings:
|
||||||
|
exclusion_string = 'EXCLUDE_FILE(%s)' % ' '.join(exclusion_strings)
|
||||||
|
|
||||||
|
for section in sorted(self.sections):
|
||||||
|
section_strings.append('%s %s' % (exclusion_string, section))
|
||||||
|
else:
|
||||||
|
for section in sorted(self.sections):
|
||||||
|
section_strings.append(section)
|
||||||
|
|
||||||
|
sections_string = '(%s)' % ' '.join(section_strings)
|
||||||
|
else:
|
||||||
|
sections_string = '( )'
|
||||||
|
|
||||||
|
command = None
|
||||||
|
|
||||||
|
if self.entity.specificity == Entity.Specificity.NONE:
|
||||||
|
command = '*%s' % (sections_string)
|
||||||
|
elif self.entity.specificity == Entity.Specificity.ARCHIVE:
|
||||||
|
command = '*%s:%s' % (self.entity.archive, sections_string)
|
||||||
|
else:
|
||||||
|
command = '*%s:%s.*%s' % (self.entity.archive, self.entity.obj, sections_string)
|
||||||
|
|
||||||
|
return command
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
return (self.entity == other.entity and
|
||||||
|
self.sections == other.sections and
|
||||||
|
self.exclusions == other.exclusions)
|
@@ -343,6 +343,111 @@ Idx Name Size VMA LMA File off Algn
|
|||||||
49 .xt.prop 00000408 00000000 00000000 00002f3e 2**0
|
49 .xt.prop 00000408 00000000 00000000 00002f3e 2**0
|
||||||
CONTENTS, RELOC, READONLY
|
CONTENTS, RELOC, READONLY
|
||||||
|
|
||||||
|
port.cpp.obj: file format elf32-xtensa-le
|
||||||
|
|
||||||
|
Sections:
|
||||||
|
Idx Name Size VMA LMA File off Algn
|
||||||
|
0 .literal.pxPortInitialiseStack 00000018 00000000 00000000 00000034 2**2
|
||||||
|
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
|
||||||
|
1 .literal.xPortStartScheduler 00000014 00000000 00000000 0000004c 2**2
|
||||||
|
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
|
||||||
|
2 .literal.xPortSysTickHandler 00000008 00000000 00000000 00000060 2**2
|
||||||
|
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
|
||||||
|
3 .literal.vPortYieldOtherCore 00000004 00000000 00000000 00000068 2**2
|
||||||
|
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
|
||||||
|
4 .literal.vPortReleaseTaskMPUSettings 00000004 00000000 00000000 0000006c 2**2
|
||||||
|
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
|
||||||
|
5 .literal.xPortInIsrContext 00000008 00000000 00000000 00000070 2**2
|
||||||
|
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
|
||||||
|
6 .iram1.literal 00000004 00000000 00000000 00000078 2**2
|
||||||
|
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
|
||||||
|
7 .literal.vPortAssertIfInISR 00000018 00000000 00000000 0000007c 2**2
|
||||||
|
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
|
||||||
|
8 .literal.vPortCPUInitializeMutex 00000004 00000000 00000000 00000094 2**2
|
||||||
|
CONTENTS, ALLOC, LOAD, READONLY, CODE
|
||||||
|
9 .literal.vPortCPUAcquireMutex 00000030 00000000 00000000 00000098 2**2
|
||||||
|
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
|
||||||
|
10 .literal.vPortCPUAcquireMutexTimeout 00000030 00000000 00000000 000000c8 2**2
|
||||||
|
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
|
||||||
|
11 .literal.vPortCPUReleaseMutex 00000028 00000000 00000000 000000f8 2**2
|
||||||
|
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
|
||||||
|
12 .literal.vPortSetStackWatchpoint 00000008 00000000 00000000 00000120 2**2
|
||||||
|
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
|
||||||
|
13 .text 00000000 00000000 00000000 00000128 2**0
|
||||||
|
CONTENTS, ALLOC, LOAD, READONLY, CODE
|
||||||
|
14 .data 00000000 00000000 00000000 00000128 2**0
|
||||||
|
CONTENTS, ALLOC, LOAD, DATA
|
||||||
|
15 .bss 00000000 00000000 00000000 00000128 2**0
|
||||||
|
ALLOC
|
||||||
|
16 .text.pxPortInitialiseStack 00000086 00000000 00000000 00000128 2**2
|
||||||
|
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
|
||||||
|
17 .text.vPortEndScheduler 00000005 00000000 00000000 000001b0 2**2
|
||||||
|
CONTENTS, ALLOC, LOAD, READONLY, CODE
|
||||||
|
18 .text.xPortStartScheduler 0000002e 00000000 00000000 000001b8 2**2
|
||||||
|
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
|
||||||
|
19 .text.xPortSysTickHandler 00000016 00000000 00000000 000001e8 2**2
|
||||||
|
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
|
||||||
|
20 .text.vPortYieldOtherCore 0000000e 00000000 00000000 00000200 2**2
|
||||||
|
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
|
||||||
|
21 .text.vPortStoreTaskMPUSettings 00000013 00000000 00000000 00000210 2**2
|
||||||
|
CONTENTS, ALLOC, LOAD, READONLY, CODE
|
||||||
|
22 .text.vPortReleaseTaskMPUSettings 0000000e 00000000 00000000 00000224 2**2
|
||||||
|
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
|
||||||
|
23 .text.xPortInIsrContext 00000026 00000000 00000000 00000234 2**2
|
||||||
|
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
|
||||||
|
24 .iram1 0000001a 00000000 00000000 0000025c 2**2
|
||||||
|
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
|
||||||
|
25 .rodata.str1.4 0000013b 00000000 00000000 00000278 2**2
|
||||||
|
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
||||||
|
26 .text.vPortAssertIfInISR 00000025 00000000 00000000 000003b4 2**2
|
||||||
|
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
|
||||||
|
27 .text.vPortCPUInitializeMutex 0000000e 00000000 00000000 000003dc 2**2
|
||||||
|
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
|
||||||
|
28 .text.vPortCPUAcquireMutex 00000088 00000000 00000000 000003ec 2**2
|
||||||
|
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
|
||||||
|
29 .text.vPortCPUAcquireMutexTimeout 000000ab 00000000 00000000 00000474 2**2
|
||||||
|
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
|
||||||
|
30 .text.vPortCPUReleaseMutex 00000061 00000000 00000000 00000520 2**2
|
||||||
|
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
|
||||||
|
31 .text.vPortSetStackWatchpoint 0000001a 00000000 00000000 00000584 2**2
|
||||||
|
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
|
||||||
|
32 .text.xPortGetTickRateHz 00000008 00000000 00000000 000005a0 2**2
|
||||||
|
CONTENTS, ALLOC, LOAD, READONLY, CODE
|
||||||
|
33 .rodata.__func__$5264 00000029 00000000 00000000 000005a8 2**2
|
||||||
|
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
||||||
|
34 .rodata.__func__$5259 00000029 00000000 00000000 000005d4 2**2
|
||||||
|
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
||||||
|
35 .rodata.__FUNCTION__$5243 00000013 00000000 00000000 00000600 2**2
|
||||||
|
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
||||||
|
36 .bss.port_interruptNesting 00000008 00000000 00000000 00000614 2**2
|
||||||
|
ALLOC
|
||||||
|
37 .bss.port_xSchedulerRunning 00000008 00000000 00000000 00000614 2**2
|
||||||
|
ALLOC
|
||||||
|
38 .debug_frame 00000190 00000000 00000000 00000614 2**2
|
||||||
|
CONTENTS, RELOC, READONLY, DEBUGGING
|
||||||
|
39 .debug_info 00000e78 00000000 00000000 000007a4 2**0
|
||||||
|
CONTENTS, RELOC, READONLY, DEBUGGING
|
||||||
|
40 .debug_abbrev 00000404 00000000 00000000 0000161c 2**0
|
||||||
|
CONTENTS, READONLY, DEBUGGING
|
||||||
|
41 .debug_loc 000005f1 00000000 00000000 00001a20 2**0
|
||||||
|
CONTENTS, RELOC, READONLY, DEBUGGING
|
||||||
|
42 .debug_aranges 00000098 00000000 00000000 00002011 2**0
|
||||||
|
CONTENTS, RELOC, READONLY, DEBUGGING
|
||||||
|
43 .debug_ranges 000000a0 00000000 00000000 000020a9 2**0
|
||||||
|
CONTENTS, RELOC, READONLY, DEBUGGING
|
||||||
|
44 .debug_line 000005fb 00000000 00000000 00002149 2**0
|
||||||
|
CONTENTS, RELOC, READONLY, DEBUGGING
|
||||||
|
45 .debug_str 0000071f 00000000 00000000 00002744 2**0
|
||||||
|
CONTENTS, READONLY, DEBUGGING
|
||||||
|
46 .comment 0000003b 00000000 00000000 00002e63 2**0
|
||||||
|
CONTENTS, READONLY
|
||||||
|
47 .xtensa.info 00000038 00000000 00000000 00002e9e 2**0
|
||||||
|
CONTENTS, READONLY
|
||||||
|
48 .xt.lit 00000068 00000000 00000000 00002ed6 2**0
|
||||||
|
CONTENTS, RELOC, READONLY
|
||||||
|
49 .xt.prop 00000408 00000000 00000000 00002f3e 2**0
|
||||||
|
CONTENTS, RELOC, READONLY
|
||||||
|
|
||||||
portasm.S.obj: file format elf32-xtensa-le
|
portasm.S.obj: file format elf32-xtensa-le
|
||||||
|
|
||||||
Sections:
|
Sections:
|
39
tools/ldgen/test/data/test_entity/libfreertos.a.txt
Normal file
39
tools/ldgen/test/data/test_entity/libfreertos.a.txt
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
In archive /home/user/build/esp-idf/freertos/libfreertos.a:
|
||||||
|
|
||||||
|
croutine.c.obj: file format elf32-xtensa-le
|
||||||
|
|
||||||
|
Sections:
|
||||||
|
Idx Name Size VMA LMA File off Algn
|
||||||
|
0 .literal.prvCheckPendingReadyList 00000018 00000000 00000000 00000034 2**2
|
||||||
|
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
|
||||||
|
1 .literal.prvCheckDelayedList 0000002c 00000000 00000000 0000004c 2**2
|
||||||
|
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
|
||||||
|
|
||||||
|
croutine.cpp.obj: file format elf32-xtensa-le
|
||||||
|
|
||||||
|
Sections:
|
||||||
|
Idx Name Size VMA LMA File off Algn
|
||||||
|
9 .text.prvCheckPendingReadyList 00000056 00000000 00000000 000000d8 2**2
|
||||||
|
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
|
||||||
|
10 .text.prvCheckDelayedList 000000ac 00000000 00000000 00000130 2**2
|
||||||
|
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
|
||||||
|
|
||||||
|
croutine.S.obj: file format elf32-xtensa-le
|
||||||
|
|
||||||
|
Sections:
|
||||||
|
Idx Name Size VMA LMA File off Algn
|
||||||
|
26 .debug_frame 000000a0 00000000 00000000 00000394 2**2
|
||||||
|
CONTENTS, RELOC, READONLY, DEBUGGING
|
||||||
|
27 .debug_info 000006b8 00000000 00000000 00000434 2**0
|
||||||
|
CONTENTS, RELOC, READONLY, DEBUGGING
|
||||||
|
28 .debug_abbrev 00000233 00000000 00000000 00000aec 2**0
|
||||||
|
CONTENTS, READONLY, DEBUGGING
|
||||||
|
|
||||||
|
timers.o: file format elf32-xtensa-le
|
||||||
|
|
||||||
|
Sections:
|
||||||
|
Idx Name Size VMA LMA File off Algn
|
||||||
|
0 .literal.prvGetNextExpireTime 00000004 00000000 00000000 00000034 2**2
|
||||||
|
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
|
||||||
|
1 .literal.prvInsertTimerInActiveList 00000010 00000000 00000000 00000038 2**2
|
||||||
|
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
|
@@ -1,4 +1,4 @@
|
|||||||
In archive /home/user/ãóç+ěščřžýáíé/build/esp-idf/freertos/libsections_parse.a:
|
In archive /home/user/ãóç+ěščřžýáíé/build/esp-idf/freertos/ěščřžýáíé.a:
|
||||||
|
|
||||||
croutine.c.obj: file format elf32-littleriscv
|
croutine.c.obj: file format elf32-littleriscv
|
||||||
|
|
||||||
@@ -11,9 +11,9 @@ Idx Name Size VMA LMA File off Algn
|
|||||||
2 .bss 00000000 00000000 00000000 00000034 2**0
|
2 .bss 00000000 00000000 00000000 00000034 2**0
|
||||||
ALLOC
|
ALLOC
|
||||||
|
|
||||||
FreeRTOS-openocd.c.obj: file format elf32-xtensa-le // 'F' should not get included in match for 'CONTENTS, ALLOC, LOAD ...' prior
|
FreeRTOS-ěščřžýáíé.c.obj: file format elf32-xtensa-le // 'F' should not get included in match for 'CONTENTS, ALLOC, LOAD ...' prior
|
||||||
|
|
||||||
Sections:
|
Sections:
|
||||||
Idx Name Size VMA LMA File off Algn
|
Idx Name Size VMA LMA File off Algn
|
||||||
0 .literal.prvCheckPendingReadyList 00000018 00000000 00000000 00000034 2**2
|
0 .literal.ěščřžýáíé 00000018 00000000 00000000 00000034 2**2
|
||||||
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
|
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
|
251
tools/ldgen/test/test_entity.py
Executable file
251
tools/ldgen/test/test_entity.py
Executable file
@@ -0,0 +1,251 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# coding=utf-8
|
||||||
|
#
|
||||||
|
# Copyright 2018-2020 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
try:
|
||||||
|
from entity import Entity, EntityDB
|
||||||
|
except ImportError:
|
||||||
|
sys.path.append('../')
|
||||||
|
from entity import Entity, EntityDB
|
||||||
|
|
||||||
|
|
||||||
|
class EntityTest(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_create_none(self):
|
||||||
|
entity = Entity(Entity.ALL)
|
||||||
|
self.assertEqual(Entity.Specificity.NONE, entity.specificity)
|
||||||
|
|
||||||
|
entity = Entity(None)
|
||||||
|
self.assertEqual(Entity.Specificity.NONE, entity.specificity)
|
||||||
|
|
||||||
|
entity = Entity()
|
||||||
|
self.assertEqual(Entity.Specificity.NONE, entity.specificity)
|
||||||
|
|
||||||
|
def test_create_archive(self):
|
||||||
|
entity = Entity('libfreertos.a')
|
||||||
|
self.assertEqual(Entity.Specificity.ARCHIVE, entity.specificity)
|
||||||
|
|
||||||
|
entity = Entity('libfreertos.a', Entity.ALL, Entity.ALL)
|
||||||
|
self.assertEqual(Entity.Specificity.ARCHIVE, entity.specificity)
|
||||||
|
|
||||||
|
entity = Entity('libfreertos.a', None, None)
|
||||||
|
self.assertEqual(Entity.Specificity.ARCHIVE, entity.specificity)
|
||||||
|
|
||||||
|
entity = Entity('libfreertos.a', Entity.ALL, None)
|
||||||
|
self.assertEqual(Entity.Specificity.ARCHIVE, entity.specificity)
|
||||||
|
|
||||||
|
entity = Entity('libfreertos.a', None, Entity.ALL)
|
||||||
|
self.assertEqual(Entity.Specificity.ARCHIVE, entity.specificity)
|
||||||
|
|
||||||
|
def test_create_obj(self):
|
||||||
|
entity = Entity('libfreertos.a', 'croutine')
|
||||||
|
self.assertEqual(Entity.Specificity.OBJ, entity.specificity)
|
||||||
|
|
||||||
|
entity = Entity('libfreertos.a', 'croutine', Entity.ALL)
|
||||||
|
self.assertEqual(Entity.Specificity.OBJ, entity.specificity)
|
||||||
|
|
||||||
|
entity = Entity('libfreertos.a', 'croutine', None)
|
||||||
|
self.assertEqual(Entity.Specificity.OBJ, entity.specificity)
|
||||||
|
|
||||||
|
def test_create_symbol(self):
|
||||||
|
entity = Entity('libfreertos.a', 'croutine', 'prvCheckPendingReadyList')
|
||||||
|
self.assertEqual(Entity.Specificity.SYMBOL, entity.specificity)
|
||||||
|
|
||||||
|
def test_create_invalid(self):
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
Entity(None, 'croutine')
|
||||||
|
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
Entity(Entity.ALL, 'croutine')
|
||||||
|
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
Entity(None, None, 'prvCheckPendingReadyList')
|
||||||
|
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
Entity(Entity.ALL, Entity.ALL, 'prvCheckPendingReadyList')
|
||||||
|
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
Entity(None, Entity.ALL, 'prvCheckPendingReadyList')
|
||||||
|
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
Entity(Entity.ALL, None, 'prvCheckPendingReadyList')
|
||||||
|
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
Entity('libfreertos.a', None, 'prvCheckPendingReadyList')
|
||||||
|
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
Entity('libfreertos.a', Entity.ALL, 'prvCheckPendingReadyList')
|
||||||
|
|
||||||
|
def test_compare_different_specificity(self):
|
||||||
|
# Different specificity: NONE < ARCHIVE < OBJ < SYMBOL
|
||||||
|
entity_a = Entity()
|
||||||
|
entity_b = Entity('libfreertos.a')
|
||||||
|
self.assertLess(entity_a, entity_b)
|
||||||
|
|
||||||
|
entity_a = Entity('libfreertos.a')
|
||||||
|
entity_b = Entity('libfreertos.a', 'croutine')
|
||||||
|
self.assertLess(entity_a, entity_b)
|
||||||
|
|
||||||
|
entity_a = Entity('libfreertos.a', 'croutine')
|
||||||
|
entity_b = Entity('libfreertos.a', 'croutine', 'prvCheckPendingReadyList')
|
||||||
|
self.assertLess(entity_a, entity_b)
|
||||||
|
|
||||||
|
entity_a = Entity(Entity.ALL)
|
||||||
|
entity_b = Entity('libfreertos.a')
|
||||||
|
self.assertLess(entity_a, entity_b)
|
||||||
|
|
||||||
|
entity_a = Entity('libfreertos.a', Entity.ALL)
|
||||||
|
entity_b = Entity('libfreertos.a', 'croutine')
|
||||||
|
self.assertLess(entity_a, entity_b)
|
||||||
|
|
||||||
|
entity_a = Entity('libfreertos.a', 'croutine', Entity.ALL)
|
||||||
|
entity_b = Entity('libfreertos.a', 'croutine', 'prvCheckPendingReadyList')
|
||||||
|
self.assertLess(entity_a, entity_b)
|
||||||
|
|
||||||
|
def test_compare_equal(self):
|
||||||
|
# Compare equal specificities and members
|
||||||
|
entity_a = Entity()
|
||||||
|
entity_b = Entity()
|
||||||
|
self.assertEqual(entity_a, entity_b)
|
||||||
|
|
||||||
|
entity_a = Entity('libfreertos.a')
|
||||||
|
entity_b = Entity('libfreertos.a')
|
||||||
|
self.assertEqual(entity_a, entity_b)
|
||||||
|
|
||||||
|
entity_a = Entity('libfreertos.a', 'croutine')
|
||||||
|
entity_b = Entity('libfreertos.a', 'croutine')
|
||||||
|
self.assertEqual(entity_a, entity_b)
|
||||||
|
|
||||||
|
entity_a = Entity('libfreertos.a', 'croutine', 'prvCheckPendingReadyList')
|
||||||
|
entity_b = Entity('libfreertos.a', 'croutine', 'prvCheckPendingReadyList')
|
||||||
|
self.assertEqual(entity_a, entity_b)
|
||||||
|
|
||||||
|
def test_compare_none_vs_all(self):
|
||||||
|
# Two entities might have the same specifity whether
|
||||||
|
# Entity.ALL is used or not specified; the latter is
|
||||||
|
# considered less than the former.
|
||||||
|
entity_a = Entity()
|
||||||
|
entity_b = Entity(Entity.ALL)
|
||||||
|
self.assertLess(entity_a, entity_b)
|
||||||
|
|
||||||
|
entity_a = Entity('libfreertos.a')
|
||||||
|
entity_b = Entity('libfreertos.a', Entity.ALL, Entity.ALL)
|
||||||
|
self.assertLess(entity_a, entity_b)
|
||||||
|
|
||||||
|
entity_a = Entity('libfreertos.a', 'croutine')
|
||||||
|
entity_b = Entity('libfreertos.a', 'croutine', Entity.ALL)
|
||||||
|
self.assertLess(entity_a, entity_b)
|
||||||
|
|
||||||
|
def test_compare_same_specificity(self):
|
||||||
|
# Test that entities will be compared alphabetically
|
||||||
|
# when the specificities are the same.
|
||||||
|
entity_a = Entity('libfreertos_a.a')
|
||||||
|
entity_b = Entity('libfreertos_b.a')
|
||||||
|
self.assertLess(entity_a, entity_b)
|
||||||
|
|
||||||
|
entity_a = Entity('libfreertos_b.a', 'croutine_a')
|
||||||
|
entity_b = Entity('libfreertos_a.a', 'croutine_b')
|
||||||
|
self.assertLess(entity_b, entity_a)
|
||||||
|
|
||||||
|
entity_a = Entity('libfreertos.a', 'croutine', 'prvCheckPendingReadyList_a')
|
||||||
|
entity_b = Entity('libfreertos.a', 'croutine', 'prvCheckPendingReadyList_b')
|
||||||
|
self.assertLess(entity_a, entity_b)
|
||||||
|
|
||||||
|
entity_a = Entity('libfreertos.a', 'croutine_b', 'prvCheckPendingReadyList_a')
|
||||||
|
entity_b = Entity('libfreertos.a', 'croutine_a', 'prvCheckPendingReadyList_b')
|
||||||
|
self.assertLess(entity_b, entity_a)
|
||||||
|
|
||||||
|
entity_a = Entity('libfreertos_a.a', 'croutine_b', 'prvCheckPendingReadyList_a')
|
||||||
|
entity_b = Entity('libfreertos_b.a', 'croutine_a', 'prvCheckPendingReadyList_b')
|
||||||
|
self.assertLess(entity_a, entity_b)
|
||||||
|
|
||||||
|
def test_compare_all_non_character(self):
|
||||||
|
# Test that Entity.ALL is not treated as an
|
||||||
|
# ordinary character in comparisons.
|
||||||
|
entity_a = Entity(Entity.ALL)
|
||||||
|
entity_b = Entity(chr(ord(Entity.ALL[0]) - 1))
|
||||||
|
|
||||||
|
self.assertLess(entity_a, entity_b)
|
||||||
|
|
||||||
|
entity_a = Entity('libfreertos.a', Entity.ALL)
|
||||||
|
entity_b = Entity('libfreertos.a', chr(ord(Entity.ALL[0]) - 1))
|
||||||
|
|
||||||
|
self.assertLess(entity_a, entity_b)
|
||||||
|
|
||||||
|
entity_a = Entity('libfreertos.a', 'croutine', '*')
|
||||||
|
entity_b = Entity('libfreertos.a', 'croutine', chr(ord(Entity.ALL[0]) - 1))
|
||||||
|
|
||||||
|
self.assertLess(entity_a, entity_b)
|
||||||
|
|
||||||
|
|
||||||
|
class EntityDBTest(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.entities = EntityDB()
|
||||||
|
|
||||||
|
with open('data/test_entity/libfreertos.a.txt') as objdump:
|
||||||
|
self.entities.add_sections_info(objdump)
|
||||||
|
|
||||||
|
def test_get_archives(self):
|
||||||
|
archives = self.entities.get_archives()
|
||||||
|
self.assertEqual(set(archives), set(['libfreertos.a']))
|
||||||
|
|
||||||
|
def test_get_objs(self):
|
||||||
|
objs = self.entities.get_objects('libfreertos.a')
|
||||||
|
self.assertEqual(set(objs), set(['croutine.S.obj', 'croutine.c.obj', 'croutine.cpp.obj', 'timers.o']))
|
||||||
|
|
||||||
|
def test_get_sections(self):
|
||||||
|
# Needs disambugation between possible matches: croutine.S, croutine.c, croutine.cpp
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
self.entities.get_sections('libfreertos.a', 'croutine')
|
||||||
|
|
||||||
|
# Test disambugation works
|
||||||
|
sections = self.entities.get_sections('libfreertos.a', 'croutine.c')
|
||||||
|
expected = set(['.literal.prvCheckPendingReadyList', '.literal.prvCheckDelayedList'])
|
||||||
|
self.assertEqual(set(sections), expected)
|
||||||
|
|
||||||
|
sections = self.entities.get_sections('libfreertos.a', 'croutine.S')
|
||||||
|
expected = set(['.debug_frame', '.debug_info', '.debug_abbrev'])
|
||||||
|
self.assertEqual(set(sections), expected)
|
||||||
|
|
||||||
|
# Test .o extension works
|
||||||
|
sections = self.entities.get_sections('libfreertos.a', 'timers')
|
||||||
|
expected = set(['.literal.prvGetNextExpireTime', '.literal.prvInsertTimerInActiveList'])
|
||||||
|
self.assertEqual(set(sections), expected)
|
||||||
|
|
||||||
|
def test_parsing(self):
|
||||||
|
# Tests parsing objdump with the following:
|
||||||
|
#
|
||||||
|
# - non-ascii characters
|
||||||
|
# - different architecture string
|
||||||
|
# - different column entries for each sections
|
||||||
|
# - unexpected 'comments'
|
||||||
|
with open('data/test_entity/parse_test.txt') as objdump:
|
||||||
|
self.entities.add_sections_info(objdump)
|
||||||
|
|
||||||
|
sections = self.entities.get_sections('ěščřžýáíé.a', 'croutine')
|
||||||
|
self.assertEqual(set(sections), set(['.text', '.data', '.bss']))
|
||||||
|
|
||||||
|
sections = self.entities.get_sections('ěščřžýáíé.a', 'FreeRTOS-ěščřžýáíé')
|
||||||
|
self.assertEqual(set(sections), set(['.literal.ěščřžýáíé']))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
141
tools/ldgen/test/test_output_commands.py
Executable file
141
tools/ldgen/test/test_output_commands.py
Executable file
@@ -0,0 +1,141 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
try:
|
||||||
|
from output_commands import InputSectionDesc
|
||||||
|
except ImportError:
|
||||||
|
sys.path.append('../')
|
||||||
|
from output_commands import InputSectionDesc
|
||||||
|
|
||||||
|
from entity import Entity
|
||||||
|
|
||||||
|
SECTIONS = ['.text', '.text.*', '.literal', '.literal.*']
|
||||||
|
|
||||||
|
FREERTOS = Entity('libfreertos.a')
|
||||||
|
CROUTINE = Entity('libfreertos.a', 'croutine')
|
||||||
|
|
||||||
|
|
||||||
|
class InputSectionDescTest(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_output_00(self):
|
||||||
|
# Test default (catch-all) command
|
||||||
|
expected = '*(.literal .literal.* .text .text.*)'
|
||||||
|
|
||||||
|
desc = InputSectionDesc(Entity(), SECTIONS)
|
||||||
|
self.assertEqual(expected, str(desc))
|
||||||
|
|
||||||
|
desc = InputSectionDesc(Entity(Entity.ALL), SECTIONS)
|
||||||
|
self.assertEqual(expected, str(desc))
|
||||||
|
|
||||||
|
def test_output_01(self):
|
||||||
|
# Test library placement command
|
||||||
|
expected = '*libfreertos.a:(.literal .literal.* .text .text.*)'
|
||||||
|
|
||||||
|
desc = InputSectionDesc(Entity('libfreertos.a'), SECTIONS)
|
||||||
|
self.assertEqual(expected, str(desc))
|
||||||
|
|
||||||
|
desc = InputSectionDesc(Entity('libfreertos.a', Entity.ALL), SECTIONS)
|
||||||
|
self.assertEqual(expected, str(desc))
|
||||||
|
|
||||||
|
desc = InputSectionDesc(Entity('libfreertos.a', None, Entity.ALL), SECTIONS)
|
||||||
|
self.assertEqual(expected, str(desc))
|
||||||
|
|
||||||
|
desc = InputSectionDesc(Entity('libfreertos.a', Entity.ALL, Entity.ALL), SECTIONS)
|
||||||
|
self.assertEqual(expected, str(desc))
|
||||||
|
|
||||||
|
def test_output_02(self):
|
||||||
|
# Test object placement command
|
||||||
|
expected = '*libfreertos.a:croutine.*(.literal .literal.* .text .text.*)'
|
||||||
|
|
||||||
|
desc = InputSectionDesc(Entity('libfreertos.a', 'croutine'), SECTIONS)
|
||||||
|
self.assertEqual(expected, str(desc))
|
||||||
|
|
||||||
|
desc = InputSectionDesc(Entity('libfreertos.a', 'croutine'), SECTIONS)
|
||||||
|
self.assertEqual(expected, str(desc))
|
||||||
|
|
||||||
|
desc = InputSectionDesc(Entity('libfreertos.a', 'croutine', Entity.ALL), SECTIONS)
|
||||||
|
self.assertEqual(expected, str(desc))
|
||||||
|
|
||||||
|
# Disambugated placement
|
||||||
|
expected = '*libfreertos.a:croutine.c.*(.literal .literal.* .text .text.*)'
|
||||||
|
|
||||||
|
desc = InputSectionDesc(Entity('libfreertos.a', 'croutine.c'), SECTIONS)
|
||||||
|
self.assertEqual(expected, str(desc))
|
||||||
|
|
||||||
|
def test_output_03(self):
|
||||||
|
# Invalid entity specification
|
||||||
|
with self.assertRaises(AssertionError):
|
||||||
|
InputSectionDesc(Entity('libfreertos.a', 'croutine', 'prvCheckPendingReadyList'), SECTIONS)
|
||||||
|
|
||||||
|
with self.assertRaises(AssertionError):
|
||||||
|
InputSectionDesc(Entity('libfreertos.a', 'croutine'), SECTIONS, [Entity()])
|
||||||
|
|
||||||
|
with self.assertRaises(AssertionError):
|
||||||
|
InputSectionDesc(Entity('libfreertos.a', 'croutine'), SECTIONS, [Entity('libfreertos.a', 'croutine', 'prvCheckPendingReadyList')])
|
||||||
|
|
||||||
|
def test_output_04(self):
|
||||||
|
# Test exclusions
|
||||||
|
|
||||||
|
# Library
|
||||||
|
expected = ('*libfreertos.a:croutine.*'
|
||||||
|
'(EXCLUDE_FILE(*libfreertos.a) '
|
||||||
|
'.literal EXCLUDE_FILE(*libfreertos.a) '
|
||||||
|
'.literal.* EXCLUDE_FILE(*libfreertos.a) '
|
||||||
|
'.text EXCLUDE_FILE(*libfreertos.a) .text.*)')
|
||||||
|
desc = InputSectionDesc(CROUTINE, SECTIONS, [FREERTOS])
|
||||||
|
self.assertEqual(expected, str(desc))
|
||||||
|
|
||||||
|
# Object
|
||||||
|
expected = ('*libfreertos.a:croutine.*'
|
||||||
|
'(EXCLUDE_FILE(*libfreertos.a:croutine.*) '
|
||||||
|
'.literal EXCLUDE_FILE(*libfreertos.a:croutine.*) '
|
||||||
|
'.literal.* EXCLUDE_FILE(*libfreertos.a:croutine.*) '
|
||||||
|
'.text EXCLUDE_FILE(*libfreertos.a:croutine.*) .text.*)')
|
||||||
|
desc = InputSectionDesc(CROUTINE, SECTIONS, [CROUTINE])
|
||||||
|
self.assertEqual(expected, str(desc))
|
||||||
|
|
||||||
|
# Multiple exclusions
|
||||||
|
expected = ('*libfreertos.a:croutine.*'
|
||||||
|
'(EXCLUDE_FILE(*libfreertos.a *libfreertos.a:croutine.*) '
|
||||||
|
'.literal EXCLUDE_FILE(*libfreertos.a *libfreertos.a:croutine.*) '
|
||||||
|
'.literal.* EXCLUDE_FILE(*libfreertos.a *libfreertos.a:croutine.*) '
|
||||||
|
'.text EXCLUDE_FILE(*libfreertos.a *libfreertos.a:croutine.*) .text.*)')
|
||||||
|
desc = InputSectionDesc(CROUTINE, SECTIONS, [FREERTOS, CROUTINE])
|
||||||
|
self.assertEqual(expected, str(desc))
|
||||||
|
|
||||||
|
# Disambugated exclusion
|
||||||
|
expected = ('*libfreertos.a:croutine.*'
|
||||||
|
'(EXCLUDE_FILE(*libfreertos.a:croutine.c.*) '
|
||||||
|
'.literal EXCLUDE_FILE(*libfreertos.a:croutine.c.*) '
|
||||||
|
'.literal.* EXCLUDE_FILE(*libfreertos.a:croutine.c.*) '
|
||||||
|
'.text EXCLUDE_FILE(*libfreertos.a:croutine.c.*) .text.*)')
|
||||||
|
desc = InputSectionDesc(CROUTINE, SECTIONS, [Entity('libfreertos.a', 'croutine.c')])
|
||||||
|
self.assertEqual(expected, str(desc))
|
||||||
|
|
||||||
|
def test_output_05(self):
|
||||||
|
# Test empty sections
|
||||||
|
expected = '*libfreertos.a:croutine.*( )'
|
||||||
|
|
||||||
|
desc = InputSectionDesc(Entity('libfreertos.a', 'croutine'), [])
|
||||||
|
self.assertEqual(expected, str(desc))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
Reference in New Issue
Block a user