Support floats in valid config (#1297)
* Add tests for invalid ranges * Refactor loadLibErrors This reduces the amount of code slightly and will simplify adding more tests. * Handle empty valid field Before this change, the sequence <valid></valid> in a config file would result in a segmentation fault. Now an empty field results in the error message: cppcheck: Failed to load library configuration file 'mycfg.cfg'. Bad attribute value '""' * Add support for valid for floating point arguments Previously, it was not possible to add valid ranges to floating point arguments since it only handled integers. This made ranges not work well for floating point arguments since arguments were cast to integers before the ranges were handled. Fix this by using doubles instead of integers if the argument is a float. Add some tests for this and make sure errors are printed with enough precision (somewhat arbitrarily chosen). Note that it is still only possible to add integer ranges (i.e. -1:1). * Add support for floats in configuration valid range Now that it is possible to handle decimal arguments, there is no reason to not allow non-integer ranges. Take care to not allow broken configurations. * Move check to within if-clause * Move asin{,f,l} and acos{,f,l} input checks to config file
This commit is contained in:
parent
b05ae44edb
commit
491ee577c6
|
@ -154,7 +154,7 @@
|
|||
<element name="not-uninit"><empty/></element>
|
||||
<element name="valid">
|
||||
<data type="string">
|
||||
<param name="pattern">(-?[0-9]*[,:])*([-]?[0-9]+)?</param>
|
||||
<param name="pattern">(-?[0-9]*(\.[0-9]+)?[,:])*([-]?[0-9]+(\.[0-9]+)?)?</param>
|
||||
</data>
|
||||
</element>
|
||||
<element name="minsize">
|
||||
|
|
|
@ -108,6 +108,7 @@
|
|||
<leak-ignore/>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
<valid>-1.0:1.0</valid>
|
||||
</arg>
|
||||
</function>
|
||||
<!-- float acosf(float x); -->
|
||||
|
@ -119,6 +120,7 @@
|
|||
<leak-ignore/>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
<valid>-1.0:1.0</valid>
|
||||
</arg>
|
||||
</function>
|
||||
<!-- long double acosl(long double x); -->
|
||||
|
@ -130,6 +132,7 @@
|
|||
<leak-ignore/>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
<valid>-1.0:1.0</valid>
|
||||
</arg>
|
||||
</function>
|
||||
<!-- double acosh(double x); -->
|
||||
|
@ -348,6 +351,7 @@
|
|||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<arg nr="1">
|
||||
<valid>-1.0:1.0</valid>
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
</function>
|
||||
|
@ -359,6 +363,7 @@
|
|||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<arg nr="1">
|
||||
<valid>-1.0:1.0</valid>
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
</function>
|
||||
|
@ -370,6 +375,7 @@
|
|||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<arg nr="1">
|
||||
<valid>-1.0:1.0</valid>
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
</function>
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <iomanip>
|
||||
#include <ostream>
|
||||
#include <vector>
|
||||
|
||||
|
@ -119,9 +120,9 @@ void CheckFunctions::invalidFunctionUsage()
|
|||
invalidFunctionArgBoolError(argtok, functionToken->str(), argnr);
|
||||
|
||||
// Are the values 0 and 1 valid?
|
||||
else if (!mSettings->library.isargvalid(functionToken, argnr, 0))
|
||||
else if (!mSettings->library.isargvalid(functionToken, argnr, static_cast<MathLib::bigint>(0)))
|
||||
invalidFunctionArgError(argtok, functionToken->str(), argnr, nullptr, mSettings->library.validarg(functionToken, argnr));
|
||||
else if (!mSettings->library.isargvalid(functionToken, argnr, 1))
|
||||
else if (!mSettings->library.isargvalid(functionToken, argnr, static_cast<MathLib::bigint>(1)))
|
||||
invalidFunctionArgError(argtok, functionToken->str(), argnr, nullptr, mSettings->library.validarg(functionToken, argnr));
|
||||
}
|
||||
}
|
||||
|
@ -139,7 +140,7 @@ void CheckFunctions::invalidFunctionArgError(const Token *tok, const std::string
|
|||
else
|
||||
errmsg << "Invalid $symbol() argument nr " << argnr << '.';
|
||||
if (invalidValue)
|
||||
errmsg << " The value is " << invalidValue->intvalue << " but the valid values are '" << validstr << "'.";
|
||||
errmsg << " The value is " << std::setprecision(10) << (invalidValue->isIntValue() ? invalidValue->intvalue : invalidValue->floatValue) << " but the valid values are '" << validstr << "'.";
|
||||
else
|
||||
errmsg << " The value is 0 or 1 (boolean) but the valid values are '" << validstr << "'.";
|
||||
if (invalidValue)
|
||||
|
@ -241,11 +242,6 @@ void CheckFunctions::checkMathFunctions()
|
|||
}
|
||||
}
|
||||
|
||||
// acos( x ), asin( x ) where x is defined for interval [-1,+1], but not beyond
|
||||
else if (Token::Match(tok, "acos|acosl|acosf|asin|asinf|asinl ( %num% )")) {
|
||||
if (std::fabs(MathLib::toDoubleNumber(tok->strAt(2))) > 1.0)
|
||||
mathfunctionCallWarning(tok);
|
||||
}
|
||||
// sqrt( x ): if x is negative the result is undefined
|
||||
else if (Token::Match(tok, "sqrt|sqrtf|sqrtl ( %num% )")) {
|
||||
if (MathLib::isNegative(tok->strAt(2)))
|
||||
|
|
|
@ -43,6 +43,18 @@ static std::vector<std::string> getnames(const char *names)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void gettokenlistfromvalid(const std::string& valid, TokenList& tokenList)
|
||||
{
|
||||
std::istringstream istr(valid + ',');
|
||||
tokenList.createTokens(istr);
|
||||
for (Token *tok = tokenList.front(); tok; tok = tok->next()) {
|
||||
if (Token::Match(tok,"- %num%")) {
|
||||
tok->str("-" + tok->strAt(1));
|
||||
tok->deleteNext();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Library::Library() : mAllocId(0)
|
||||
{
|
||||
}
|
||||
|
@ -578,19 +590,33 @@ Library::Error Library::loadFunction(const tinyxml2::XMLElement * const node, co
|
|||
const char *p = argnode->GetText();
|
||||
bool error = false;
|
||||
bool range = false;
|
||||
bool has_dot = false;
|
||||
|
||||
if (!p)
|
||||
return Error(BAD_ATTRIBUTE_VALUE, "\"\"");
|
||||
|
||||
error = *p == '.';
|
||||
for (; *p; p++) {
|
||||
if (std::isdigit(*p))
|
||||
error |= (*(p+1) == '-');
|
||||
else if (*p == ':')
|
||||
error |= range;
|
||||
else if (*p == ':') {
|
||||
error |= range | (*(p+1) == '.');
|
||||
range = true;
|
||||
has_dot = false;
|
||||
}
|
||||
else if (*p == '-')
|
||||
error |= (!std::isdigit(*(p+1)));
|
||||
else if (*p == ',')
|
||||
else if (*p == ',') {
|
||||
range = false;
|
||||
error |= *(p+1) == '.';
|
||||
has_dot = false;
|
||||
}
|
||||
else if (*p == '.') {
|
||||
error |= has_dot | (!std::isdigit(*(p+1)));
|
||||
has_dot = true;
|
||||
}
|
||||
else
|
||||
error = true;
|
||||
|
||||
range |= (*p == ':');
|
||||
}
|
||||
if (error)
|
||||
return Error(BAD_ATTRIBUTE_VALUE, argnode->GetText());
|
||||
|
@ -705,15 +731,10 @@ bool Library::isargvalid(const Token *ftok, int argnr, const MathLib::bigint arg
|
|||
const ArgumentChecks *ac = getarg(ftok, argnr);
|
||||
if (!ac || ac->valid.empty())
|
||||
return true;
|
||||
else if (ac->valid.find('.') != std::string::npos)
|
||||
return isargvalid(ftok, argnr, static_cast<double>(argvalue));
|
||||
TokenList tokenList(nullptr);
|
||||
std::istringstream istr(ac->valid + ',');
|
||||
tokenList.createTokens(istr);
|
||||
for (Token *tok = tokenList.front(); tok; tok = tok->next()) {
|
||||
if (Token::Match(tok,"- %num%")) {
|
||||
tok->str("-" + tok->strAt(1));
|
||||
tok->deleteNext();
|
||||
}
|
||||
}
|
||||
gettokenlistfromvalid(ac->valid, tokenList);
|
||||
for (const Token *tok = tokenList.front(); tok; tok = tok->next()) {
|
||||
if (tok->isNumber() && argvalue == MathLib::toLongNumber(tok->str()))
|
||||
return true;
|
||||
|
@ -727,6 +748,24 @@ bool Library::isargvalid(const Token *ftok, int argnr, const MathLib::bigint arg
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Library::isargvalid(const Token *ftok, int argnr, double argvalue) const
|
||||
{
|
||||
const ArgumentChecks *ac = getarg(ftok, argnr);
|
||||
if (!ac || ac->valid.empty())
|
||||
return true;
|
||||
TokenList tokenList(nullptr);
|
||||
gettokenlistfromvalid(ac->valid, tokenList);
|
||||
for (const Token *tok = tokenList.front(); tok; tok = tok->next()) {
|
||||
if (Token::Match(tok, "%num% : %num%") && argvalue >= MathLib::toDoubleNumber(tok->str()) && argvalue <= MathLib::toDoubleNumber(tok->strAt(2)))
|
||||
return true;
|
||||
if (Token::Match(tok, "%num% : ,") && argvalue >= MathLib::toDoubleNumber(tok->str()))
|
||||
return true;
|
||||
if ((!tok->previous() || tok->previous()->str() == ",") && Token::Match(tok,": %num%") && argvalue <= MathLib::toDoubleNumber(tok->strAt(1)))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string Library::getFunctionName(const Token *ftok, bool *error) const
|
||||
{
|
||||
if (!ftok) {
|
||||
|
|
|
@ -301,6 +301,7 @@ public:
|
|||
}
|
||||
|
||||
bool isargvalid(const Token *ftok, int argnr, const MathLib::bigint argvalue) const;
|
||||
bool isargvalid(const Token *ftok, int argnr, double argvalue) const;
|
||||
|
||||
const std::string& validarg(const Token *ftok, int argnr) const {
|
||||
const ArgumentChecks *arg = getarg(ftok, argnr);
|
||||
|
|
|
@ -1497,7 +1497,8 @@ const ValueFlow::Value * Token::getInvalidValue(const Token *ftok, unsigned int
|
|||
const ValueFlow::Value *ret = nullptr;
|
||||
std::list<ValueFlow::Value>::const_iterator it;
|
||||
for (it = mValues->begin(); it != mValues->end(); ++it) {
|
||||
if (it->isIntValue() && !settings->library.isargvalid(ftok, argnr, it->intvalue)) {
|
||||
if ((it->isIntValue() && !settings->library.isargvalid(ftok, argnr, it->intvalue)) ||
|
||||
(it->isFloatValue() && !settings->library.isargvalid(ftok, argnr, it->floatValue))) {
|
||||
if (!ret || ret->isInconclusive() || (ret->condition && !it->isInconclusive()))
|
||||
ret = &(*it);
|
||||
if (!ret->isInconclusive() && !ret->condition)
|
||||
|
|
|
@ -1498,7 +1498,8 @@ Checking range.c...
|
|||
-10:20 => all values between -10 and 20 are valid
|
||||
:0 => all values that are less or equal to 0 are valid
|
||||
0: => all values that are greater or equal to 0 are valid
|
||||
0,2:32 => the value 0 and all values between 2 and 32 are valid </programlisting>
|
||||
0,2:32 => the value 0 and all values between 2 and 32 are valid
|
||||
-1.5:5.6 => all values between -1.5 and 5.6 are valid </programlisting>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
|
|
|
@ -604,9 +604,9 @@ private:
|
|||
" std::cout << acosf(1.1) << std::endl;\n"
|
||||
" std::cout << acosl(1.1) << std::endl;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (warning) Passing value 1.1 to acos() leads to implementation-defined result.\n"
|
||||
"[test.cpp:4]: (warning) Passing value 1.1 to acosf() leads to implementation-defined result.\n"
|
||||
"[test.cpp:5]: (warning) Passing value 1.1 to acosl() leads to implementation-defined result.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Invalid acos() argument nr 1. The value is 1.1 but the valid values are '-1.0:1.0'.\n"
|
||||
"[test.cpp:4]: (error) Invalid acosf() argument nr 1. The value is 1.1 but the valid values are '-1.0:1.0'.\n"
|
||||
"[test.cpp:5]: (error) Invalid acosl() argument nr 1. The value is 1.1 but the valid values are '-1.0:1.0'.\n", errout.str());
|
||||
|
||||
check("void foo()\n"
|
||||
"{\n"
|
||||
|
@ -614,9 +614,9 @@ private:
|
|||
" std::cout << acosf(-1.1) << std::endl;\n"
|
||||
" std::cout << acosl(-1.1) << std::endl;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (warning) Passing value -1.1 to acos() leads to implementation-defined result.\n"
|
||||
"[test.cpp:4]: (warning) Passing value -1.1 to acosf() leads to implementation-defined result.\n"
|
||||
"[test.cpp:5]: (warning) Passing value -1.1 to acosl() leads to implementation-defined result.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Invalid acos() argument nr 1. The value is -1.1 but the valid values are '-1.0:1.0'.\n"
|
||||
"[test.cpp:4]: (error) Invalid acosf() argument nr 1. The value is -1.1 but the valid values are '-1.0:1.0'.\n"
|
||||
"[test.cpp:5]: (error) Invalid acosl() argument nr 1. The value is -1.1 but the valid values are '-1.0:1.0'.\n", errout.str());
|
||||
}
|
||||
|
||||
void mathfunctionCall_asin() {
|
||||
|
@ -665,9 +665,9 @@ private:
|
|||
" std::cout << asinf(1.1) << std::endl;\n"
|
||||
" std::cout << asinl(1.1) << std::endl;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (warning) Passing value 1.1 to asin() leads to implementation-defined result.\n"
|
||||
"[test.cpp:4]: (warning) Passing value 1.1 to asinf() leads to implementation-defined result.\n"
|
||||
"[test.cpp:5]: (warning) Passing value 1.1 to asinl() leads to implementation-defined result.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Invalid asin() argument nr 1. The value is 1.1 but the valid values are '-1.0:1.0'.\n"
|
||||
"[test.cpp:4]: (error) Invalid asinf() argument nr 1. The value is 1.1 but the valid values are '-1.0:1.0'.\n"
|
||||
"[test.cpp:5]: (error) Invalid asinl() argument nr 1. The value is 1.1 but the valid values are '-1.0:1.0'.\n", errout.str());
|
||||
|
||||
check("void foo()\n"
|
||||
"{\n"
|
||||
|
@ -675,9 +675,9 @@ private:
|
|||
" std::cout << asinf(-1.1) << std::endl;\n"
|
||||
" std::cout << asinl(-1.1) << std::endl;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (warning) Passing value -1.1 to asin() leads to implementation-defined result.\n"
|
||||
"[test.cpp:4]: (warning) Passing value -1.1 to asinf() leads to implementation-defined result.\n"
|
||||
"[test.cpp:5]: (warning) Passing value -1.1 to asinl() leads to implementation-defined result.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Invalid asin() argument nr 1. The value is -1.1 but the valid values are '-1.0:1.0'.\n"
|
||||
"[test.cpp:4]: (error) Invalid asinf() argument nr 1. The value is -1.1 but the valid values are '-1.0:1.0'.\n"
|
||||
"[test.cpp:5]: (error) Invalid asinl() argument nr 1. The value is -1.1 but the valid values are '-1.0:1.0'.\n", errout.str());
|
||||
}
|
||||
|
||||
void mathfunctionCall_pow() {
|
||||
|
|
|
@ -282,6 +282,11 @@ private:
|
|||
" <arg nr=\"3\"><valid>1:5,8</valid></arg>\n"
|
||||
" <arg nr=\"4\"><valid>-1,5</valid></arg>\n"
|
||||
" <arg nr=\"5\"><valid>:1,5</valid></arg>\n"
|
||||
" <arg nr=\"6\"><valid>1.5:</valid></arg>\n"
|
||||
" <arg nr=\"7\"><valid>-6.7:-5.5,-3.3:-2.7</valid></arg>\n"
|
||||
" <arg nr=\"8\"><valid>0.0:</valid></arg>\n"
|
||||
" <arg nr=\"9\"><valid>:2.0</valid></arg>\n"
|
||||
" <arg nr=\"10\"><valid>0.0</valid></arg>\n"
|
||||
" </function>\n"
|
||||
"</def>";
|
||||
|
||||
|
@ -289,41 +294,125 @@ private:
|
|||
ASSERT_EQUALS(true, Library::OK == (readLibrary(library, xmldata)).errorcode);
|
||||
|
||||
TokenList tokenList(nullptr);
|
||||
std::istringstream istr("foo(a,b,c,d,e);");
|
||||
std::istringstream istr("foo(a,b,c,d,e,f,g,h,i,j);");
|
||||
tokenList.createTokens(istr);
|
||||
tokenList.front()->next()->astOperand1(tokenList.front());
|
||||
|
||||
// 1-
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 1, -10));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 1, 0));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 1, 1));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 1, 10));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 1, static_cast<MathLib::bigint>(-10)));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 1, -10.0));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 1, static_cast<MathLib::bigint>(0)));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 1, 0.0));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 1, static_cast<MathLib::bigint>(1)));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 1, 1.0));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 1, static_cast<MathLib::bigint>(10)));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 1, 10.0));
|
||||
|
||||
// -7-0
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 2, -10));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 2, -7));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 2, -3));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 2, 0));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 2, 1));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 2, static_cast<MathLib::bigint>(-10)));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 2, -10.0));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 2, -7.5));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 2, -7.1));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 2, static_cast<MathLib::bigint>(-7)));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 2, -7.0));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 2, static_cast<MathLib::bigint>(-3)));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 2, -3.0));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 2, -3.5));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 2, static_cast<MathLib::bigint>(0)));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 2, 0.0));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 2, 0.5));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 2, static_cast<MathLib::bigint>(1)));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 2, 1.0));
|
||||
|
||||
// 1-5,8
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 3, 0));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 3, 1));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 3, 3));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 3, 5));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 3, 6));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 3, 7));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 3, 8));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 3, 9));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 3, static_cast<MathLib::bigint>(0)));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 3, 0.0));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 3, static_cast<MathLib::bigint>(1)));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 3, 1.0));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 3, static_cast<MathLib::bigint>(3)));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 3, 3.0));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 3, static_cast<MathLib::bigint>(5)));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 3, 5.0));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 3, static_cast<MathLib::bigint>(6)));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 3, 6.0));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 3, static_cast<MathLib::bigint>(7)));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 3, 7.0));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 3, static_cast<MathLib::bigint>(8)));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 3, 8.0));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 3, static_cast<MathLib::bigint>(9)));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 3, 9.0));
|
||||
|
||||
// -1,5
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 4, -10));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 4, -1));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 4, static_cast<MathLib::bigint>(-10)));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 4, -10.0));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 4, static_cast<MathLib::bigint>(-1)));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 4, -1.0));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 4, 5.000001));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 4, 5.5));
|
||||
|
||||
// :1,5
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 5, -10));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 5, 1));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 5, 2));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 5, static_cast<MathLib::bigint>(-10)));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 5, -10.0));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 5, static_cast<MathLib::bigint>(1)));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 5, 1.0));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 5, static_cast<MathLib::bigint>(2)));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 5, 2.0));
|
||||
|
||||
// 1.5:
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 6, static_cast<MathLib::bigint>(0)));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 6, 0.0));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 6, static_cast<MathLib::bigint>(1)));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 6, 1.499999));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 6, 1.5));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 6, static_cast<MathLib::bigint>(2)));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 6, static_cast<MathLib::bigint>(10)));
|
||||
|
||||
// -6.7:-5.5,-3.3:-2.7
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 7, static_cast<MathLib::bigint>(-7)));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 7, -7.0));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 7, -6.7000001));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 7, -6.7));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 7, static_cast<MathLib::bigint>(-6)));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 7, -6.0));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 7, -5.5));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 7, -5.4999999));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 7, -3.3000001));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 7, -3.3));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 7, static_cast<MathLib::bigint>(-3)));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 7, -3.0));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 7, -2.7));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 7, -2.6999999));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 7, static_cast<MathLib::bigint>(-2)));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 7, -2.0));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 7, static_cast<MathLib::bigint>(0)));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 7, 0.0));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 7, static_cast<MathLib::bigint>(3)));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 7, 3.0));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 7, static_cast<MathLib::bigint>(6)));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 7, 6.0));
|
||||
|
||||
// 0.0:
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 8, static_cast<MathLib::bigint>(-1)));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 8, -1.0));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 8, -0.00000001));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 8, static_cast<MathLib::bigint>(0)));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 8, 0.0));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 8, 0.000000001));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 8, static_cast<MathLib::bigint>(1)));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 8, 1.0));
|
||||
|
||||
// :2.0
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 9, static_cast<MathLib::bigint>(-1)));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 9, -1.0));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 9, static_cast<MathLib::bigint>(2)));
|
||||
ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 9, 2.0));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 9, 2.00000001));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 9, static_cast<MathLib::bigint>(200)));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 9, 200.0));
|
||||
|
||||
// 0.0
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 10, static_cast<MathLib::bigint>(0)));
|
||||
ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 10, 0.0));
|
||||
}
|
||||
|
||||
void function_arg_minsize() const {
|
||||
|
@ -724,54 +813,105 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
void loadLibError(const char xmldata [], Library::ErrorCode errorcode, const char* file, unsigned line) const {
|
||||
Library library;
|
||||
assertEquals(file, line, errorcode, readLibrary(library, xmldata).errorcode);
|
||||
}
|
||||
|
||||
#define LOADLIBERROR(xmldata, errorcode) loadLibError(xmldata, errorcode, __FILE__, __LINE__)
|
||||
#define LOADLIB_ERROR_INVALID_RANGE(valid) LOADLIBERROR("<?xml version=\"1.0\"?>\n" \
|
||||
"<def>\n" \
|
||||
"<function name=\"f\">\n" \
|
||||
"<arg nr=\"1\">\n" \
|
||||
"<valid>" valid "</valid>\n" \
|
||||
"</arg>\n" \
|
||||
"</function>\n" \
|
||||
"</def>", \
|
||||
Library::BAD_ATTRIBUTE_VALUE)
|
||||
|
||||
void loadLibErrors() const {
|
||||
// UNKNOWN_ELEMENT
|
||||
{
|
||||
const char xmldata [] = "<?xml version=\"1.0\"?>\n"
|
||||
"<def>\n"
|
||||
" <X name=\"uint8_t,std::uint8_t\" size=\"1\"/>\n"
|
||||
"</def>";
|
||||
Library library;
|
||||
ASSERT_EQUALS(Library::UNKNOWN_ELEMENT, readLibrary(library, xmldata).errorcode);
|
||||
}
|
||||
// MISSING_ATTRIBUTE
|
||||
{
|
||||
// #define without attributes
|
||||
{
|
||||
const char xmldata [] = "<?xml version=\"1.0\"?>\n"
|
||||
"<def>\n"
|
||||
" <define />\n" // no attributes provided at all
|
||||
"</def>";
|
||||
Library library;
|
||||
ASSERT_EQUALS(Library::MISSING_ATTRIBUTE, readLibrary(library, xmldata).errorcode);
|
||||
}
|
||||
// #define with name but without value
|
||||
{
|
||||
const char xmldata [] = "<?xml version=\"1.0\"?>\n"
|
||||
"<def>\n"
|
||||
" <define name=\"foo\" />\n" // no value provided
|
||||
"</def>";
|
||||
Library library;
|
||||
ASSERT_EQUALS(Library::MISSING_ATTRIBUTE, readLibrary(library, xmldata).errorcode);
|
||||
}
|
||||
// #define with value but without a name
|
||||
{
|
||||
const char xmldata [] = "<?xml version=\"1.0\"?>\n"
|
||||
"<def>\n"
|
||||
" <define value=\"1\" />\n" // no name provided
|
||||
"</def>";
|
||||
Library library;
|
||||
ASSERT_EQUALS(Library::MISSING_ATTRIBUTE, readLibrary(library, xmldata).errorcode);
|
||||
}
|
||||
}
|
||||
// UNSUPPORTED_FORMAT
|
||||
{
|
||||
const char xmldata [] = "<?xml version=\"1.0\"?>\n"
|
||||
"<X>\n"
|
||||
"</X>";
|
||||
Library library;
|
||||
ASSERT_EQUALS(Library::UNSUPPORTED_FORMAT, readLibrary(library, xmldata).errorcode);
|
||||
}
|
||||
|
||||
LOADLIBERROR("<?xml version=\"1.0\"?>\n"
|
||||
"<def>\n"
|
||||
" <X name=\"uint8_t,std::uint8_t\" size=\"1\"/>\n"
|
||||
"</def>",
|
||||
Library::UNKNOWN_ELEMENT);
|
||||
|
||||
// #define without attributes
|
||||
LOADLIBERROR("<?xml version=\"1.0\"?>\n"
|
||||
"<def>\n"
|
||||
" <define />\n" // no attributes provided at all
|
||||
"</def>",
|
||||
Library::MISSING_ATTRIBUTE);
|
||||
|
||||
// #define with name but without value
|
||||
LOADLIBERROR("<?xml version=\"1.0\"?>\n"
|
||||
"<def>\n"
|
||||
" <define name=\"foo\" />\n" // no value provided
|
||||
"</def>",
|
||||
Library::MISSING_ATTRIBUTE);
|
||||
|
||||
LOADLIBERROR("<?xml version=\"1.0\"?>\n"
|
||||
"<def>\n"
|
||||
" <define value=\"1\" />\n" // no name provided
|
||||
"</def>",
|
||||
Library::MISSING_ATTRIBUTE);
|
||||
|
||||
LOADLIBERROR("<?xml version=\"1.0\"?>\n"
|
||||
"<X>\n"
|
||||
"</X>",
|
||||
Library::UNSUPPORTED_FORMAT);
|
||||
|
||||
// empty range
|
||||
LOADLIB_ERROR_INVALID_RANGE("");
|
||||
|
||||
// letter as range
|
||||
LOADLIB_ERROR_INVALID_RANGE("a");
|
||||
|
||||
// letter and number as range
|
||||
LOADLIB_ERROR_INVALID_RANGE("1a");
|
||||
|
||||
// digit followed by dash
|
||||
LOADLIB_ERROR_INVALID_RANGE("0:2-1");
|
||||
|
||||
// single dash
|
||||
LOADLIB_ERROR_INVALID_RANGE("-");
|
||||
|
||||
// range with multiple colons
|
||||
LOADLIB_ERROR_INVALID_RANGE("1:2:3");
|
||||
|
||||
// extra dot
|
||||
LOADLIB_ERROR_INVALID_RANGE("1.0.0:10");
|
||||
|
||||
// consecutive dots
|
||||
LOADLIB_ERROR_INVALID_RANGE("1..0:10");
|
||||
|
||||
// dot followed by dash
|
||||
LOADLIB_ERROR_INVALID_RANGE("1.-0:10");
|
||||
|
||||
// dot without preceding number
|
||||
LOADLIB_ERROR_INVALID_RANGE(".5:10");
|
||||
|
||||
// dash followed by dot
|
||||
LOADLIB_ERROR_INVALID_RANGE("-.5:10");
|
||||
|
||||
// colon followed by dot without preceding number
|
||||
LOADLIB_ERROR_INVALID_RANGE("0:.5");
|
||||
|
||||
// colon followed by dash followed by dot
|
||||
LOADLIB_ERROR_INVALID_RANGE("-10:-.5");
|
||||
|
||||
// dot not followed by number
|
||||
LOADLIB_ERROR_INVALID_RANGE("1:5.");
|
||||
|
||||
// dot not followed by number
|
||||
LOADLIB_ERROR_INVALID_RANGE("1.:5");
|
||||
|
||||
// dot followed by comma
|
||||
LOADLIB_ERROR_INVALID_RANGE("1:5.,6:10");
|
||||
|
||||
// comma followed by dot
|
||||
LOADLIB_ERROR_INVALID_RANGE("-10:0,.5:");
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue