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/inc/MantidAPI/Sample.h b/Framework/API/inc/MantidAPI/Sample.h index dc70c2391fa669bfebce66789eef89b700e5092b..7d5c79373ead04be140ea3b95081af07784ab75f 100644 --- a/Framework/API/inc/MantidAPI/Sample.h +++ b/Framework/API/inc/MantidAPI/Sample.h @@ -116,6 +116,9 @@ public: /// Delete the oriented lattice void clearOrientedLattice(); + bool operator==(const Sample &other) const; + bool operator!=(const Sample &other) const; + private: /// The sample name std::string m_name; 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/src/Sample.cpp b/Framework/API/src/Sample.cpp index b26a1a04bafcfe80d37d1636cde7ddfa7e3900b1..fb301a0b13eb2637338cd2db0b3cdb702353bfd8 100644 --- a/Framework/API/src/Sample.cpp +++ b/Framework/API/src/Sample.cpp @@ -423,5 +423,36 @@ void Sample::clearOrientedLattice() { m_lattice.reset(nullptr); } } + +bool Sample::operator==(const Sample &other) const { + if (m_samples.size() != other.m_samples.size()) + return false; + for (size_t i = 0; i < m_samples.size(); ++i) { + if (*m_samples[i] != *other.m_samples[i]) + return false; + } + auto compare = [](const auto &a, const auto &b, auto call_on) { + // both null or both not null + if (bool(a) ^ bool(b)) + return false; + if (a) + return call_on(a) == call_on(b); + else + return true; + }; + return *m_lattice == *other.m_lattice && this->m_name == other.m_name && + this->m_height == other.m_height && this->m_width == other.m_width && + this->m_thick == other.m_thick && m_geom_id == other.m_geom_id && + compare(m_environment, other.m_environment, + [](const auto &x) { return x->name(); }) && + compare(m_shape, other.m_shape, + [](const auto &x) { return x->shape(); }) && + compare(m_crystalStructure, other.m_crystalStructure, + [](const auto &x) { return *(x->spaceGroup()); }); +} + +bool Sample::operator!=(const Sample &other) const { + return !this->operator==(other); +} } // namespace API } // namespace Mantid 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/API/test/SampleTest.h b/Framework/API/test/SampleTest.h index b4583c3705678cf5d5f5aa5bb30e8d16f934710b..5092ea50bc342541e680c637e660736cd9e6cf9a 100644 --- a/Framework/API/test/SampleTest.h +++ b/Framework/API/test/SampleTest.h @@ -359,4 +359,126 @@ public: TS_ASSERT(loaded.getName().empty()); } + + void test_equal_when_sample_identical() { + Sample a; + Sample b; + TS_ASSERT_EQUALS(a, b); + } + + void test_not_equal_when_sample_differs_in_extents() { + Sample a; + auto b = a; + a.setHeight(10); + TS_ASSERT_DIFFERS(a, b); + TS_ASSERT(!(a == b)); + b = a; + a.setWidth(10); + TS_ASSERT_DIFFERS(a, b); + TS_ASSERT(!(a == b)); + b = a; + a.setThickness(10); + TS_ASSERT_DIFFERS(a, b); + TS_ASSERT(!(a == b)); + } + + void test_not_equal_when_sample_differs_in_geom_id() { + Sample a; + auto b = a; + TS_ASSERT_EQUALS(a, b); + a.setGeometryFlag(1); + b.setGeometryFlag(2); + TS_ASSERT_DIFFERS(a, b); + TS_ASSERT(!(a == b)); + } + void test_not_equal_when_sample_differs_in_name() { + Sample a; + auto b = a; + b.setName("something"); + TS_ASSERT_DIFFERS(a, b); + TS_ASSERT(!(a == b)); + } + + void test_not_equal_when_sample_differs_in_environment() { + auto kit1 = std::make_unique<SampleEnvironment>( + "Env", boost::make_shared<const Container>("")); + + auto kit2 = std::make_unique<SampleEnvironment>( + "Env2", boost::make_shared<const Container>("")); + + // same as kit1 + auto kit3 = std::make_unique<SampleEnvironment>( + kit1->name(), boost::make_shared<const Container>("")); + + Sample a; + auto b = a; + b.setEnvironment(std::move(kit1)); + // A has no environment + TS_ASSERT_DIFFERS(a, b); + TS_ASSERT(!(a == b)); + + // A has valid but different same environment + a.setEnvironment(std::move(kit2)); + TS_ASSERT_DIFFERS(a, b); + TS_ASSERT(!(a == b)); + + // A has valid but different same environment + a.setEnvironment(std::move(kit3)); + TS_ASSERT_EQUALS(a, b); + TS_ASSERT(!(a != b)); + } + + void test_not_equal_when_sample_differs_in_shape() { + IObject_sptr shape1 = ComponentCreationHelper::createCappedCylinder( + 0.0127, 1.0, V3D(), V3D(0.0, 1.0, 0.0), "cyl"); + + IObject_sptr shape2 = ComponentCreationHelper::createCappedCylinder( + 0.0137, 1.0, V3D(), V3D(0.0, 0.0, 0.0), "cyl"); + + Sample a; + auto b = a; + a.setShape(shape1); + // b has no shape + TS_ASSERT_DIFFERS(a, b); + TS_ASSERT(!(a == b)); + + // b has different shape + b.setShape(shape2); + TS_ASSERT_DIFFERS(a, b); + TS_ASSERT(!(a == b)); + + // b has same shape + b.setShape(IObject_sptr(shape1->clone())); + TS_ASSERT_EQUALS(a, b); + TS_ASSERT(!(a != b)); + } + + void test_not_equal_when_sample_differs_in_space_group() { + CrystalStructure structure1("3 4 5 90 90 90", "C m m m", + "Fe 0.12 0.23 0.121"); + // Same as above + CrystalStructure structure2("3 4 5 90 90 90", "C m m m", + "Fe 0.12 0.23 0.121"); + // Different + CrystalStructure structure3("5.431 5.431 5.431", "F d -3 m", + "Si 0 0 0 1.0 0.02"); + + Sample a; + auto b = a; + // b has no structure + a.setCrystalStructure(structure1); + TS_ASSERT_DIFFERS(a, b); + TS_ASSERT(!(a == b)); + + // b has different structure + b.setCrystalStructure(structure3); + TS_ASSERT_DIFFERS(a, b); + TS_ASSERT(!(a == b)); + + // b has same structure + b = Sample{}; + b.setCrystalStructure(structure2); + TS_ASSERT_EQUALS(a, b); + TS_ASSERT(!(a != b)); + } }; diff --git a/Framework/Geometry/inc/MantidGeometry/Crystal/OrientedLattice.h b/Framework/Geometry/inc/MantidGeometry/Crystal/OrientedLattice.h index b39fd0944206398502bfea2aec605272e10a7700..4334d1b7c97411c161ce2e6019cc2b8c513ffdc7 100644 --- a/Framework/Geometry/inc/MantidGeometry/Crystal/OrientedLattice.h +++ b/Framework/Geometry/inc/MantidGeometry/Crystal/OrientedLattice.h @@ -67,6 +67,9 @@ public: static bool GetABC(const Kernel::DblMatrix &UB, Kernel::V3D &a_dir, Kernel::V3D &b_dir, Kernel::V3D &c_dir); + bool operator==(const OrientedLattice &other) const; + bool operator!=(const OrientedLattice &other) const; + private: Kernel::DblMatrix U; Kernel::DblMatrix UB; @@ -79,4 +82,4 @@ private: void recalculate() override; }; } // namespace Geometry -} // namespace Mantid \ No newline at end of file +} // namespace Mantid diff --git a/Framework/Geometry/inc/MantidGeometry/Crystal/UnitCell.h b/Framework/Geometry/inc/MantidGeometry/Crystal/UnitCell.h index c84c586d813e4212fa89432fcb48f75d79c9284f..b34c2a0dbfc5d0847a4318cf2d5c888193de4d21 100644 --- a/Framework/Geometry/inc/MantidGeometry/Crystal/UnitCell.h +++ b/Framework/Geometry/inc/MantidGeometry/Crystal/UnitCell.h @@ -161,6 +161,8 @@ public: double volume() const; double recVolume() const; virtual void recalculateFromGstar(const Kernel::Matrix<double> &NewGstar); + bool operator==(const UnitCell &other) const; + bool operator!=(const UnitCell &other) const; protected: /// Lattice parameter a,b,c,alpha,beta,gamma (in \f$ \mbox{ \AA } \f$ and 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/Crystal/OrientedLattice.cpp b/Framework/Geometry/src/Crystal/OrientedLattice.cpp index dae0f1c61d6fa37e297c4f1772a42190b735c925..94284f3413f0c3be9425c20c0c78807119804785 100644 --- a/Framework/Geometry/src/Crystal/OrientedLattice.cpp +++ b/Framework/Geometry/src/Crystal/OrientedLattice.cpp @@ -344,5 +344,11 @@ void OrientedLattice::recalculate() { UnitCell::recalculate(); UB = U * getB(); } +bool OrientedLattice::operator==(const OrientedLattice &other) const { + return UB == other.UB; +} +bool OrientedLattice::operator!=(const OrientedLattice &other) const { + return UB != other.UB; +} } // Namespace Geometry } // Namespace Mantid diff --git a/Framework/Geometry/src/Crystal/UnitCell.cpp b/Framework/Geometry/src/Crystal/UnitCell.cpp index c1e93394240a49e0c26a7adba44a90872f319673..3a7feab47aa4d1665c9ceefdf1dd49f5ae4a1f50 100644 --- a/Framework/Geometry/src/Crystal/UnitCell.cpp +++ b/Framework/Geometry/src/Crystal/UnitCell.cpp @@ -880,6 +880,13 @@ void UnitCell::recalculateFromGstar(const DblMatrix &NewGstar) { calculateB(); } +bool UnitCell::operator==(const UnitCell &other) const { + return da == other.da; // da error not used in comparison +} +bool UnitCell::operator!=(const UnitCell &other) const { + return !this->operator==(other); +} + std::ostream &operator<<(std::ostream &out, const UnitCell &unitCell) { // always show the lattice constants out << "Lattice Parameters:" << std::fixed << std::setprecision(6) 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/Geometry/test/OrientedLatticeTest.h b/Framework/Geometry/test/OrientedLatticeTest.h index b1f9379f2ea05d3c5c8971a4039c94a37428768a..be341d5de64aec2786f9dcd1d2d1346198a86cf6 100644 --- a/Framework/Geometry/test/OrientedLatticeTest.h +++ b/Framework/Geometry/test/OrientedLatticeTest.h @@ -300,4 +300,29 @@ public: TSM_ASSERT_EQUALS(" should be along the y direction", V3D(0, 1, 0), ey); TSM_ASSERT_EQUALS("y direction is", V3D(0, -1, 0), eyPrime); } + void test_equals_when_orientedlattice_identical() { + OrientedLattice a(1.0, 2.0, 3.0, 90.0, 90.0, + 90.0); // create via lattice parameters + OrientedLattice b{a}; + TS_ASSERT_EQUALS(a, b); + TS_ASSERT(!(a != b)); + } + + void test_not_equals_when_orientedlattice_different_b() { + OrientedLattice a(1.0, 2.0, 3.0, 90.0, 90.0, + 90.0); // create via lattice parameters + OrientedLattice b{a}; + b.seta(10); // Results in B change + TS_ASSERT_DIFFERS(a, b); + TS_ASSERT(!(a == b)); + } + + void test_not_equals_when_orientedlattice_different_u() { + OrientedLattice a(1.0, 2.0, 3.0, 90.0, 90.0, + 90.0); // create via lattice parameters + OrientedLattice b{a}; + b.setUFromVectors(V3D(0, 1, 0), V3D(1, 0, 0)); // Different U + TS_ASSERT_DIFFERS(a, b); + TS_ASSERT(!(a == b)); + } }; diff --git a/Framework/Geometry/test/UnitCellTest.h b/Framework/Geometry/test/UnitCellTest.h index 45f02dd43b70d34f8f6545ab9973fe294bdc71ce..8450c8c973eb4ef74c2b7ec4ab93e91c37886750 100644 --- a/Framework/Geometry/test/UnitCellTest.h +++ b/Framework/Geometry/test/UnitCellTest.h @@ -170,4 +170,53 @@ public: TS_ASSERT_DIFFERS(precisionLimit.c(), precisionLimitOther.c()); TS_ASSERT_DELTA(precisionLimit.c(), precisionLimitOther.c(), 1e-9); } + + void test_equals_when_unitcell_identical() { + const UnitCell a(2.0, 4.0, 5.0, 90.0, 100.0, 102.0); + const UnitCell b(a); + TS_ASSERT_EQUALS(a, b); + TS_ASSERT(!(a != b)); + } + + void test_not_equals_when_unitcell_differs_in_a() { + const UnitCell a(1.0, 1.0, 1.0, 90.0, 90.0, 90.0); + UnitCell b(a); + b.seta(2.0); + TS_ASSERT_DIFFERS(a, b); + } + + void test_not_equals_when_unitcell_differs_in_b() { + const UnitCell a(1.0, 1.0, 1.0, 90.0, 90.0, 90.0); + UnitCell b(a); + b.setb(2.0); + TS_ASSERT_DIFFERS(a, b); + } + + void test_not_equals_when_unitcell_differs_in_c() { + const UnitCell a(1.0, 1.0, 1.0, 90.0, 90.0, 90.0); + UnitCell b(a); + b.setc(2.0); + TS_ASSERT_DIFFERS(a, b); + } + + void test_not_equals_when_unitcell_differs_in_alpha() { + const UnitCell a(1.0, 1.0, 1.0, 90.0, 90.0, 90.0); + UnitCell b(a); + b.setalpha(100); + TS_ASSERT_DIFFERS(a, b); + } + + void test_not_equals_when_unitcell_differs_in_beta() { + const UnitCell a(1.0, 1.0, 1.0, 90.0, 90.0, 90.0); + UnitCell b(a); + b.setbeta(100); + TS_ASSERT_DIFFERS(a, b); + } + + void test_not_equals_when_unitcell_differs_in_gamma() { + const UnitCell a(1.0, 1.0, 1.0, 90.0, 90.0, 90.0); + UnitCell b(a); + b.setgamma(100); + TS_ASSERT_DIFFERS(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..17a51367f32ff456ab353ab49260062566587a2f 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; }; diff --git a/Framework/PythonInterface/mantid/api/src/Exports/Run.cpp b/Framework/PythonInterface/mantid/api/src/Exports/Run.cpp index 1a7e17e2221e264269fef95550ce39d5af8e889c..a05ffb787e3699d793277ed2d1f199dd9e399b03 100644 --- a/Framework/PythonInterface/mantid/api/src/Exports/Run.cpp +++ b/Framework/PythonInterface/mantid/api/src/Exports/Run.cpp @@ -243,5 +243,6 @@ void export_Run() { .def("__setitem__", &addOrReplaceProperty, (arg("self"), arg("name"), arg("value"))) .def("__copy__", &Mantid::PythonInterface::generic__copy__<Run>) - .def("__deepcopy__", &Mantid::PythonInterface::generic__deepcopy__<Run>); + .def("__deepcopy__", &Mantid::PythonInterface::generic__deepcopy__<Run>) + .def("__eq__", &Run::operator==, arg("self"), arg("other")); } diff --git a/Framework/PythonInterface/mantid/api/src/Exports/Sample.cpp b/Framework/PythonInterface/mantid/api/src/Exports/Sample.cpp index c8f153e8715ca740be8dca73ea84a48e0cbba964..ffba827eca114e114acccf7424aca1d2c77eb0fc 100644 --- a/Framework/PythonInterface/mantid/api/src/Exports/Sample.cpp +++ b/Framework/PythonInterface/mantid/api/src/Exports/Sample.cpp @@ -87,5 +87,6 @@ void export_Sample() { return_internal_reference<>()) .def("__copy__", &Mantid::PythonInterface::generic__copy__<Sample>) .def("__deepcopy__", - &Mantid::PythonInterface::generic__deepcopy__<Sample>); + &Mantid::PythonInterface::generic__deepcopy__<Sample>) + .def("__eq__", &Sample::operator==,(arg("self"), arg("other"))); } diff --git a/Framework/PythonInterface/test/python/mantid/api/RunTest.py b/Framework/PythonInterface/test/python/mantid/api/RunTest.py index 1bbe8fedc23479111aca600e8b12f713f1bce65d..27c7947ad1c9c3b6cf4d3bdd1d02ef3bd70cd4c6 100644 --- a/Framework/PythonInterface/test/python/mantid/api/RunTest.py +++ b/Framework/PythonInterface/test/python/mantid/api/RunTest.py @@ -155,6 +155,12 @@ class RunTest(unittest.TestCase): def test_deep_copyable(self): self.do_test_copyable(copy.deepcopy) + def test_equals(self): + other = copy.deepcopy(self._run) + self.assertEqual(self._run, other) + other.addProperty("pressure", 1, True) + self.assertNotEqual(self._run, other) + if __name__ == '__main__': unittest.main() diff --git a/Framework/PythonInterface/test/python/mantid/api/SampleTest.py b/Framework/PythonInterface/test/python/mantid/api/SampleTest.py index 845075019e5fab9405f5bdd69b095495f9483a27..f3f7244902d721d2c1488bcc47e429a8e5f4eea6 100644 --- a/Framework/PythonInterface/test/python/mantid/api/SampleTest.py +++ b/Framework/PythonInterface/test/python/mantid/api/SampleTest.py @@ -124,8 +124,12 @@ class SampleTest(unittest.TestCase): def test_deep_copyable(self): self.do_test_copyable(copy.deepcopy) - - + def test_equals(self): + a = Sample() + b = Sample() + self.assertEqual(a, b) + b.setThickness(10) + self.assertNotEqual(a, b) if __name__ == '__main__': unittest.main()