From c1ab549ebfb6704c98d73e4b40481684194ba2f1 Mon Sep 17 00:00:00 2001 From: Robert Applin <40830825+robertapplin@users.noreply.github.com> Date: Thu, 20 Sep 2018 09:44:40 +0100 Subject: [PATCH] Unit tests and fix excludeRegion crash Refs #23463 --- .../Indirect/IndirectFitData.cpp | 44 ++++++++- .../Indirect/IndirectFitData.h | 5 + .../Indirect/test/IndirectFitDataTest.h | 94 ++++++++++++++----- 3 files changed, 115 insertions(+), 28 deletions(-) diff --git a/qt/scientific_interfaces/Indirect/IndirectFitData.cpp b/qt/scientific_interfaces/Indirect/IndirectFitData.cpp index c50891e76df..48d8af15566 100644 --- a/qt/scientific_interfaces/Indirect/IndirectFitData.cpp +++ b/qt/scientific_interfaces/Indirect/IndirectFitData.cpp @@ -242,7 +242,13 @@ IndirectFitData::excludeRegionsVector(std::size_t spectrum) const { } void IndirectFitData::setSpectra(const std::string &spectra) { - setSpectra(DiscontinuousSpectra<std::size_t>(spectra)); + try { + const Spectra spec = DiscontinuousSpectra<std::size_t>(spectra); + setSpectra(spec); + } catch (std::exception &ex) { + throw std::runtime_error("Spectra too large for cast: " + + QString(ex.what()).toStdString()); + } } void IndirectFitData::setSpectra(Spectra &&spectra) { @@ -288,9 +294,39 @@ void IndirectFitData::setEndX(double endX, std::size_t spectrum) { throw std::runtime_error("Unable to set EndX: Workspace no longer exists."); } -void IndirectFitData::setExcludeRegionString(const std::string &excludeRegion, - std::size_t spectrum) { - m_excludeRegions[spectrum] = excludeRegion; +void IndirectFitData::setExcludeRegionString( + const std::string &excludeRegionString, std::size_t spectrum) { + m_excludeRegions[spectrum] = validateExcludeRegionString(excludeRegionString); +} + +std::string IndirectFitData::validateExcludeRegionString( + const std::string &excludeRegionString) const { + std::vector<std::string> boundStrings; + boost::split(boundStrings, excludeRegionString, boost::is_any_of(", ")); + + std::vector<std::size_t> bounds; + for (auto bound : boundStrings) + if (!bound.empty()) + bounds.emplace_back(std::stoull(bound)); + return orderExcludeRegionString(bounds); +} + +std::string IndirectFitData::orderExcludeRegionString( + std::vector<std::size_t> &bounds) const { + for (auto it = bounds.begin(); it < bounds.end() - 1; it += 2) + if (*it > *(it + 1)) + std::iter_swap(it, it + 1); + return constructExcludeRegionString(bounds); +} + +std::string IndirectFitData::constructExcludeRegionString( + const std::vector<std::size_t> &bounds) const { + std::string excludeRegion; + for (auto it = bounds.begin(); it < bounds.end(); ++it) { + excludeRegion += std::to_string(*it); + excludeRegion += it == bounds.end() - 1 ? "" : ","; + } + return excludeRegion; } IndirectFitData &IndirectFitData::combine(const IndirectFitData &fitData) { diff --git a/qt/scientific_interfaces/Indirect/IndirectFitData.h b/qt/scientific_interfaces/Indirect/IndirectFitData.h index df60514bd02..155006a978c 100644 --- a/qt/scientific_interfaces/Indirect/IndirectFitData.h +++ b/qt/scientific_interfaces/Indirect/IndirectFitData.h @@ -191,6 +191,11 @@ public: void setEndX(double endX, std::size_t spectrum); void setExcludeRegionString(const std::string &excludeRegion, std::size_t spectrum); + std::string + validateExcludeRegionString(const std::string &excludeRegionString) const; + std::string orderExcludeRegionString(std::vector<std::size_t> &bounds) const; + std::string + constructExcludeRegionString(const std::vector<std::size_t> &bounds) const; private: void validateSpectra(const Spectra &spectra); diff --git a/qt/scientific_interfaces/Indirect/test/IndirectFitDataTest.h b/qt/scientific_interfaces/Indirect/test/IndirectFitDataTest.h index e2592a8d8ab..4f9bb45322d 100644 --- a/qt/scientific_interfaces/Indirect/test/IndirectFitDataTest.h +++ b/qt/scientific_interfaces/Indirect/test/IndirectFitDataTest.h @@ -91,40 +91,86 @@ public: } } - void test_that_correct_excludeRegion_is_returned() { - auto data = getIndirectFitData(10, 3); + void + test_that_correct_excludeRegion_is_returned_when_regions_are_in_correct_order() { + /// When each pair of numbers in the string are in order, then the whole + /// string is in the correct order + auto data = getIndirectFitData(4, 3); - data.setExcludeRegionString("1,8", 1); - data.setExcludeRegionString("1,5", 2); - data.setExcludeRegionString("2,6", 3); + data.setExcludeRegionString("1,8", 0); + data.setExcludeRegionString("2,5", 1); + data.setExcludeRegionString("1,2,5,6,3,4", 2); std::vector<double> regionVector1; regionVector1.emplace_back(1.0); regionVector1.emplace_back(8.0); std::vector<double> regionVector2; - regionVector2.emplace_back(1.0); + regionVector2.emplace_back(2.0); regionVector2.emplace_back(5.0); - std::vector<double> regionVector3; - regionVector3.emplace_back(2.0); - regionVector3.emplace_back(6.0); - TS_ASSERT_EQUALS(data.getExcludeRegion(1), "1,8"); - TS_ASSERT_EQUALS(data.getExcludeRegion(2), "1,5"); - TS_ASSERT_EQUALS(data.getExcludeRegion(3), "2,6"); - TS_ASSERT_EQUALS(data.getExcludeRegion(4), ""); - TS_ASSERT_EQUALS(data.excludeRegionsVector(1), regionVector1); - TS_ASSERT_EQUALS(data.excludeRegionsVector(2), regionVector2); - TS_ASSERT_EQUALS(data.excludeRegionsVector(3), regionVector3); - TS_ASSERT_EQUALS(data.excludeRegionsVector(4).empty(), true); + + TS_ASSERT_EQUALS(data.getExcludeRegion(0), "1,8"); + TS_ASSERT_EQUALS(data.getExcludeRegion(1), "2,5"); + TS_ASSERT_EQUALS(data.getExcludeRegion(2), "1,2,5,6,3,4"); + TS_ASSERT_EQUALS(data.getExcludeRegion(3), ""); + TS_ASSERT_EQUALS(data.excludeRegionsVector(0), regionVector1); + TS_ASSERT_EQUALS(data.excludeRegionsVector(1), regionVector2); + TS_ASSERT_EQUALS(data.excludeRegionsVector(3).empty(), true); } - void test_that_Spectra_is_set_correctly() { - auto data = getIndirectFitData(1, 3); + void test_that_excludeRegion_is_stored_in_correct_order() { + auto data = getIndirectFitData(10, 3); + + data.setExcludeRegionString("6,2", 0); + data.setExcludeRegionString("6,2,1,2,3,4,7,6", 1); + data.setExcludeRegionString("1,2,2,3,20,18,21,22,7,8", 2); + + std::vector<double> regionVector; + regionVector.emplace_back(2.0); + regionVector.emplace_back(6.0); + + TS_ASSERT_EQUALS(data.getExcludeRegion(0), "2,6"); + TS_ASSERT_EQUALS(data.getExcludeRegion(1), "2,6,1,2,3,4,6,7"); + TS_ASSERT_EQUALS(data.getExcludeRegion(2), "1,2,2,3,18,20,21,22,7,8"); + TS_ASSERT_EQUALS(data.excludeRegionsVector(0), regionVector); + } + + void test_throws_when_setSpectra_is_provided_an_out_of_range_spectra() { + auto data = getIndirectFitData(10, 3); + + std::vector<Spectra> spectraPairs; + spectraPairs.emplace_back(std::make_pair(0u, 11u)); + spectraPairs.emplace_back(std::make_pair(0u, 1000000000000000000u)); + spectraPairs.emplace_back(std::make_pair(10u, 10u)); + std::vector<std::string> spectraStrings; + spectraStrings.emplace_back("-1"); + spectraStrings.emplace_back("10"); + spectraStrings.emplace_back("100000000000000000000000000000"); + spectraStrings.emplace_back("1,5,10,20,30,60,80,100"); + spectraStrings.emplace_back("1,2,3,4,5,6,22"); + + for (auto i = 0u; i < spectraPairs.size(); ++i) + TS_ASSERT_THROWS(data.setSpectra(spectraPairs[i]), std::runtime_error); + for (auto i = 0u; i < spectraStrings.size(); ++i) + TS_ASSERT_THROWS(data.setSpectra(spectraStrings[i]), std::runtime_error); + } + + void test_no_throw_when_setSpectra_is_provided_a_valid_spectra() { + auto data = getIndirectFitData(10, 3); - const Spectra spec = std::make_pair(0u, 5u); - data.setSpectra(spec); - // NOT FINISHED - TS_ASSERT_EQUALS(data.spectra().empty(), false); - //TS_ASSERT_EQUALS(data.spectra().which(), spec.type()); + std::vector<Spectra> spectraPairs; + spectraPairs.emplace_back(std::make_pair(0u, 9u)); + spectraPairs.emplace_back(std::make_pair(4u, 4u)); + spectraPairs.emplace_back(std::make_pair(7u, 4u)); + std::vector<std::string> spectraStrings; + spectraStrings.emplace_back("0"); + spectraStrings.emplace_back("9"); + spectraStrings.emplace_back("0,9,6,4,5"); + spectraStrings.emplace_back("1,2,3,4,5,6"); + + for (auto i = 0u; i < spectraPairs.size(); ++i) + TS_ASSERT_THROWS_NOTHING(data.setSpectra(spectraPairs[i])); + for (auto i = 0u; i < spectraStrings.size(); ++i) + TS_ASSERT_THROWS_NOTHING(data.setSpectra(spectraStrings[i])); } }; -- GitLab