Skip to content
Snippets Groups Projects
DynamicFactoryTest.h 6.68 KiB
Newer Older
#ifndef DYNAMICFACTORYTEST_H_
#define DYNAMICFACTORYTEST_H_

#include "MantidKernel/DynamicFactory.h"

#include <boost/shared_ptr.hpp>
#include <Poco/NObserver.h>

#include <vector>
#include <string>
class IntFactory : public DynamicFactory<int> {};
class CaseSensitiveIntFactory
    : public DynamicFactory<int, CaseSensitiveStringComparator> {};
class DynamicFactoryTest : public CxxTest::TestSuite {
Nick Draper's avatar
Nick Draper committed
  typedef boost::shared_ptr<int> int_ptr;
  // This pair of boilerplate methods prevent the suite being created statically
  // This means the constructor isn't called when running other tests
  static DynamicFactoryTest *createSuite() { return new DynamicFactoryTest(); }
  static void destroySuite(DynamicFactoryTest *suite) { delete suite; }
  DynamicFactoryTest()
      : CxxTest::TestSuite(), factory(),
        m_notificationObserver(*this, &DynamicFactoryTest::handleFactoryUpdate),
        m_updateNoticeReceived(false) {
    factory.notificationCenter.addObserver(m_notificationObserver);
  }

  ~DynamicFactoryTest() {
    factory.notificationCenter.removeObserver(m_notificationObserver);
  }

  void testCreate() {
    TS_ASSERT_THROWS(factory.create("testEntry"), std::runtime_error)
    factory.subscribe<int>("testEntry");
    TS_ASSERT_THROWS_NOTHING(int_ptr i = factory.create("testEntry"));
    TS_ASSERT_THROWS_NOTHING(int_ptr i = factory.create("TESTENTRY"));
  void testCreateCaseSensitive() {
    TS_ASSERT_THROWS(caseSensitiveFactory.create("testEntryCaseSensitive"),
                     std::runtime_error)
    caseSensitiveFactory.subscribe<int>("testEntryCaseSensitive");
    TS_ASSERT_THROWS(
        int_ptr i = caseSensitiveFactory.create("testEntryCaseSENSITIVE"),
        std::runtime_error); // case error on a case sensitive dynamic factory
    TS_ASSERT_THROWS_NOTHING(
        int_ptr i2 = caseSensitiveFactory.create("testEntryCaseSensitive"));
    caseSensitiveFactory.unsubscribe("testEntryCaseSensitive");
  }

  void testCreateUnwrapped() {
    TS_ASSERT_THROWS(factory.createUnwrapped("testUnrappedEntry"),
                     std::runtime_error)
    factory.subscribe<int>("testUnwrappedEntry");
    TS_ASSERT_THROWS_NOTHING(i = factory.createUnwrapped("testUnwrappedEntry"));
    TS_ASSERT_THROWS_NOTHING(j = factory.createUnwrapped("TESTUnwrappedEntry"));
    factory.unsubscribe("testUnwrappedEntry");
  }

  void testCreateUnwrappedCaseSensitive() {
    TS_ASSERT_THROWS(
        caseSensitiveFactory.create("testUnrappedEntryCaseSensitive"),
        std::runtime_error)
    caseSensitiveFactory.subscribe<int>("testUnrappedEntryCaseSensitive");
    int *i = NULL;
    TS_ASSERT_THROWS(
        i = caseSensitiveFactory.createUnwrapped(
            "testUnrappedentrycaseSENSITIVE"),
        std::runtime_error); // case error on a case sensitive dynamic factory
    TS_ASSERT_THROWS_NOTHING(i = caseSensitiveFactory.createUnwrapped(
                                 "testUnrappedEntryCaseSensitive"));
    delete i;
    caseSensitiveFactory.unsubscribe("testUnrappedEntryCaseSensitive");
  }

  void testSubscribeWithEmptyNameThrowsInvalidArgument() {
    TS_ASSERT_THROWS(factory.subscribe<int>(""), std::invalid_argument);
  void
  testSubscribeWithReplaceEqualsErrorIfExistsThrowsRegisteringMatchingClass() {
    TS_ASSERT_THROWS_NOTHING(
        factory.subscribe("int", new Instantiator<int, int>));
    TS_ASSERT_THROWS(factory.subscribe("int", new Instantiator<int, int>,
                                       IntFactory::ErrorIfExists),
                     std::runtime_error);
  void testSubscribeWithReplaceEqualsOverwriteCurrentReplacesMatchingClass() {
    TS_ASSERT_THROWS_NOTHING(
        factory.subscribe("int", new Instantiator<int, int>));
    TS_ASSERT_THROWS_NOTHING(factory.subscribe(
        "int", new Instantiator<int, int>, IntFactory::OverwriteCurrent));
  void testSubscribeByDefaultDoesNotNotify() {
    TS_ASSERT_THROWS_NOTHING(factory.subscribe<int>("int"));
    TS_ASSERT_EQUALS(m_updateNoticeReceived, false)
  void testSubscribeNotifiesIfTheyAreSwitchedOn() {
    m_updateNoticeReceived = false;
    factory.enableNotifications();
    TS_ASSERT_THROWS_NOTHING(factory.subscribe<int>("intWithNotice"));
    TS_ASSERT_EQUALS(m_updateNoticeReceived, true)
    TS_ASSERT_THROWS_NOTHING(factory.unsubscribe("intWithNotice"));
  }
  void testUnsubscribeByDefaultDoesNotNotify() {
    TS_ASSERT_THROWS(factory.unsubscribe("tester"), std::runtime_error);
    factory.subscribe<int>("tester");
    m_updateNoticeReceived = false;
    TS_ASSERT_THROWS_NOTHING(factory.unsubscribe("tester"));
    TS_ASSERT_EQUALS(m_updateNoticeReceived, false)
  void testUnsubscribeNotifiesIfTheyAreSwitchedOn() {
    TS_ASSERT_THROWS_NOTHING(factory.subscribe<int>("intWithNotice"));
    factory.enableNotifications();
    m_updateNoticeReceived = false;
    TS_ASSERT_THROWS_NOTHING(factory.unsubscribe("intWithNotice"));
    TS_ASSERT_EQUALS(m_updateNoticeReceived, true)

    factory.disableNotifications();
    m_updateNoticeReceived = false;
  void testExists() {
    TS_ASSERT(!factory.exists("testing"));
    factory.subscribe<int>("testing");
    TS_ASSERT(factory.exists("testing"));
    TS_ASSERT(factory.exists("TESTING"));

  void testGetKeys() {
    std::string testKey = "testGetKeys";
    // check it is not already present
    TS_ASSERT_THROWS(factory.create(testKey), std::runtime_error)
    factory.subscribe<int>(testKey);

    std::vector<std::string> keys = factory.getKeys();

    TSM_ASSERT("Could not find the test key in the returned vector.",
               std::find(keys.begin(), keys.end(), testKey) !=
                   keys.end()) // check the case is correct
    TS_ASSERT(!keys.empty());
  void testGetKeysRetainsCase() {
    std::string testKey = "testGetKeysRetainsCase";
    // check it is not already present
    TS_ASSERT_THROWS(factory.create(testKey), std::runtime_error)
    factory.subscribe<int>(testKey);

    std::vector<std::string> keys = factory.getKeys();

    factory.unsubscribe(testKey);
  void
  handleFactoryUpdate(const Poco::AutoPtr<IntFactory::UpdateNotification> &) {
  CaseSensitiveIntFactory caseSensitiveFactory;
  Poco::NObserver<DynamicFactoryTest, IntFactory::UpdateNotification>
      m_notificationObserver;