mirror of https://github.com/ARMmbed/mbed-os.git
Move script to check for floats and make it Python 2 compatible.
All scripts pertaining to example projects tests should be in the same directory. The test framework uses Python2 therefore this script also needs to be Python2 compatible.pull/11429/head
parent
1798c246cc
commit
c712d2f6ee
|
@ -1,4 +1,4 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python
|
||||||
# Copyright (c) 2019 Arm Limited and Contributors. All rights reserved.
|
# Copyright (c) 2019 Arm Limited and Contributors. All rights reserved.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
@ -10,6 +10,15 @@ import logging
|
||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
class ReturnCode(Enum):
|
||||||
|
"""Return codes."""
|
||||||
|
|
||||||
|
SUCCESS = 0
|
||||||
|
ERROR = 1
|
||||||
|
INVALID_OPTIONS = 2
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -41,25 +50,26 @@ class SymbolParser:
|
||||||
"Get the symbol table for ELF format file '{}'".format(elf_file)
|
"Get the symbol table for ELF format file '{}'".format(elf_file)
|
||||||
)
|
)
|
||||||
|
|
||||||
cmd = [*OBJECT_FILE_ANALYSIS_CMD, elf_file]
|
cmd = [OBJECT_FILE_ANALYSIS_CMD[0], OBJECT_FILE_ANALYSIS_CMD[1], elf_file]
|
||||||
log.debug("command: '{}'".format(cmd))
|
log.debug("command: '{}'".format(cmd))
|
||||||
try:
|
try:
|
||||||
process = subprocess.run(
|
process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
cmd,
|
except OSError as error:
|
||||||
check=True,
|
raise SymbolTableError(
|
||||||
stdin=None,
|
|
||||||
stdout=subprocess.PIPE,
|
|
||||||
stderr=subprocess.STDOUT,
|
|
||||||
)
|
|
||||||
except subprocess.CalledProcessError as error:
|
|
||||||
err_output = error.stdout.decode()
|
|
||||||
msg = (
|
|
||||||
"Getting symbol table for ELF format file '{}' failed,"
|
"Getting symbol table for ELF format file '{}' failed,"
|
||||||
" error: {}".format(elf_file, err_output)
|
" error: {}".format(elf_file, error)
|
||||||
)
|
)
|
||||||
raise SymbolTableError(msg)
|
|
||||||
|
|
||||||
symbol_table = process.stdout.decode()
|
stdout, _ = process.communicate()
|
||||||
|
|
||||||
|
if process.returncode:
|
||||||
|
raise SymbolTableError(
|
||||||
|
"Getting symbol table for ELF format file '{}' failed,"
|
||||||
|
" error: {}".format(elf_file, stdout.decode())
|
||||||
|
)
|
||||||
|
|
||||||
|
symbol_table = stdout.decode()
|
||||||
|
|
||||||
log.debug("Symbol table:\n{}\n".format(symbol_table))
|
log.debug("Symbol table:\n{}\n".format(symbol_table))
|
||||||
|
|
||||||
return symbol_table
|
return symbol_table
|
||||||
|
@ -69,6 +79,9 @@ class SymbolTableError(Exception):
|
||||||
"""An exception for a failure to obtain a symbol table."""
|
"""An exception for a failure to obtain a symbol table."""
|
||||||
|
|
||||||
|
|
||||||
|
class FloatSymbolsFound(Exception):
|
||||||
|
"""An exception generated when floating point symbols are found."""
|
||||||
|
|
||||||
class ArgumentParserWithDefaultHelp(argparse.ArgumentParser):
|
class ArgumentParserWithDefaultHelp(argparse.ArgumentParser):
|
||||||
"""Subclass that always shows the help message on invalid arguments."""
|
"""Subclass that always shows the help message on invalid arguments."""
|
||||||
|
|
||||||
|
@ -76,6 +89,7 @@ class ArgumentParserWithDefaultHelp(argparse.ArgumentParser):
|
||||||
"""Error handler."""
|
"""Error handler."""
|
||||||
sys.stderr.write("error: {}\n".format(message))
|
sys.stderr.write("error: {}\n".format(message))
|
||||||
self.print_help()
|
self.print_help()
|
||||||
|
raise SystemExit(ReturnCode.INVALID_OPTIONS.value)
|
||||||
|
|
||||||
|
|
||||||
def set_log_verbosity(increase_verbosity):
|
def set_log_verbosity(increase_verbosity):
|
||||||
|
@ -91,6 +105,7 @@ def check_float_symbols(elf_file):
|
||||||
|
|
||||||
Return the floating point symbols found.
|
Return the floating point symbols found.
|
||||||
"""
|
"""
|
||||||
|
print("Checking {} for floating point symbols".format(elf_file))
|
||||||
parser = SymbolParser()
|
parser = SymbolParser()
|
||||||
symbol_table = parser.get_symbol_table(elf_file)
|
symbol_table = parser.get_symbol_table(elf_file)
|
||||||
|
|
||||||
|
@ -105,11 +120,12 @@ def check_action(args):
|
||||||
"""Entry point for checking the ELF file."""
|
"""Entry point for checking the ELF file."""
|
||||||
float_symbols = check_float_symbols(args.elf_file)
|
float_symbols = check_float_symbols(args.elf_file)
|
||||||
if float_symbols:
|
if float_symbols:
|
||||||
print("Found float symbols:")
|
print("Failed - Found float symbols:")
|
||||||
for float_symbol in float_symbols:
|
for float_symbol in float_symbols:
|
||||||
print(float_symbol)
|
print(float_symbol)
|
||||||
|
raise FloatSymbolsFound("Found float symbols in {}".format(args.elf_file))
|
||||||
else:
|
else:
|
||||||
print("No float symbols found.")
|
print("Passed - No float symbols found.")
|
||||||
|
|
||||||
|
|
||||||
def parse_args():
|
def parse_args():
|
||||||
|
@ -160,9 +176,15 @@ def run_elf_floats_checker():
|
||||||
args.func(args)
|
args.func(args)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
def _main():
|
||||||
"""Run elf-floats-checker."""
|
"""Run elf-floats-checker."""
|
||||||
try:
|
try:
|
||||||
run_elf_floats_checker()
|
run_elf_floats_checker()
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
print(error)
|
print(error)
|
||||||
|
return ReturnCode.ERROR.value
|
||||||
|
else:
|
||||||
|
return ReturnCode.SUCCESS.value
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(_main())
|
|
@ -7,11 +7,11 @@
|
||||||
|
|
||||||
import importlib
|
import importlib
|
||||||
import mock
|
import mock
|
||||||
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
|
|
||||||
TARGET = importlib.import_module("elf-float-checker")
|
TARGET = importlib.import_module("elf_float_checker")
|
||||||
|
|
||||||
SYMBOL_TABLE_WITHOUT_FLOATS = (
|
SYMBOL_TABLE_WITHOUT_FLOATS = (
|
||||||
" Symbol table '.symtab' contains 2723 entries:\n"
|
" Symbol table '.symtab' contains 2723 entries:\n"
|
||||||
|
@ -39,24 +39,28 @@ FLOAT_SYMBOLS = [
|
||||||
]
|
]
|
||||||
|
|
||||||
SYMBOL_TABLE_WITH_FLOATS = (
|
SYMBOL_TABLE_WITH_FLOATS = (
|
||||||
" Symbol table '.symtab' contains 2723 entries:\n"
|
" Symbol table '.symtab' contains 2723 entries:\n"+
|
||||||
"Num: Value Size Type Bind Vis Ndx Name\n"
|
"Num: Value Size Type Bind Vis Ndx Name\n"+
|
||||||
f" 0: 00000000 0 NOTYPE LOCAL DEFAULT UND \n"
|
" 0: 00000000 0 NOTYPE LOCAL DEFAULT UND \n"+
|
||||||
f" 1: 000045fd 16 FUNC GLOBAL HIDDEN 3 {FLOAT_SYMBOLS[0]}\n"
|
" 1: 000045fd 16 FUNC GLOBAL HIDDEN 3 {}\n".format(FLOAT_SYMBOLS[0])+
|
||||||
f" 2: 00004609 16 FUNC GLOBAL HIDDEN 3 lp_ticker_disable_interrupt\n"
|
" 2: 00004609 16 FUNC GLOBAL HIDDEN 3 lp_ticker_disable_interrupt\n"+
|
||||||
f" 3: 00004615 16 FUNC GLOBAL HIDDEN 3 {FLOAT_SYMBOLS[1]}\n"
|
" 3: 00004615 16 FUNC GLOBAL HIDDEN 3 {}\n".format(FLOAT_SYMBOLS[1])+
|
||||||
f" 4: 00004625 36 FUNC GLOBAL HIDDEN 3 {FLOAT_SYMBOLS[2]}\n"
|
" 4: 00004625 36 FUNC GLOBAL HIDDEN 3 {}\n".format(FLOAT_SYMBOLS[2])+
|
||||||
f" 5: 00004645 8 FUNC GLOBAL HIDDEN 3 lp_ticker_get_info\n"
|
" 5: 00004645 8 FUNC GLOBAL HIDDEN 3 lp_ticker_get_info\n"+
|
||||||
f" 6: 0000464d 116 FUNC GLOBAL HIDDEN 3 {FLOAT_SYMBOLS[3]}\n"
|
" 6: 0000464d 116 FUNC GLOBAL HIDDEN 3 {}\n".format(FLOAT_SYMBOLS[3])+
|
||||||
f" 7: 000046bd 20 FUNC GLOBAL HIDDEN 3 lp_ticker_irq_handler\n"
|
" 7: 000046bd 20 FUNC GLOBAL HIDDEN 3 lp_ticker_irq_handler\n"+
|
||||||
f" 8: 000046d1 16 FUNC GLOBAL HIDDEN 3 {FLOAT_SYMBOLS[4]}\n"
|
" 8: 000046d1 16 FUNC GLOBAL HIDDEN 3 {}\n".format(FLOAT_SYMBOLS[4])+
|
||||||
f" 9: 000046e1 52 FUNC GLOBAL HIDDEN 3 {FLOAT_SYMBOLS[5]}\n"
|
" 9: 000046e1 52 FUNC GLOBAL HIDDEN 3 {}\n".format(FLOAT_SYMBOLS[5])+
|
||||||
f" 10: 000046f1 52 FUNC GLOBAL HIDDEN 3 {FLOAT_SYMBOLS[6]}\n"
|
" 10: 000046f1 52 FUNC GLOBAL HIDDEN 3 {}\n".format(FLOAT_SYMBOLS[6])
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
ELF_FORMAT_FILE = "mbed-os-example.elf"
|
ELF_FORMAT_FILE = "mbed-os-example.elf"
|
||||||
OBJECT_FILE_ANALYSIS_CMD = [*(TARGET.OBJECT_FILE_ANALYSIS_CMD), f"{ELF_FORMAT_FILE}"]
|
OBJECT_FILE_ANALYSIS_CMD = [
|
||||||
|
TARGET.OBJECT_FILE_ANALYSIS_CMD[0],
|
||||||
|
TARGET.OBJECT_FILE_ANALYSIS_CMD[1],
|
||||||
|
"{}".format(ELF_FORMAT_FILE)
|
||||||
|
]
|
||||||
|
|
||||||
class TestElfFloatChecker:
|
class TestElfFloatChecker:
|
||||||
"""Test class"""
|
"""Test class"""
|
||||||
|
@ -64,57 +68,55 @@ class TestElfFloatChecker:
|
||||||
@classmethod
|
@classmethod
|
||||||
def setup_class(cls):
|
def setup_class(cls):
|
||||||
# Create a dummy ELF format file
|
# Create a dummy ELF format file
|
||||||
Path(ELF_FORMAT_FILE).touch()
|
if not os.path.exists(ELF_FORMAT_FILE):
|
||||||
|
with open(ELF_FORMAT_FILE, 'w'): pass
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def teardown_class(cls):
|
def teardown_class(cls):
|
||||||
# Remove the dummy ELF format file
|
# Remove the dummy ELF format file
|
||||||
Path(ELF_FORMAT_FILE).unlink()
|
if os.path.exists(ELF_FORMAT_FILE):
|
||||||
|
os.remove(ELF_FORMAT_FILE)
|
||||||
|
|
||||||
@mock.patch("subprocess.run")
|
@mock.patch("subprocess.Popen")
|
||||||
def test_correctly_detect_absence_of_float_symbols(
|
def test_correctly_detect_absence_of_float_symbols(
|
||||||
self, mock_subprocess_run
|
self, mock_subprocess_popen
|
||||||
):
|
):
|
||||||
"""Test that no false positive occur."""
|
"""Test that no false positive occur."""
|
||||||
mock_subprocess_run.return_value = subprocess.CompletedProcess(
|
process_mock = mock.Mock()
|
||||||
args=(
|
attrs = {
|
||||||
f"{OBJECT_FILE_ANALYSIS_CMD}"
|
"communicate.return_value":(
|
||||||
" check=True, stderr=-2, stdin=None, stdout=-1"
|
SYMBOL_TABLE_WITHOUT_FLOATS.encode(), None
|
||||||
),
|
),
|
||||||
returncode=0,
|
"returncode": 0,
|
||||||
stdout=SYMBOL_TABLE_WITHOUT_FLOATS.encode(),
|
}
|
||||||
stderr=None,
|
process_mock.configure_mock(**attrs)
|
||||||
)
|
mock_subprocess_popen.return_value = process_mock
|
||||||
assert [] == TARGET.check_float_symbols(ELF_FORMAT_FILE)
|
assert [] == TARGET.check_float_symbols(ELF_FORMAT_FILE)
|
||||||
mock_subprocess_run.assert_called_with(
|
mock_subprocess_popen.assert_called_with(
|
||||||
OBJECT_FILE_ANALYSIS_CMD,
|
OBJECT_FILE_ANALYSIS_CMD,
|
||||||
check=True,
|
|
||||||
stdin=None,
|
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.STDOUT,
|
stderr=subprocess.STDOUT,
|
||||||
)
|
)
|
||||||
|
|
||||||
@mock.patch("subprocess.run")
|
@mock.patch("subprocess.Popen")
|
||||||
def test_correctly_detect_presence_of_float_symbols(
|
def test_correctly_detect_presence_of_float_symbols(
|
||||||
self, mock_subprocess_run
|
self, mock_subprocess_popen
|
||||||
):
|
):
|
||||||
"""Test that float symbols can be discovered in a symbol table."""
|
"""Test that float symbols can be discovered in a symbol table."""
|
||||||
mock_subprocess_run.return_value = subprocess.CompletedProcess(
|
process_mock = mock.Mock()
|
||||||
args=(
|
attrs = {
|
||||||
f"{OBJECT_FILE_ANALYSIS_CMD}"
|
"communicate.return_value":(
|
||||||
" check=True, stderr=-2, stdin=None, stdout=-1"
|
SYMBOL_TABLE_WITH_FLOATS.encode(), None
|
||||||
),
|
),
|
||||||
returncode=0,
|
"returncode": 0,
|
||||||
stdout=SYMBOL_TABLE_WITH_FLOATS.encode(),
|
}
|
||||||
stderr=None,
|
process_mock.configure_mock(**attrs)
|
||||||
)
|
mock_subprocess_popen.return_value = process_mock
|
||||||
assert FLOAT_SYMBOLS == TARGET.check_float_symbols(
|
assert FLOAT_SYMBOLS == TARGET.check_float_symbols(
|
||||||
ELF_FORMAT_FILE
|
ELF_FORMAT_FILE
|
||||||
)
|
)
|
||||||
mock_subprocess_run.assert_called_with(
|
mock_subprocess_popen.assert_called_with(
|
||||||
OBJECT_FILE_ANALYSIS_CMD,
|
OBJECT_FILE_ANALYSIS_CMD,
|
||||||
check=True,
|
|
||||||
stdin=None,
|
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.STDOUT,
|
stderr=subprocess.STDOUT,
|
||||||
)
|
)
|
Loading…
Reference in New Issue