Skip to content

Commit f248513

Browse files
committed
Refactor skipAnalysis and add unit tests
1 parent d8b4a8f commit f248513

3 files changed

Lines changed: 133 additions & 11 deletions

File tree

lib/analyzerinfo.cpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -83,25 +83,22 @@ void AnalyzerInformation::close()
8383
}
8484
}
8585

86-
static bool skipAnalysis(const std::string &analyzerInfoFile, std::size_t hash, std::list<ErrorMessage> &errors)
86+
bool AnalyzerInformation::skipAnalysis(const tinyxml2::XMLDocument &analyzerInfoDoc, std::size_t hash, std::list<ErrorMessage> &errors)
8787
{
88-
tinyxml2::XMLDocument doc;
89-
const tinyxml2::XMLError error = doc.LoadFile(analyzerInfoFile.c_str());
90-
if (error != tinyxml2::XML_SUCCESS)
91-
return false;
92-
93-
const tinyxml2::XMLElement * const rootNode = doc.FirstChildElement();
88+
const tinyxml2::XMLElement * const rootNode = analyzerInfoDoc.FirstChildElement();
9489
if (rootNode == nullptr)
9590
return false;
9691

9792
const char *attr = rootNode->Attribute("hash");
9893
if (!attr || attr != std::to_string(hash))
9994
return false;
10095

101-
// Check for invalid license error, in which case we should retry analysis
102-
// Any kind of internal error should be checked for here
96+
// Check for invalid license error or internal error, in which case we should retry analysis
10397
for (const tinyxml2::XMLElement *e = rootNode->FirstChildElement(); e; e = e->NextSiblingElement()) {
104-
if (std::strcmp(e->Name(), "error") == 0 && e->Attribute("id", "premium-invalidLicense"))
98+
if (std::strcmp(e->Name(), "error") == 0 &&
99+
(e->Attribute("id", "premium-invalidLicense") ||
100+
e->Attribute("id", "internal")
101+
))
105102
return false;
106103
}
107104

@@ -154,7 +151,10 @@ bool AnalyzerInformation::analyzeFile(const std::string &buildDir, const std::st
154151

155152
mAnalyzerInfoFile = AnalyzerInformation::getAnalyzerInfoFile(buildDir,sourcefile,cfg,fileIndex);
156153

157-
if (skipAnalysis(mAnalyzerInfoFile, hash, errors))
154+
tinyxml2::XMLDocument analyzerInfoDoc;
155+
analyzerInfoDoc.LoadFile(mAnalyzerInfoFile.c_str());
156+
157+
if (skipAnalysis(analyzerInfoDoc, hash, errors))
158158
return false;
159159

160160
mOutputStream.open(mAnalyzerInfoFile);

lib/analyzerinfo.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@
3131
class ErrorMessage;
3232
struct FileSettings;
3333

34+
namespace tinyxml2 {
35+
class XMLDocument;
36+
};
37+
3438
/// @addtogroup Core
3539
/// @{
3640

@@ -49,6 +53,8 @@ struct FileSettings;
4953
*/
5054
class CPPCHECKLIB AnalyzerInformation {
5155
public:
56+
friend class TestAnalyzerInformation;
57+
5258
~AnalyzerInformation();
5359

5460
static std::string getFilesTxt(const std::list<std::string> &sourcefiles, const std::string &userDefines, const std::list<FileSettings> &fileSettings);
@@ -75,7 +81,10 @@ class CPPCHECKLIB AnalyzerInformation {
7581

7682
protected:
7783
static std::string getAnalyzerInfoFileFromFilesTxt(std::istream& filesTxt, const std::string &sourcefile, const std::string &cfg, int fileIndex);
84+
7885
private:
86+
static bool skipAnalysis(const tinyxml2::XMLDocument &analyzerInfoDoc, std::size_t hash, std::list<ErrorMessage> &errors);
87+
7988
std::ofstream mOutputStream;
8089
std::string mAnalyzerInfoFile;
8190
};

test/testanalyzerinformation.cpp

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@
2020
#include "analyzerinfo.h"
2121
#include "filesettings.h"
2222
#include "fixture.h"
23+
#include "xml.h"
2324

2425
#include <sstream>
26+
#include <tinyxml2.h>
2527

2628
class TestAnalyzerInformation : public TestFixture, private AnalyzerInformation {
2729
public:
@@ -34,6 +36,7 @@ class TestAnalyzerInformation : public TestFixture, private AnalyzerInformation
3436
TEST_CASE(duplicateFile);
3537
TEST_CASE(filesTextDuplicateFile);
3638
TEST_CASE(parse);
39+
TEST_CASE(skipAnalysis);
3740
}
3841

3942
void getAnalyzerInfoFile() const {
@@ -95,6 +98,116 @@ class TestAnalyzerInformation : public TestFixture, private AnalyzerInformation
9598
ASSERT_EQUALS(0, info.fileIndex);
9699
ASSERT_EQUALS("C:/dm/cppcheck-fix-13333/test/cli/whole-program/odr1.cpp", info.sourceFile);
97100
}
101+
102+
void skipAnalysis() const {
103+
// Matching hash with license error (don't skip)
104+
{
105+
std::list<ErrorMessage> errorList;
106+
tinyxml2::XMLDocument doc;
107+
108+
const tinyxml2::XMLError xmlError = doc.Parse(
109+
"<?xml version=\"1.0\"?>"
110+
"<analyzerinfo hash=\"100\">"
111+
"<error id=\"premium-invalidLicense\" severity=\"error\" msg=\"Invalid license: No license file was found, contact sales@cppchecksolutions.com\" verbose=\"Invalid license: No license file was found, contact sales@cppchecksolutions.com\" file0=\"test.c\">"
112+
"<location file=\"Cppcheck Premium\" line=\"0\" column=\"0\"/>"
113+
"</error>"
114+
"</analyzerinfo>"
115+
);
116+
ASSERT_EQUALS(xmlError, tinyxml2::XML_SUCCESS);
117+
118+
ASSERT_EQUALS(AnalyzerInformation::skipAnalysis(doc, 100, errorList), false);
119+
ASSERT_EQUALS(errorList.size(), 0);
120+
}
121+
122+
// Matching hash with internal error (don't skip)
123+
{
124+
std::list<ErrorMessage> errorList;
125+
tinyxml2::XMLDocument doc;
126+
127+
const tinyxml2::XMLError xmlError = doc.Parse(
128+
"<?xml version=\"1.0\"?>"
129+
"<analyzerinfo hash=\"100\">"
130+
"<error id=\"internal\" severity=\"error\" msg=\"Something went wrong\" verbose=\"Something went wrong\" file0=\"test.c\">"
131+
"<location file=\"Cppcheck\" line=\"0\" column=\"0\"/>"
132+
"</error>"
133+
"</analyzerinfo>"
134+
);
135+
ASSERT_EQUALS(xmlError, tinyxml2::XML_SUCCESS);
136+
137+
ASSERT_EQUALS(AnalyzerInformation::skipAnalysis(doc, 100, errorList), false);
138+
ASSERT_EQUALS(errorList.size(), 0);
139+
}
140+
141+
// Matching hash with normal error (skip)
142+
{
143+
std::list<ErrorMessage> errorList;
144+
tinyxml2::XMLDocument doc;
145+
146+
const tinyxml2::XMLError xmlError = doc.Parse(
147+
"<?xml version=\"1.0\"?>"
148+
"<analyzerinfo hash=\"100\">"
149+
"<error id=\"nullPointer\" severity=\"error\" msg=\"Null pointer dereference: ptr\" verbose=\"Null pointer dereference: ptr\" cwe=\"476\" file0=\"test.c\">"
150+
"<location file=\"test.c\" line=\"4\" column=\"3\" info=\"Null pointer dereference\"/>"
151+
"<location file=\"test.c\" line=\"3\" column=\"12\" info=\"Assignment &apos;ptr=NULL&apos;, assigned value is 0\"/>"
152+
"<symbol>ptr</symbol>"
153+
"</error>"
154+
"</analyzerinfo>"
155+
);
156+
ASSERT_EQUALS(xmlError, tinyxml2::XML_SUCCESS);
157+
158+
ASSERT_EQUALS(AnalyzerInformation::skipAnalysis(doc, 100, errorList), true);
159+
ASSERT_EQUALS(errorList.size(), 1);
160+
}
161+
162+
// Matching hash with no error (skip)
163+
{
164+
std::list<ErrorMessage> errorList;
165+
tinyxml2::XMLDocument doc;
166+
167+
const tinyxml2::XMLError xmlError = doc.Parse(
168+
"<?xml version=\"1.0\"?>"
169+
"<analyzerinfo hash=\"100\">"
170+
"</analyzerinfo>"
171+
);
172+
ASSERT_EQUALS(xmlError, tinyxml2::XML_SUCCESS);
173+
174+
ASSERT_EQUALS(AnalyzerInformation::skipAnalysis(doc, 100, errorList), true);
175+
ASSERT_EQUALS(errorList.size(), 0);
176+
}
177+
178+
// Different hash with normal error (don't skip)
179+
{
180+
std::list<ErrorMessage> errorList;
181+
tinyxml2::XMLDocument doc;
182+
183+
const tinyxml2::XMLError xmlError = doc.Parse(
184+
"<?xml version=\"1.0\"?>"
185+
"<analyzerinfo hash=\"100\">"
186+
"<error id=\"nullPointer\" severity=\"error\" msg=\"Null pointer dereference: ptr\" verbose=\"Null pointer dereference: ptr\" cwe=\"476\" file0=\"test.c\">"
187+
"<location file=\"test.c\" line=\"4\" column=\"3\" info=\"Null pointer dereference\"/>"
188+
"<location file=\"test.c\" line=\"3\" column=\"12\" info=\"Assignment &apos;ptr=NULL&apos;, assigned value is 0\"/>"
189+
"<symbol>ptr</symbol>"
190+
"</error>"
191+
"</analyzerinfo>"
192+
);
193+
ASSERT_EQUALS(xmlError, tinyxml2::XML_SUCCESS);
194+
195+
ASSERT_EQUALS(AnalyzerInformation::skipAnalysis(doc, 99, errorList), false);
196+
ASSERT_EQUALS(errorList.size(), 0);
197+
}
198+
199+
// Empty document (don't skip)
200+
{
201+
std::list<ErrorMessage> errorList;
202+
tinyxml2::XMLDocument doc;
203+
204+
const tinyxml2::XMLError xmlError = doc.Parse("");
205+
ASSERT_EQUALS(xmlError, tinyxml2::XML_ERROR_EMPTY_DOCUMENT);
206+
207+
ASSERT_EQUALS(AnalyzerInformation::skipAnalysis(doc, 100, errorList), false);
208+
ASSERT_EQUALS(errorList.size(), 0);
209+
}
210+
}
98211
};
99212

100213
REGISTER_TEST(TestAnalyzerInformation)

0 commit comments

Comments
 (0)