diff --git a/Framework/API/inc/MantidAPI/LogManager.h b/Framework/API/inc/MantidAPI/LogManager.h index 577e64a38872ac201ac285fdfe81e26f862c9d2c..f5c49e6d9ee07fb1aa068422cd0780cbf5311818 100644 --- a/Framework/API/inc/MantidAPI/LogManager.h +++ b/Framework/API/inc/MantidAPI/LogManager.h @@ -182,6 +182,9 @@ public: /// Clear the logs void clearLogs(); + bool operator==(const LogManager &other) const; + bool operator!=(const LogManager &other) const; + protected: /// Load the run from a NeXus file with a given group name void loadNexus(::NeXus::File *file, diff --git a/Framework/API/inc/MantidAPI/Run.h b/Framework/API/inc/MantidAPI/Run.h index 747140a27e9d4c96765150c40a2b6183aab6b7a6..568c25dbdce5ac9da5f4e207d8c240af1dfa320e 100644 --- a/Framework/API/inc/MantidAPI/Run.h +++ b/Framework/API/inc/MantidAPI/Run.h @@ -41,6 +41,8 @@ public: Run(const Run &other); ~Run(); Run &operator=(const Run &other); + bool operator==(const Run &other); + bool operator!=(const Run &other); /// Clone boost::shared_ptr<Run> clone(); diff --git a/Framework/API/src/LogManager.cpp b/Framework/API/src/LogManager.cpp index 4f6b9d41c5d6e3b56e608c6ebe57b7305b09bd47..451dbe145c054f9b8410274373ae344359de9d75 100644 --- a/Framework/API/src/LogManager.cpp +++ b/Framework/API/src/LogManager.cpp @@ -549,6 +549,14 @@ void LogManager::loadNexus(::NeXus::File *file, */ void LogManager::clearLogs() { m_manager->clear(); } +bool LogManager::operator==(const LogManager &other) const { + return *m_manager == *(other.m_manager); +} + +bool LogManager::operator!=(const LogManager &other) const { + return *m_manager != *(other.m_manager); +} + //----------------------------------------------------------------------------------------------------------------------- // Private methods //----------------------------------------------------------------------------------------------------------------------- diff --git a/Framework/API/src/Run.cpp b/Framework/API/src/Run.cpp index f178c78c5eaf7df021bfa2fd66c6071e1201068a..7818d5770453811dde3a64d40b6f101d658d5620 100644 --- a/Framework/API/src/Run.cpp +++ b/Framework/API/src/Run.cpp @@ -62,6 +62,14 @@ Run &Run::operator=(const Run &other) { return *this; } +bool Run::operator==(const Run &other) { + return *m_goniometer == *other.m_goniometer && + LogManager::operator==(other) && + this->m_histoBins == other.m_histoBins; +} + +bool Run::operator!=(const Run &other) { return !this->operator==(other); } + boost::shared_ptr<Run> Run::clone() { auto clone = boost::make_shared<Run>(); for (auto property : this->m_manager->getProperties()) { diff --git a/Framework/API/test/LogManagerTest.h b/Framework/API/test/LogManagerTest.h index c047bd8e1e057e7196d78b95760644e810fd1ff1..9710ebb4fab940a10fe48852ea98f9dd06fc30ae 100644 --- a/Framework/API/test/LogManagerTest.h +++ b/Framework/API/test/LogManagerTest.h @@ -28,6 +28,7 @@ namespace { class ConcreteProperty : public Property { public: ConcreteProperty() : Property("Test", typeid(int)) {} + ConcreteProperty(std::string name) : Property(name, typeid(int)) {} ConcreteProperty *clone() const override { return new ConcreteProperty(*this); } @@ -35,15 +36,21 @@ public: std::string getDefault() const override { return "getDefault() is not implemented in this class"; } - std::string value() const override { return "Nothing"; } + std::string value() const override { return m_value; } Json::Value valueAsJson() const override { return Json::Value(); } - std::string setValue(const std::string &) override { return ""; } + std::string setValue(const std::string &value) override { + m_value = value; + return m_value; + } std::string setValueFromJson(const Json::Value &) override { return ""; } std::string setValueFromProperty(const Property &) override { return ""; } std::string setDataItem(const boost::shared_ptr<DataItem>) override { return ""; } Property &operator+=(Property const *) override { return *this; } + +private: + std::string m_value = "Nothing"; }; template <typename T> @@ -185,7 +192,7 @@ public: runInfo.addProperty(p); TS_ASSERT_EQUALS(runInfo.getMemorySize(), - sizeof(ConcreteProperty) + sizeof(void *)); + p->getMemorySize() + sizeof(Property *)); } void test_GetTimeSeriesProperty_Returns_TSP_When_Log_Exists() { @@ -530,6 +537,48 @@ public: run3.loadNexus(th.file.get(), ""); } + void test_operator_equals() { + LogManager a; + LogManager b; + a.addProperty(std::make_unique<ConcreteProperty>()); + b.addProperty(std::make_unique<ConcreteProperty>()); + TS_ASSERT_EQUALS(a, b); + TS_ASSERT(!(a != b)); + } + + void test_not_equals_when_number_of_entries_differ() { + LogManager a; + LogManager b; + a.addProperty(std::make_unique<ConcreteProperty>("a1")); + b.addProperty(std::make_unique<ConcreteProperty>("b1")); + b.addProperty(std::make_unique<ConcreteProperty>("b2")); + TS_ASSERT_DIFFERS(a, b); + TS_ASSERT(!(a == b)); + } + + void test_not_equals_when_values_differ() { + LogManager a; + LogManager b; + auto prop1 = std::make_unique<ConcreteProperty>(); + auto prop2 = std::make_unique<ConcreteProperty>(); + prop2->setValue("another_value"); + a.addProperty(std::move(prop1)); + b.addProperty(std::move(prop2)); + TS_ASSERT_DIFFERS(a, b); + TS_ASSERT(!(a == b)); + } + + void test_not_equals_when_keys_differ() { + LogManager a; + LogManager b; + auto prop1 = std::make_unique<ConcreteProperty>("Temp"); + auto prop2 = std::make_unique<ConcreteProperty>("Pressure"); + a.addProperty(std::move(prop1)); + b.addProperty(std::move(prop2)); + TS_ASSERT_DIFFERS(a, b); + TS_ASSERT(!(a == b)); + } + private: template <typename T> void doTest_GetPropertyAsSingleValue_SingleType(const T value) { diff --git a/Framework/API/test/RunTest.h b/Framework/API/test/RunTest.h index a41f319a7eae852b0a4d9b5ebdca618e2a06d844..d9489980074ef7997216ea2a0de1a61c728ba23b 100644 --- a/Framework/API/test/RunTest.h +++ b/Framework/API/test/RunTest.h @@ -609,6 +609,65 @@ public: TS_ASSERT_DELTA(run3.getProtonCharge(), 1.234, 1e-5); } + void test_equals_when_runs_empty() { + Run a{}; + Run b{a}; + TS_ASSERT_EQUALS(a, b); + } + + void test_equals_when_runs_identical() { + Run a{}; + a.addProperty(std::make_unique<ConcreteProperty>()); + const DblMatrix rotation_x{ + {1, 0, 0, 0, 0, -1, 0, 1, 0}}; // 90 degrees around x axis + a.setGoniometer(Goniometer{rotation_x}, false /*do not use log angles*/); + a.storeHistogramBinBoundaries({1, 2, 3, 4}); + Run b{a}; + TS_ASSERT_EQUALS(a, b); + TS_ASSERT(!(a != b)); + } + + void test_not_equal_when_histogram_bin_boundaries_differ() { + Run a{}; + a.addProperty(std::make_unique<ConcreteProperty>()); + DblMatrix rotation_x{ + {1, 0, 0, 0, 0, -1, 0, 1, 0}}; // 90 degrees around x axis + a.setGoniometer(Goniometer{rotation_x}, false /*do not use log angles*/); + a.storeHistogramBinBoundaries({1, 2, 3, 4}); + Run b{a}; + b.storeHistogramBinBoundaries({0, 2, 3, 4}); + TS_ASSERT_DIFFERS(a, b); + TS_ASSERT(!(a == b)); + } + + void test_not_equal_when_properties_differ() { + Run a{}; + a.addProperty(std::make_unique<ConcreteProperty>()); + DblMatrix rotation_x{ + {1, 0, 0, 0, 0, -1, 0, 1, 0}}; // 90 degrees around x axis + a.setGoniometer(Goniometer{rotation_x}, false /*do not use log angles*/); + a.storeHistogramBinBoundaries({1, 2, 3, 4}); + Run b{a}; + b.removeProperty("Test"); + TS_ASSERT_DIFFERS(a, b); + TS_ASSERT(!(a == b)); + } + + void test_not_equal_when_goniometer_differ() { + Run a{}; + a.addProperty(std::make_unique<ConcreteProperty>()); + DblMatrix rotation_x{ + {1, 0, 0, 0, 0, -1, 0, 1, 0}}; // 90 degrees around x axis + a.setGoniometer(Goniometer{rotation_x}, false /*do not use log angles*/); + a.storeHistogramBinBoundaries({1, 2, 3, 4}); + Run b{a}; + Mantid::Kernel::DblMatrix rotation_y{ + {0, 0, 1, 0, 1, 0, -1, 0, 0}}; // 90 degrees around y axis + b.setGoniometer(Goniometer{rotation_y}, false /*do not use log angles*/); + TS_ASSERT_DIFFERS(a, b); + TS_ASSERT(!(a == b)); + } + private: /// Testing bins std::vector<double> m_test_energy_bins; diff --git a/Framework/Geometry/inc/MantidGeometry/Instrument/Goniometer.h b/Framework/Geometry/inc/MantidGeometry/Instrument/Goniometer.h index e09c1b7301e6ba95ea4f81b8f1150747d972a45f..86069b5781d9e86706a2de8c58b45fbe47c4a88f 100644 --- a/Framework/Geometry/inc/MantidGeometry/Instrument/Goniometer.h +++ b/Framework/Geometry/inc/MantidGeometry/Instrument/Goniometer.h @@ -97,6 +97,8 @@ public: void loadNexus(::NeXus::File *file, const std::string &group); /// the method reports if the goniometer was defined with some parameters bool isDefined() const; + bool operator==(const Goniometer &other) const; + bool operator!=(const Goniometer &other) const; private: /// Global rotation matrix of the goniometer diff --git a/Framework/Geometry/src/Instrument/Goniometer.cpp b/Framework/Geometry/src/Instrument/Goniometer.cpp index e2dd92bd4764f54b2ec037d0586a12a739f0c9fe..4fda260a72865f7c6e8859db079d7ad0e6d17318 100644 --- a/Framework/Geometry/src/Instrument/Goniometer.cpp +++ b/Framework/Geometry/src/Instrument/Goniometer.cpp @@ -92,6 +92,14 @@ void Goniometer::setR(Kernel::DblMatrix rot) { /// Function reports if the goniometer is defined bool Goniometer::isDefined() const { return initFromR || (!motors.empty()); } +bool Goniometer::operator==(const Goniometer &other) const { + return this->R == other.R; +} + +bool Goniometer::operator!=(const Goniometer &other) const { + return this->R != other.R; +} + /// Return information about axes. /// @return str :: string that contains on each line one motor information (axis /// name, direction, sense, angle) diff --git a/Framework/Geometry/test/GoniometerTest.h b/Framework/Geometry/test/GoniometerTest.h index 3059f0495ddf205bda8d0f344b50e3083c46251a..0b05a15a8989a5147ecad833339432fb2ed0ac6e 100644 --- a/Framework/Geometry/test/GoniometerTest.h +++ b/Framework/Geometry/test/GoniometerTest.h @@ -255,4 +255,24 @@ public: // Rotation matrices should be the same after loading TS_ASSERT_EQUALS(G2.getR(), G.getR()); } + + void test_equals_when_identical() { + Mantid::Kernel::DblMatrix rotation_x{ + {1, 0, 0, 0, 0, -1, 0, 1, 0}}; // 90 degrees around x axis + Goniometer a(rotation_x); + Goniometer b(rotation_x); + TS_ASSERT_EQUALS(a, b); + TS_ASSERT(!(a != b)); + } + + void test_not_equals_when_not_identical() { + Mantid::Kernel::DblMatrix rotation_x{ + {1, 0, 0, 0, 0, -1, 0, 1, 0}}; // 90 degrees around x axis + Mantid::Kernel::DblMatrix rotation_y{ + {0, 0, 1, 0, 1, 0, -1, 0, 0}}; // 90 degrees around y axis + Goniometer a(rotation_x); + Goniometer b(rotation_y); + TS_ASSERT_DIFFERS(a, b); + TS_ASSERT(!(a == b)); + } }; diff --git a/Framework/Kernel/inc/MantidKernel/PropertyManager.h b/Framework/Kernel/inc/MantidKernel/PropertyManager.h index 3314b5d9253e6ef7eaac07e84d48baafcb654b64..fc0d44126012710f6badb73825cdc0c30811c150 100644 --- a/Framework/Kernel/inc/MantidKernel/PropertyManager.h +++ b/Framework/Kernel/inc/MantidKernel/PropertyManager.h @@ -108,6 +108,9 @@ public: /// Return the property manager serialized as a json object. ::Json::Value asJson(bool withDefaultValues = false) const override; + bool operator==(const PropertyManager &other) const; + bool operator!=(const PropertyManager &other) const; + protected: friend class PropertyManagerOwner; diff --git a/Framework/Kernel/src/PropertyManager.cpp b/Framework/Kernel/src/PropertyManager.cpp index fb5da0dddb339f995d210402903af4ad0fdc0177..72e08854f18b810c0332d4c8274997fb62eb986d 100644 --- a/Framework/Kernel/src/PropertyManager.cpp +++ b/Framework/Kernel/src/PropertyManager.cpp @@ -583,6 +583,22 @@ std::string PropertyManager::asString(bool withDefaultValues) const { return jsonMap; } +bool PropertyManager::operator==(const PropertyManager &other) const { + if (other.m_properties.size() != m_properties.size()) + return false; + for (const auto & [ key, value ] : m_properties) { + if (other.m_properties.count(key) != 1) + return false; + if (*other.m_properties.at(key) != *value) + return false; + } + return true; +} + +bool PropertyManager::operator!=(const PropertyManager &other) const { + return !this->operator==(other); +} + //----------------------------------------------------------------------------------------------- /** Get a property by name * @param name :: The name of the property (case insensitive) diff --git a/Framework/Kernel/test/PropertyManagerTest.h b/Framework/Kernel/test/PropertyManagerTest.h index b20f36210793a57905352f382e9b71a49c2837c9..2f95d6edc2f2ccdc0444eb93d5743669a54cb525 100644 --- a/Framework/Kernel/test/PropertyManagerTest.h +++ b/Framework/Kernel/test/PropertyManagerTest.h @@ -659,6 +659,43 @@ public: TS_ASSERT_EQUALS(i, 33); } + void test_operator_equals_same_contents() { + PropertyManager a; + PropertyManager b; + + a.declareProperty("Prop1", 10); + b.declareProperty("Prop1", 10); + TS_ASSERT_EQUALS(a, b); + TS_ASSERT(!(a != b)); + } + + void test_operator_not_equals_different_sizes() { + PropertyManager a; + PropertyManager b; + + b.declareProperty("Prop1", 10); + TSM_ASSERT_DIFFERS("Unequal sizes", a, b); + TSM_ASSERT("Unequal sizes", !(a == b)); + } + + void test_operator_not_equals_different_keys() { + PropertyManager a; + PropertyManager b; + a.declareProperty("Prop1", 1); + b.declareProperty("Prop2", 1); + TSM_ASSERT_DIFFERS("Different Keys", a, b); + TSM_ASSERT("Different Keys", !(a == b)); + } + + void test_operator_not_equals_different_vaues() { + PropertyManager a; + PropertyManager b; + a.declareProperty("Prop1", 1); + b.declareProperty("Prop1", 2); + TSM_ASSERT_DIFFERS("Different Values", a, b); + TSM_ASSERT("Different Values", !(a == b)); + } + private: std::unique_ptr<PropertyManagerHelper> manager; };