Newer
Older
#ifndef MANTID_KERNEL_DATASERVICETEST_H_
#define MANTID_KERNEL_DATASERVICETEST_H_
#include "MantidKernel/DataService.h"
#include <cxxtest/TestSuite.h>
#include <Poco/NObserver.h>
#include <boost/make_shared.hpp>
using namespace Mantid;
using namespace Mantid::Kernel;
/// A simple data service
class FakeDataService : public DataService<int> {
FakeDataService() : DataService<int>("FakeDataService") {}
class DataServiceTest : public CxxTest::TestSuite {
private:
// A data service storing an int
FakeDataService svc;
int notificationFlag; // A flag to help with testing notifications
std::vector<int> vector;
public:
static DataServiceTest *createSuite() { return new DataServiceTest(); }
static void destroySuite(DataServiceTest *suite) { delete suite; }
notificationFlag = 0;
ConfigService::Instance().setString("MantidOptions.InvisibleWorkspaces",
"0");
}
// Handler for an observer, called each time an object is added
void handleAddNotification(
const Poco::AutoPtr<FakeDataService::AddNotification> &) {
std::lock_guard<std::mutex> _lock(m_vectorMutex);
vector.push_back(123);
++notificationFlag;
void test_add() {
Poco::NObserver<DataServiceTest, FakeDataService::AddNotification> observer(
*this, &DataServiceTest::handleAddNotification);
svc.notificationCenter.addObserver(observer);
auto one = boost::make_shared<int>(1);
// Add and check that it is in there
TS_ASSERT_THROWS_NOTHING(svc.add("one", one););
TS_ASSERT_EQUALS(svc.size(), 1);
TS_ASSERT(svc.doesExist("one"));
TS_ASSERT(svc.retrieve("one") == one);
// Same object can go in with different name
svc.add("anotherOne", one);
TS_ASSERT_EQUALS(svc.retrieve("anotherOne"), one);
// Can't re-add the same name
TS_ASSERT_THROWS(svc.add("one", one), std::runtime_error);
// Can't add blank name
TS_ASSERT_THROWS(svc.add("", one), std::runtime_error);
// Can't add empty pointer
TS_ASSERT_THROWS(svc.add("Null", boost::shared_ptr<int>()),
std::runtime_error);
svc.add("__hidden", boost::make_shared<int>(99));
TS_ASSERT_EQUALS(notificationFlag, 3)
svc.notificationCenter.removeObserver(observer);
}
void handlePreDeleteNotification(const Poco::AutoPtr<
FakeDataService::PreDeleteNotification> ¬ification) {
TS_ASSERT_EQUALS(notification->objectName(), "one");
TS_ASSERT_EQUALS(*notification->object(), 1);
++notificationFlag;
}
void handlePostDeleteNotification(const Poco::AutoPtr<
FakeDataService::PostDeleteNotification> ¬ification) {
TS_ASSERT_EQUALS(notification->objectName(), "one");
++notificationFlag;
void test_remove() {
Poco::NObserver<DataServiceTest, FakeDataService::PreDeleteNotification>
observer(*this, &DataServiceTest::handlePreDeleteNotification);
svc.notificationCenter.addObserver(observer);
Poco::NObserver<DataServiceTest, FakeDataService::PreDeleteNotification>
postobserver(*this, &DataServiceTest::handlePreDeleteNotification);
svc.notificationCenter.addObserver(postobserver);
TS_ASSERT_THROWS_NOTHING(svc.add("one", boost::make_shared<int>(1)););
TS_ASSERT_EQUALS(svc.size(), 1);
TS_ASSERT_THROWS_NOTHING(
svc.remove("two")); // Nothing happens if the workspace isn't there
TS_ASSERT_THROWS_NOTHING(svc.remove("one"));
TS_ASSERT_EQUALS(svc.size(), 0);
TS_ASSERT_EQUALS(notificationFlag, 2);
svc.notificationCenter.removeObserver(observer);
svc.notificationCenter.removeObserver(postobserver);
void test_addOrReplace() {
TS_ASSERT_EQUALS(svc.size(), 0);
TS_ASSERT_THROWS_NOTHING(svc.add("one", boost::make_shared<int>(1)););
TS_ASSERT_EQUALS(svc.size(), 1);
// Does it replace?
boost::shared_ptr<int> two = boost::make_shared<int>(2);
TS_ASSERT_THROWS_NOTHING(svc.addOrReplace("one", two););
TS_ASSERT_EQUALS(svc.size(), 1);
TS_ASSERT(svc.doesExist("one"));
// Was the name replaced? One equals two, what funny math!!!
TS_ASSERT(svc.retrieve("one") == two);
TS_ASSERT_EQUALS(*svc.retrieve("one"), 2);
// Can't add blank names
TS_ASSERT_THROWS(svc.addOrReplace("", two), std::runtime_error);
// Can't add empty pointer
TS_ASSERT_THROWS(svc.addOrReplace("one", boost::shared_ptr<int>()),
std::runtime_error);
void handleAfterReplaceNotification(
const Poco::AutoPtr<FakeDataService::AfterReplaceNotification> &) {
++notificationFlag;
}
void handleRenameNotification(
const Poco::AutoPtr<FakeDataService::RenameNotification> &) {
++notificationFlag;
}
void test_rename() {
Poco::NObserver<DataServiceTest, FakeDataService::AfterReplaceNotification>
observer(*this, &DataServiceTest::handleAfterReplaceNotification);
svc.notificationCenter.addObserver(observer);
Poco::NObserver<DataServiceTest, FakeDataService::RenameNotification>
observer2(*this, &DataServiceTest::handleRenameNotification);
svc.notificationCenter.addObserver(observer2);
auto one = boost::make_shared<int>(1);
auto two = boost::make_shared<int>(2);
svc.add("One", one);
svc.add("Two", two);
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
TS_ASSERT_EQUALS(svc.size(), 2);
TSM_ASSERT_THROWS_NOTHING("Nothing should happen if the names match",
svc.rename("One", "One"));
TSM_ASSERT_THROWS_NOTHING("Should be just a warning if object not there",
svc.rename("NotThere", "NewName"));
svc.rename(
"one",
"anotherOne"); // Note: Rename is case-insensitive on the old name
TS_ASSERT_EQUALS(svc.size(), 2);
TSM_ASSERT_THROWS("One should have been renamed to anotherOne",
svc.retrieve("one"), Exception::NotFoundError);
TSM_ASSERT_EQUALS("One should have been renamed to anotherOne",
svc.retrieve("anotherOne"), one);
TSM_ASSERT_EQUALS("The observers should have been called 2 times in total",
notificationFlag, 2);
svc.rename("Two", "anotherOne");
TS_ASSERT_EQUALS(svc.size(), 1);
TSM_ASSERT_THROWS("Two should have been renamed to anotherOne",
svc.retrieve("two"), Exception::NotFoundError);
TSM_ASSERT_EQUALS("Two should have been renamed to anotherOne",
svc.retrieve("anotherOne"), two);
TSM_ASSERT_EQUALS("The observers should have been called 4 times in total",
notificationFlag, 4);
svc.notificationCenter.removeObserver(observer);
svc.notificationCenter.removeObserver(observer2);
TS_ASSERT_THROWS(svc.rename("anotherOne", ""), std::runtime_error);
TSM_ASSERT_THROWS_NOTHING("'AnotherOne' should still be there",
svc.retrieve("anotherOne"));
void handleClearNotification(
const Poco::AutoPtr<FakeDataService::ClearNotification> &) {
++notificationFlag;
}
void test_clear() {
svc.add("something", boost::make_shared<int>(10));
TSM_ASSERT_LESS_THAN("Size should be 1", 0, svc.size());
svc.clear();
TSM_ASSERT_EQUALS("DataService should be empty", svc.size(), 0);
TSM_ASSERT("handleClearNotification should not have been called",
!notificationFlag);
Poco::NObserver<DataServiceTest, FakeDataService::ClearNotification>
observer(*this, &DataServiceTest::handleClearNotification);
svc.notificationCenter.addObserver(observer);
svc.add("something", boost::make_shared<int>(10));
svc.clear();
TSM_ASSERT_EQUALS("DataService should be empty", svc.size(), 0);
TSM_ASSERT("handleClearNotification should have been called",
notificationFlag);
svc.notificationCenter.removeObserver(observer);
}
void test_retrieve_and_doesExist() {
auto one = boost::make_shared<int>(1);
TS_ASSERT_EQUALS(svc.retrieve("one"), one);
TSM_ASSERT_EQUALS("Retrieval should be case-insensitive",
svc.retrieve("oNE"), one);
TS_ASSERT_THROWS(svc.retrieve("NOTone"), Exception::NotFoundError);
TS_ASSERT(svc.doesExist("one"));
TSM_ASSERT("doesExist should be case-insensitive", svc.doesExist("oNE"));
TS_ASSERT(!svc.doesExist("NOTone"));
void test_size() {
TS_ASSERT_EQUALS(svc.size(), 0);
svc.add("something", boost::make_shared<int>(-1));
TS_ASSERT_EQUALS(svc.size(), 1);
svc.add("__hidden", boost::make_shared<int>(1));
TSM_ASSERT_EQUALS("Hidden workspaces should not be counted", svc.size(), 1);
ConfigService::Instance().setString("MantidOptions.InvisibleWorkspaces",
"1");
TS_ASSERT_EQUALS(svc.size(), 2);
void test_getObjectNames_and_getObjects() {
auto one = boost::make_shared<int>(1);
auto two = boost::make_shared<int>(2);
auto three = boost::make_shared<int>(3);
svc.add("One", one);
svc.add("Two", two);
svc.add("TwoAgain",
two); // Same pointer again - should appear twice in getObjects()
svc.add("__Three", three);
auto names = svc.getObjectNames();
auto objects = svc.getObjects();
TSM_ASSERT_EQUALS("Hidden entries should not be returned", names.size(), 3);
TSM_ASSERT_EQUALS("Hidden entries should not be returned", objects.size(),
3);
TS_ASSERT_DIFFERS(std::find(names.cbegin(), names.cend(), "One"),
names.end());
TS_ASSERT_DIFFERS(std::find(names.cbegin(), names.cend(), "Two"),
names.end());
TS_ASSERT_DIFFERS(std::find(names.cbegin(), names.cend(), "TwoAgain"),
names.end());
TS_ASSERT_EQUALS(std::find(names.cbegin(), names.cend(), "__Three"),
names.end());
TSM_ASSERT_EQUALS("Hidden entries should not be returned",
std::find(names.cbegin(), names.cend(), "__Three"),
names.end());
TS_ASSERT_EQUALS(objects.at(0), one);
TS_ASSERT_EQUALS(objects.at(1), two);
TS_ASSERT_EQUALS(objects.at(2), two);
auto allNamesSize = svc.getObjectNames().size();
ConfigService::Instance().setString("MantidOptions.InvisibleWorkspaces",
"1");
TS_ASSERT_EQUALS(allNamesSize, 3)
names = svc.getObjectNames();
objects = svc.getObjects();
TS_ASSERT_EQUALS(names.size(), 4);
TS_ASSERT_EQUALS(objects.size(), 4);
TS_ASSERT_DIFFERS(std::find(names.cbegin(), names.cend(), "__Three"),
names.end());
TS_ASSERT_EQUALS(objects.at(3), three);
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
void test_sortedAndHiddenGetNames() {
auto one = boost::make_shared<int>(1);
auto two = boost::make_shared<int>(2);
auto three = boost::make_shared<int>(3);
auto four = boost::make_shared<int>(4);
// This time add them in a random order
svc.add("One", one);
svc.add("__Three", three);
svc.add("Four", four);
svc.add("Two", two);
typedef Mantid::Kernel::DataServiceSort sortedEnum;
typedef Mantid::Kernel::DataServiceHidden hiddenEnum;
// First assert that sort does not impact size
TS_ASSERT_EQUALS(svc.getObjectNames(sortedEnum::Sorted).size(),
svc.getObjectNames(sortedEnum::Unsorted).size());
// Get unsorted and sort the manually
auto sortReference = svc.getObjectNames();
std::sort(sortReference.begin(), sortReference.end());
TS_ASSERT_EQUALS(svc.getObjectNames(sortedEnum::Sorted), sortReference);
// Next assert that Hidden flags behave
TS_ASSERT_EQUALS(
svc.getObjectNames(sortedEnum::Unsorted, hiddenEnum::Exclude).size(),
3);
TS_ASSERT_EQUALS(
svc.getObjectNames(sortedEnum::Unsorted, hiddenEnum::Include).size(),
4);
}
// This starts observing the notifications of "add"
Poco::NObserver<DataServiceTest, FakeDataService::AddNotification> observer(
*this, &DataServiceTest::handleAddNotification);
svc.notificationCenter.addObserver(observer);
vector.clear();
svc.add("object1", boost::make_shared<int>(12345));
int num = 5000;
PARALLEL_FOR_NO_WSP_CHECK()
boost::shared_ptr<int> object = boost::make_shared<int>(i);
std::ostringstream mess;
mess << "item" << i;
// Adding/replacing some items
svc.addOrReplace(mess.str(), object);
// And retrieving some at the same time
boost::shared_ptr<int> retrieved = svc.retrieve("object1");
TS_ASSERT_EQUALS(*retrieved, 12345);
// Also add then remove another object
std::string otherName = "other_" + mess.str();
boost::shared_ptr<int> other = boost::make_shared<int>(i);
svc.add(otherName, other);
svc.remove(otherName);
TS_ASSERT_EQUALS(svc.size(), size_t(num + 1));
// Vector was append twice per loop
TS_ASSERT_EQUALS(vector.size(), size_t(num * 2 + 1));
// Try a few random items, check that they are there
TS_ASSERT_EQUALS(*svc.retrieve("item19"), 19);
TS_ASSERT_EQUALS(*svc.retrieve("item765"), 765);
TS_ASSERT_EQUALS(*svc.retrieve("item2345"), 2345);
void test_prefixToHide() {
TS_ASSERT_EQUALS(FakeDataService::prefixToHide(), "__");
void test_isHiddenDataServiceObject() {
TS_ASSERT(FakeDataService::isHiddenDataServiceObject("__hidden"));
TS_ASSERT(FakeDataService::isHiddenDataServiceObject("__HIDDEN"));
TS_ASSERT(!FakeDataService::isHiddenDataServiceObject("NotHidden"));
TS_ASSERT(!FakeDataService::isHiddenDataServiceObject("_NotHidden"));
TS_ASSERT(!FakeDataService::isHiddenDataServiceObject("NotHidden__"));
TS_ASSERT(!FakeDataService::isHiddenDataServiceObject("Not__Hidden"));
void test_showingHiddenObjects() {
TS_ASSERT(!FakeDataService::showingHiddenObjects());
ConfigService::Instance().setString("MantidOptions.InvisibleWorkspaces",
"1");
TS_ASSERT(FakeDataService::showingHiddenObjects());
// Check behaviour if it's set to some invalid values
ConfigService::Instance().setString("MantidOptions.InvisibleWorkspaces",
"invalid");
TS_ASSERT(!FakeDataService::showingHiddenObjects());
ConfigService::Instance().setString("MantidOptions.InvisibleWorkspaces",
"-1");
TS_ASSERT(!FakeDataService::showingHiddenObjects());
ConfigService::Instance().setString("MantidOptions.InvisibleWorkspaces",
"2");
TS_ASSERT(!FakeDataService::showingHiddenObjects());
ConfigService::Instance().setString("MantidOptions.InvisibleWorkspaces",
"^~");
TS_ASSERT(!FakeDataService::showingHiddenObjects());
};
#endif /* MANTID_KERNEL_DATASERVICETEST_H_ */