Unit Testing: Start

This commit is contained in:
Daniel Marjamäki 2008-02-16 15:46:32 +00:00
parent a8e6a4c343
commit 4cb3c7b96b
7 changed files with 116 additions and 41 deletions

View File

@ -5,6 +5,7 @@
#include <sstream>
//---------------------------------------------------------------------------
bool HasErrors;
std::ostringstream errout;
//---------------------------------------------------------------------------
std::string FileLine(TOKEN *tok)
@ -17,7 +18,7 @@ std::string FileLine(TOKEN *tok)
void ReportErr(const std::string errmsg)
{
std::cerr << errmsg << std::endl;
errout << errmsg << std::endl;
HasErrors = true;
}
//---------------------------------------------------------------------------

View File

@ -4,12 +4,14 @@
//---------------------------------------------------------------------------
#include <string>
#include <sstream>
struct TOKEN;
std::string FileLine(TOKEN *tok);
void ReportErr(const std::string errmsg);
extern std::ostringstream errout;
bool IsName(const char str[]);

View File

@ -3,11 +3,11 @@ OBJS=$(SRCS:%.cpp=%.o)
%.o: %.cpp
g++ -Wall -pedantic -I. -o $@ -c $^
g++ -Wall -pedantic -g -I. -o $@ -c $^
all: ${OBJS} main.o
g++ -o cppcheck $^
test: ${OBJS} TestTok.o
g++ -o cppcheck_test $^
g++ -Wall -g -o cppcheck $^
test: ${OBJS} tests.o
g++ -Wall -g -o cppcheck_test $^
clean:
rm -f *.o cppcheck_test cppcheck

View File

@ -4,6 +4,7 @@
#include "tokenize.h" // <- Tokenizer
#include "Statements.h" // <- Statement list
#include "CommonCheck.h"
#include "CheckMemoryLeak.h"
#include "CheckBufferOverrun.h"
@ -62,6 +63,8 @@ int main(int argc, char* argv[])
CppCheck(fname);
std::cerr << errout.str();
return 0;
}

56
tests.cpp Normal file
View File

@ -0,0 +1,56 @@
// Unit-testing cppcheck
#include "tokenize.h" // <- Tokenizer
#include "CommonCheck.h"
#include "CheckBufferOverrun.h"
#include <iostream>
#include <sstream>
#define assert_equal(A,B) if (A!=B) { std::cerr << "Failed at line " << __LINE__ << "\n"; FailCount++; } else { SuccessCount++; }
bool Debug = false;
bool ShowAll = false;
bool CheckCodingStyle = false;
static unsigned int FailCount, SuccessCount;
static void buffer_overrun_1();
int main()
{
Files.push_back( std::string("test.cpp") );
buffer_overrun_1();
std::cout << "Success Rate: "
<< SuccessCount
<< " / "
<< (SuccessCount + FailCount)
<< std::endl;
return 0;
}
static void buffer_overrun_1()
{
const char code[] = "void f()\n"
"{\n"
" char str[0x10];\n"
" str[15] = 0;\n"
" str[16] = 0;\n"
"}\n";
// Tokenize..
tokens = tokens_back = NULL;
std::istringstream istr(code);
TokenizeCode( istr );
SimplifyTokenList();
errout.str("");
CheckBufferOverrun();
std::string err = errout.str();
assert_equal( errout.str(), "[test.cpp:5]: Array index out of bounds\n" );
}

View File

@ -264,21 +264,34 @@ void Tokenize(const char FileName[])
return;
// The "Files" vector remembers what files have been tokenized..
unsigned int CurrentFile = Files.size();
Files.push_back(FileName);
// Tokenize the file..
TokenizeCode( fin, Files.size() - 1 );
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// Tokenize - tokenizes input stream
//---------------------------------------------------------------------------
void TokenizeCode(std::istream &code, const unsigned int FileIndex)
{
// Tokenize the file.
unsigned int lineno = 1;
char CurrentToken[1000];
memset(CurrentToken, 0, sizeof(CurrentToken));
char CurrentToken[1000] = {0};
char *pToken = CurrentToken;
for (char ch = (char)fin.get(); !fin.eof(); ch = (char)fin.get())
for (char ch = (char)code.get(); !code.eof(); ch = (char)code.get())
{
// Preprocessor stuff?
if (ch == '#' && !CurrentToken[0])
{
std::string line;
getline(fin,line);
getline(code,line);
line = "#" + line;
if (strncmp(line.c_str(),"#include",8)==0 &&
line.find("\"") != std::string::npos)
@ -288,17 +301,15 @@ void Tokenize(const char FileName[])
line.erase(line.find("\""));
// Relative path..
if (strchr(FileName,'\\'))
if (Files.back().find_first_of("\\/") != std::string::npos)
{
char path[1000];
memset(path,0,sizeof(path));
const char *p = strrchr(FileName, '\\');
memcpy(path, FileName, p-FileName+1);
std::string path = Files.back();
path.erase( 1 + path.find_last_of("\\/") );
line = path + line;
}
addtoken("#include", lineno, CurrentFile);
addtoken(line.c_str(), lineno, CurrentFile);
addtoken("#include", lineno, FileIndex);
addtoken(line.c_str(), lineno, FileIndex);
Tokenize(line.c_str());
}
@ -332,9 +343,9 @@ void Tokenize(const char FileName[])
if (State==Value)
{
addtoken("def", lineno, CurrentFile);
addtoken(strId, lineno, CurrentFile);
addtoken(";", lineno, CurrentFile);
addtoken("def", lineno, FileIndex);
addtoken(strId, lineno, FileIndex);
addtoken(";", lineno, FileIndex);
Define(strId, CurrentToken);
}
@ -345,8 +356,8 @@ void Tokenize(const char FileName[])
else
{
addtoken("#", lineno, CurrentFile);
addtoken(";", lineno, CurrentFile);
addtoken("#", lineno, FileIndex);
addtoken(";", lineno, FileIndex);
}
lineno++;
@ -356,27 +367,27 @@ void Tokenize(const char FileName[])
if (ch == '\n')
{
// Add current token..
addtoken(CurrentToken, lineno++, CurrentFile);
addtoken(CurrentToken, lineno++, FileIndex);
memset(CurrentToken, 0, sizeof(CurrentToken));
pToken = CurrentToken;
continue;
}
// Comments..
if (ch == '/' && !fin.eof())
if (ch == '/' && !code.eof())
{
// Add current token..
addtoken(CurrentToken, lineno, CurrentFile);
addtoken(CurrentToken, lineno, FileIndex);
memset(CurrentToken, 0, sizeof(CurrentToken));
pToken = CurrentToken;
// Read next character..
ch = (char)fin.get();
ch = (char)code.get();
// If '//'..
if (ch == '/')
{
while (!fin.eof() && (char)fin.get()!='\n');
while (!code.eof() && (char)code.get()!='\n');
lineno++;
continue;
}
@ -386,10 +397,10 @@ void Tokenize(const char FileName[])
{
char chPrev;
ch = chPrev = 'A';
while (!fin.eof() && (chPrev!='*' || ch!='/'))
while (!code.eof() && (chPrev!='*' || ch!='/'))
{
chPrev = ch;
ch = (char)fin.get();
ch = (char)code.get();
if (ch == '\n')
lineno++;
}
@ -397,25 +408,25 @@ void Tokenize(const char FileName[])
}
// Not a comment.. add token..
addtoken("/", lineno, CurrentFile);
addtoken("/", lineno, FileIndex);
}
// char..
if (ch == '\'')
{
// Add previous token
addtoken(CurrentToken, lineno, CurrentFile);
addtoken(CurrentToken, lineno, FileIndex);
memset(CurrentToken, 0, sizeof(CurrentToken));
// Read this ..
CurrentToken[0] = ch;
CurrentToken[1] = (char)fin.get();
CurrentToken[2] = (char)fin.get();
CurrentToken[1] = (char)code.get();
CurrentToken[2] = (char)code.get();
if (CurrentToken[1] == '\\')
CurrentToken[3] = (char)fin.get();
CurrentToken[3] = (char)code.get();
// Add token and start on next..
addtoken(CurrentToken, lineno, CurrentFile);
addtoken(CurrentToken, lineno, FileIndex);
memset(CurrentToken, 0, sizeof(CurrentToken));
pToken = CurrentToken;
@ -425,7 +436,7 @@ void Tokenize(const char FileName[])
// String..
if (ch == '\"')
{
addtoken(CurrentToken, lineno, CurrentFile);
addtoken(CurrentToken, lineno, FileIndex);
memset(CurrentToken, 0, sizeof(CurrentToken));
pToken = CurrentToken;
bool special = false;
@ -446,11 +457,11 @@ void Tokenize(const char FileName[])
special = (c == '\\');
// Get next character
c = (char)fin.get();
c = (char)code.get();
}
while (special || c != '\"');
*pToken = '\"';
addtoken(CurrentToken, lineno, CurrentFile);
addtoken(CurrentToken, lineno, FileIndex);
memset(CurrentToken, 0, sizeof(CurrentToken));
pToken = CurrentToken;
continue;
@ -458,10 +469,10 @@ void Tokenize(const char FileName[])
if (strchr("+-*/%&|^?!=<>[](){};:,.",ch))
{
addtoken(CurrentToken, lineno, CurrentFile);
addtoken(CurrentToken, lineno, FileIndex);
memset(CurrentToken, 0, sizeof(CurrentToken));
CurrentToken[0] = ch;
addtoken(CurrentToken, lineno, CurrentFile);
addtoken(CurrentToken, lineno, FileIndex);
memset(CurrentToken, 0, sizeof(CurrentToken));
pToken = CurrentToken;
continue;
@ -470,7 +481,7 @@ void Tokenize(const char FileName[])
if (std::isspace(ch) || std::iscntrl(ch))
{
addtoken(CurrentToken, lineno, CurrentFile);
addtoken(CurrentToken, lineno, FileIndex);
pToken = CurrentToken;
memset(CurrentToken, 0, sizeof(CurrentToken));
continue;

View File

@ -20,6 +20,8 @@ extern struct TOKEN *tokens, *tokens_back;
void Tokenize(const char FileName[]);
void TokenizeCode(std::istream &code, const unsigned int FileIndex=0);
// Return size.
int SizeOfType(const char type[]);