#include
#include
#include
#include "simplecpp.h"
static int numberOfFailedAssertions = 0;
#define ASSERT_EQUALS(expected, actual) (assertEquals((expected), (actual), __LINE__))
static int assertEquals(const std::string &expected, const std::string &actual, int line)
{
if (expected != actual) {
numberOfFailedAssertions++;
std::cerr next;
ASSERT_EQUALS("2", tok->str());
ASSERT_EQUALS("", tok->macro);
}
static void tokenMacro3()
{
const char code[] = "#define ADD(X,Y) X+Y\n"
"#define FRED 1\n"
"ADD(FRED,2)";
const simplecpp::DUI dui;
std::vector files;
std::map filedata;
std::istringstream istr(code);
simplecpp::TokenList tokenList(files);
simplecpp::preprocess(tokenList, simplecpp::TokenList(istr,files), files, filedata, dui);
const simplecpp::Token *tok = tokenList.cfront();
ASSERT_EQUALS("1", tok->str());
ASSERT_EQUALS("FRED", tok->macro);
tok = tok->next;
ASSERT_EQUALS("+", tok->str());
ASSERT_EQUALS("ADD", tok->macro);
tok = tok->next;
ASSERT_EQUALS("2", tok->str());
ASSERT_EQUALS("", tok->macro);
}
static void tokenMacro4()
{
const char code[] = "#define A B\n"
"#define B 1\n"
"A";
const simplecpp::DUI dui;
std::vector files;
std::map filedata;
std::istringstream istr(code);
simplecpp::TokenList tokenList(files);
simplecpp::preprocess(tokenList, simplecpp::TokenList(istr,files), files, filedata, dui);
const simplecpp::Token *tok = tokenList.cfront();
ASSERT_EQUALS("1", tok->str());
ASSERT_EQUALS("A", tok->macro);
}
static void undef()
{
std::istringstream istr("#define A\n"
"#undef A\n"
"#ifdef A\n"
"123\n"
"#endif");
const simplecpp::DUI dui;
std::vector files;
std::map filedata;
simplecpp::TokenList tokenList(files);
simplecpp::preprocess(tokenList, simplecpp::TokenList(istr,files), files, filedata, dui);
ASSERT_EQUALS("", tokenList.stringify());
}
static void userdef()
{
std::istringstream istr("#ifdef A\n123\n#endif\n");
simplecpp::DUI dui;
dui.defines.push_back("A=1");
std::vector files;
const simplecpp::TokenList tokens1 = simplecpp::TokenList(istr, files);
std::map filedata;
simplecpp::TokenList tokens2(files);
simplecpp::preprocess(tokens2, tokens1, files, filedata, dui);
ASSERT_EQUALS("\n123", tokens2.stringify());
}
static void utf8()
{
ASSERT_EQUALS("123", readfile("\xEF\xBB\xBF 123"));
}
static void unicode()
{
ASSERT_EQUALS("12", readfile("\xFE\xFF\x00\x31\x00\x32", 6));
ASSERT_EQUALS("12", readfile("\xFF\xFE\x31\x00\x32\x00", 6));
ASSERT_EQUALS("//\n1", readfile("\xFE\xFF\x00\x2f\x00\x2f\x00\x0a\x00\x31", 10));
ASSERT_EQUALS("//\n1", readfile("\xFF\xFE\x2f\x00\x2f\x00\x0a\x00\x31\x00", 10));
ASSERT_EQUALS("\"a\"", readfile("\xFE\xFF\x00\x22\x00\x61\x00\x22", 8));
ASSERT_EQUALS("\"a\"", readfile("\xFF\xFE\x22\x00\x61\x00\x22\x00", 8));
ASSERT_EQUALS("\n//1", readfile("\xff\xfe\x0d\x00\x0a\x00\x2f\x00\x2f\x00\x31\x00\x0d\x00\x0a\x00",16));
}
static void warning()
{
std::istringstream istr("#warning MSG\n1");
std::vector files;
std::map filedata;
simplecpp::OutputList outputList;
simplecpp::TokenList tokens2(files);
simplecpp::preprocess(tokens2, simplecpp::TokenList(istr,files,"test.c"), files, filedata, simplecpp::DUI(), &outputList);
ASSERT_EQUALS("\n1", tokens2.stringify());
ASSERT_EQUALS("file0,1,#warning,#warning MSG\n", toString(outputList));
}
static void simplifyPath()
{
ASSERT_EQUALS("1.c", simplecpp::simplifyPath("./1.c"));
ASSERT_EQUALS("1.c", simplecpp::simplifyPath("././1.c"));
ASSERT_EQUALS("/1.c", simplecpp::simplifyPath("/./1.c"));
ASSERT_EQUALS("/1.c", simplecpp::simplifyPath("/././1.c"));
ASSERT_EQUALS("trailing_dot./1.c", simplecpp::simplifyPath("trailing_dot./1.c"));
ASSERT_EQUALS("1.c", simplecpp::simplifyPath("a/../1.c"));
ASSERT_EQUALS("1.c", simplecpp::simplifyPath("a/b/../../1.c"));
ASSERT_EQUALS("a/1.c", simplecpp::simplifyPath("a/b/../1.c"));
ASSERT_EQUALS("/a/1.c", simplecpp::simplifyPath("/a/b/../1.c"));
ASSERT_EQUALS("/a/1.c", simplecpp::simplifyPath("/a/b/c/../../1.c"));
ASSERT_EQUALS("/a/1.c", simplecpp::simplifyPath("/a/b/c/../.././1.c"));
ASSERT_EQUALS("../1.c", simplecpp::simplifyPath("../1.c"));
ASSERT_EQUALS("../1.c", simplecpp::simplifyPath("../a/../1.c"));
ASSERT_EQUALS("/../1.c", simplecpp::simplifyPath("/../1.c"));
ASSERT_EQUALS("/../1.c", simplecpp::simplifyPath("/../a/../1.c"));
ASSERT_EQUALS("a/..b/1.c", simplecpp::simplifyPath("a/..b/1.c"));
ASSERT_EQUALS("../../1.c", simplecpp::simplifyPath("../../1.c"));
ASSERT_EQUALS("../../../1.c", simplecpp::simplifyPath("../../../1.c"));
ASSERT_EQUALS("../../../1.c", simplecpp::simplifyPath("../../../a/../1.c"));
ASSERT_EQUALS("../../1.c", simplecpp::simplifyPath("a/../../../1.c"));
}
// tests transferred from cppcheck
// https://github.com/danmar/cppcheck/blob/d3e79b71b5ec6e641ca3e516cfced623b27988af/test/testpath.cpp#L43
static void simplifyPath_cppcheck()
{
ASSERT_EQUALS("index.h", simplecpp::simplifyPath("index.h"));
ASSERT_EQUALS("index.h", simplecpp::simplifyPath("./index.h"));
ASSERT_EQUALS("index.h", simplecpp::simplifyPath(".//index.h"));
ASSERT_EQUALS("index.h", simplecpp::simplifyPath(".///index.h"));
ASSERT_EQUALS("/index.h", simplecpp::simplifyPath("/index.h"));
ASSERT_EQUALS("/path/", simplecpp::simplifyPath("/path/"));
ASSERT_EQUALS("/", simplecpp::simplifyPath("/"));
ASSERT_EQUALS("/", simplecpp::simplifyPath("/."));
ASSERT_EQUALS("/", simplecpp::simplifyPath("/./"));
ASSERT_EQUALS("/index.h", simplecpp::simplifyPath("/./index.h"));
ASSERT_EQUALS("/", simplecpp::simplifyPath("/.//"));
ASSERT_EQUALS("/index.h", simplecpp::simplifyPath("/.//index.h"));
ASSERT_EQUALS("../index.h", simplecpp::simplifyPath("../index.h"));
ASSERT_EQUALS("/index.h", simplecpp::simplifyPath("/path/../index.h"));
ASSERT_EQUALS("index.h", simplecpp::simplifyPath("./path/../index.h"));
ASSERT_EQUALS("index.h", simplecpp::simplifyPath("path/../index.h"));
ASSERT_EQUALS("/index.h", simplecpp::simplifyPath("/path//../index.h"));
ASSERT_EQUALS("index.h", simplecpp::simplifyPath("./path//../index.h"));
ASSERT_EQUALS("index.h", simplecpp::simplifyPath("path//../index.h"));
ASSERT_EQUALS("/index.h", simplecpp::simplifyPath("/path/..//index.h"));
ASSERT_EQUALS("index.h", simplecpp::simplifyPath("./path/..//index.h"));
ASSERT_EQUALS("index.h", simplecpp::simplifyPath("path/..//index.h"));
ASSERT_EQUALS("/index.h", simplecpp::simplifyPath("/path//..//index.h"));
ASSERT_EQUALS("index.h", simplecpp::simplifyPath("./path//..//index.h"));
ASSERT_EQUALS("index.h", simplecpp::simplifyPath("path//..//index.h"));
ASSERT_EQUALS("/index.h", simplecpp::simplifyPath("/path/../other/../index.h"));
ASSERT_EQUALS("/index.h", simplecpp::simplifyPath("/path/../other///././../index.h"));
ASSERT_EQUALS("/index.h", simplecpp::simplifyPath("/path/../other/././..///index.h"));
ASSERT_EQUALS("/index.h", simplecpp::simplifyPath("/path/../other///././..///index.h"));
ASSERT_EQUALS("../path/index.h", simplecpp::simplifyPath("../path/other/../index.h"));
ASSERT_EQUALS("a/index.h", simplecpp::simplifyPath("a/../a/index.h"));
ASSERT_EQUALS(".", simplecpp::simplifyPath("a/.."));
ASSERT_EQUALS(".", simplecpp::simplifyPath("./a/.."));
ASSERT_EQUALS("../../src/test.cpp", simplecpp::simplifyPath("../../src/test.cpp"));
ASSERT_EQUALS("../../../src/test.cpp", simplecpp::simplifyPath("../../../src/test.cpp"));
ASSERT_EQUALS("src/test.cpp", simplecpp::simplifyPath(".//src/test.cpp"));
ASSERT_EQUALS("src/test.cpp", simplecpp::simplifyPath(".///src/test.cpp"));
ASSERT_EQUALS("test.cpp", simplecpp::simplifyPath("./././././test.cpp"));
ASSERT_EQUALS("src/", simplecpp::simplifyPath("src/abc/.."));
ASSERT_EQUALS("src/", simplecpp::simplifyPath("src/abc/../"));
// Handling of UNC paths on Windows
ASSERT_EQUALS("//src/test.cpp", simplecpp::simplifyPath("//src/test.cpp"));
ASSERT_EQUALS("//src/test.cpp", simplecpp::simplifyPath("///src/test.cpp"));
}
static void simplifyPath_New()
{
ASSERT_EQUALS("", simplecpp::simplifyPath(""));
ASSERT_EQUALS("/", simplecpp::simplifyPath("/"));
ASSERT_EQUALS("//", simplecpp::simplifyPath("//"));
ASSERT_EQUALS("//", simplecpp::simplifyPath("///"));
ASSERT_EQUALS("/", simplecpp::simplifyPath("\\"));
}
static void preprocessSizeOf()
{
simplecpp::OutputList outputList;
preprocess("#if 3 > sizeof", simplecpp::DUI(), &outputList);
ASSERT_EQUALS("file0,1,syntax_error,failed to evaluate #if condition, missing sizeof argument\n", toString(outputList));
outputList.clear();
preprocess("#if 3 > sizeof A", simplecpp::DUI(), &outputList);
ASSERT_EQUALS("file0,1,syntax_error,failed to evaluate #if condition, missing sizeof argument\n", toString(outputList));
outputList.clear();
preprocess("#if 3 > sizeof(int", simplecpp::DUI(), &outputList);
ASSERT_EQUALS("file0,1,syntax_error,failed to evaluate #if condition, invalid sizeof expression\n", toString(outputList));
}
int main(int argc, char **argv)
{
TEST_CASE(backslash);
TEST_CASE(builtin);
TEST_CASE(combineOperators_floatliteral);
TEST_CASE(combineOperators_increment);
TEST_CASE(combineOperators_coloncolon);
TEST_CASE(combineOperators_andequal);
TEST_CASE(combineOperators_ellipsis);
TEST_CASE(comment);
TEST_CASE(comment_multiline);
TEST_CASE(constFold);
TEST_CASE(convertCygwinPath);
TEST_CASE(define1);
TEST_CASE(define2);
TEST_CASE(define3);
TEST_CASE(define4);
TEST_CASE(define5);
TEST_CASE(define6);
TEST_CASE(define7);
TEST_CASE(define8);
TEST_CASE(define9);
TEST_CASE(define10);
TEST_CASE(define_invalid_1);
TEST_CASE(define_invalid_2);
TEST_CASE(define_define_1);
TEST_CASE(define_define_2);
TEST_CASE(define_define_3);
TEST_CASE(define_define_4);
TEST_CASE(define_define_5);
TEST_CASE(define_define_6);
TEST_CASE(define_define_7);
TEST_CASE(define_define_8); // line break in nested macro call
TEST_CASE(define_define_9); // line break in nested macro call
TEST_CASE(define_define_10);
TEST_CASE(define_define_11);
TEST_CASE(define_define_12); // expand result of ##
TEST_CASE(define_define_13);
TEST_CASE(define_define_14);
TEST_CASE(define_va_args_1);
TEST_CASE(define_va_args_2);
TEST_CASE(define_va_args_3);
// UB: #ifdef as macro parameter
TEST_CASE(define_ifdef);
TEST_CASE(dollar);
TEST_CASE(error1);
TEST_CASE(error2);
TEST_CASE(error3);
TEST_CASE(error4);
TEST_CASE(error5);
TEST_CASE(garbage);
TEST_CASE(garbage_endif);
TEST_CASE(hash);
TEST_CASE(hashhash1);
TEST_CASE(hashhash2);
TEST_CASE(hashhash3);
TEST_CASE(hashhash4);
TEST_CASE(hashhash5);
TEST_CASE(hashhash6);
TEST_CASE(hashhash7); // # ## # (C standard; 6.10.3.3.p4)
TEST_CASE(hashhash8);
TEST_CASE(hashhash9);
TEST_CASE(hashhash_invalid_1);
TEST_CASE(hashhash_invalid_2);
TEST_CASE(ifdef1);
TEST_CASE(ifdef2);
TEST_CASE(ifndef);
TEST_CASE(ifA);
TEST_CASE(ifCharLiteral);
TEST_CASE(ifDefined);
TEST_CASE(ifDefinedNoPar);
TEST_CASE(ifDefinedNested);
TEST_CASE(ifDefinedNestedNoPar);
TEST_CASE(ifDefinedInvalid1);
TEST_CASE(ifDefinedInvalid2);
TEST_CASE(ifLogical);
TEST_CASE(ifSizeof);
TEST_CASE(elif);
TEST_CASE(ifif);
TEST_CASE(ifoverflow);
TEST_CASE(ifdiv0);
TEST_CASE(ifalt); // using "and", "or", etc
TEST_CASE(ifexpr);
TEST_CASE(location1);
TEST_CASE(location2);
TEST_CASE(location3);
TEST_CASE(missingHeader1);
TEST_CASE(missingHeader2);
TEST_CASE(missingHeader3);
TEST_CASE(nestedInclude);
TEST_CASE(nullDirective1);
TEST_CASE(nullDirective2);
TEST_CASE(nullDirective3);
TEST_CASE(include1);
TEST_CASE(include2);
TEST_CASE(include3);
TEST_CASE(include4); // -include
TEST_CASE(include5); // #include MACRO
TEST_CASE(include6); // invalid code: #include MACRO(,)
TEST_CASE(include7); // #include MACRO
TEST_CASE(include8); // #include MACRO(X)
TEST_CASE(multiline1);
TEST_CASE(multiline2);
TEST_CASE(multiline3);
TEST_CASE(multiline4);
TEST_CASE(multiline5); // column
TEST_CASE(multiline6); // multiline string in macro
TEST_CASE(multiline7); // multiline string in macro
TEST_CASE(multiline8); // multiline prefix string in macro
TEST_CASE(multiline9); // multiline prefix string in macro
TEST_CASE(multiline10);
TEST_CASE(readfile_nullbyte);
TEST_CASE(readfile_char);
TEST_CASE(readfile_char_error);
TEST_CASE(readfile_string);
TEST_CASE(readfile_string_error);
TEST_CASE(readfile_cpp14_number);
TEST_CASE(readfile_unhandled_chars);
TEST_CASE(readfile_error);
TEST_CASE(stringify1);
TEST_CASE(tokenMacro1);
TEST_CASE(tokenMacro2);
TEST_CASE(tokenMacro3);
TEST_CASE(tokenMacro4);
TEST_CASE(undef);
TEST_CASE(userdef);
// utf/unicode
TEST_CASE(utf8);
TEST_CASE(unicode);
TEST_CASE(warning);
// utility functions.
TEST_CASE(simplifyPath);
TEST_CASE(simplifyPath_cppcheck);
TEST_CASE(simplifyPath_New);
TEST_CASE(preprocessSizeOf);
return numberOfFailedAssertions > 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}