From c391a03db6bd25c03e05d9f328bfafbd511f3b19 Mon Sep 17 00:00:00 2001 From: Martin Ettl Date: Fri, 2 Apr 2010 20:23:37 +0200 Subject: [PATCH] added acos() check to ticket #1513; added testcases for MathLib::toDoubleNumber(), now double conversion of zeros is handled correctly; changed assertEquals() function of testsuite parameters from unsigned int to double. This is needed to avoid overflow of unsigned int by comparing negative floating point values. --- lib/checkother.cpp | 7 +++++++ lib/mathlib.cpp | 5 +++++ test/testmathlib.cpp | 21 +++++++++++++++++++++ test/testother.cpp | 38 ++++++++++++++++++++++++++++++++++++-- test/testsuite.cpp | 2 +- test/testsuite.h | 6 +++++- 6 files changed, 75 insertions(+), 4 deletions(-) diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 3405ad00b..155d0ea9d 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -30,6 +30,7 @@ #include #include #include +#include // fabs() //--------------------------------------------------------------------------- // Register this check class (by creating a static instance of it) @@ -2472,6 +2473,12 @@ void CheckOther::checkMathFunctions() MathLib::toLongNumber(tok->tokAt(2)->str()) <= 0) { mathfunctionCallError(tok); + } + // acos( x ) x is defined for intervall [-1,+1], but not beyound + else if(Token::Match(tok, "acos ( %num% )") && + fabs(MathLib::toDoubleNumber(tok->tokAt(2)->str())) > 1.0) + { + mathfunctionCallError(tok); } } } diff --git a/lib/mathlib.cpp b/lib/mathlib.cpp index c1f002dcd..006e41a7e 100644 --- a/lib/mathlib.cpp +++ b/lib/mathlib.cpp @@ -55,6 +55,11 @@ double MathLib::toDoubleNumber(const std::string &str) { return std::strtoul(str.c_str(), '\0', 16); } + // nullcheck + else if (str == "-0" || str == "-0.0" || str == "-0." + || str == "+0" || str == "+0.0" || str == "+0.") + return 0.0; + // otherwise, convert to double std::istringstream istr(str.c_str()); double ret; istr >> ret; diff --git a/test/testmathlib.cpp b/test/testmathlib.cpp index 12a24c304..c59d75682 100644 --- a/test/testmathlib.cpp +++ b/test/testmathlib.cpp @@ -115,6 +115,27 @@ private: ASSERT_EQUALS(-1 , MathLib::toLongNumber("-10.E-1")); ASSERT_EQUALS(100 , MathLib::toLongNumber("+10.0E+1")); ASSERT_EQUALS(-1 , MathLib::toLongNumber("-10.0E-1")); + + // ----------------- + // to double number: + // ----------------- + ASSERT_EQUALS(10.0 , MathLib::toDoubleNumber("10")); + ASSERT_EQUALS(1000.0, MathLib::toDoubleNumber("10E+2")); + ASSERT_EQUALS(100.0 , MathLib::toDoubleNumber("1.0E+2")); + ASSERT_EQUALS(-100.0, MathLib::toDoubleNumber("-1.0E+2")); + ASSERT_EQUALS(-1e+10, MathLib::toDoubleNumber("-1.0E+10")); + ASSERT_EQUALS(100.0 , MathLib::toDoubleNumber("+1.0E+2")); + ASSERT_EQUALS(1e+10 , MathLib::toDoubleNumber("+1.0E+10")); + ASSERT_EQUALS(100.0 , MathLib::toDoubleNumber("1.0E+2")); + ASSERT_EQUALS(1e+10 , MathLib::toDoubleNumber("1.0E+10")); + ASSERT_EQUALS(0.0 , MathLib::toDoubleNumber("0")); + ASSERT_EQUALS(0.0 , MathLib::toDoubleNumber("-0")); + ASSERT_EQUALS(0.0 , MathLib::toDoubleNumber("+0")); + ASSERT_EQUALS(0.0 , MathLib::toDoubleNumber("-0.")); + ASSERT_EQUALS(0.0 , MathLib::toDoubleNumber("+0.")); + ASSERT_EQUALS(0.0 , MathLib::toDoubleNumber("-0.0")); + ASSERT_EQUALS(0.0 , MathLib::toDoubleNumber("+0.0")); + } void isint() diff --git a/test/testother.cpp b/test/testother.cpp index 7ae987a10..229ad3c58 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -2169,6 +2169,7 @@ private: void mathfunctionCall1() { + // log|log10 check("void foo()\n" "{\n" " std::cout << log(-2) << std::endl;\n" @@ -2228,9 +2229,42 @@ private: " std::cout << log(1E-3) << std::endl;\n" "}"); TODO_ASSERT_EQUALS("", errout.str()); + + // acos + check("void foo()\n" + "{\n" + " std::cout << acos(1) << std::endl;\n" + " std::cout << acos(-1) << std::endl;\n" + " std::cout << acos(0.1) << std::endl;\n" + " std::cout << acos(0.0001) << std::endl;\n" + " std::cout << acos(0.01) << std::endl;\n" + " std::cout << acos(1.0E-1) << std::endl;\n" + " std::cout << acos(-1.0E-1) << std::endl;\n" + " std::cout << acos(+1.0E-1) << std::endl;\n" + " std::cout << acos(0.1E-1) << std::endl;\n" + " std::cout << acos(+0.1E-1) << std::endl;\n" + " std::cout << acos(-0.1E-1) << std::endl;\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + check("void foo()\n" + "{\n" + " std::cout << acos(1.1) << std::endl;\n" + "}"); + ASSERT_EQUALS("[test.cpp:3]: (error) Passing value 1.1 to acos() leads to undefined result\n", errout.str()); + + check("void foo()\n" + "{\n" + " std::cout << acos(-1.1) << std::endl;\n" + "}"); + ASSERT_EQUALS("[test.cpp:3]: (error) Passing value -1.1 to acos() leads to undefined result\n", errout.str()); + + check("void foo()\n" + "{\n" + " std::cout << acos(-110) << std::endl;\n" + "}"); + ASSERT_EQUALS("[test.cpp:3]: (error) Passing value -110 to acos() leads to undefined result\n", errout.str()); } - - }; REGISTER_TEST(TestOther) diff --git a/test/testsuite.cpp b/test/testsuite.cpp index 431be1415..c69f313ba 100644 --- a/test/testsuite.cpp +++ b/test/testsuite.cpp @@ -118,7 +118,7 @@ void TestFixture::assertEquals(const char *filename, int linenr, const std::stri } } -void TestFixture::assertEquals(const char *filename, int linenr, unsigned int expected, unsigned int actual) +void TestFixture::assertEquals(const char *filename, int linenr, double expected, double actual) { std::ostringstream ostr1; ostr1 << expected; diff --git a/test/testsuite.h b/test/testsuite.h index e14015b39..1eb5af95f 100644 --- a/test/testsuite.h +++ b/test/testsuite.h @@ -42,7 +42,11 @@ protected: bool runTest(const char testname[]); void assertEquals(const char *filename, int linenr, const std::string &expected, const std::string &actual); - void assertEquals(const char *filename, int linenr, unsigned int expected, unsigned int actual); + + // the vars expected and actual need to be of type double, in order to avoid overflow of unsigned int + // e.g: ASSERT_EQUALS(-100.0, MathLib::toDoubleNumber("-1.0E+2")); whould not work without this. + void assertEquals(const char *filename, int linenr, double expected, double actual); + void todoAssertEquals(const char *filename, int linenr, const std::string &expected, const std::string &actual); void todoAssertEquals(const char *filename, int linenr, unsigned int expected, unsigned int actual); void assertThrowFail(const char *filename, int linenr);