def _generate_xml_report(self, instr_dir, traces, working_dir): """ Helper for generate_report. Run "gnatcov run" to produce a XML report. :rtype: str :return: Output directory for the XML report. """ # Compute the list of SID files sid_dir = os.path.join(instr_dir, 'sids') sid_list = os.path.join(working_dir, 'sids.txt') with open(sid_list, 'w') as f: for t in glob.glob(os.path.join(sid_dir, '*.sid')): f.write(t + '\n') # Compute the list of traces files trace_list = os.path.join(working_dir, 'traces.txt') with open(trace_list, 'w') as f: for t in traces: f.write(t + '\n') # Compute a first coverage report, for all Ada source files xml_dir = os.path.join(working_dir, 'xml-report') ensure_clean_dir(xml_dir) subprocess.check_call([ 'gnatcov', 'coverage', '-P', os.path.join(instr_dir, 'to_cover.gpr'), '--level', self.covlevel, '--annotate', 'xml', '--output-dir', xml_dir, '--sid', '@' + sid_list, '@' + trace_list ]) return xml_dir
def generate_report(self, title, instr_dir, traces, output_dir, working_dir): """ Generate a HTML coverage report. :param str title: Title for the coverage report. :param str instr_dir: Directory that contains instrumentation data (see the corresponding argument in the "instrument" method). :param listr[str] traces: List of source trace files to discharge coverage obligations. Typically: execution traces from a testsuite. :param str output_dir: Path to the directory where gnatcov will output the coverage report. Beware, this removes this directory if it exists. :param str working_dir: Temporary directory. """ # Make sure we start with a clean output directory ensure_clean_dir(output_dir) xml_dir = self._generate_xml_report(instr_dir, traces, working_dir) self._generate_final_report(title, instr_dir, xml_dir, output_dir)
def instrument(self, emitter: Emitter, instr_dir: str) -> None: """ Run "gnatcov instrument" on the generated library. :param instr_dir: Directory used to store instrumentation data, i.e. data produced by instrumentation and required to produce coverage reports. Put SID files in the ``$BUILD_DIR/obj/$LIBNAME/sids`` directory (removed and created if needed). """ ensure_clean_dir(instr_dir) subprocess.check_call([ 'gnatcov', 'instrument', '--level', self.covlevel, '-P', emitter.main_project_file, '--no-subprojects', '-X{}_COVINSTR=true'.format(emitter.lib_name_up) ]) default_build_mode = 'dev' project_instr_dir = '{}-gnatcov-instr'.format(emitter.lib_name_low) # At this point, instrumented sources are located in the object # directory, which depends on the build mode: relocate it somewhere # else (i.e. rename to instr_src_dir) so that the same set of # instrumented sources applies to all builds. lib_obj_dir = os.path.join(emitter.lib_root, 'obj', default_build_mode) instr_src_dir = os.path.join( emitter.lib_root, 'obj', project_instr_dir ) if os.path.exists(instr_src_dir): shutil.rmtree(instr_src_dir) os.rename(os.path.join(lib_obj_dir, project_instr_dir), instr_src_dir) # "gnatcov instrument" instruments only Ada sources, so we need to # manually copy the C sources (if any). lib_src_dir = os.path.join(emitter.lib_root, 'include', emitter.lib_name_low) for pattern in ('*.c', '*.h'): for filename in glob.glob(os.path.join(lib_src_dir, pattern)): copy_to_dir(filename, instr_src_dir) # Create a directory to gather all SID files sid_dir = os.path.join(instr_dir, 'sids') ensure_clean_dir(sid_dir) for filename in glob.glob(os.path.join(lib_obj_dir, '*.sid')): copy_to_dir(filename, sid_dir) # Create a directory to gather all non-instrumented sources (generated # and additional ones). "gnatcov # coverage" will use this project to generate its coverage report. src_dir = os.path.join(instr_dir, 'src') ensure_clean_dir(src_dir) for filename in emitter.context.additional_source_files: copy_to_dir(filename, src_dir) for pattern in ('*.adb', '*.ads'): for filename in glob.glob(os.path.join(emitter.src_dir, pattern)): copy_to_dir(filename, src_dir) # Also generate a dummy project file to give easy access to these # sources. with open(os.path.join(instr_dir, 'to_cover.gpr'), 'w') as f: f.write('project To_Cover is' '\n for Source_Dirs use ("src");' '\nend To_Cover;') # Create instrumentation metadata emitter.instr_md.save(instr_dir)