EXSWHTEC-223 - Implement HIP API coverage tool (#98)

- Upload the initial version of HIP API coverage tool
- Add argument to fetch path to the HIP/include directory
Within the new repository structure, HIP tests are separated from the HIP headers. Added parameter to the executable used to pass the path to the HIP/include directory.
- Add tracking of test cases via doxygen comments
- Add test cases to the HTML report
- Adjust table size for HIP API test cases
- Remove style class from the empty row in test cases table
- Create TestCaseOccurrence to display more information about found Test Cases
- Change the name of table columns to differentiate information
- Remove duplicated path to the hiprtc.h file
- Add newline at the end of file
- Add newline at the end of makefile and coverage.css
Этот коммит содержится в:
milos-mozetic
2023-03-02 07:59:30 +01:00
коммит произвёл GitHub
родитель 12fb9350ad
Коммит dc93a4e6cd
17 изменённых файлов: 1688 добавлений и 0 удалений
+38
Просмотреть файл
@@ -0,0 +1,38 @@
# Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
CC=g++
CPPFLAGS=-std=c++17
SRC=mainCoverage.cpp hipAPI.cpp hipAPIGroup.cpp reportGenerators.cpp hipAPICoverageUtils.cpp
OBJ=generateHipAPICoverage
default_target: all
.PHONY : default_target
all: ${SRC}
${CC} ${CPPFLAGS} $^ -o ${OBJ}
clean:
rm ${OBJ}
rm *.xml
rm -r ./coverageReportHTML/testModules
rm -r ./coverageReportHTML/testAPIs
rm ./coverageReportHTML/*.html
.PHONY : clean
Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 141 B

+227
Просмотреть файл
@@ -0,0 +1,227 @@
/* All views: initial background and text color */
body
{
color: #000000;
background-color: #FFFFFF;
}
/* All views: standard link format*/
a:link
{
color: #284FA8;
text-decoration: underline;
}
/* All views: standard link - activated format */
a:active
{
color: #FF0040;
text-decoration: underline;
}
/* All views: main title format */
td.title
{
text-align: center;
padding-bottom: 10px;
font-family: sans-serif;
font-size: 20pt;
font-style: italic;
font-weight: bold;
}
/* All views: header item format */
td.headerItem
{
text-align: right;
padding-right: 6px;
font-family: sans-serif;
font-weight: bold;
vertical-align: top;
white-space: nowrap;
}
/* All views: header item value format */
td.headerValue
{
text-align: left;
color: #284FA8;
font-family: sans-serif;
font-weight: bold;
}
/* All views: header item coverage table heading */
td.headerCovTableHead
{
text-align: center;
padding-right: 6px;
padding-left: 6px;
padding-bottom: 0px;
font-family: sans-serif;
font-size: 80%;
white-space: nowrap;
}
/* All views: header item coverage table entry */
td.headerCovTableEntry
{
text-align: center;
color: #284FA8;
font-family: sans-serif;
font-weight: bold;
white-space: nowrap;
padding-left: 6px;
padding-right: 6px;
background-color: #DAE7FE;
}
/* All views: header item coverage table entry for high coverage rate */
td.headerCovTableEntryHi
{
text-align: center;
color: #000000;
font-family: sans-serif;
font-weight: bold;
white-space: nowrap;
padding-left: 12px;
padding-right: 4px;
background-color: #77DD77;
}
/* All views: header item coverage table entry for medium coverage rate */
td.headerCovTableEntryMed
{
text-align: center;
color: #000000;
font-family: sans-serif;
font-weight: bold;
white-space: nowrap;
padding-left: 12px;
padding-right: 4px;
background-color: #E9EC6B;
}
/* All views: header item coverage table entry for ow coverage rate */
td.headerCovTableEntryLo
{
text-align: center;
color: #000000;
font-family: sans-serif;
font-weight: bold;
white-space: nowrap;
padding-left: 12px;
padding-right: 4px;
background-color: #E66360;
}
/* All views: color of horizontal ruler */
td.ruler
{
background-color: #6688D4;
}
/* All views: version string format */
td.versionInfo
{
text-align: center;
padding-top: 2px;
font-family: sans-serif;
font-style: italic;
}
/* Directory view/File view (all)/Test case descriptions:
table headline format */
td.tableHead
{
text-align: center;
color: #FFFFFF;
background-color: #6688D4;
font-family: sans-serif;
font-weight: bold;
white-space: nowrap;
padding-left: 4px;
padding-right: 4px;
word-break: break-all;
}
/* Directory view/File view (all): filename entry format */
td.coverFile
{
text-align: left;
padding-left: 10px;
padding-right: 20px;
color: #284FA8;
background-color: #DAE7FE;
font-family: monospace;
}
/* Directory view/File view (all): bar-graph entry format*/
td.coverBar
{
padding-left: 10px;
padding-right: 10px;
background-color: #DAE7FE;
}
/* Directory view/File view (all): bar-graph outline color */
td.coverBarOutline
{
background-color: #000000;
}
/* Directory view/File view (all): line count entry for files with
high coverage rate */
td.coverNumHi
{
text-align: center;
padding-left: 10px;
padding-right: 10px;
background-color: #77DD77;
white-space: nowrap;
font-family: sans-serif;
}
/* Directory view/File view (all): line count entry for files with
medium coverage rate */
td.coverNumMed
{
text-align: center;
padding-left: 10px;
padding-right: 10px;
background-color: #E9EC6B;
white-space: nowrap;
font-family: sans-serif;
}
/* Directory view/File view (all): line count entry for files with
low coverage rate */
td.coverNumLo
{
text-align: center;
padding-left: 10px;
padding-right: 10px;
background-color: #E66360;
white-space: nowrap;
font-family: sans-serif;
}
/* File view (all): "show/hide details" link format */
a.detail:link
{
color: #B8D0FF;
font-size:80%;
}
/* File view (all): "show/hide details" link - visited format */
a.detail:visited
{
color: #B8D0FF;
font-size:80%;
}
/* File view (all): "show/hide details" link - activated format */
a.detail:active
{
color: #FFFFFF;
font-size:80%;
}
Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 141 B

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 167 B

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 141 B

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 141 B

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 117 B

+222
Просмотреть файл
@@ -0,0 +1,222 @@
/*
Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "hipAPI.h"
FileOccurrence::FileOccurrence(std::string file_name, int line_number):
file_name{file_name}, line_number{line_number} {}
TestCaseOccurrence::TestCaseOccurrence(std::string test_case_name, std::string file_name, int line_number):
FileOccurrence{file_name, line_number}, test_case_name{test_case_name} {}
bool operator==(const HipAPI& l_hip_api, const HipAPI& r_hip_api) {
return l_hip_api.api_name == r_hip_api.api_name;
}
bool operator<(const HipAPI& l_hip_api, const HipAPI& r_hip_api) {
return l_hip_api.api_name < r_hip_api.api_name;
}
HipAPI::HipAPI(std::string api_name, bool deprecated_flag, std::string api_group_name):
api_name{api_name}, deprecated{deprecated_flag}, api_group_name{api_group_name} {}
std::string HipAPI::getName() const {
return api_name;
}
std::string HipAPI::getGroupName() const {
return api_group_name;
}
int HipAPI::getNumberOfCalls() const {
return file_occurrences.size();
}
int HipAPI::getNumberOfTestCases() const {
return test_cases.size();
}
void HipAPI::addFileOccurrence(FileOccurrence file_occurrence) {
file_occurrences.push_back(file_occurrence);
}
void HipAPI::addTestCase(TestCaseOccurrence test_case) {
test_cases.push_back(test_case);
}
bool HipAPI::isDeprecated() const
{
return deprecated;
}
std::string HipAPI::getBasicStatsXML() const
{
std::stringstream xml_node;
xml_node << "\t\t<HIP-API>\n";
if (!deprecated) {
xml_node << "\t\t\t<NAME>" << api_name << "</NAME>\n";
} else {
xml_node << "\t\t\t<NAME>" << "[DEPRECATED] " << api_name << "</NAME>\n";
}
if (!file_occurrences.empty()) {
xml_node << "\t\t\t<NUMBER-OF-API-CALLS>" << file_occurrences.size() << "</NUMBER-OF-API-CALLS>\n";
xml_node << "\t\t\t<FILE-OCCURRENCES>\n";
for (auto const& file_occurrence: file_occurrences) {
xml_node << "\t\t\t\t<FILE-OCCURRENCE>" << file_occurrence.file_name << ":" << file_occurrence.line_number << "</FILE-OCCURRENCE>\n";
}
xml_node << "\t\t\t</FILE-OCCURRENCES>\n";
}
xml_node << "\t\t</HIP-API>\n";
return xml_node.str();
}
std::string HipAPI::createHTMLReport() const {
std::stringstream html_report;
std::string one_tab{"\n\t"};
std::string two_tabs{"\n\t\t"};
std::string three_tabs{"\n\t\t\t"};
std::string four_tabs{"\n\t\t\t\t"};
std::string five_tabs{"\n\t\t\t\t\t"};
std::string six_tabs{"\n\t\t\t\t\t\t"};
html_report << "<html lang=\"en\">";
html_report << "<head>" << one_tab << "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">";
html_report << one_tab << "<title>" << api_name << " Coverage report</title>" << one_tab << "<link rel=\"stylesheet\" type=\"text/css\" href=\"../resources/coverage.css\">" << one_tab<< "</head>";
html_report << one_tab << "<body>" << one_tab << "<table width=\"100%\" border=0 cellspacing=0 cellpadding=0>";
html_report << two_tabs << "<tr><td class=\"title\">" << api_name << " Coverage report</td></tr>";
html_report << two_tabs << "<tr><td class=\"ruler\"><img src=\"../resources/glass.png\" width=3 height=3></td></tr>\n";
html_report << two_tabs << "<tr>" << three_tabs << "<td width=\"100%\">" << four_tabs << "<table cellpading=1 border=0 width=\"100%\"";
html_report << five_tabs << "<tr>";
html_report << six_tabs << "<td width=\"70%\"</td>";
html_report << six_tabs << "<td width=\"10%\"></td>";
html_report << six_tabs << "<td width=\"10%\"></td>";
html_report << six_tabs << "<td width=\"10%\"></td>";
html_report << five_tabs << "</tr>";
html_report << five_tabs << "<tr>";
html_report << six_tabs << "<td class=\"headerItem\">Group:</td>";
html_report << six_tabs << "<td class=\"headerValue\" colspan=2>" << api_group_name << "</td>";
html_report << six_tabs << "<td></td>";
html_report << five_tabs << "</tr>";
html_report << five_tabs << "<tr>";
html_report << six_tabs << "<td class=\"headerItem\">Calls within test source files:</td>";
html_report << six_tabs << "<td class=\"headerCovTableEntry\">" << file_occurrences.size() << "</td>";
html_report << six_tabs << "<td></td>";
html_report << six_tabs << "<td></td>";
html_report << five_tabs << "</tr>";
html_report << five_tabs << "<tr>";
html_report << six_tabs << "<td class=\"headerItem\">Number of test cases:</td>";
html_report << six_tabs << "<td class=\"headerCovTableEntry\">" << test_cases.size() << "</td>";
html_report << six_tabs << "<td></td>";
html_report << six_tabs << "<td></td>";
html_report << five_tabs << "</tr>";
html_report << five_tabs << "<tr><td><img src=\"../resources/glass.png\" width=3 height=3></td></tr>";
html_report << four_tabs << "</table>";
html_report << three_tabs << "</td>";
html_report << two_tabs << "</tr>";
html_report << two_tabs << "<tr><td class=\"ruler\"><img src=\"../resources/glass.png\" width=3 height=3></td></tr>\n";
html_report << one_tab << "</table>";
html_report << one_tab << "<center>";
// Add info about test cases
html_report << one_tab << "<table width=\"70%\" cellpadding=1 cellspacing=1 border=0>";
if (!test_cases.empty()) {
html_report << two_tabs << "<tr>";
html_report << three_tabs << "<td width=\"20%\"><br></td>";
html_report << three_tabs << "<td width=\"60%\"><br></td>";
html_report << three_tabs << "<td width=\"20%\"><br></td>";
html_report << two_tabs << "</tr>";
html_report << two_tabs << "<tr>";
html_report << three_tabs << "<td class=\"tableHead\">Test case ID</td>";
html_report << three_tabs << "<td class=\"tableHead\">Test case occurrence in file</td>";
html_report << three_tabs << "<td class=\"tableHead\">Line number</td>";
html_report << two_tabs << "</tr>";
for (auto const& test_case: test_cases) {
html_report << two_tabs << "<tr>";
html_report << three_tabs << "<td class=\"coverFile\">" << test_case.test_case_name << "</td>";
html_report << three_tabs << "<td class=\"coverFile\">" << test_case.file_name << "</td>";
html_report << three_tabs << "<td class=\"headerCovTableEntry\">" << test_case.line_number << "</td>";
html_report << two_tabs << "</tr>";
}
} else {
html_report << two_tabs << "<tr>";
html_report << three_tabs << "<td class=\"headerItem\" style=\"text-align:center\"><br>There are no test cases detected within doxygen comments.</td>";
html_report << two_tabs << "</tr>";
}
html_report << one_tab << "</table>";
html_report << one_tab << "<br>";
html_report << one_tab << "<table width=\"100%\" border=0 cellspacing=0 cellpadding=0>";
html_report << two_tabs << "<tr><td class=\"ruler\"><img src=\"../resources/glass.png\" width=3 height=3></td></tr>";
html_report << one_tab << "</table>";
// Add info about API occurrences in the test files.
html_report << one_tab << "<table width=\"50%\" cellpadding=1 cellspacing=1 border=0>";
if (!file_occurrences.empty()) {
html_report << two_tabs << "<tr>";
html_report << three_tabs << "<td width=\"80%\"><br></td>";
html_report << three_tabs << "<td width=\"20%\"><br></td>";
html_report << two_tabs << "</tr>";
html_report << two_tabs << "<tr>";
html_report << three_tabs << "<td class=\"tableHead\">API occurrence in file</td>";
html_report << three_tabs << "<td class=\"tableHead\">Line number</td>";
html_report << two_tabs << "</tr>";
for (auto const& file_occurrence: file_occurrences) {
html_report << two_tabs << "<tr>";
html_report << three_tabs << "<td class=\"coverFile\">" << file_occurrence.file_name << "</td>";
html_report << three_tabs << "<td class=\"headerCovTableEntry\">" << file_occurrence.line_number << "</td>";
html_report << two_tabs << "</tr>";
}
} else {
html_report << two_tabs << "<tr>";
html_report << three_tabs << "<td class=\"headerItem\" style=\"text-align:center\"><br>There are no occurrences within test source files.</td>";
html_report << two_tabs << "</tr>";
}
html_report << one_tab << "</table>";
html_report << one_tab << "</center>";
html_report << one_tab << "<br>";
html_report << one_tab << "<table width=\"100%\" border=0 cellspacing=0 cellpadding=0>";
html_report << two_tabs << "<tr><td class=\"ruler\"><img src=\"../resources/glass.png\" width=3 height=3></td></tr>";
time_t now{time(nullptr)};
std::string date{asctime(gmtime(&now))};
html_report << two_tabs << "<tr><td class=\"versionInfo\">Generated: " << date;
html_report << two_tabs << " UTC</td></tr>";
html_report << one_tab << "</table>";
html_report << one_tab << "<br>";
html_report << "\n</body>\n</html>";
return html_report.str();
}
+75
Просмотреть файл
@@ -0,0 +1,75 @@
/*
Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <iostream>
#include <vector>
#include <sstream>
/*
Helper class used to store information in what file has HIP API been detected,
and on what line of code in that file.
*/
class FileOccurrence {
public:
std::string file_name;
int line_number;
FileOccurrence(std::string file_name, int line_number);
};
/*
Helper class used to store information in what file has the API Test Case been detected,
and on what line of code in that file.
*/
class TestCaseOccurrence : public FileOccurrence {
public:
std::string test_case_name;
TestCaseOccurrence(std::string test_case_name, std::string file_name, int line_number);
};
/*
Class used to store infromation about each HIP API. All information
is related to the API name, number of calls from test .cc files,
and its status of deprecation.
*/
class HipAPI {
friend bool operator==(const HipAPI& l_hip_api, const HipAPI& r_hip_api);
friend bool operator<(const HipAPI& l_hip_api, const HipAPI& r_hip_api);
public:
HipAPI(std::string api_name, bool deprecated_flag, std::string api_group_name);
std::string getName() const;
std::string getGroupName() const;
int getNumberOfCalls() const;
int getNumberOfTestCases() const;
void addFileOccurrence(FileOccurrence file_occurence);
void addTestCase(TestCaseOccurrence test_case);
bool isDeprecated() const;
std::string getBasicStatsXML() const;
std::string createHTMLReport() const;
private:
std::string api_name;
int number_of_calls;
bool deprecated;
std::string api_group_name;
std::vector<FileOccurrence> file_occurrences;
std::vector<TestCaseOccurrence> test_cases;
};
+284
Просмотреть файл
@@ -0,0 +1,284 @@
/*
Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "hipAPICoverageUtils.h"
/*
Used to find all HIP API occurrences within the passed test .cc files.
Occurrence is detected when the HIP API is called in several scenarios.
- API Call with assertion, e.g. REQUIRE(hipAPI());
- API call with assignment, e.g. result = hipAPI();
- API call with parameter, e.g. ASSERT_EQUAL(hipSuccess, hipGetDevice(&deviceId));
*/
void findAPICallInFile(HipAPI& hip_api, std::string test_module_file) {
std::fstream test_module_file_handler;
test_module_file_handler.open(test_module_file);
int line_number{0};
std::string line;
/*
Closed brackets might be in another line, if the API
call is multiline.
*/
std::string api_call_with_assert{"(" + hip_api.getName() + "("};
std::string api_call_with_assignment{"= " + hip_api.getName() + "("};
std::string api_call_with_parameter{", " + hip_api.getName() + "("};
while (std::getline(test_module_file_handler, line)) {
++line_number;
if ((line.find(api_call_with_assert) != std::string::npos) ||
(line.find(api_call_with_assignment) != std::string::npos) ||
(line.find(api_call_with_parameter) != std::string::npos)) {
hip_api.addFileOccurrence(FileOccurrence(test_module_file, line_number));
}
}
test_module_file_handler.close();
}
/*
Used to find all HIP API test cases within the passed test .cc files.
Matching test case is detected when the HIP API in defined within doxygen comment.
*/
void findAPITestCaseInFile(HipAPI& hip_api, std::string test_module_file) {
std::fstream test_module_file_handler;
test_module_file_handler.open(test_module_file);
int line_number{0};
std::string line;
std::string add_group_definition{"@addtogroup"};
std::string ref_test_case{"@ref"};
std::string test_case_definition{"TEST_CASE("};
std::string current_api_name{"None"};
std::string test_case{"None"};
while (std::getline(test_module_file_handler, line)) {
++line_number;
if (line.find(add_group_definition) != std::string::npos) {
current_api_name = line.substr(line.find(add_group_definition) + 1);
current_api_name = current_api_name.substr(current_api_name.rfind(" ") + 1);
}
if (hip_api.getName() != current_api_name) {
continue;
}
if (line.find(ref_test_case) != std::string::npos) {
test_case = line.substr(line.rfind(" ") + 1);
hip_api.addTestCase(TestCaseOccurrence{test_case, test_module_file, line_number});
continue;
}
if (line.find(test_case_definition) != std::string::npos) {
test_case = line.substr(line.find("\"") + 1);
test_case = test_case.substr(0, test_case.find("\""));
hip_api.addTestCase(TestCaseOccurrence{test_case, test_module_file, line_number});
}
}
test_module_file_handler.close();
}
/*
Used to iterate through all passed test .cc files and search for passed
HIP API instance. This instance shall be used to update occurrences.
*/
void searchForAPI(HipAPI& hip_api, std::vector<std::string>& test_module_files) {
std::cout << "Searching for " << hip_api.getName() << " in test module files." << std::endl;
for (auto const& test_module_file: test_module_files) {
findAPICallInFile(hip_api, test_module_file);
findAPITestCaseInFile(hip_api, test_module_file);
}
}
/*
Used to extract all HIP APIs from the passed header file.
*/
std::vector<HipAPI> extractHipAPIs(std::string& hip_api_header_file,
std::vector<std::string>& api_group_names, bool start_groups) {
std::fstream hip_header_file_handler;
hip_header_file_handler.open(hip_api_header_file);
std::string line;
std::vector<HipAPI> hip_apis;
/*
If the HIP API is deprecated, it will be marked with
the following deprecation line in code.
*/
std::string deprecated_line{"DEPRECATED("};
/*
Each HIP API has prefix hip in the name. Groups are marked with @defgroup, and the
main group that shall be considered is HIP API. Before that group is defined, lines
of code shall not be considered.
*/
std::string hip_api_prefix{"hip"};
std::string group_definition{"@defgroup"};
std::string add_group_definition{"@addtogroup"};
std::string start_of_api_groups{"HIP API"};
std::string end_of_api_groups{"doxygen end HIP API"};
std::string end_group_definition{"@}"};
bool deprecated_flag{false};
bool api_group_names_start{start_groups};
std::vector<std::string> api_group_names_tracker{api_group_names};
int line_number{0};
while (std::getline(hip_header_file_handler, line)) {
++line_number;
// Declarations of the HIP APIs start after the HIP API group has been defined.
if ((line.find(group_definition) != std::string::npos || line.find(add_group_definition) != std::string::npos)
&& line.find(start_of_api_groups) != std::string::npos) {
api_group_names_start = true;
continue;
}
// If the API Groups have not started yet, go to the next file line.
if (!api_group_names_start) {
continue;
}
// If the end of HIP API group has been detected, break the loop.
if (line.find(end_of_api_groups) != std::string::npos) {
break;
}
/*
If the API is deprecated, raise a flag and go to the
next line where the API is declared.
*/
if (line.find(deprecated_line) != std::string::npos) {
std::getline(hip_header_file_handler, line);
++line_number;
deprecated_flag = true;
} else {
deprecated_flag = false;
}
if (line.find(group_definition) != std::string::npos) {
std::string group_name = line.substr(line.find(group_definition) + group_definition.length() + 1);
group_name = group_name.substr(group_name.find(' ') + 1);
api_group_names.push_back(group_name);
api_group_names_tracker.push_back(group_name);
}
else if (line.find(add_group_definition) != std::string::npos)
{
std::string group_name = line.substr(line.find(add_group_definition) + add_group_definition.length() + 1);
group_name = group_name.substr(group_name.find(' ') + 1);
api_group_names.push_back(group_name);
api_group_names_tracker.push_back(group_name);
}
/*
Possible case is that there are nested groups. While api_group_names
vector contains all detected groups, api_group_names_tracker is responsible
to track the last defined group, because of the nested cases.
*/
if (line.find(end_group_definition) != std::string::npos) {
api_group_names_tracker.pop_back();
}
/*
The line which contains HIP API declaration looks like:
hipError_t hipMalloc(void** ptr, size_t size);
The name of HIP API is found by following steps:
- Take the substring from the start to the first open bracket.
- Extract the name from that substring by finding the last "hip".
Avoid comments.
*/
if (line.find(hip_api_prefix) != std::string::npos &&
line.find("(") != std::string::npos &&
line.find(" ") != 0 &&
line.find(" *") != 0) {
std::string api_name_no_brackets{line.substr(0, line.find("("))};
/*
If there is no hip substring, then there is no valid API in that line.
*/
if (api_name_no_brackets.rfind(hip_api_prefix) == std::string::npos) {
continue;
}
/*
Extract the substring that starts from the last hip substring to the
end of that string (until the open bracket from the original string).
Remove all spaces if they exist in the parsed string, e.g.,
hipError_t hipDeviceSetLimit ( enum hipLimit_t limit, size_t value );.
*/
std::string api_name{api_name_no_brackets.substr(api_name_no_brackets.rfind(hip_api_prefix))};
api_name.erase(std::remove(api_name.begin(), api_name.end(), ' '), api_name.end());
if (!api_group_names_tracker.empty()) {
/*
If the API is not present in the global list of HIP APIs, add it.
*/
HipAPI hip_api{api_name, deprecated_flag, api_group_names_tracker.back()};
if(std::find(hip_apis.begin(), hip_apis.end(), hip_api) == hip_apis.end())
{
hip_apis.push_back(hip_api);
}
} else {
std::cout << "[SKIP_FROM_COV] Group not detected for \"" << api_name << "\" in file \""
<< hip_api_header_file << "\", line " << line_number << std::endl;
}
}
}
hip_header_file_handler.close();
return hip_apis;
}
/*
Used to extract test .cc files from the passed tests root directory.
Goes through all subdirectories and searches for .cc and .hh files for
HIP API invocations.
Implements BFS algorithm to avoid recursion.
*/
std::vector<std::string> extractTestModuleFiles(std::string& tests_root_directory)
{
std::vector<std::string> directory_queue;
directory_queue.push_back(tests_root_directory);
std::vector<std::string> test_module_files;
while (!directory_queue.empty()) {
std::string processed_entry = directory_queue.back();
directory_queue.pop_back();
for (const auto& entry: std::filesystem::directory_iterator(processed_entry)) {
if (std::filesystem::is_directory(entry.path())) {
directory_queue.push_back(entry.path());
} else {
if (entry.path().string().find(".cc") != std::string::npos ||
entry.path().string().find(".hh") != std::string::npos) {
test_module_files.push_back(entry.path());
}
}
}
}
return test_module_files;
}
std::string findAbsolutePathOfFile(std::string file_path)
{
return std::filesystem::canonical(std::filesystem::absolute(file_path));
}
+32
Просмотреть файл
@@ -0,0 +1,32 @@
/*
Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <fstream>
#include <filesystem>
#include "hipAPIGroup.h"
void findAPICallInFile(HipAPI& hip_api, std::string test_module_file);
void findAPITestCaseInFile(HipAPI& hip_api, std::string test_module_file);
void searchForAPI(HipAPI& hip_api, std::vector<std::string>& test_module_files);
std::vector<HipAPI> extractHipAPIs(std::string& hip_api_header_file, std::vector<std::string>& api_group_names, bool start_groups);
std::vector<std::string> extractTestModuleFiles(std::string& tests_root_directory);
std::string findAbsolutePathOfFile(std::string file_path);
+335
Просмотреть файл
@@ -0,0 +1,335 @@
/*
Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "hipAPIGroup.h"
bool operator==(const HipAPIGroup& l_hip_api_group, const HipAPIGroup& r_hip_api_group) {
return l_hip_api_group.group_name == r_hip_api_group.group_name;
}
HipAPIGroup::HipAPIGroup(std::string group_name, std::vector<HipAPI>& hip_apis):
group_name{group_name}, number_of_api_calls{0}, percentage_of_called_apis{0.f},
total_number_of_apis{0}, number_of_test_cases{0}
{
for (auto const& hip_api: hip_apis) {
if (hip_api.getGroupName() != group_name) {
continue;
}
if (hip_api.isDeprecated()) {
deprecated_apis.push_back(hip_api);
} else {
if (hip_api.getNumberOfCalls()) {
called_apis.push_back(hip_api);
} else {
not_called_apis.push_back(hip_api);
}
}
number_of_api_calls += hip_api.getNumberOfCalls();
number_of_test_cases += hip_api.getNumberOfTestCases();
}
total_number_of_apis = called_apis.size() + not_called_apis.size() + deprecated_apis.size();
if (not_called_apis.empty()) {
percentage_of_called_apis = 100.f;
} else {
percentage_of_called_apis = 100.f * called_apis.size() / (total_number_of_apis - deprecated_apis.size());
}
}
std::string HipAPIGroup::getName() const {
return group_name;
}
int HipAPIGroup::getTotalNumberOfAPIs() const {
return total_number_of_apis;
}
int HipAPIGroup::getTotalNumberOfCalls() const {
return number_of_api_calls;
}
int HipAPIGroup::getTotalNumberOfTestCases() const {
return number_of_test_cases;
}
int HipAPIGroup::getNumberOfCalledAPIs() const {
return called_apis.size();
}
int HipAPIGroup::getNumberOfNotCalledAPIs() const {
return not_called_apis.size();
}
int HipAPIGroup::getNumberOfDeprecatedAPIs() const {
return deprecated_apis.size();
}
float HipAPIGroup::getPercentageOfCalledAPIs() const {
return percentage_of_called_apis;
}
std::string HipAPIGroup::getBasicStatsXML() const {
std::stringstream xml_node;
std::string tag_name;
std::transform(group_name.begin(), group_name.end(), std::back_inserter(tag_name), ::toupper);
std::replace(tag_name.begin(), tag_name.end(), ' ', '-');
xml_node << "\n<" << tag_name << ">";
xml_node << "\n\t<COVERAGE-RESULTS>";
xml_node << "\n\t\t<TOTAL-NUMBER-OF-APIs>" << total_number_of_apis << "</TOTAL-NUMBER-OF-APIs>";
xml_node << "\n\t\t<TOTAL-NUMBER-OF-API-CALLS>" << number_of_api_calls << "</TOTAL-NUMBER-OF-API-CALLS>";
xml_node << "\n\t\t<CALLED-APIs>" << called_apis.size() << "</CALLED-APIs>";
xml_node << "\n\t\t<NOT-CALLED-APIs>" << not_called_apis.size() << "</NOT-CALLED-APIs>";
xml_node << "\n\t\t<DEPRECATED-APIs>" << deprecated_apis.size() << "</DEPRECATED-APIs>";
xml_node << "\n\t\t<COVERAGE-PERCENTAGE>" << percentage_of_called_apis << "%</COVERAGE-PERCENTAGE>";
xml_node << "\n\t</COVERAGE-RESULTS>";
if (!called_apis.empty()) {
xml_node << "\n\t<LIST-OF-CALLED-APIs>\n";
for (auto const& hip_api: called_apis) {
xml_node << hip_api.getBasicStatsXML();
}
xml_node << "\t</LIST-OF-CALLED-APIs>";
}
if (!not_called_apis.empty()) {
xml_node << "\n\t<LIST-OF-NOT-CALLED-APIs>\n";
for (auto const& hip_api: not_called_apis) {
xml_node << hip_api.getBasicStatsXML();
}
xml_node << "\t</LIST-OF-NOT-CALLED-APIs>";
}
if (!deprecated_apis.empty()) {
xml_node << "\n\t<DEPRECATED-APIs>\n";
for (auto const& hip_api: deprecated_apis) {
xml_node << hip_api.getBasicStatsXML();
}
xml_node << "\t</DEPRECATED-APIs>";
}
xml_node << "\n</" << tag_name << ">";
return xml_node.str();
}
std::string HipAPIGroup::getBasicStatsHTML() const
{
std::stringstream html_object;
std::string two_tabs{"\n\t\t"};
std::string three_tabs{"\n\t\t\t"};
std::string four_tabs{"\n\t\t\t\t"};
std::string five_tabs{"\n\t\t\t\t\t"};
// Determine font class from coverage.css and image for color bar.
std::string font_class;
std::string color_bar;
if (percentage_of_called_apis < 40.f) {
font_class = "coverNumLo";
color_bar = "resources/ruby.png";
} else if (percentage_of_called_apis < 80.f) {
font_class = "coverNumMed";
color_bar = "resources/amber.png";
} else {
font_class = "coverNumHi";
color_bar = "resources/emerald.png";
}
html_object << two_tabs << "<tr>";
html_object << three_tabs << "<td class=\"coverFile\"><a href=\"testModules/" << group_name << ".html\">" << group_name << "</a></td>";
html_object << three_tabs << "<td class=\"" << font_class << "\">" << total_number_of_apis << "</td>";
html_object << three_tabs << "<td class=\"" << font_class << "\">" << number_of_api_calls << "</td>";
html_object << three_tabs << "<td class=\"" << font_class << "\">" << number_of_test_cases << "</td>";
html_object << three_tabs << "<td class=\"" << font_class << "\">" << called_apis.size() << "</td>";
html_object << three_tabs << "<td class=\"" << font_class << "\">" << not_called_apis.size() << "</td>";
html_object << three_tabs << "<td class=\"" << font_class << "\">" << deprecated_apis.size() << "</td>";
html_object << three_tabs << "<td class=\"" << font_class << "\">" << std::fixed << std::setprecision(2) << percentage_of_called_apis << "%</td>";
html_object << three_tabs << "<td class=\"coverBar\" align=\"center\">";
html_object << four_tabs << "<table border=0 cellspacing=0 cellpadding=1>";
html_object << five_tabs << "<tr><td class=\"coverBarOutline\"><img src=\"";
html_object << color_bar << "\" width=" << percentage_of_called_apis<< " height=10 alt=\"" << percentage_of_called_apis << "%\">";
html_object << "<img src=\"resources/snow.png\" width=" << 100.f - percentage_of_called_apis << " height=10 alt=\"" << percentage_of_called_apis << "\"></td></tr></table>";
html_object << four_tabs << "</td>";
html_object << three_tabs << "</tr>";
return html_object.str();
}
std::string HipAPIGroup::createHTMLReport() const
{
std::stringstream html_report;
std::string one_tab{"\n\t"};
std::string two_tabs{"\n\t\t"};
std::string three_tabs{"\n\t\t\t"};
std::string four_tabs{"\n\t\t\t\t"};
std::string five_tabs{"\n\t\t\t\t\t"};
std::string six_tabs{"\n\t\t\t\t\t\t"};
html_report << "<html lang=\"en\">";
html_report << "<head>" << one_tab << "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">";
html_report << one_tab << "<title>" << group_name << " Coverage report</title>";
html_report << one_tab << "<link rel=\"stylesheet\" type=\"text/css\" href=\"../resources/coverage.css\">" << one_tab<< "</head>";
html_report << one_tab << "<body>" << one_tab << "<table width=\"100%\" border=0 cellspacing=0 cellpadding=0>";
html_report << two_tabs << "<tr><td class=\"title\">" << group_name << " Coverage report</td></tr>";
html_report << two_tabs << "<tr><td class=\"ruler\"><img src=\"../resources/glass.png\" width=3 height=3></td></tr>\n";
html_report << two_tabs << "<tr>" << three_tabs << "<td width=\"100%\">" << four_tabs << "<table cellpading=1 border=0 width=\"100%\"";
html_report << five_tabs << "<tr>";
html_report << six_tabs << "<td width=\"70%\"></td>";
html_report << six_tabs << "<td width=\"10%\" class=\"headerCovTableHead\">Value</td>";
html_report << six_tabs << "<td width=\"20%\"></td>";
html_report << five_tabs << "</tr>";
html_report << five_tabs << "<tr>";
html_report << six_tabs << "<td class=\"headerItem\">Total number of detected HIP APIs:</td>";
html_report << six_tabs << "<td class=\"headerCovTableEntry\">" << total_number_of_apis << "</td>";
html_report << six_tabs << "<td></td>";
html_report << five_tabs << "</tr>";
html_report << five_tabs << "<tr>";
html_report << six_tabs << "<td class=\"headerItem\">HIP API calls within test source files:</td>";
html_report << six_tabs << "<td class=\"headerCovTableEntry\">" << number_of_api_calls << "</td>";
html_report << six_tabs << "<td></td>";
html_report << five_tabs << "</tr>";
html_report << five_tabs << "<tr>";
html_report << six_tabs << "<td class=\"headerItem\">Total number of test cases:</td>";
html_report << six_tabs << "<td class=\"headerCovTableEntry\">" << number_of_test_cases << "</td>";
html_report << six_tabs << "<td></td>";
html_report << five_tabs << "</tr>";
html_report << five_tabs << "<tr>";
html_report << six_tabs << "<td class=\"headerItem\">HIP APIs that are called at least once:</td>";
html_report << six_tabs << "<td class=\"headerCovTableEntry\">" << called_apis.size() << "</td>";
html_report << six_tabs << "<td></td>";
html_report << five_tabs << "</tr>";
html_report << five_tabs << "<tr>";
html_report << six_tabs << "<td class=\"headerItem\">HIP APIs that are not called at all:</td>";
html_report << six_tabs << "<td class=\"headerCovTableEntry\">" << not_called_apis.size() << "</td>";
html_report << six_tabs << "<td></td>";
html_report << five_tabs << "</tr>";
html_report << five_tabs << "<tr>";
html_report << six_tabs << "<td class=\"headerItem\">HIP APIs that are marked as deprecated:</td>";
html_report << six_tabs << "<td class=\"headerCovTableEntry\">" << deprecated_apis.size() << "</td>";
html_report << six_tabs << "<td></td>";
html_report << five_tabs << "</tr>";
// Determine font class from coverage.css file based on coverage percentage.
std::string font_class;
if (percentage_of_called_apis < 40.f) {
font_class = "headerCovTableEntryLo";
} else if (percentage_of_called_apis < 80.f) {
font_class = "headerCovTableEntryMed";
} else {
font_class = "headerCovTableEntryHi";
}
html_report << five_tabs << "<tr>";
html_report << six_tabs << "<td class=\"headerItem\">Test coverage by implemented tests for the HIP APIs:</td>";
html_report << six_tabs << "<td class=\"" << font_class << "\">" << std::fixed << std::setprecision(2) << percentage_of_called_apis << "%</td>";
html_report << six_tabs << "<td></td>";
html_report << five_tabs << "</tr>";
html_report << five_tabs << "<tr><td><img src=\"../resources/glass.png\" width=3 height=3></td></tr>";
html_report << four_tabs << "</table>";
html_report << three_tabs << "</td>";
html_report << two_tabs << "</tr>";
html_report << two_tabs << "<tr><td class=\"ruler\"><img src=\"../resources/glass.png\" width=3 height=3></td></tr>\n";
html_report << one_tab << "</table>";
// Add info about Test module APIs.
html_report << one_tab << "<center>";
html_report << one_tab << "<table width=\"60%\" cellpadding=1 cellspacing=1 border=0>";
html_report << two_tabs << "<tr>";
html_report << three_tabs << "<td width=\"33%\"><br></td>";
html_report << three_tabs << "<td width=\"33%\"</td>";
html_report << three_tabs << "<td width=\"33%\"></td>";
html_report << two_tabs << "</tr>";
html_report << two_tabs << "<tr>";
html_report << three_tabs << "<td style=\"vertical-align:top\">";
html_report << four_tabs << "<table width=\"100%\" cellpadding=1 cellspacing=1 border=0>";
html_report << five_tabs << "<tr>";
html_report << six_tabs << "<td class=\"tableHead\">Called APIs</td>";
html_report << five_tabs << "</tr>";
for (auto const& hip_api: called_apis) {
html_report << five_tabs << "<tr>";
html_report << six_tabs << "<td class=\"coverFile\"><a href=\"../testAPIs/" << hip_api.getName() << ".html\">" << hip_api.getName() << "</a></td>";
html_report << five_tabs << "</tr>";
}
html_report << four_tabs << "</table>";
html_report << three_tabs << "</td>";
html_report << three_tabs << "<td style=\"vertical-align:top\">";
html_report << four_tabs << "<table width=\"100%\" cellpadding=1 cellspacing=1 border=0>";
html_report << five_tabs << "<tr>";
html_report << six_tabs << "<td class=\"tableHead\">Not called APIs</td>";
html_report << five_tabs << "</tr>";
for (auto const& hip_api: not_called_apis) {
html_report << five_tabs << "<tr>";
html_report << six_tabs << "<td class=\"coverFile\"><a href=\"../testAPIs/" << hip_api.getName() << ".html\">" << hip_api.getName() << "</a></td>";
html_report << five_tabs << "</tr>";
}
html_report << four_tabs << "</table>";
html_report << three_tabs << "</td>";
html_report << three_tabs << "<td style=\"vertical-align:top\">";
html_report << four_tabs << "<table width=\"100%\" cellpadding=1 cellspacing=1 border=0>";
html_report << five_tabs << "<tr>";
html_report << six_tabs << "<td class=\"tableHead\">Deprecated APIs</td>";
html_report << five_tabs << "</tr>";
for (auto const& hip_api: deprecated_apis) {
html_report << five_tabs << "<tr>";
html_report << six_tabs << "<td class=\"coverFile\"><a href=\"../testAPIs/" << hip_api.getName() << ".html\">" << hip_api.getName() << "</a></td>";
html_report << five_tabs << "</tr>";
}
html_report << four_tabs << "</table>";
html_report << three_tabs << "</td>";
html_report << two_tabs << "</tr>";
html_report << one_tab << "</table>";
html_report << one_tab << "</center>";
html_report << one_tab << "<br>";
html_report << one_tab << "<table width=\"100%\" border=0 cellspacing=0 cellpadding=0>";
html_report << two_tabs << "<tr><td class=\"ruler\"><img src=\"../resources/glass.png\" width=3 height=3></td></tr>";
time_t now{time(nullptr)};
std::string date{asctime(gmtime(&now))};
html_report << two_tabs << "<tr><td class=\"versionInfo\">Generated: " << date;
html_report << two_tabs << " UTC</td></tr>";
html_report << one_tab << "</table>";
html_report << one_tab << "<br>";
html_report << "\n</body>\n</html>";
return html_report.str();
}
+53
Просмотреть файл
@@ -0,0 +1,53 @@
/*
Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "hipAPI.h"
#include <algorithm>
#include <iomanip>
class HipAPIGroup{
friend bool operator==(const HipAPIGroup& l_hip_api_group, const HipAPIGroup& r_hip_api_group);
public:
HipAPIGroup(std::string group_name, std::vector<HipAPI>& hip_apis);
std::string getName() const;
int getTotalNumberOfAPIs() const;
int getTotalNumberOfCalls() const;
int getTotalNumberOfTestCases() const;
int getNumberOfCalledAPIs() const;
int getNumberOfNotCalledAPIs() const;
int getNumberOfDeprecatedAPIs() const;
float getPercentageOfCalledAPIs() const;
std::string getBasicStatsXML() const;
std::string getBasicStatsHTML() const;
std::string createHTMLReport() const;
private:
std::string group_name;
int total_number_of_apis;
int number_of_api_calls;
float percentage_of_called_apis;
int number_of_test_cases;
std::string parent_group_name;
std::vector<HipAPI> called_apis;
std::vector<HipAPI> not_called_apis;
std::vector<HipAPI> deprecated_apis;
};
+74
Просмотреть файл
@@ -0,0 +1,74 @@
/*
Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "reportGenerators.h"
int main(int argc, char** argv)
{
if (argc != 2) {
std::cout << "Please provide the path to the cloned HIP/include/ directory as an argument! Only one argument supported." << std::endl;
std::cout << "\tExample: ./generateHipAPICoverage /workspace/user1/HIP/include/" << std::endl;
return -1;
}
std::string hip_include_path = argv[1];
/*
Relative paths to all needed files, as it is expected that the application
is called from the HIP/tests/catch/coverage directory.
*/
std::string hip_api_header_file{findAbsolutePathOfFile(hip_include_path + "/hip/hip_runtime_api.h")};
std::string hip_rtc_header_file{findAbsolutePathOfFile(hip_include_path + "/hip/hiprtc.h")};
std::string tests_root_directory{findAbsolutePathOfFile("../../catch")};
std::vector<std::string> api_group_names;
// Extract all HIP API declarations from the HIP API header file.
std::vector<HipAPI> hip_apis{extractHipAPIs(hip_api_header_file, api_group_names, false)};
std::cout << "Number of detected HIP APIs from " << hip_api_header_file << ": " << hip_apis.size() << std::endl;
std::vector<HipAPI> hip_rtc_apis{extractHipAPIs(hip_rtc_header_file, api_group_names, true)};
std::cout << "Number of detected HIP APIs from " << hip_rtc_header_file << ": " << hip_rtc_apis.size() << std::endl;
hip_apis.insert(hip_apis.end(), hip_rtc_apis.begin(), hip_rtc_apis.end());
// Extract all test module .cc files that shall be used for API searching.
std::cout << "Searching for HIP API calls in source files within " << tests_root_directory << "." << std::endl;
std::vector<std::string> test_module_files{extractTestModuleFiles(tests_root_directory)};
// Search for each HIP API in the extracted test .cc files.
for(HipAPI& hip_api: hip_apis) {
searchForAPI(hip_api, test_module_files);
}
std::vector<HipAPIGroup> hip_api_groups;
for (auto const& api_group_name: api_group_names) {
HipAPIGroup hip_api_group{api_group_name, hip_apis};
// Avoid having duplicated groups.
if (std::find(hip_api_groups.begin(), hip_api_groups.end(), hip_api_group) == hip_api_groups.end()) {
hip_api_groups.push_back(hip_api_group);
}
}
std::cout << "Generating XML report files." << std::endl;
generateXMLReportFiles(hip_apis, hip_api_groups);
std::cout << "Generating HTML report files." << std::endl;
generateHTMLReportFiles(hip_apis, hip_api_groups, tests_root_directory, hip_api_header_file, hip_rtc_header_file);
return 0;
}
+307
Просмотреть файл
@@ -0,0 +1,307 @@
/*
Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "reportGenerators.h"
BasicAPIStats::BasicAPIStats(std::vector<HipAPIGroup>& hip_api_groups):
number_of_called_apis{0}, number_of_not_called_apis{0},
number_of_deprecated_apis{0}, total_number_of_api_calls{0},
total_number_of_test_cases{0}
{
for (auto const& hip_api_group: hip_api_groups) {
number_of_called_apis += hip_api_group.getNumberOfCalledAPIs();
number_of_not_called_apis += hip_api_group.getNumberOfNotCalledAPIs();
number_of_deprecated_apis += hip_api_group.getNumberOfDeprecatedAPIs();
total_number_of_api_calls += hip_api_group.getTotalNumberOfCalls();
total_number_of_test_cases += hip_api_group.getTotalNumberOfTestCases();
}
total_number_of_apis = number_of_called_apis + number_of_not_called_apis + number_of_deprecated_apis;
tests_coverage_percentage = 100.f * number_of_called_apis / (number_of_called_apis + number_of_not_called_apis);
}
float BasicAPIStats::getLowCoverageLimit() const {
return 40.f;
}
float BasicAPIStats::getMediumCoverageLimit() const {
return 80.f;
}
void generateXMLReportFiles(std::vector<HipAPI>& hip_apis, std::vector<HipAPIGroup>& hip_api_groups) {
BasicAPIStats basic_stats{hip_api_groups};
std::cout << "Total number of HIP API calls: " << basic_stats.total_number_of_api_calls << std::endl;
std::cout << "Number of the HIP APIs that are called at least once: " << basic_stats.number_of_called_apis << std::endl;
std::cout << "Number of the HIP APIs that are not called at all: " << basic_stats.number_of_not_called_apis << std::endl;
std::cout << "Number of the HIP APIs that are marked as deprecated: " << basic_stats.number_of_deprecated_apis << std::endl;
std::cout << "Test coverage by implemented tests, for the HIP APIs that are not marked as deprecated: ";
std::cout << basic_stats.tests_coverage_percentage << "%" << std::endl;
/*
Generate XML file that contains relevant information about test coverage.
The XML file is created using raw handling of XML files, as there is no need
for the additional 3rd party library that implements XML file CRUD operations.
*/
std::fstream coverage_report;
std::string report_file_name{"CoverageReport.xml"};
coverage_report.open(report_file_name, std::ios::out);
time_t now{time(nullptr)};
std::string date{asctime(gmtime(&now))};
coverage_report << "<REPORT-GENERATED-UTC>" << date << "</REPORT-GENERATED-UTC>\n";
coverage_report << "<COVERAGE-RESULTS>\n";
coverage_report << "\t<TOTAL-NUMBER-OF-APIs>\n\t\t<DESCRIPTION>Total number of detected HIP APIs.</DESCRIPTION>";
coverage_report << "\n\t\t<NUMBER>" << hip_apis.size() << "</NUMBER>\n\t</TOTAL-NUMBER-OF-APIs>\n";
coverage_report << "\t<TOTAL-NUMBER-OF-API-CALLS>\n\t\t<DESCRIPTION>Total number of HIP API calls within test source files.</DESCRIPTION>";
coverage_report << "\n\t\t<NUMBER>" << basic_stats.total_number_of_api_calls << "</NUMBER>\n\t</TOTAL-NUMBER-OF-API-CALLS>\n";
coverage_report << "\t<CALLED-APIs>\n\t\t<DESCRIPTION>Number of the HIP APIs that are called at least once.</DESCRIPTION>";
coverage_report << "\n\t\t<NUMBER>" << basic_stats.number_of_called_apis << "</NUMBER>\n\t</CALLED-APIs>\n";
coverage_report << "\t<NOT-CALLED-APIs>\n\t\t<DESCRIPTION>Number of the HIP APIs that are not called at all.</DESCRIPTION>";
coverage_report << "\n\t\t<NUMBER>" << basic_stats.number_of_not_called_apis << "</NUMBER>\n\t</NOT-CALLED-APIs>\n";
coverage_report << "\t<DEPRECATED-APIs>\n\t\t<DESCRIPTION>Number of the HIP APIs that are marked as deprecated.</DESCRIPTION>";
coverage_report << "\n\t\t<NUMBER>" << basic_stats.number_of_deprecated_apis << "</NUMBER>\n\t</DEPRECATED-APIs>\n";
coverage_report << "\t<COVERAGE-PERCENTAGE>\n\t\t<DESCRIPTION>Test coverage by implemented tests for the HIP APIs that are not marked as deprecated.</DESCRIPTION>";
coverage_report << "\n\t\t<VALUE>" << basic_stats.tests_coverage_percentage << "%</VALUE>\n\t</COVERAGE-PERCENTAGE>";
coverage_report << "\n</COVERAGE-RESULTS>";
for (auto const& hip_api_group: hip_api_groups) {
coverage_report << hip_api_group.getBasicStatsHTML();
}
coverage_report.close();
std::cout << "Generated XML report file " << findAbsolutePathOfFile(report_file_name) << std::endl;
}
void generateHTMLReportFiles(std::vector<HipAPI>& hip_apis, std::vector<HipAPIGroup>& hip_api_groups,
std::string tests_root_directory, std::string hipApiHeaderFile, std::string hip_rtc_header_file) {
BasicAPIStats basic_stats{hip_api_groups};
std::fstream coverage_report;
// Main HTML report file.
std::string report_file_name{"./coverageReportHTML/CoverageReport.html"};
// Directories used to store generated HTML files.
std::string test_modules_directory{"./coverageReportHTML/testModules"};
std::string test_apis_directory{"./coverageReportHTML/testAPIs"};
std::filesystem::create_directories(test_modules_directory);
std::filesystem::create_directories(test_apis_directory);
coverage_report.open(report_file_name, std::ios::out);
// Helper strings with tabs and newlines for better HTML formatting.
std::string one_tab{"\n\t"};
std::string two_tabs{"\n\t\t"};
std::string three_tabs{"\n\t\t\t"};
std::string four_tabs{"\n\t\t\t\t"};
std::string five_tabs{"\n\t\t\t\t\t"};
std::string six_tabs{"\n\t\t\t\t\t\t"};
/*
Create HTML file which contains report from coverage. There is no need for
3rd party HTML libraries as the HTML report file is pretty simple and only
consists of tables and appropriate data.
It is better to open CoverageReport.html file in browser and view page
source, as it is much more clear.
*/
coverage_report << "<html lang=\"en\">";
coverage_report << "<head>" << one_tab << "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">";
coverage_report << one_tab << "<title>HIP API Coverage report</title>";
coverage_report << one_tab << "<link rel=\"stylesheet\" type=\"text/css\" href=\"resources/coverage.css\">" << one_tab << "</head>";
coverage_report << one_tab << "<body>" << one_tab << "<table width=\"100%\" border=0 cellspacing=0 cellpadding=0>";
coverage_report << two_tabs << "<tr><td class=\"title\">HIP API Coverage report</td></tr>";
coverage_report << two_tabs << "<tr><td class=\"ruler\"><img src=\"resources/glass.png\" width=3 height=3></td></tr>\n";
coverage_report << two_tabs << "<tr>" << three_tabs << "<td width=\"100%\">" << four_tabs << "<table cellpading=1 border=0 width=\"100%\"";
coverage_report << five_tabs << "<tr>";
coverage_report << six_tabs << "<td width=\"20%\" class=\"headerItem\">Catch2 tests location:</td>";
coverage_report << six_tabs << "<td width=\"30%\" class=\"headerValue\">" << tests_root_directory << "</td>";
coverage_report << six_tabs << "<td width=\"20%\"></td>";
coverage_report << six_tabs << "<td width=\"10%\" class=\"headerCovTableHead\">Value</td>";
coverage_report << six_tabs << "<td width=\"20%\"></td>";
coverage_report << five_tabs << "</tr>";
coverage_report << five_tabs << "<tr>";
coverage_report << six_tabs << "<td class=\"headerItem\">Source files included:</td>";
coverage_report << six_tabs << "<td class=\"headerValue\">" << hipApiHeaderFile << "</td>";
coverage_report << six_tabs << "<td class=\"headerItem\">Total number of detected HIP APIs:</td>";
coverage_report << six_tabs << "<td class=\"headerCovTableEntry\">" << basic_stats.total_number_of_apis << "</td>";
coverage_report << six_tabs << "<td></td>";
coverage_report << five_tabs << "</tr>";
coverage_report << five_tabs << "<tr>";
coverage_report << six_tabs << "<td></td>";
coverage_report << six_tabs << "<td class=\"headerValue\">" << hip_rtc_header_file << "</td>";
coverage_report << six_tabs << "<td class=\"headerItem\">HIP API calls within test source files:</td>";
coverage_report << six_tabs << "<td class=\"headerCovTableEntry\">" << basic_stats.total_number_of_api_calls << "</td>";
coverage_report << six_tabs << "<td></td>";
coverage_report << five_tabs << "</tr>";
coverage_report << five_tabs << "<tr>";
coverage_report << six_tabs << "<td></td>";
coverage_report << six_tabs << "<td></td>";
coverage_report << six_tabs << "<td class=\"headerItem\">Total number of test cases:</td>";
coverage_report << six_tabs << "<td class=\"headerCovTableEntry\">" << basic_stats.total_number_of_test_cases << "</td>";
coverage_report << six_tabs << "<td></td>";
coverage_report << five_tabs << "</tr>";
coverage_report << five_tabs << "<tr>";
coverage_report << six_tabs << "<td></td>";
coverage_report << six_tabs << "<td></td>";
coverage_report << six_tabs << "<td class=\"headerItem\">HIP APIs that are called at least once:</td>";
coverage_report << six_tabs << "<td class=\"headerCovTableEntry\">" << basic_stats.number_of_called_apis << "</td>";
coverage_report << six_tabs << "<td></td>";
coverage_report << five_tabs << "</tr>";
coverage_report << five_tabs << "<tr>";
coverage_report << six_tabs << "<td></td>";
coverage_report << six_tabs << "<td></td>";
coverage_report << six_tabs << "<td class=\"headerItem\">HIP APIs that are not called at all:</td>";
coverage_report << six_tabs << "<td class=\"headerCovTableEntry\">" << basic_stats.number_of_not_called_apis << "</td>";
coverage_report << six_tabs << "<td></td>";
coverage_report << five_tabs << "</tr>";
coverage_report << five_tabs << "<tr>";
coverage_report << six_tabs << "<td></td>";
coverage_report << six_tabs << "<td></td>";
coverage_report << six_tabs << "<td class=\"headerItem\">HIP APIs that are marked as deprecated:</td>";
coverage_report << six_tabs << "<td class=\"headerCovTableEntry\">" << basic_stats.number_of_deprecated_apis << "</td>";
coverage_report << six_tabs << "<td></td>";
coverage_report << five_tabs << "</tr>";
// Based on the tests coverage percentage, pick a color for displaying it.
std::string font_class;
if (basic_stats.tests_coverage_percentage < basic_stats.getLowCoverageLimit()) {
font_class = "headerCovTableEntryLo";
}
else if (basic_stats.tests_coverage_percentage < basic_stats.getMediumCoverageLimit()) {
font_class = "headerCovTableEntryMed";
}
else {
font_class = "headerCovTableEntryHi";
}
coverage_report << five_tabs << "<tr>";
coverage_report << six_tabs << "<td></td>";
coverage_report << six_tabs << "<td></td>";
coverage_report << six_tabs << "<td class=\"headerItem\">Test coverage by implemented tests for the HIP APIs:</td>";
coverage_report << six_tabs << "<td class=\""<< font_class << "\">" <<
std::fixed << std::setprecision(2) << basic_stats.tests_coverage_percentage << "%</td>";
coverage_report << six_tabs << "<td></td>";
coverage_report << five_tabs << "</tr>";
coverage_report << five_tabs << "<tr><td><img src=\"resources/glass.png\" width=3 height=3></td></tr>";
coverage_report << four_tabs << "</table>";
coverage_report << three_tabs << "</td>";
coverage_report << two_tabs << "</tr>";
coverage_report << two_tabs << "<tr><td class=\"ruler\"><img src=\"resources/glass.png\" width=3 height=3></td></tr>\n";
coverage_report << one_tab << "</table>";
// Add info about HIP API Groups.
coverage_report << one_tab << "<center>";
coverage_report << one_tab << "<table width=\"60%\" cellpadding=1 cellspacing=1 border=0>";
coverage_report << two_tabs << "<tr>";
coverage_report << three_tabs << "<td width=\"30%\"><br></td>";
coverage_report << three_tabs << "<td width=\"10%\"></td>";
coverage_report << three_tabs << "<td width=\"10%\"></td>";
coverage_report << three_tabs << "<td width=\"10%\"></td>";
coverage_report << three_tabs << "<td width=\"10%\"></td>";
coverage_report << three_tabs << "<td width=\"10%\"></td>";
coverage_report << three_tabs << "<td width=\"10%\"></td>";
coverage_report << three_tabs << "<td width=\"5%\"></td>";
coverage_report << three_tabs << "<td width=\"5%\"></td>";
coverage_report << two_tabs << "</tr>";
coverage_report << two_tabs << "<tr>";
coverage_report << three_tabs << "<td class=\"tableHead\">Module</td>";
coverage_report << three_tabs << "<td class=\"tableHead\">HIP APIs</td>";
coverage_report << three_tabs << "<td class=\"tableHead\">HIP API Calls</td>";
coverage_report << three_tabs << "<td class=\"tableHead\">Test cases</td>";
coverage_report << three_tabs << "<td class=\"tableHead\">Called APIs</td>";
coverage_report << three_tabs << "<td class=\"tableHead\">Not called APIs</td>";
coverage_report << three_tabs << "<td class=\"tableHead\">Deprecated APIs</td>";
coverage_report << three_tabs << "<td class=\"tableHead\" colspan=2>Coverage</td>";
coverage_report << two_tabs << "</tr>";
/*
Get basic stats for each API Group in HTML format and append it to the main HTML.
Create an HTML page for each API Group for more detailed information, as they are
used as hyperlinks from the main HTML page.
*/
for (auto const& hip_api_group: hip_api_groups) {
coverage_report << hip_api_group.getBasicStatsHTML();
std::fstream coverage_module_report;
std::string report_module_file_name{test_modules_directory + "/" + hip_api_group.getName() + ".html"};
coverage_module_report.open(report_module_file_name, std::ios::out);
coverage_module_report << hip_api_group.createHTMLReport();
coverage_module_report.close();
}
coverage_report << two_tabs << "<tr>";
coverage_report << three_tabs << "<td></td>";
coverage_report << three_tabs << "<td class=\"headerCovTableEntry\">" << basic_stats.total_number_of_apis << "</td>";
coverage_report << three_tabs << "<td class=\"headerCovTableEntry\">" << basic_stats.total_number_of_api_calls << "</td>";
coverage_report << three_tabs << "<td class=\"headerCovTableEntry\">" << basic_stats.total_number_of_test_cases << "</td>";
coverage_report << three_tabs << "<td class=\"headerCovTableEntry\">" << basic_stats.number_of_called_apis << "</td>";
coverage_report << three_tabs << "<td class=\"headerCovTableEntry\">" << basic_stats.number_of_not_called_apis << "</td>";
coverage_report << three_tabs << "<td class=\"headerCovTableEntry\">" << basic_stats.number_of_deprecated_apis << "</td>";
coverage_report << three_tabs << "<td class=\"headerCovTableEntry\">" <<
std::fixed << std::setprecision(2) << basic_stats.tests_coverage_percentage << "%</td>";
coverage_report << three_tabs << "<td></td>";
coverage_report << two_tabs << "</tr>";
coverage_report << one_tab << "</table>";
coverage_report << one_tab << "</center>";
coverage_report << one_tab << "<br>";
coverage_report << one_tab << "<table width=\"100%\" border=0 cellspacing=0 cellpadding=0>";
coverage_report << two_tabs << "<tr><td class=\"ruler\"><img src=\"resources/glass.png\" width=3 height=3></td></tr>";
time_t now{time(nullptr)};
std::string date{asctime(gmtime(&now))};
coverage_report << two_tabs << "<tr><td class=\"versionInfo\">Generated: " << date;
coverage_report << two_tabs << " UTC</td></tr>";
coverage_report << one_tab << "</table>";
coverage_report << one_tab << "<br>";
coverage_report << "\n</body>\n</html>";
coverage_report.close();
// Create HTML report for each API, as they are used as hyperlinks from Groups HTML.
for (auto const& hip_api: hip_apis) {
std::fstream coverage_api_report;
std::string report_api_file_name{test_apis_directory + "/" + hip_api.getName() + ".html"};
coverage_api_report.open(report_api_file_name, std::ios::out);
coverage_api_report << hip_api.createHTMLReport();
coverage_api_report.close();
}
std::cout << "Generated HTML report file " << findAbsolutePathOfFile(report_file_name) << std::endl;
}
+41
Просмотреть файл
@@ -0,0 +1,41 @@
/*
Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "hipAPICoverageUtils.h"
class BasicAPIStats {
public:
int number_of_called_apis;
int number_of_not_called_apis;
int number_of_deprecated_apis;
int total_number_of_api_calls;
int total_number_of_test_cases;
int total_number_of_apis;
float tests_coverage_percentage;
BasicAPIStats(std::vector<HipAPIGroup>& hip_api_groups);
float getLowCoverageLimit() const;
float getMediumCoverageLimit() const;
};
void generateXMLReportFiles(std::vector<HipAPI>& hip_apis, std::vector<HipAPIGroup>& hip_api_groups);
void generateHTMLReportFiles(std::vector<HipAPI>& hip_apis, std::vector<HipAPIGroup>& hip_api_groups,
std::string tests_root_directory, std::string hipApiHeaderFile, std::string hip_rtc_header_file);