def test_get_output_path_on_windows(self): output_path = "output_path" report = TestReport() runner = TestRunner(report, output_path) with mock.patch("sys.platform", new="win32"): with mock.patch("os.environ", new={}): test_name = "_" * 400 test_output = runner._get_output_path(test_name) self.assertEqual(len(test_output), 260 - 100 + 1) with mock.patch("os.environ", new={"VUNIT_TEST_OUTPUT_PATH_MARGIN": "-1000"}): output_path = "output_path" test_name = "_" * 400 test_output = runner._get_output_path(test_name) self.assertEqual( test_output, str( Path(output_path).resolve() / (test_name + "_" + hash_string(test_name))), ) with mock.patch("os.environ", new={"VUNIT_SHORT_TEST_OUTPUT_PATHS": ""}): output_path = "output_path" test_name = "_" * 400 test_output = runner._get_output_path(test_name) self.assertEqual( test_output, str(Path(output_path).resolve() / hash_string(test_name)), )
def test_create_output_path_on_windows(self): with mock.patch("sys.platform", new="win32"): with mock.patch("os.environ", new={}): output_path = "output_path" test_name = "_" * 400 test_output = create_output_path(output_path, test_name) self.assertEqual(len(test_output), 260 - 100 + 1) with mock.patch("os.environ", new={"VUNIT_TEST_OUTPUT_PATH_MARGIN": "-1000"}): output_path = "output_path" test_name = "_" * 400 test_output = create_output_path(output_path, test_name) self.assertEqual( test_output, join(abspath(output_path), test_name + "_" + hash_string(test_name))) with mock.patch("os.environ", new={"VUNIT_SHORT_TEST_OUTPUT_PATHS": ""}): output_path = "output_path" test_name = "_" * 400 test_output = create_output_path(output_path, test_name) self.assertEqual( test_output, join(abspath(output_path), hash_string(test_name)))
def _file_content_hash(file_name, encoding, database=None, newline=None): """ Returns the file content as well as the hash of the content Use the database to keep a persistent cache of the last content hash. If the file modification date has not changed assume the hash is the same and do not re-open the file. """ if database is None: content = read_file(file_name, encoding=encoding, newline=newline) return content, hash_string(content) key = ("cached._file_content_hash(%s, newline=%s)" % (file_name, newline)).encode() if key not in database: content = read_file(file_name, encoding=encoding, newline=newline) content_hash = hash_string(content) timestamp = os.path.getmtime(file_name) database[key] = timestamp, content_hash return content, content_hash timestamp = os.path.getmtime(file_name) last_timestamp, last_content_hash = database[key] if timestamp != last_timestamp: content = read_file(file_name, encoding=encoding, newline=newline) content_hash = hash_string(content) database[key] = timestamp, content_hash return content, content_hash return None, last_content_hash
def test_create_output_path_on_linux(self): with mock.patch("sys.platform", new="linux"): with mock.patch("os.environ", new={}): output_path = "output_path" test_name = "_" * 400 test_output = create_output_path(output_path, test_name) self.assertEqual( test_output, join(abspath(output_path), test_name + "_" + hash_string(test_name))) output_path = "output_path" test_name = "123._-+" test_output = create_output_path(output_path, test_name) self.assertEqual( test_output, join(abspath(output_path), test_name + "_" + hash_string(test_name))) output_path = "output_path" test_name = "#<>:" safe_name = "____" test_output = create_output_path(output_path, test_name) self.assertEqual( test_output, join(abspath(output_path), safe_name + "_" + hash_string(test_name)))
def test_get_output_path_on_linux(self): output_path = "output_path" report = TestReport() runner = TestRunner(report, output_path) with mock.patch("sys.platform", new="linux"): with mock.patch("os.environ", new={}): test_name = "_" * 400 test_output = runner._get_output_path(test_name) self.assertEqual( test_output, str(Path(output_path).resolve() / (test_name + "_" + hash_string(test_name))), ) output_path = "output_path" test_name = "123._-+" test_output = runner._get_output_path(test_name) self.assertEqual( test_output, str(Path(output_path).resolve() / (test_name + "_" + hash_string(test_name))), ) output_path = "output_path" test_name = "#<>:" safe_name = "____" test_output = runner._get_output_path(test_name) self.assertEqual( test_output, str(Path(output_path).resolve() / (safe_name + "_" + hash_string(test_name))), )
def content_hash(self): """ Compute hash of contents and compile options """ return hash_string( self._content_hash + self._compile_options_hash() + hash_string(str(self._vhdl_standard)) )
def __init__(self, name, library, verilog_parser, include_dirs=None, defines=None): SourceFile.__init__(self, name, library, 'verilog') self.package_dependencies = [] self.module_dependencies = [] self.include_dirs = include_dirs if include_dirs is not None else [] self.defines = defines.copy() if defines is not None else {} code = ostools.read_file(self.name, encoding=HDL_FILE_ENCODING) self._content_hash = hash_string(code) for key, value in self.defines.items(): self._content_hash = hash_string(self._content_hash + hash_string(key)) self._content_hash = hash_string(self._content_hash + hash_string(value)) self.parse(code, verilog_parser, include_dirs)
def __init__(self, name, library, verilog_parser, include_dirs=None, defines=None): SourceFile.__init__(self, name, library, 'verilog') self.package_dependencies = [] self.module_dependencies = [] self.include_dirs = include_dirs if include_dirs is not None else [] self.defines = defines.copy() if defines is not None else {} code = ostools.read_file(self.name) self._content_hash = hash_string(code) for key, value in self.defines.items(): self._content_hash = hash_string(self._content_hash + hash_string(key)) self._content_hash = hash_string(self._content_hash + hash_string(value)) self.parse(code, verilog_parser, include_dirs)
def parse(self, code, parser, include_dirs): """ Parse Verilog code and adding dependencies and design units """ try: design_file = parser.parse(code, self.name, include_dirs, self.defines) for included_file_name in design_file.included_files: self._content_hash = hash_string(self._content_hash + ostools.read_file(included_file_name, encoding=HDL_FILE_ENCODING)) for module in design_file.modules: self.design_units.append(ModuleDesignUnit(module.name, self, module.parameters)) for package in design_file.packages: self.design_units.append(VerilogDesignUnit(package.name, self, "package")) for package_name in design_file.imports: self.package_dependencies.append(package_name) for package_name in design_file.package_references: self.package_dependencies.append(package_name) for instance_name in design_file.instances: self.module_dependencies.append(instance_name) except KeyboardInterrupt: raise except: # pylint: disable=bare-except traceback.print_exc() LOGGER.error("Failed to parse %s", self.name)
def _hash_file_name_of(self, source_file): """ Returns the name of the hash file associated with the source_file """ library = self.get_library(source_file.library.name) prefix = hash_string(str(Path(source_file.name).parent)) return str(Path(library.directory) / prefix / Path(source_file.name).name / ".vunit_hash")
def _compile_options_hash(self): """ Compute hash of compile options Needs to be updated if there are nested dictionaries """ return hash_string(repr(sorted(self._compile_options.items())))
def _create_test_mapping_file(self, test_suites): """ Create a file mapping test name to test output folder. This is to allow the user to find the test output folder when it is hashed """ mapping_file_name = join(self._output_path, "test_name_to_path_mapping.txt") # Load old mapping to remember non-deleted test folders as well # even when re-running only a single test case if exists(mapping_file_name): with open(mapping_file_name, "r") as fptr: mapping = set(fptr.read().splitlines()) else: mapping = set() for test_suite in test_suites: name_hash = hash_string(test_suite.name) HASH_TO_TEST_NAME[name_hash] = test_suite.name mapping.add("%s %s" % (name_hash, test_suite.name)) # Sort by everything except hash mapping = sorted(mapping, key=lambda value: value[value.index(" "):]) with open(mapping_file_name, "w") as fptr: for value in mapping: fptr.write(value + "\n")
def __init__(self, name, library, vhdl_parser): SourceFile.__init__(self, name, library, 'vhdl') self.dependencies = [] self.depending_components = [] code = ostools.read_file(self.name) self._content_hash = hash_string(code) self.parse(code, vhdl_parser)
def _hash_file_name_of(self, source_file): """ Returns the name of the hash file associated with the source_file """ library = self.get_library(source_file.library.name) prefix = hash_string(dirname(source_file.name)) return join(library.directory, prefix, basename(source_file.name) + ".vunit_hash")
def create_output_path(output_file, test_suite_name): """ Create the full output path of a test case. Ensure no bad characters and no long path names. """ hash_name = hash_string(test_suite_name) return join(output_file, hash_name)
def _create_test_mapping_file(self, test_suites): """ Create a file mapping test name to test output folder. This is to allow the user to find the test output folder when it is hashed """ mapping_file_name = join(self._output_path, "test_name_to_path_mapping.txt") # Load old mapping to remember non-deleted test folders as well # even when re-running only a single test case if exists(mapping_file_name): with open(mapping_file_name, "r") as fptr: mapping = set(fptr.read().splitlines()) else: mapping = set() for test_suite in test_suites: name_hash = hash_string(test_suite.name) mapping.add("%s %s" % (name_hash, test_suite.name)) # Sort by everything except hash mapping = sorted(mapping, key=lambda value: value[value.index(" "):]) with open(mapping_file_name, "w") as fptr: for value in mapping: fptr.write(value + "\n")
def parse(self, code, parser, include_dirs): """ Parse Verilog code and adding dependencies and design units """ try: design_file = parser.parse(code, self.name, include_dirs, self.defines) for included_file_name in design_file.included_files: self._content_hash = hash_string( self._content_hash + ostools.read_file(included_file_name)) for module in design_file.modules: self.design_units.append( ModuleDesignUnit(module.name, self, module.parameters)) for package in design_file.packages: self.design_units.append( VerilogDesignUnit(package.name, self, "package")) for package_name in design_file.imports: self.package_dependencies.append(package_name) for package_name in design_file.package_references: self.package_dependencies.append(package_name) for instance_name in design_file.instances: self.module_dependencies.append(instance_name) except KeyboardInterrupt: raise except: # pylint: disable=bare-except traceback.print_exc() LOGGER.error("Failed to parse %s", self.name)
def __init__(self, name, library, verilog_parser, include_dirs): SourceFile.__init__(self, name, library, 'verilog') self.package_dependencies = [] self.module_dependencies = [] self.include_dirs = include_dirs if include_dirs is not None else [] code = ostools.read_file(self.name) self._content_hash = hash_string(code) self.parse(code, verilog_parser, include_dirs)
def __init__( self, # pylint: disable=too-many-arguments name, library, verilog_parser, include_dirs=None, defines=None, no_parse=False): SourceFile.__init__(self, name, library, 'verilog') self.package_dependencies = [] self.module_dependencies = [] self.include_dirs = include_dirs if include_dirs is not None else [] self.defines = defines.copy() if defines is not None else {} code = ostools.read_file(self.name, encoding=HDL_FILE_ENCODING) self._content_hash = hash_string(code) for path in self.include_dirs: self._content_hash = hash_string(self._content_hash + hash_string(path)) for key, value in self.defines.items(): self._content_hash = hash_string(self._content_hash + hash_string(key)) self._content_hash = hash_string(self._content_hash + hash_string(value)) if not no_parse: self.parse(code, verilog_parser, include_dirs)
def _content_hash(self, file_name): """ Hash the contents of the file """ if file_name is None or not exists(file_name): return None if file_name not in self._content_cache: self._content_cache[file_name] = "sha1:" + hash_string(read_file(file_name)) return self._content_cache[file_name]
def __init__(self, name, library, vhdl_parser, vhdl_standard): SourceFile.__init__(self, name, library, 'vhdl') self.dependencies = [] self.depending_components = [] self._vhdl_standard = vhdl_standard check_vhdl_standard(vhdl_standard) code = ostools.read_file(self.name, encoding=HDL_FILE_ENCODING) self._content_hash = hash_string(code) self.parse(code, vhdl_parser)
def __init__( # pylint: disable=too-many-arguments self, file_type, name, library, verilog_parser, database, include_dirs=None, defines=None, no_parse=False, ): SourceFile.__init__(self, name, library, file_type) self.package_dependencies = [] self.module_dependencies = [] self.include_dirs = include_dirs if include_dirs is not None else [] self.defines = defines.copy() if defines is not None else {} self._content_hash = file_content_hash(self.name, encoding=HDL_FILE_ENCODING, database=database) for path in self.include_dirs: self._content_hash = hash_string(self._content_hash + hash_string(path)) for key, value in sorted(self.defines.items()): self._content_hash = hash_string(self._content_hash + hash_string(key)) self._content_hash = hash_string(self._content_hash + hash_string(value)) if not no_parse: self.parse(verilog_parser, database, include_dirs)
def test_create_output_path_on_windows(self): with mock.patch("sys.platform", new="win32"): with mock.patch("os.environ", new={}): output_path = "output_path" test_name = "_" * 400 test_output = create_output_path(output_path, test_name) self.assertEqual(len(test_output), 260 - 100 + 1) with mock.patch("os.environ", new={"VUNIT_TEST_OUTPUT_PATH_MARGIN": "-1000"}): output_path = "output_path" test_name = "_" * 400 test_output = create_output_path(output_path, test_name) self.assertEqual(test_output, join(abspath(output_path), test_name + "_" + hash_string(test_name))) with mock.patch("os.environ", new={"VUNIT_SHORT_TEST_OUTPUT_PATHS": ""}): output_path = "output_path" test_name = "_" * 400 test_output = create_output_path(output_path, test_name) self.assertEqual(test_output, join(abspath(output_path), hash_string(test_name)))
def create_output_path(output_path, test_suite_name): """ Create the full output path of a test case. Ensure no bad characters and no long path names. """ output_path = abspath(output_path) safe_name = "".join(char if _is_legal(char) else '_' for char in test_suite_name) + "_" hash_name = hash_string(test_suite_name) if "VUNIT_SHORT_TEST_OUTPUT_PATHS" in os.environ: full_name = hash_name elif sys.platform == "win32": max_path = 260 margin = int(os.environ.get("VUNIT_TEST_OUTPUT_PATH_MARGIN", "100")) prefix_len = len(output_path) full_name = safe_name[:min(max_path - margin - prefix_len - len(hash_name), len(safe_name))] + hash_name else: full_name = safe_name + hash_name return join(output_path, full_name)
def parse(self, code, file_name, content_hash=None): """ Parse the VHDL code and return a VHDLDesignFile parse result parse result is re-used if content hash found in database """ file_name = abspath(file_name) if content_hash is None: content_hash = "sha1:" + hash_string(code) key = ("CachedVHDLParser.parse(%s)" % file_name).encode() if key in self._database: design_file, old_content_hash = self._database[key] if content_hash == old_content_hash: LOGGER.debug("Re-using cached VHDL parse results for %s with content_hash=%s", file_name, content_hash) return design_file design_file = VHDLDesignFile.parse(code) self._database[key] = design_file, content_hash return design_file
def parse(self, parser, database, include_dirs): """ Parse Verilog code and adding dependencies and design units """ try: design_file = parser.parse(self.name, include_dirs, self.defines) for included_file_name in design_file.included_files: self._content_hash = hash_string( self._content_hash + file_content_hash( included_file_name, encoding=HDL_FILE_ENCODING, database=database, )) for module in design_file.modules: self.design_units.append( Module(module.name, self, module.parameters)) for package in design_file.packages: self.design_units.append( DesignUnit(package.name, self, "package")) for package_name in design_file.imports: self.package_dependencies.append(package_name) for package_name in design_file.package_references: self.package_dependencies.append(package_name) for instance_name in design_file.instances: self.module_dependencies.append(instance_name) except KeyboardInterrupt as exk: raise KeyboardInterrupt from exk except: # pylint: disable=bare-except traceback.print_exc() LOGGER.error("Failed to parse %s", self.name)
def __init__(self, # pylint: disable=too-many-arguments file_type, name, library, verilog_parser, database, include_dirs=None, defines=None, no_parse=False): SourceFile.__init__(self, name, library, file_type) self.package_dependencies = [] self.module_dependencies = [] self.include_dirs = include_dirs if include_dirs is not None else [] self.defines = defines.copy() if defines is not None else {} self._content_hash = file_content_hash(self.name, encoding=HDL_FILE_ENCODING, database=database) for path in self.include_dirs: self._content_hash = hash_string(self._content_hash + hash_string(path)) for key, value in sorted(self.defines.items()): self._content_hash = hash_string(self._content_hash + hash_string(key)) self._content_hash = hash_string(self._content_hash + hash_string(value)) if not no_parse: self.parse(verilog_parser, database, include_dirs)
def content_hash(self): """ Compute hash of contents and compile options """ return hash_string(self._content_hash + self._compile_options_hash() + hash_string(self._vhdl_standard))
def test_create_output_path_on_linux(self): with mock.patch("sys.platform", new="linux"): with mock.patch("os.environ", new={}): output_path = "output_path" test_name = "_" * 400 test_output = create_output_path(output_path, test_name) self.assertEqual(test_output, join(abspath(output_path), test_name + "_" + hash_string(test_name))) output_path = "output_path" test_name = "123._-+" test_output = create_output_path(output_path, test_name) self.assertEqual(test_output, join(abspath(output_path), test_name + "_" + hash_string(test_name))) output_path = "output_path" test_name = "#<>:" safe_name = "____" test_output = create_output_path(output_path, test_name) self.assertEqual(test_output, join(abspath(output_path), safe_name + "_" + hash_string(test_name)))