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.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
@ -10,6 +10,15 @@ import logging
|
|||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
from enum import Enum
|
||||
|
||||
class ReturnCode(Enum):
|
||||
"""Return codes."""
|
||||
|
||||
SUCCESS = 0
|
||||
ERROR = 1
|
||||
INVALID_OPTIONS = 2
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
@ -41,25 +50,26 @@ class SymbolParser:
|
|||
"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))
|
||||
try:
|
||||
process = subprocess.run(
|
||||
cmd,
|
||||
check=True,
|
||||
stdin=None,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
)
|
||||
except subprocess.CalledProcessError as error:
|
||||
err_output = error.stdout.decode()
|
||||
msg = (
|
||||
process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||
except OSError as error:
|
||||
raise SymbolTableError(
|
||||
"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))
|
||||
|
||||
return symbol_table
|
||||
|
@ -69,6 +79,9 @@ class SymbolTableError(Exception):
|
|||
"""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):
|
||||
"""Subclass that always shows the help message on invalid arguments."""
|
||||
|
||||
|
@ -76,6 +89,7 @@ class ArgumentParserWithDefaultHelp(argparse.ArgumentParser):
|
|||
"""Error handler."""
|
||||
sys.stderr.write("error: {}\n".format(message))
|
||||
self.print_help()
|
||||
raise SystemExit(ReturnCode.INVALID_OPTIONS.value)
|
||||
|
||||
|
||||
def set_log_verbosity(increase_verbosity):
|
||||
|
@ -91,6 +105,7 @@ def check_float_symbols(elf_file):
|
|||
|
||||
Return the floating point symbols found.
|
||||
"""
|
||||
print("Checking {} for floating point symbols".format(elf_file))
|
||||
parser = SymbolParser()
|
||||
symbol_table = parser.get_symbol_table(elf_file)
|
||||
|
||||
|
@ -105,11 +120,12 @@ def check_action(args):
|
|||
"""Entry point for checking the ELF file."""
|
||||
float_symbols = check_float_symbols(args.elf_file)
|
||||
if float_symbols:
|
||||
print("Found float symbols:")
|
||||
print("Failed - Found float symbols:")
|
||||
for float_symbol in float_symbols:
|
||||
print(float_symbol)
|
||||
raise FloatSymbolsFound("Found float symbols in {}".format(args.elf_file))
|
||||
else:
|
||||
print("No float symbols found.")
|
||||
print("Passed - No float symbols found.")
|
||||
|
||||
|
||||
def parse_args():
|
||||
|
@ -160,9 +176,15 @@ def run_elf_floats_checker():
|
|||
args.func(args)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
def _main():
|
||||
"""Run elf-floats-checker."""
|
||||
try:
|
||||
run_elf_floats_checker()
|
||||
except Exception as 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 mock
|
||||
import os
|
||||
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 '.symtab' contains 2723 entries:\n"
|
||||
|
@ -39,24 +39,28 @@ FLOAT_SYMBOLS = [
|
|||
]
|
||||
|
||||
SYMBOL_TABLE_WITH_FLOATS = (
|
||||
" Symbol table '.symtab' contains 2723 entries:\n"
|
||||
"Num: Value Size Type Bind Vis Ndx Name\n"
|
||||
f" 0: 00000000 0 NOTYPE LOCAL DEFAULT UND \n"
|
||||
f" 1: 000045fd 16 FUNC GLOBAL HIDDEN 3 {FLOAT_SYMBOLS[0]}\n"
|
||||
f" 2: 00004609 16 FUNC GLOBAL HIDDEN 3 lp_ticker_disable_interrupt\n"
|
||||
f" 3: 00004615 16 FUNC GLOBAL HIDDEN 3 {FLOAT_SYMBOLS[1]}\n"
|
||||
f" 4: 00004625 36 FUNC GLOBAL HIDDEN 3 {FLOAT_SYMBOLS[2]}\n"
|
||||
f" 5: 00004645 8 FUNC GLOBAL HIDDEN 3 lp_ticker_get_info\n"
|
||||
f" 6: 0000464d 116 FUNC GLOBAL HIDDEN 3 {FLOAT_SYMBOLS[3]}\n"
|
||||
f" 7: 000046bd 20 FUNC GLOBAL HIDDEN 3 lp_ticker_irq_handler\n"
|
||||
f" 8: 000046d1 16 FUNC GLOBAL HIDDEN 3 {FLOAT_SYMBOLS[4]}\n"
|
||||
f" 9: 000046e1 52 FUNC GLOBAL HIDDEN 3 {FLOAT_SYMBOLS[5]}\n"
|
||||
f" 10: 000046f1 52 FUNC GLOBAL HIDDEN 3 {FLOAT_SYMBOLS[6]}\n"
|
||||
" Symbol table '.symtab' contains 2723 entries:\n"+
|
||||
"Num: Value Size Type Bind Vis Ndx Name\n"+
|
||||
" 0: 00000000 0 NOTYPE LOCAL DEFAULT UND \n"+
|
||||
" 1: 000045fd 16 FUNC GLOBAL HIDDEN 3 {}\n".format(FLOAT_SYMBOLS[0])+
|
||||
" 2: 00004609 16 FUNC GLOBAL HIDDEN 3 lp_ticker_disable_interrupt\n"+
|
||||
" 3: 00004615 16 FUNC GLOBAL HIDDEN 3 {}\n".format(FLOAT_SYMBOLS[1])+
|
||||
" 4: 00004625 36 FUNC GLOBAL HIDDEN 3 {}\n".format(FLOAT_SYMBOLS[2])+
|
||||
" 5: 00004645 8 FUNC GLOBAL HIDDEN 3 lp_ticker_get_info\n"+
|
||||
" 6: 0000464d 116 FUNC GLOBAL HIDDEN 3 {}\n".format(FLOAT_SYMBOLS[3])+
|
||||
" 7: 000046bd 20 FUNC GLOBAL HIDDEN 3 lp_ticker_irq_handler\n"+
|
||||
" 8: 000046d1 16 FUNC GLOBAL HIDDEN 3 {}\n".format(FLOAT_SYMBOLS[4])+
|
||||
" 9: 000046e1 52 FUNC GLOBAL HIDDEN 3 {}\n".format(FLOAT_SYMBOLS[5])+
|
||||
" 10: 000046f1 52 FUNC GLOBAL HIDDEN 3 {}\n".format(FLOAT_SYMBOLS[6])
|
||||
)
|
||||
|
||||
|
||||
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:
|
||||
"""Test class"""
|
||||
|
@ -64,57 +68,55 @@ class TestElfFloatChecker:
|
|||
@classmethod
|
||||
def setup_class(cls):
|
||||
# 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
|
||||
def teardown_class(cls):
|
||||
# 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(
|
||||
self, mock_subprocess_run
|
||||
self, mock_subprocess_popen
|
||||
):
|
||||
"""Test that no false positive occur."""
|
||||
mock_subprocess_run.return_value = subprocess.CompletedProcess(
|
||||
args=(
|
||||
f"{OBJECT_FILE_ANALYSIS_CMD}"
|
||||
" check=True, stderr=-2, stdin=None, stdout=-1"
|
||||
process_mock = mock.Mock()
|
||||
attrs = {
|
||||
"communicate.return_value":(
|
||||
SYMBOL_TABLE_WITHOUT_FLOATS.encode(), None
|
||||
),
|
||||
returncode=0,
|
||||
stdout=SYMBOL_TABLE_WITHOUT_FLOATS.encode(),
|
||||
stderr=None,
|
||||
)
|
||||
"returncode": 0,
|
||||
}
|
||||
process_mock.configure_mock(**attrs)
|
||||
mock_subprocess_popen.return_value = process_mock
|
||||
assert [] == TARGET.check_float_symbols(ELF_FORMAT_FILE)
|
||||
mock_subprocess_run.assert_called_with(
|
||||
mock_subprocess_popen.assert_called_with(
|
||||
OBJECT_FILE_ANALYSIS_CMD,
|
||||
check=True,
|
||||
stdin=None,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
)
|
||||
|
||||
@mock.patch("subprocess.run")
|
||||
@mock.patch("subprocess.Popen")
|
||||
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."""
|
||||
mock_subprocess_run.return_value = subprocess.CompletedProcess(
|
||||
args=(
|
||||
f"{OBJECT_FILE_ANALYSIS_CMD}"
|
||||
" check=True, stderr=-2, stdin=None, stdout=-1"
|
||||
process_mock = mock.Mock()
|
||||
attrs = {
|
||||
"communicate.return_value":(
|
||||
SYMBOL_TABLE_WITH_FLOATS.encode(), None
|
||||
),
|
||||
returncode=0,
|
||||
stdout=SYMBOL_TABLE_WITH_FLOATS.encode(),
|
||||
stderr=None,
|
||||
)
|
||||
"returncode": 0,
|
||||
}
|
||||
process_mock.configure_mock(**attrs)
|
||||
mock_subprocess_popen.return_value = process_mock
|
||||
assert FLOAT_SYMBOLS == TARGET.check_float_symbols(
|
||||
ELF_FORMAT_FILE
|
||||
)
|
||||
mock_subprocess_run.assert_called_with(
|
||||
mock_subprocess_popen.assert_called_with(
|
||||
OBJECT_FILE_ANALYSIS_CMD,
|
||||
check=True,
|
||||
stdin=None,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
)
|
Loading…
Reference in New Issue