Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 19 additions & 29 deletions lib/analyzerinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,32 +83,20 @@ void AnalyzerInformation::close()
}
}

bool AnalyzerInformation::skipAnalysis(const tinyxml2::XMLDocument &analyzerInfoDoc, std::size_t hash, std::list<ErrorMessage> &errors, bool debug)
std::string AnalyzerInformation::skipAnalysis(const tinyxml2::XMLDocument &analyzerInfoDoc, std::size_t hash, std::list<ErrorMessage> &errors)
{
const tinyxml2::XMLElement * const rootNode = analyzerInfoDoc.FirstChildElement();
if (rootNode == nullptr) {
if (debug)
std::cout << "discarding cached result - no root node found" << std::endl;
return false;
}
if (rootNode == nullptr)
return "no root node found";

if (strcmp(rootNode->Name(), "analyzerinfo") != 0) {
if (debug)
std::cout << "discarding cached result - unexpected root node" << std::endl;
return false;
}
if (strcmp(rootNode->Name(), "analyzerinfo") != 0)
return "unexpected root node";

const char * const attr = rootNode->Attribute("hash");
if (!attr) {
if (debug)
std::cout << "discarding cached result - no 'hash' attribute found" << std::endl;
return false;
}
if (attr != std::to_string(hash)) {
if (debug)
std::cout << "discarding cached result - hash mismatch" << std::endl;
return false;
}
if (!attr)
return "no 'hash' attribute found";
if (attr != std::to_string(hash))
return "hash mismatch";

for (const tinyxml2::XMLElement *e = rootNode->FirstChildElement(); e; e = e->NextSiblingElement()) {
if (std::strcmp(e->Name(), "error") != 0)
Expand All @@ -125,17 +113,15 @@ bool AnalyzerInformation::skipAnalysis(const tinyxml2::XMLDocument &analyzerInfo
{
// cppcheck-suppress useStlAlgorithm
if (e->Attribute("id", id)) {
if (debug)
std::cout << "discarding cached result - '" << id << "' encountered" << std::endl;
errors.clear();
return false;
return std::string("'") + id + "' encountered";
}
}

errors.emplace_back(e);
}

return true;
return "";
}

std::string AnalyzerInformation::getAnalyzerInfoFileFromFilesTxt(std::istream& filesTxt, const std::string &sourcefile, const std::string &cfg, int fsFileId)
Expand Down Expand Up @@ -184,18 +170,22 @@ bool AnalyzerInformation::analyzeFile(const std::string &buildDir, const std::st
tinyxml2::XMLDocument analyzerInfoDoc;
const tinyxml2::XMLError xmlError = analyzerInfoDoc.LoadFile(analyzerInfoFile.c_str());
if (xmlError == tinyxml2::XML_SUCCESS) {
if (skipAnalysis(analyzerInfoDoc, hash, errors, debug)) {
const std::string err = skipAnalysis(analyzerInfoDoc, hash, errors);
if (err.empty()) {
if (debug)
std::cout << "skipping analysis - loaded " << errors.size() << " cached finding(s) from '" << analyzerInfoFile << "'" << std::endl;
std::cout << "skipping analysis - loaded " << errors.size() << " cached finding(s) from '" << analyzerInfoFile << "' for '" << sourcefile << "'" << std::endl;
return false;
}
if (debug) {
std::cout << "discarding cached result from '" << analyzerInfoFile << "' for '" << sourcefile << "' - " << err << std::endl;
}
}
else if (xmlError != tinyxml2::XML_ERROR_FILE_NOT_FOUND) {
if (debug)
std::cout << "discarding cached result - failed to load '" << analyzerInfoFile << "' (" << tinyxml2::XMLDocument::ErrorIDToName(xmlError) << ")" << std::endl;
std::cout << "discarding cached result - failed to load '" << analyzerInfoFile << "' for '" << sourcefile << "' (" << tinyxml2::XMLDocument::ErrorIDToName(xmlError) << ")" << std::endl;
}
else if (debug)
std::cout << "no cached result '" << analyzerInfoFile << "' found" << std::endl;
std::cout << "no cached result '" << analyzerInfoFile << "' for '" << sourcefile << "' found" << std::endl;
}

mOutputStream.open(analyzerInfoFile);
Expand Down
2 changes: 1 addition & 1 deletion lib/analyzerinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ class CPPCHECKLIB AnalyzerInformation {

static std::string getAnalyzerInfoFileFromFilesTxt(std::istream& filesTxt, const std::string &sourcefile, const std::string &cfg, int fsFileId);

static bool skipAnalysis(const tinyxml2::XMLDocument &analyzerInfoDoc, std::size_t hash, std::list<ErrorMessage> &errors, bool debug = false);
static std::string skipAnalysis(const tinyxml2::XMLDocument &analyzerInfoDoc, std::size_t hash, std::list<ErrorMessage> &errors);

private:
std::ofstream mOutputStream;
Expand Down
17 changes: 9 additions & 8 deletions test/cli/other_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -4176,64 +4176,65 @@ def run_and_assert_cppcheck(stdout_exp):
assert stdout.splitlines() == stdout_exp
assert stderr.splitlines() == stderr_exp

test_file_s = str(test_file).replace('\\', '/')
test_a1_file_s = str(test_a1_file).replace('\\', '/')

# no cached results
run_and_assert_cppcheck([
"no cached result '{}' found".format(test_a1_file_s)
"no cached result '{}' for '{}' found".format(test_a1_file_s, test_file_s)
])

# cached results
run_and_assert_cppcheck([
"skipping analysis - loaded 1 cached finding(s) from '{}'".format(test_a1_file_s)
"skipping analysis - loaded 1 cached finding(s) from '{}' for '{}'".format(test_a1_file_s, test_file_s)
])

# modified file
with open(test_file, 'a') as f:
f.write('\n#define DEF')

run_and_assert_cppcheck([
"discarding cached result - hash mismatch" # TODO: add filename
"discarding cached result from '{}' for '{}' - hash mismatch".format(test_a1_file_s, test_file_s)
])

# invalid XML
with open(test_a1_file, 'a') as f:
f.write('.')

run_and_assert_cppcheck([
"discarding cached result - failed to load '{}' (XML_ERROR_PARSING_TEXT)".format(test_a1_file_s)
"discarding cached result - failed to load '{}' for '{}' (XML_ERROR_PARSING_TEXT)".format(test_a1_file_s, test_file_s)
])

# missing root node
with open(test_a1_file, 'w') as f:
f.write('<?xml version="1.0"?>')

run_and_assert_cppcheck([
"discarding cached result - no root node found" # TODO: add filename
"discarding cached result from '{}' for '{}' - no root node found".format(test_a1_file_s, test_file_s)
])

# mismatched root node
with open(test_a1_file, 'w') as f:
f.write('<?xml version="1.0"?><root/>')

run_and_assert_cppcheck([
"discarding cached result - unexpected root node" # TODO: add filename
"discarding cached result from '{}' for '{}' - unexpected root node".format(test_a1_file_s, test_file_s)
])

# missing 'hash' attribute
with open(test_a1_file, 'w') as f:
f.write('<?xml version="1.0"?><analyzerinfo/>')

run_and_assert_cppcheck([
"discarding cached result - no 'hash' attribute found" # TODO: add filename
"discarding cached result from '{}' for '{}' - no 'hash' attribute found".format(test_a1_file_s, test_file_s)
])

# invalid 'hash' attribute
with open(test_a1_file, 'w') as f:
f.write('<?xml version="1.0"?><analyzerinfo hash="hash"/>')

run_and_assert_cppcheck([
"discarding cached result - hash mismatch" # TODO: add filename
"discarding cached result from '{}' for '{}' - hash mismatch".format(test_a1_file_s, test_file_s)
])

# TODO:
Expand Down
44 changes: 37 additions & 7 deletions test/testanalyzerinformation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ class TestAnalyzerInformation : public TestFixture {
);
ASSERT_EQUALS(tinyxml2::XML_SUCCESS, xmlError);

ASSERT_EQUALS(false, AnalyzerInformationTest::skipAnalysis(doc, 100, errorList));
ASSERT_EQUALS("'premium-invalidLicense' encountered", AnalyzerInformationTest::skipAnalysis(doc, 100, errorList));
ASSERT_EQUALS(0, errorList.size());
}

Expand All @@ -145,7 +145,7 @@ class TestAnalyzerInformation : public TestFixture {
);
ASSERT_EQUALS(tinyxml2::XML_SUCCESS, xmlError);

ASSERT_EQUALS(false, AnalyzerInformationTest::skipAnalysis(doc, 100, errorList));
ASSERT_EQUALS("'premium-internalError' encountered", AnalyzerInformationTest::skipAnalysis(doc, 100, errorList));
ASSERT_EQUALS(0, errorList.size());
}

Expand All @@ -164,7 +164,7 @@ class TestAnalyzerInformation : public TestFixture {
);
ASSERT_EQUALS(tinyxml2::XML_SUCCESS, xmlError);

ASSERT_EQUALS(false, AnalyzerInformationTest::skipAnalysis(doc, 100, errorList));
ASSERT_EQUALS("'internalError' encountered", AnalyzerInformationTest::skipAnalysis(doc, 100, errorList));
ASSERT_EQUALS(0, errorList.size());
}

Expand All @@ -185,7 +185,7 @@ class TestAnalyzerInformation : public TestFixture {
);
ASSERT_EQUALS(tinyxml2::XML_SUCCESS, xmlError);

ASSERT_EQUALS(true, AnalyzerInformationTest::skipAnalysis(doc, 100, errorList));
ASSERT_EQUALS("", AnalyzerInformationTest::skipAnalysis(doc, 100, errorList));
ASSERT_EQUALS(1, errorList.size());
}

Expand All @@ -201,7 +201,7 @@ class TestAnalyzerInformation : public TestFixture {
);
ASSERT_EQUALS(tinyxml2::XML_SUCCESS, xmlError);

ASSERT_EQUALS(true, AnalyzerInformationTest::skipAnalysis(doc, 100, errorList));
ASSERT_EQUALS("", AnalyzerInformationTest::skipAnalysis(doc, 100, errorList));
ASSERT_EQUALS(0, errorList.size());
}

Expand All @@ -222,7 +222,7 @@ class TestAnalyzerInformation : public TestFixture {
);
ASSERT_EQUALS(tinyxml2::XML_SUCCESS, xmlError);

ASSERT_EQUALS(false, AnalyzerInformationTest::skipAnalysis(doc, 99, errorList));
ASSERT_EQUALS("hash mismatch", AnalyzerInformationTest::skipAnalysis(doc, 99, errorList));
ASSERT_EQUALS(0, errorList.size());
}

Expand All @@ -234,7 +234,37 @@ class TestAnalyzerInformation : public TestFixture {
const tinyxml2::XMLError xmlError = doc.Parse("");
ASSERT_EQUALS(tinyxml2::XML_ERROR_EMPTY_DOCUMENT, xmlError);

ASSERT_EQUALS(false, AnalyzerInformationTest::skipAnalysis(doc, 100, errorList));
ASSERT_EQUALS("no root node found", AnalyzerInformationTest::skipAnalysis(doc, 100, errorList));
ASSERT_EQUALS(0, errorList.size());
}

// Unexpected root node
{
std::list<ErrorMessage> errorList;
tinyxml2::XMLDocument doc;

const tinyxml2::XMLError xmlError = doc.Parse(
"<?xml version=\"1.0\"?>"
"<ainfo/>"
);
ASSERT_EQUALS(tinyxml2::XML_SUCCESS, xmlError);

ASSERT_EQUALS("unexpected root node", AnalyzerInformationTest::skipAnalysis(doc, 99, errorList));
ASSERT_EQUALS(0, errorList.size());
}

// No 'hash' attribute found
{
std::list<ErrorMessage> errorList;
tinyxml2::XMLDocument doc;

const tinyxml2::XMLError xmlError = doc.Parse(
"<?xml version=\"1.0\"?>"
"<analyzerinfo/>"
);
ASSERT_EQUALS(tinyxml2::XML_SUCCESS, xmlError);

ASSERT_EQUALS("no 'hash' attribute found", AnalyzerInformationTest::skipAnalysis(doc, 99, errorList));
ASSERT_EQUALS(0, errorList.size());
}
}
Expand Down
Loading