| 1 | /* a file to start prob_cli with coverage/profiling info enabled (for SICStus 4.2 and later) */ | |
| 2 | ||
| 3 | :- prolog_flag(compiling,_,debugcode). | |
| 4 | :- prolog_flag(source_info,_,on). | |
| 5 | :- prolog_flag(profiling,_,on). | |
| 6 | ||
| 7 | :- include(coverage_term_expander). | |
| 8 | ||
| 9 | :- use_module(prob_cli). | |
| 10 | ||
| 11 | :- use_module(coverage_tools). | |
| 12 | :- use_module(test_runner). | |
| 13 | :- use_module(tools_strings,[ajoin/2]). | |
| 14 | :- use_module(version). | |
| 15 | :- use_module(extension('pltables/pltables')). | |
| 16 | ||
| 17 | :- use_module(library(samsort), [merge/3]). | |
| 18 | :- use_module(library(system)). | |
| 19 | :- use_module(library(codesio)). | |
| 20 | :- use_module(library(lists)). | |
| 21 | :- use_module(library(file_systems)). | |
| 22 | :- use_module(library(sets),[subtract/3]). | |
| 23 | ||
| 24 | % use module_info/3 because we are not in a module here | |
| 25 | :- module_info(prob_cov,group,coverage_analysis). | |
| 26 | :- module_info(prob_cov,description,'ProB start file with coverage tests activated. Includes predicates to execute certain tests. Used by Jenkins.'). | |
| 27 | ||
| 28 | generate_makefile :- | |
| 29 | generate_makefile('Makefile_Coverage_Groups', write_coverage_target). | |
| 30 | ||
| 31 | write_coverage_target(G) :- format('~w:\n\tsicstus -l src/prob_cov.pl --goal "coverage_group_data(\'~w\'), halt ; halt."',[G,G]),nl,nl. | |
| 32 | ||
| 33 | % compute coverage for a testcase category (see testcases.pl for categories) | |
| 34 | coverage_group_data(Category) :- | |
| 35 | % ids_in_category(Category,IDs), | |
| 36 | % load_coverage_files(IDs,CoverageData), | |
| 37 | run_tests_by_category(Category,all), | |
| 38 | format('Obtaining coverage data for category ~w~n',[Category]), | |
| 39 | coverage_data(CoverageData), | |
| 40 | write_coverage_data(Category,CoverageData). | |
| 41 | ||
| 42 | % write collected coverage information to a Datafile | |
| 43 | write_coverage_data(FileName,Data) :- | |
| 44 | ajoin(['./temp_coverage_data/', FileName],Path), | |
| 45 | format('Writing coverage data to ~w~n',[Path]), | |
| 46 | open(Path,write,Stream), | |
| 47 | Out=cov(Data), | |
| 48 | write_canonical(Stream,Out), | |
| 49 | write(Stream,'.'), | |
| 50 | close(Stream). | |
| 51 | ||
| 52 | read_coverage_data(Path,Data) :- | |
| 53 | open(Path,read,S), | |
| 54 | read(S,cov(Data)), | |
| 55 | close(S). | |
| 56 | ||
| 57 | relevant_categories(units,[unit]). | |
| 58 | relevant_categories(laws,[laws]). | |
| 59 | relevant_categories(units-and-laws,[unit,laws]). | |
| 60 | relevant_categories(regression,Groups) :- | |
| 61 | all_categories(All), | |
| 62 | subtract(All,[unit,laws],Groups). | |
| 63 | relevant_categories(all,All) :- | |
| 64 | all_categories(All). | |
| 65 | relevant_categories(data_validation,[data_validation]). | |
| 66 | relevant_categories(X,[X]) :- atom(X). | |
| 67 | relevant_categories(X,X) :- is_list(X). | |
| 68 | ||
| 69 | header(units, 'Unit Tests'). | |
| 70 | header(laws, 'Law Checking'). | |
| 71 | header(units-and-laws,'Unit and Law Tests'). | |
| 72 | header(regression,'Regression Tests'). | |
| 73 | header(all,'All Tests'). | |
| 74 | header(data_validation,'Data Validation Tests'). | |
| 75 | %header(last,'Last Test Case'). | |
| 76 | header(X,Joined) :- atom(X), !, ajoin(['Testcases with Group ', X],Joined). | |
| 77 | header(X,Joined) :- is_list(X), maplist(atom,X), !, ajoin(['Testcases with Groups ', X],Joined). | |
| 78 | ||
| 79 | atom_header(Keyword, Header) :- | |
| 80 | header(Keyword,Tests), | |
| 81 | datime(datime(Year,Month,Day,Hour,Min,_Sec)), | |
| 82 | revision(CurrentCommit), | |
| 83 | format_to_codes('Coverage Report (~w, generated ~w.~w.~w ~w:~w, commit ~w)', [Tests,Day,Month,Year,Hour,Min,CurrentCommit], Codes), | |
| 84 | atom_codes(Header, Codes). | |
| 85 | ||
| 86 | :- use_module(tools,[ensure_atom/2]). | |
| 87 | load_coverage_files(IDs,CoverageData) :- | |
| 88 | maplist(ensure_atom,IDs,AtomicIDs), | |
| 89 | file_members_of_directory('./temp_coverage_data/',CoverageFiles), | |
| 90 | write('Reading Coverage Files'), nl, | |
| 91 | read_coverage_files(CoverageFiles,AtomicIDs,CoverageData). | |
| 92 | ||
| 93 | ||
| 94 | read_coverage_files(Files,RelevantIDs,CoverageData) :- | |
| 95 | read_coverage_files(Files,RelevantIDs,[],CoverageData). | |
| 96 | ||
| 97 | read_coverage_files([],_IDs,DataSoFar,DataSoFar). | |
| 98 | read_coverage_files([Name-Path|Files],IDs,DataSoFar,CovData) :- | |
| 99 | member(Name,IDs), !, | |
| 100 | format('.... Reading ~w~n',[Name]), | |
| 101 | read_coverage_data(Path,Content), | |
| 102 | % coverage data should already be sorted, only merge-step | |
| 103 | format(' .... Merging Coverage Lists~n',[]), | |
| 104 | merge(DataSoFar,Content,AppendedData), | |
| 105 | format(' .... Merging Coverage Data~n',[]), | |
| 106 | merge_coverage_data(AppendedData,NewData), | |
| 107 | length(DataSoFar,L1), length(NewData,L2), L is L2-L1, | |
| 108 | format(' .... ~w tags in old, ~w tags in new, ~w difference~n',[L1,L2,L]), | |
| 109 | garbage_collect, | |
| 110 | read_coverage_files(Files,IDs,NewData,CovData). | |
| 111 | read_coverage_files([_|Files],IDs,DataSoFar,CovData) :- | |
| 112 | read_coverage_files(Files,IDs,DataSoFar,CovData). | |
| 113 | ||
| 114 | merge_coverage_data([],[]). | |
| 115 | merge_coverage_data([C],[C]). | |
| 116 | merge_coverage_data([H1,H2|T],Out) :- | |
| 117 | merge_coverage_counter(H1,H2,HMerged), !, | |
| 118 | merge_coverage_data([HMerged|T],Out). | |
| 119 | merge_coverage_data([H1,H2|T],[H1|Out]) :- | |
| 120 | merge_coverage_data([H2|T],Out). | |
| 121 | ||
| 122 | merge_coverage_counter(counter(File,PredSpec,ClauseNo,LineNr)-Tag1, | |
| 123 | counter(File,PredSpec,ClauseNo,LineNr)-Tag2, | |
| 124 | counter(File,PredSpec,ClauseNo,LineNr)-TagOut) :- | |
| 125 | merge_coverage_tags(Tag1,Tag2,TagOut). | |
| 126 | ||
| 127 | merge_coverage_tags(Tag1,Tag2,TagOut) :- | |
| 128 | Tag1 =.. [Functor1,Count1], Tag2 =.. [Functor2,Count2], !, | |
| 129 | Count3 is Count1 + Count2, | |
| 130 | (Functor1 = Functor2 | |
| 131 | -> TagOut =.. [Functor1,Count3] | |
| 132 | ; TagOut =.. [nondet,Count3]). | |
| 133 | ||
| 134 | generate_report(Now,descriptions) :- !, | |
| 135 | ajoin(['./coverage_reports/html/descriptions/descriptions-',Now,'.html'],FilenameHTML), | |
| 136 | ajoin(['./coverage_reports/tex/descriptions/descriptions-',Now,'.tex'],FilenameTEX), | |
| 137 | gen_pltables_descriptions_table(descriptionstable, [headline('Module Descriptions')], | |
| 138 | [kernel, interpreter]), | |
| 139 | tables_to_html([descriptionstable], FilenameHTML), | |
| 140 | tables_to_latex([descriptionstable], FilenameTEX). | |
| 141 | ||
| 142 | generate_report(Now,Keyword) :- | |
| 143 | format('Generating coverage report for keyword: ~w~n',[Keyword]), | |
| 144 | relevant_categories(Keyword,Categories), | |
| 145 | load_coverage_files(Categories,CoverageInfo), | |
| 146 | % store coverage data of certain keywords, i.e. | |
| 147 | % to generate units-and-laws report by reading the units and the laws reports | |
| 148 | % and merging them | |
| 149 | write_coverage_data(Keyword,CoverageInfo), | |
| 150 | get_file_coverage_info(CoverageInfo,FinalCoverageInfo), | |
| 151 | atom_header(Keyword,Header), | |
| 152 | ajoin(['./coverage_reports/html/',Keyword,'/',Keyword,'-',Now,'.html'],FilenameHTML), | |
| 153 | ajoin(['./coverage_reports/tex/',Keyword,'/',Keyword,'-',Now,'.html'],FilenameTEX), | |
| 154 | ajoin(['./coverage_reports/xml/',Keyword,'/',Keyword,'-',Now,'.xml'],FilenameXML), | |
| 155 | ajoin(['./coverage_reports/color/',Keyword,'/'],ColorizedPath), | |
| 156 | ajoin(['../../color/',Keyword,'/'],ColorizedURL), | |
| 157 | ajoin(['./coverage_reports/emma/',Keyword,'.xml'],FilenameEmma), | |
| 158 | export(FinalCoverageInfo,Header,FilenameHTML,FilenameTEX,FilenameXML,ColorizedPath,ColorizedURL,FilenameEmma). | |
| 159 | ||
| 160 | export(Info,Header,FilenameHTML,FilenameTEX,FilenameXML,ColorizedPath,ColorizedURL,EmmaPath) :- | |
| 161 | write('colorising source files line by line'), nl, full_flush, | |
| 162 | colorize_source_files(Info, ColorizedPath), | |
| 163 | write('colorising source files line by line done'), nl, full_flush, | |
| 164 | write('generation coverage report tables'), nl, full_flush, | |
| 165 | gen_pltables_coverage_rows(Info, [headline(Header)],[kernel,interpreter],ColorizedURL), | |
| 166 | write('generation coverage report tables done'), nl, full_flush, | |
| 167 | write('exporting tables to html, tex and xml'), nl, full_flush, | |
| 168 | export_tables(FilenameHTML,FilenameTEX,FilenameXML), | |
| 169 | write('exporting tables to html, tex and xml done'), nl, full_flush, | |
| 170 | write('exporting coverage data to emma'), nl, full_flush, | |
| 171 | export_emma(EmmaPath), | |
| 172 | write('exporting coverage data to emma done'), nl, full_flush. | |
| 173 | ||
| 174 | % from old prob_cov.pl - now ported to new table module | |
| 175 | pci :- print_coverage_info. | |
| 176 | pci(X) :- print_coverage_info(X). | |
| 177 | hci :- | |
| 178 | get_file_coverage_info(Info), | |
| 179 | gen_pltables_coverage_rows(Info, [], [kernel, interpreter]), | |
| 180 | export_tables_html_stream(user_output). | |
| 181 | hci_file :- | |
| 182 | get_file_coverage_info(Info), | |
| 183 | gen_pltables_coverage_rows(Info, [], [kernel, interpreter]), | |
| 184 | export_tables_html('out.html'). | |
| 185 | lci :- | |
| 186 | get_file_coverage_info(Info), | |
| 187 | gen_pltables_coverage_rows(Info, [], [kernel, interpreter]), | |
| 188 | export_tables_latex_stream(user_output). | |
| 189 | lci_file :- | |
| 190 | get_file_coverage_info(Info), | |
| 191 | gen_pltables_coverage_rows(Info, [], [kernel, interpreter]), | |
| 192 | export_tables_latex('out.tex'). |