From 12aa76143362d8ddf53b3b0ed410dd9db9362469 Mon Sep 17 00:00:00 2001 From: Gennady Pospelov <g.pospelov@fz-juelich.de> Date: Fri, 13 Mar 2015 12:41:31 +0100 Subject: [PATCH] RealParameterWrapper::setValue now respect limits attribute, corresponding unit tests. --- Core/Tools/inc/AttLimits.h | 65 +++++++++++++---- Core/Tools/inc/RealParameterWrapper.h | 17 ++++- Core/Tools/src/RealParameterWrapper.cpp | 12 ++- Tests/UnitTests/TestCore/AttLimitsTest.h | 73 +++++++++++++++++-- .../TestCore/RealParameterWrapperTest.h | 28 +++++++ 5 files changed, 173 insertions(+), 22 deletions(-) diff --git a/Core/Tools/inc/AttLimits.h b/Core/Tools/inc/AttLimits.h index bdc542c2d33..ffd63c8674c 100644 --- a/Core/Tools/inc/AttLimits.h +++ b/Core/Tools/inc/AttLimits.h @@ -29,38 +29,49 @@ class BA_CORE_API_ AttLimits { public: AttLimits() : m_has_lower_limit(false), m_has_upper_limit(false), m_is_fixed(false), m_lower_limit(0), m_upper_limit(0) {} - virtual ~AttLimits(){} + ~AttLimits(){} //! if has lower limit - virtual bool hasLowerLimit() const { return m_has_lower_limit; } + bool hasLowerLimit() const { return m_has_lower_limit; } + //! Returns lower limit - virtual double getLowerLimit() const { return m_lower_limit; } + double getLowerLimit() const { return m_lower_limit; } + //! Sets lower limit - virtual void setLowerLimit(double value) { m_lower_limit = value; m_has_lower_limit = true; } + void setLowerLimit(double value) { m_lower_limit = value; m_has_lower_limit = true; } + //! remove lower limit - virtual void removeLowerLimit() { m_lower_limit = 0.0; m_has_lower_limit = false; } + void removeLowerLimit() { m_lower_limit = 0.0; m_has_lower_limit = false; } //! if has upper limit - virtual bool hasUpperLimit() const { return m_has_upper_limit; } + bool hasUpperLimit() const { return m_has_upper_limit; } + //! Returns upper limit - virtual double getUpperLimit() const { return m_upper_limit; } + double getUpperLimit() const { return m_upper_limit; } + //! Sets upper limit - virtual void setUpperLimit(double value) { m_upper_limit = value; m_has_upper_limit = true; } + void setUpperLimit(double value) { m_upper_limit = value; m_has_upper_limit = true; } + //! remove upper limit - virtual void removeUpperLimit() { m_upper_limit = 0.0; m_has_upper_limit = false; } + void removeUpperLimit() { m_upper_limit = 0.0; m_has_upper_limit = false; } //! if has lower and upper limit - virtual bool hasLowerAndUpperLimits() const { return (m_has_lower_limit && m_has_upper_limit); } + bool hasLowerAndUpperLimits() const { return (m_has_lower_limit && m_has_upper_limit); } //! Sets object fixed - virtual void setFixed(bool is_fixed) { m_is_fixed = is_fixed; } + void setFixed(bool is_fixed) { m_is_fixed = is_fixed; } + //! if object is fixed at some value - virtual bool isFixed() const { return m_is_fixed; } + bool isFixed() const { return m_is_fixed; } //! Sets lower and upper limits - virtual void setLimits(double xmin, double xmax) { setLowerLimit(xmin); setUpperLimit(xmax); } + void setLimits(double xmin, double xmax) { setLowerLimit(xmin); setUpperLimit(xmax); } + //! remove limits - virtual void removeLimits() { removeLowerLimit(); removeUpperLimit(); } + void removeLimits() { removeLowerLimit(); removeUpperLimit(); } + + //! returns true if proposed value is in limits range + bool isInRange(double value) const; // --------- // static creation methods @@ -83,6 +94,9 @@ class BA_CORE_API_ AttLimits //! Prints class friend std::ostream& operator<<(std::ostream& ostr, const AttLimits& m) { m.print(ostr); return ostr; } + bool operator==(const AttLimits &other) const; + bool operator!=(const AttLimits &other) const; + protected: AttLimits(bool has_lower_limit, bool has_upper_limit, bool is_fixed, double lower_limit, double upper_limit) : m_has_lower_limit(has_lower_limit) @@ -115,6 +129,29 @@ class BA_CORE_API_ AttLimits } }; + +inline bool AttLimits::isInRange(double value) const +{ + if(hasLowerLimit() && value < m_lower_limit) return false; + if(hasUpperLimit() && value >= m_upper_limit) return false; + return true; +} + +inline bool AttLimits::operator==(const AttLimits &other) const +{ + return (m_has_lower_limit == other.m_has_lower_limit) && + (m_has_upper_limit == other.m_has_upper_limit) && + (m_lower_limit == other.m_lower_limit) && + (m_upper_limit == other.m_upper_limit); + +} + +inline bool AttLimits::operator!=(const AttLimits &other) const +{ + return !(*this == other); +} + + #endif // LIMITS_H diff --git a/Core/Tools/inc/RealParameterWrapper.h b/Core/Tools/inc/RealParameterWrapper.h index 7eb4dbb9879..8b0b6577df3 100644 --- a/Core/Tools/inc/RealParameterWrapper.h +++ b/Core/Tools/inc/RealParameterWrapper.h @@ -52,6 +52,11 @@ public: ostr << p.m_data; return ostr; } + AttLimits getAttLimits() const { return m_limits; } + + bool operator==(const RealParameterWrapper &other) const; + bool operator!=(const RealParameterWrapper &other) const; + private: //! swap function void swapContent(RealParameterWrapper& other); @@ -75,7 +80,17 @@ inline void RealParameterWrapper::checkNull() const { if(isNull()) throw NullPointerException( - "RealParameterWrapper::getValue() -> Attempt to access uninitialised pointer."); + "RealParameterWrapper::getValue() -> Attempt to access uninitialised pointer."); +} + +inline bool RealParameterWrapper::operator==(const RealParameterWrapper &other) const +{ + return (m_limits == other.m_limits) && (m_data == other.m_data); +} + +inline bool RealParameterWrapper::operator!=(const RealParameterWrapper &other) const +{ + return !(*this == other); } diff --git a/Core/Tools/src/RealParameterWrapper.cpp b/Core/Tools/src/RealParameterWrapper.cpp index 3cbd1884d2f..aa77cf6d1eb 100644 --- a/Core/Tools/src/RealParameterWrapper.cpp +++ b/Core/Tools/src/RealParameterWrapper.cpp @@ -19,7 +19,11 @@ RealParameterWrapper::RealParameterWrapper(double *par, const AttLimits &limits) : m_data(par) , m_limits(limits) { - + if(par && !m_limits.isInRange(getValue())) { + throw OutOfBoundsException( + "RealParameterWrapper::RealParameterWrapper() -> Error. Initial value is out of bounds" + ); + } } RealParameterWrapper::RealParameterWrapper(const RealParameterWrapper& other ) @@ -42,7 +46,11 @@ bool RealParameterWrapper::setValue(double value) bool success(true); checkNull(); if(value != *m_data) { - *m_data = value; + if(m_limits.isInRange(value) && !m_limits.isFixed()) { + *m_data = value; + } else { + success = false; + } } return success; } diff --git a/Tests/UnitTests/TestCore/AttLimitsTest.h b/Tests/UnitTests/TestCore/AttLimitsTest.h index 7acf045956d..8d376ece6f9 100644 --- a/Tests/UnitTests/TestCore/AttLimitsTest.h +++ b/Tests/UnitTests/TestCore/AttLimitsTest.h @@ -2,6 +2,7 @@ #define ATTLIMITSTEST_H #include "AttLimits.h" +#include <limits> #include "gtest/gtest.h" @@ -30,38 +31,63 @@ TEST_F(AttLimitsTest, AttLimitsSetLimit) { AttLimits attLimits; - //set limit + //set limit [-1.0, 10.0[ attLimits.setLimits(-1.0,10.0); EXPECT_TRUE(attLimits.hasLowerLimit()); EXPECT_TRUE(attLimits.hasUpperLimit()); EXPECT_TRUE(attLimits.hasLowerAndUpperLimits()); EXPECT_FALSE(attLimits.isFixed()); - //lower limit EXPECT_EQ(-1.0,attLimits.getLowerLimit()); + EXPECT_EQ(10.0,attLimits.getUpperLimit()); + + EXPECT_FALSE(attLimits.isInRange(-2.0)); + EXPECT_TRUE(attLimits.isInRange(-1.0)); + EXPECT_TRUE(attLimits.isInRange(0.0)); + EXPECT_TRUE(attLimits.isInRange(9.0)); + EXPECT_FALSE(attLimits.isInRange(10.0)); + EXPECT_FALSE(attLimits.isInRange(20.0)); + // [inf, -10.0[ attLimits.removeLowerLimit(); EXPECT_FALSE(attLimits.hasLowerAndUpperLimits()); EXPECT_FALSE(attLimits.hasLowerLimit()); EXPECT_EQ(0.0,attLimits.getLowerLimit()); + EXPECT_TRUE(attLimits.isInRange(-std::numeric_limits<double>::infinity())); + EXPECT_TRUE(attLimits.isInRange(-2.0)); + EXPECT_TRUE(attLimits.isInRange(9.0)); + EXPECT_FALSE(attLimits.isInRange(10.0)); + EXPECT_FALSE(attLimits.isInRange(std::numeric_limits<double>::infinity())); + + // [2.1, -10.0[ attLimits.setLowerLimit(2.1); EXPECT_TRUE(attLimits.hasLowerLimit()); EXPECT_EQ(2.1,attLimits.getLowerLimit()); - //upper limit - EXPECT_EQ(10.0,attLimits.getUpperLimit()); + EXPECT_FALSE(attLimits.isInRange(-std::numeric_limits<double>::infinity())); + EXPECT_FALSE(attLimits.isInRange(2.0)); + EXPECT_TRUE(attLimits.isInRange(2.1)); + //[2.1, inf] attLimits.removeUpperLimit(); EXPECT_FALSE(attLimits.hasLowerAndUpperLimits()); EXPECT_FALSE(attLimits.hasUpperLimit()); EXPECT_EQ(0.0,attLimits.getUpperLimit()); + EXPECT_FALSE(attLimits.isInRange(-std::numeric_limits<double>::infinity())); + EXPECT_FALSE(attLimits.isInRange(2.0)); + EXPECT_TRUE(attLimits.isInRange(2.1)); + EXPECT_TRUE(attLimits.isInRange(20.0)); + EXPECT_TRUE(attLimits.isInRange(std::numeric_limits<double>::infinity())); + + // [2.1, 2.2[ attLimits.setUpperLimit(2.2); EXPECT_TRUE(attLimits.hasUpperLimit()); EXPECT_EQ(2.2,attLimits.getUpperLimit()); - EXPECT_TRUE(attLimits.hasLowerAndUpperLimits()); + EXPECT_TRUE(attLimits.isInRange(2.15)); + EXPECT_FALSE(attLimits.isInRange(2.2)); //remove limit attLimits.removeLimits(); @@ -70,6 +96,9 @@ TEST_F(AttLimitsTest, AttLimitsSetLimit) EXPECT_FALSE(attLimits.hasLowerAndUpperLimits()); EXPECT_FALSE(attLimits.isFixed()); + EXPECT_TRUE(attLimits.isInRange(-std::numeric_limits<double>::infinity())); + EXPECT_TRUE(attLimits.isInRange(std::numeric_limits<double>::infinity())); + } TEST_F(AttLimitsTest, AttLimitsLowerLimited) @@ -134,5 +163,39 @@ TEST_F(AttLimitsTest, AttLimitsFixed) EXPECT_FALSE(attLimits.isFixed()); } +TEST_F(AttLimitsTest, ComparisonOperators) +{ + AttLimits lim1 = AttLimits::limited(1.0, 2.0); + AttLimits lim2 = AttLimits::limited(1.0, 2.0); + EXPECT_TRUE(lim1 == lim2); + EXPECT_FALSE(lim1 != lim2); + + AttLimits lim3 = AttLimits::limitless(); + AttLimits lim4 = AttLimits::limitless(); + EXPECT_TRUE(lim3 == lim4); + EXPECT_FALSE(lim3 != lim4); + + AttLimits lim5 = AttLimits::lowerLimited(1.0); + AttLimits lim6 = AttLimits::lowerLimited(1.0); + EXPECT_TRUE(lim5 == lim6); + EXPECT_FALSE(lim5 != lim6); + + AttLimits lim7 = AttLimits::upperLimited(1.0); + AttLimits lim8 = AttLimits::upperLimited(1.0); + EXPECT_TRUE(lim7 == lim8); + EXPECT_FALSE(lim7 != lim8); +} + +TEST_F(AttLimitsTest, CopyConstructor) +{ + AttLimits lim1 = AttLimits::limited(1.0, 2.0); + AttLimits lim2 = lim1; + EXPECT_TRUE(lim1 == lim2); + EXPECT_FALSE(lim1 != lim2); + + AttLimits lim3(lim1); + EXPECT_TRUE(lim1 == lim3); + EXPECT_FALSE(lim1 != lim3); +} #endif // ATTLIMITSTEST_H diff --git a/Tests/UnitTests/TestCore/RealParameterWrapperTest.h b/Tests/UnitTests/TestCore/RealParameterWrapperTest.h index 98d36ef5c0d..b7e4dc63c8e 100644 --- a/Tests/UnitTests/TestCore/RealParameterWrapperTest.h +++ b/Tests/UnitTests/TestCore/RealParameterWrapperTest.h @@ -44,6 +44,8 @@ TEST_F(RealParameterWrapperTest, InitialState) EXPECT_TRUE( par.isNull() ); ASSERT_THROW( par.getValue(), NullPointerException ); ASSERT_THROW( par.setValue(1.0), NullPointerException ); + + EXPECT_EQ(par.getAttLimits(), AttLimits::limitless()); } TEST_F(RealParameterWrapperTest, ParameterAccess) @@ -90,5 +92,31 @@ TEST_F(RealParameterWrapperTest, ParameterAccess) // EXPECT_FALSE( obj2.m_status ); //} +TEST_F(RealParameterWrapperTest, LimitedParameter) +{ + m_real_parameter = 1.0; + EXPECT_THROW(RealParameterWrapper(&m_real_parameter, AttLimits::limited(10.0, 20.0)), OutOfBoundsException); + EXPECT_THROW(RealParameterWrapper(&m_real_parameter, AttLimits::lowerLimited(2.0)), OutOfBoundsException); + EXPECT_THROW(RealParameterWrapper(&m_real_parameter, AttLimits::upperLimited(0.0)), OutOfBoundsException); + + m_real_parameter = 15.0; + AttLimits limits = AttLimits::limited(10, 20); + RealParameterWrapper par1(&m_real_parameter, limits); + + EXPECT_TRUE(par1.setValue(16.0)); + EXPECT_EQ(16.0, m_real_parameter); + + EXPECT_FALSE(par1.setValue(21.0)); + EXPECT_EQ(16.0, m_real_parameter); + + RealParameterWrapper par2(par1); + EXPECT_TRUE(par1 == par2); + + EXPECT_FALSE(par1.setValue(21.0)); + EXPECT_EQ(16.0, m_real_parameter); + + EXPECT_TRUE(par1.setValue(11.0)); + EXPECT_EQ(11.0, m_real_parameter); +} #endif // REALPARAMETERWRAPPERTEST_H -- GitLab