summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/base/Makefile.am2
-rw-r--r--src/base/listener.cpp66
-rw-r--r--src/base/listener.h99
-rw-r--r--src/cvc4.i2
-rw-r--r--src/expr/Makefile.am3
-rw-r--r--src/expr/node_manager.cpp3
-rw-r--r--src/expr/resource_manager.i5
-rw-r--r--src/parser/parser.cpp2
-rw-r--r--src/prop/prop_engine.cpp2
-rw-r--r--src/smt/smt_engine.cpp58
-rw-r--r--src/smt/smt_options_handler.cpp2
-rw-r--r--src/theory/bv/bitblaster_template.h2
-rw-r--r--src/theory/output_channel.h2
-rw-r--r--src/theory/rewriter.cpp3
-rw-r--r--src/theory/theory_engine.cpp2
-rw-r--r--src/util/Makefile.am3
-rw-r--r--src/util/resource_manager.cpp (renamed from src/expr/resource_manager.cpp)31
-rw-r--r--src/util/resource_manager.h (renamed from src/expr/resource_manager.h)20
-rw-r--r--src/util/resource_manager.i5
-rw-r--r--test/unit/Makefile.am1
-rw-r--r--test/unit/theory/theory_black.h5
-rw-r--r--test/unit/util/listener_black.h156
22 files changed, 435 insertions, 39 deletions
diff --git a/src/base/Makefile.am b/src/base/Makefile.am
index ed41db8ed..f2fe3f306 100644
--- a/src/base/Makefile.am
+++ b/src/base/Makefile.am
@@ -19,6 +19,8 @@ libbase_la_SOURCES = \
cvc4_assert.h \
exception.cpp \
exception.h \
+ listener.cpp \
+ listener.h \
modal_exception.h \
output.cpp \
output.h
diff --git a/src/base/listener.cpp b/src/base/listener.cpp
new file mode 100644
index 000000000..62bec5990
--- /dev/null
+++ b/src/base/listener.cpp
@@ -0,0 +1,66 @@
+/********************* */
+/*! \file managed_listener.h
+ ** \verbatim
+ ** Original author: Tim King
+ ** Major contributors: none
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2016 New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief Output utility classes and functions
+ **
+ ** Output utility classes and functions.
+ **/
+
+#include "base/listener.h"
+
+#include <list>
+
+#include "base/cvc4_assert.h"
+
+namespace CVC4 {
+
+Listener::Listener(){}
+Listener::~Listener(){}
+
+ListenerCollection::ListenerCollection() : d_listeners() {}
+ListenerCollection::~ListenerCollection() { Assert(empty()); }
+
+ListenerCollection::iterator ListenerCollection::addListener(Listener* listener)
+{
+ return d_listeners.insert(d_listeners.end(), listener);
+}
+
+void ListenerCollection::removeListener(iterator position) {
+ d_listeners.erase(position);
+}
+
+void ListenerCollection::notify() {
+ for(iterator i = d_listeners.begin(), iend = d_listeners.end(); i != iend;
+ ++i)
+ {
+ Listener* listener = *i;
+ listener->notify();
+ }
+}
+
+bool ListenerCollection::empty() const { return d_listeners.empty(); }
+
+
+RegisterListener::RegisterListener(ListenerCollection* collection,
+ Listener* listener)
+ : d_listener(listener)
+ , d_position()
+ , d_collection(collection)
+{
+ d_position = d_collection->addListener(d_listener);
+}
+
+RegisterListener::~RegisterListener() {
+ d_collection->removeListener(d_position);
+ delete d_listener;
+}
+
+}/* CVC4 namespace */
diff --git a/src/base/listener.h b/src/base/listener.h
new file mode 100644
index 000000000..d6828818c
--- /dev/null
+++ b/src/base/listener.h
@@ -0,0 +1,99 @@
+/********************* */
+/*! \file listener.h
+ ** \verbatim
+ ** Original author: Tim King
+ ** Major contributors: none
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2016 New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief Utility classes for listeners and collections of listeners.
+ **
+ ** Utilities for the development of a Listener interface class. This class
+ ** provides a single notification that must be overwritten. This file also
+ ** provides a utility class for a collection of listeners and an RAII style
+ ** RegisterListener class for managing the relationship between Listeners
+ ** and the manager.
+ **/
+
+#include "cvc4_public.h"
+
+#ifndef __CVC4__LISTENER_H
+#define __CVC4__LISTENER_H
+
+#include <list>
+
+namespace CVC4 {
+
+/**
+ * Listener interface class.
+ *
+ * The interface provides a notify() function.
+ */
+class CVC4_PUBLIC Listener {
+public:
+ Listener();
+ virtual ~Listener();
+
+ /** Note that notify may throw arbitrary exceptions. */
+ virtual void notify() = 0;
+};
+
+/**
+ * ListenerCollection is a list of Listener instances.
+ * One can add and remove Listeners.
+ *
+ * ListenerCollection does not own the memory of the Listeners.
+ * As a sanity check, it asserted that all of its listeners
+ * have been removed.
+ */
+class CVC4_PUBLIC ListenerCollection {
+public:
+ typedef std::list<Listener*> ListenerList;
+ typedef ListenerList::iterator iterator;
+
+ ListenerCollection();
+
+ ~ListenerCollection();
+
+ iterator addListener(Listener* listener);
+
+ void removeListener(iterator position);
+
+ void notify();
+
+ bool empty() const;
+
+private:
+ ListenerList d_listeners;
+};
+
+/**
+ * RegisterListener is an RAII utility function for using Listener
+ * with ListenerCollection.
+ *
+ * On construction, the RegisterListener takes a ListenerCollection, collection,
+ * and a Listener*, listener. It takes over the memory for listener. It then
+ * add listener to collection. On destruction it removes listener and calls
+ * delete on listener.
+ *
+ * Because of this usage, a RegisterListener must be destroyed before
+ * collection.
+ */
+class CVC4_PUBLIC RegisterListener {
+public:
+ RegisterListener(ListenerCollection* collection, Listener* listener);
+ ~RegisterListener();
+
+private:
+ Listener* d_listener;
+ ListenerCollection::iterator d_position;
+ ListenerCollection* d_collection;
+};
+
+
+}/* CVC4 namespace */
+
+#endif /* __CVC4__LISTENER_H */
diff --git a/src/cvc4.i b/src/cvc4.i
index b5ce4a5fa..4b954489c 100644
--- a/src/cvc4.i
+++ b/src/cvc4.i
@@ -322,6 +322,7 @@ std::set<JavaInputStreamAdapter*> CVC4::JavaInputStreamAdapter::s_adapters;
%include "util/hash.i"
%include "util/proof.i"
%include "util/regexp.i"
+%include "util/resource_manager.i"
%include "util/result.i"
%include "util/sexpr.i"
%include "util/statistics.i"
@@ -336,7 +337,6 @@ std::set<JavaInputStreamAdapter*> CVC4::JavaInputStreamAdapter::s_adapters;
%include "expr/datatype.i"
%include "expr/predicate.i"
%include "expr/record.i"
-%include "expr/resource_manager.i"
%include "proof/unsat_core.i"
// TIM:
diff --git a/src/expr/Makefile.am b/src/expr/Makefile.am
index 4648ed3af..b3fb13253 100644
--- a/src/expr/Makefile.am
+++ b/src/expr/Makefile.am
@@ -39,8 +39,6 @@ libexpr_la_SOURCES = \
pickle_data.h \
pickler.cpp \
pickler.h \
- resource_manager.cpp \
- resource_manager.h \
symbol_table.cpp \
symbol_table.h \
type.cpp \
@@ -92,7 +90,6 @@ EXTRA_DIST = \
type.i \
kind.i \
expr.i \
- resource_manager.i \
record.i \
predicate.i \
variable_type_map.i \
diff --git a/src/expr/node_manager.cpp b/src/expr/node_manager.cpp
index 4cb75bfc7..13960b717 100644
--- a/src/expr/node_manager.cpp
+++ b/src/expr/node_manager.cpp
@@ -29,9 +29,8 @@
#include "expr/type_checker.h"
#include "options/options.h"
#include "options/smt_options.h"
-#include "expr/resource_manager.h"
#include "util/statistics_registry.h"
-
+#include "util/resource_manager.h"
using namespace std;
using namespace CVC4::expr;
diff --git a/src/expr/resource_manager.i b/src/expr/resource_manager.i
deleted file mode 100644
index 77edbd8c3..000000000
--- a/src/expr/resource_manager.i
+++ /dev/null
@@ -1,5 +0,0 @@
-%{
-#include "expr/resource_manager.h"
-%}
-
-%include "expr/resource_manager.h"
diff --git a/src/parser/parser.cpp b/src/parser/parser.cpp
index 120f63987..adbeaabd3 100644
--- a/src/parser/parser.cpp
+++ b/src/parser/parser.cpp
@@ -28,13 +28,13 @@
#include "expr/expr.h"
#include "expr/expr_iomanip.h"
#include "expr/kind.h"
-#include "expr/resource_manager.h"
#include "expr/type.h"
#include "options/options.h"
#include "options/smt_options.h"
#include "parser/input.h"
#include "parser/parser_exception.h"
#include "smt_util/command.h"
+#include "util/resource_manager.h"
using namespace std;
using namespace CVC4::kind;
diff --git a/src/prop/prop_engine.cpp b/src/prop/prop_engine.cpp
index 630825103..9767ac7c7 100644
--- a/src/prop/prop_engine.cpp
+++ b/src/prop/prop_engine.cpp
@@ -24,7 +24,6 @@
#include "base/output.h"
#include "decision/decision_engine.h"
#include "expr/expr.h"
-#include "expr/resource_manager.h"
#include "options/base_options.h"
#include "options/decision_options.h"
#include "options/main_options.h"
@@ -40,6 +39,7 @@
#include "smt_util/command.h"
#include "theory/theory_engine.h"
#include "theory/theory_registrar.h"
+#include "util/resource_manager.h"
#include "util/result.h"
using namespace std;
diff --git a/src/smt/smt_engine.cpp b/src/smt/smt_engine.cpp
index 1999930d1..1962c6433 100644
--- a/src/smt/smt_engine.cpp
+++ b/src/smt/smt_engine.cpp
@@ -27,6 +27,7 @@
#include <vector>
#include "base/exception.h"
+#include "base/listener.h"
#include "base/modal_exception.h"
#include "base/output.h"
#include "context/cdhashset.h"
@@ -40,7 +41,6 @@
#include "expr/node.h"
#include "expr/node_builder.h"
#include "expr/node_self_iterator.h"
-#include "expr/resource_manager.h"
#include "options/arith_options.h"
#include "options/arrays_options.h"
#include "options/base_options.h"
@@ -99,6 +99,7 @@
#include "util/configuration_private.h"
#include "util/hash.h"
#include "util/proof.h"
+#include "util/resource_manager.h"
using namespace std;
using namespace CVC4;
@@ -296,6 +297,32 @@ struct SmtEngineStatistics {
}
};/* struct SmtEngineStatistics */
+
+class SoftResourceOutListener : public Listener {
+ public:
+ SoftResourceOutListener(SmtEngine& smt) : d_smt(&smt) {}
+ virtual void notify() {
+ SmtScope scope(d_smt);
+ Assert(smt::smtEngineInScope());
+ d_smt->interrupt();
+ }
+ private:
+ SmtEngine* d_smt;
+}; /* class SoftResourceOutListener */
+
+
+class HardResourceOutListener : public Listener {
+ public:
+ HardResourceOutListener(SmtEngine& smt) : d_smt(&smt) {}
+ virtual void notify() {
+ SmtScope scope(d_smt);
+ theory::Rewriter::clearCaches();
+ }
+ private:
+ SmtEngine* d_smt;
+}; /* class HardResourceOutListener */
+
+
/**
* This is an inelegant solution, but for the present, it will work.
* The point of this is to separate the public and private portions of
@@ -318,6 +345,16 @@ class SmtEnginePrivate : public NodeManagerListener {
*/
ResourceManager* d_resourceManager;
+ /**
+ * Listener for the when a soft resource out occurs.
+ */
+ RegisterListener* d_softResourceOutListener;
+
+ /**
+ * Listener for the when a hard resource out occurs.
+ */
+ RegisterListener* d_hardResourceOutListener;
+
/** Learned literals */
vector<Node> d_nonClausalLearnedLiterals;
@@ -465,6 +502,8 @@ public:
SmtEnginePrivate(SmtEngine& smt) :
d_smt(smt),
d_resourceManager(NULL),
+ d_softResourceOutListener(NULL),
+ d_hardResourceOutListener(NULL),
d_nonClausalLearnedLiterals(),
d_realAssertionsEnd(0),
d_booleanTermConverter(NULL),
@@ -485,9 +524,23 @@ public:
d_smt.d_nodeManager->subscribeEvents(this);
d_true = NodeManager::currentNM()->mkConst(true);
d_resourceManager = NodeManager::currentResourceManager();
+
+ d_softResourceOutListener = new RegisterListener(
+ d_resourceManager->getSoftListeners(),
+ new SoftResourceOutListener(d_smt));
+
+ d_hardResourceOutListener = new RegisterListener(
+ d_resourceManager->getHardListeners(),
+ new HardResourceOutListener(d_smt));
+
}
~SmtEnginePrivate() throw() {
+ delete d_hardResourceOutListener;
+ d_hardResourceOutListener = NULL;
+ delete d_softResourceOutListener;
+ d_softResourceOutListener = NULL;
+
if(d_propagatorNeedsFinish) {
d_propagator.finish();
d_propagatorNeedsFinish = false;
@@ -733,7 +786,8 @@ SmtEngine::SmtEngine(ExprManager* em) throw() :
d_private = new smt::SmtEnginePrivate(*this);
d_statisticsRegistry = new StatisticsRegistry();
d_stats = new SmtEngineStatistics();
- d_stats->d_resourceUnitsUsed.setData(d_private->getResourceManager()->d_cumulativeResourceUsed);
+ d_stats->d_resourceUnitsUsed.setData(
+ d_private->getResourceManager()->getResourceUsage());
// We have mutual dependency here, so we add the prop engine to the theory
// engine later (it is non-essential there)
d_theoryEngine = new TheoryEngine(d_context, d_userContext,
diff --git a/src/smt/smt_options_handler.cpp b/src/smt/smt_options_handler.cpp
index 147a53368..758ffaec8 100644
--- a/src/smt/smt_options_handler.cpp
+++ b/src/smt/smt_options_handler.cpp
@@ -28,7 +28,6 @@
#include "expr/expr_iomanip.h"
#include "expr/metakind.h"
#include "expr/node_manager.h"
-#include "expr/resource_manager.h"
#include "lib/strtok_r.h"
#include "options/arith_heuristic_pivot_rule.h"
#include "options/arith_propagation_mode.h"
@@ -59,6 +58,7 @@
#include "theory/logic_info.h"
#include "util/configuration.h"
#include "util/configuration_private.h"
+#include "util/resource_manager.h"
#warning "TODO: Make SmtOptionsHandler non-public and refactor driver unified."
diff --git a/src/theory/bv/bitblaster_template.h b/src/theory/bv/bitblaster_template.h
index 7b071b9e9..ec76bb4f6 100644
--- a/src/theory/bv/bitblaster_template.h
+++ b/src/theory/bv/bitblaster_template.h
@@ -25,11 +25,11 @@
#include "bitblast_strategies_template.h"
#include "context/cdhashmap.h"
#include "expr/node.h"
-#include "expr/resource_manager.h"
#include "prop/sat_solver.h"
#include "smt/smt_globals.h"
#include "theory/theory_registrar.h"
#include "theory/valuation.h"
+#include "util/resource_manager.h"
class Abc_Obj_t_;
typedef Abc_Obj_t_ Abc_Obj_t;
diff --git a/src/theory/output_channel.h b/src/theory/output_channel.h
index 2113ea66e..2491aef3a 100644
--- a/src/theory/output_channel.h
+++ b/src/theory/output_channel.h
@@ -20,9 +20,9 @@
#define __CVC4__THEORY__OUTPUT_CHANNEL_H
#include "base/cvc4_assert.h"
-#include "expr/resource_manager.h"
#include "smt/logic_exception.h"
#include "theory/interrupted.h"
+#include "util/resource_manager.h"
namespace CVC4 {
namespace theory {
diff --git a/src/theory/rewriter.cpp b/src/theory/rewriter.cpp
index 697736ebf..c98429dd2 100644
--- a/src/theory/rewriter.cpp
+++ b/src/theory/rewriter.cpp
@@ -17,12 +17,11 @@
#include "theory/rewriter.h"
-#include "expr/resource_manager.h"
#include "theory/theory.h"
#include "smt/smt_engine_scope.h"
#include "smt/smt_statistics_registry.h"
#include "theory/rewriter_tables.h"
-
+#include "util/resource_manager.h"
using namespace std;
diff --git a/src/theory/theory_engine.cpp b/src/theory/theory_engine.cpp
index bcc16c63a..25eac2ed4 100644
--- a/src/theory/theory_engine.cpp
+++ b/src/theory/theory_engine.cpp
@@ -23,7 +23,6 @@
#include "expr/attribute.h"
#include "expr/node.h"
#include "expr/node_builder.h"
-#include "expr/resource_manager.h"
#include "options/bv_options.h"
#include "options/options.h"
#include "options/quantifiers_options.h"
@@ -46,6 +45,7 @@
#include "theory/theory_traits.h"
#include "theory/uf/equality_engine.h"
#include "theory/unconstrained_simplifier.h"
+#include "util/resource_manager.h"
using namespace std;
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index e1c593243..e95faea56 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -43,6 +43,8 @@ libutil_la_SOURCES = \
proof.h \
regexp.cpp \
regexp.h \
+ resource_manager.cpp \
+ resource_manager.h \
result.cpp \
result.h \
sexpr.cpp \
@@ -97,6 +99,7 @@ EXTRA_DIST = \
rational_gmp_imp.cpp \
rational_gmp_imp.h \
regexp.i \
+ resource_manager.i \
result.i \
sexpr.i \
statistics.i \
diff --git a/src/expr/resource_manager.cpp b/src/util/resource_manager.cpp
index f36200282..d426ab03e 100644
--- a/src/expr/resource_manager.cpp
+++ b/src/util/resource_manager.cpp
@@ -13,15 +13,10 @@
**
** Manages and updates various resource and time limits.
**/
-#include "expr/resource_manager.h"
+#include "util/resource_manager.h"
+#include "base/cvc4_assert.h"
#include "base/output.h"
-#include "options/smt_options.h"
-#include "smt/smt_engine_scope.h"
-#include "theory/rewriter.h"
-
-#warning "TODO: Break the dependence of the ResourceManager on the theory"
-#warning "rewriter and scope. Move this file back into util/ afterwards."
using namespace std;
@@ -121,6 +116,8 @@ ResourceManager::ResourceManager()
, d_on(false)
, d_cpuTime(false)
, d_spendResourceCalls(0)
+ , d_hardListeners()
+ , d_softListeners()
{}
@@ -150,7 +147,7 @@ void ResourceManager::setTimeLimit(uint64_t millis, bool cumulative) {
}
-uint64_t ResourceManager::getResourceUsage() const {
+const uint64_t& ResourceManager::getResourceUsage() const {
return d_cumulativeResourceUsed;
}
@@ -189,16 +186,12 @@ void ResourceManager::spendResource(unsigned ammount) throw (UnsafeInterruptExce
}
if (d_isHardLimit) {
- if (smt::smtEngineInScope()) {
- theory::Rewriter::clearCaches();
- }
+ d_hardListeners.notify();
throw UnsafeInterruptException();
+ } else {
+ d_softListeners.notify();
}
- // interrupt it next time resources are checked
- if (smt::smtEngineInScope()) {
- smt::currentSmtEngine()->interrupt();
- }
}
}
@@ -288,4 +281,12 @@ void ResourceManager::enable(bool on) {
d_on = on;
}
+ListenerCollection* ResourceManager::getHardListeners() {
+ return &d_hardListeners;
+}
+
+ListenerCollection* ResourceManager::getSoftListeners() {
+ return &d_softListeners;
+}
+
} /* namespace CVC4 */
diff --git a/src/expr/resource_manager.h b/src/util/resource_manager.h
index c4ad35564..2c54011a5 100644
--- a/src/expr/resource_manager.h
+++ b/src/util/resource_manager.h
@@ -23,6 +23,7 @@
#include <sys/time.h>
#include "base/exception.h"
+#include "base/listener.h"
#include "util/unsafe_interrupt_exception.h"
namespace CVC4 {
@@ -107,6 +108,12 @@ class CVC4_PUBLIC ResourceManager {
/** Counter indicating how often to check resource manager in loops */
static const uint64_t s_resourceCount;
+ /** Receives a notification on reaching a hard limit. */
+ ListenerCollection d_hardListeners;
+
+ /** Receives a notification on reaching a hard limit. */
+ ListenerCollection d_softListeners;
+
public:
ResourceManager();
@@ -119,7 +126,11 @@ public:
bool outOfTime() const;
bool out() const { return d_on && (outOfResources() || outOfTime()); }
- uint64_t getResourceUsage() const;
+
+ /**
+ * This returns a const uint64_t& to support being used as a ReferenceStat.
+ */
+ const uint64_t& getResourceUsage() const;
uint64_t getTimeUsage() const;
uint64_t getResourceRemaining() const;
uint64_t getTimeRemaining() const;
@@ -150,7 +161,12 @@ public:
void endCall();
static uint64_t getFrequencyCount() { return s_resourceCount; }
- friend class SmtEngine;
+
+ /** Collection of listeners that are notified on a hard resource out. */
+ ListenerCollection* getHardListeners();
+
+ /** Collection of listeners that are notified on a soft resource out. */
+ ListenerCollection* getSoftListeners();
};/* class ResourceManager */
}/* CVC4 namespace */
diff --git a/src/util/resource_manager.i b/src/util/resource_manager.i
new file mode 100644
index 000000000..0f55c2bce
--- /dev/null
+++ b/src/util/resource_manager.i
@@ -0,0 +1,5 @@
+%{
+#include "util/resource_manager.h"
+%}
+
+%include "util/resource_manager.h"
diff --git a/test/unit/Makefile.am b/test/unit/Makefile.am
index 36203725f..9d934a6e0 100644
--- a/test/unit/Makefile.am
+++ b/test/unit/Makefile.am
@@ -48,6 +48,7 @@ UNIT_TESTS += \
util/exception_black \
util/integer_black \
util/integer_white \
+ util/listener_black \
util/rational_black \
util/rational_white \
util/stats_black \
diff --git a/test/unit/theory/theory_black.h b/test/unit/theory/theory_black.h
index bafd572c3..fe8bebdbf 100644
--- a/test/unit/theory/theory_black.h
+++ b/test/unit/theory/theory_black.h
@@ -49,11 +49,14 @@ public:
void setUp() {
d_em = new ExprManager();
d_smt = new SmtEngine(d_em);
- d_nm = NodeManager::fromExprManager(d_em);
d_scope = new SmtScope(d_smt);
+
+ d_nm = NodeManager::fromExprManager(d_em);
}
void tearDown() {
+ delete d_scope;
+ delete d_smt;
delete d_em;
}
diff --git a/test/unit/util/listener_black.h b/test/unit/util/listener_black.h
new file mode 100644
index 000000000..cd3a08d4e
--- /dev/null
+++ b/test/unit/util/listener_black.h
@@ -0,0 +1,156 @@
+/********************* */
+/*! \file output_black.h
+ ** \verbatim
+ ** Original author: Morgan Deters
+ ** Major contributors: none
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2014 New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief Black box testing of CVC4 output classes.
+ **
+ ** Black box testing of CVC4 output classes.
+ **/
+
+#include <cxxtest/TestSuite.h>
+#include <sstream>
+
+#include "base/listener.h"
+
+using namespace CVC4;
+using namespace std;
+
+class ListenerBlack : public CxxTest::TestSuite {
+
+ std::multiset<std::string> d_events;
+
+ class EventListener : public Listener {
+ public:
+ EventListener(std::multiset<std::string>& events, std::string name)
+ : d_events(events), d_name(name) {}
+ ~EventListener(){}
+
+ virtual void notify() { d_events.insert(d_name); }
+
+ private:
+ std::multiset<std::string>& d_events;
+ std::string d_name;
+ };
+
+public:
+
+ static std::multiset<std::string> mkMultiset(std::string arr[], int len){
+ return std::multiset<std::string>(arr, arr + len);
+ }
+
+ void setUp() {
+ d_events.clear();
+ }
+
+ void tearDown() {
+ d_events.clear();
+ }
+
+ void testEmptyCollection() {
+ // Makes an new collection and tests that it is empty.
+ ListenerCollection* collection = new ListenerCollection;
+ TS_ASSERT(collection->empty());
+ TS_ASSERT_THROWS_NOTHING( delete collection );
+ }
+
+ void testSingletonCollection() {
+ ListenerCollection collection;
+ std::string expected[1] = {"a"};
+ {
+ RegisterListener a(&collection, new EventListener(d_events, "a"));
+ collection.notify();
+ TS_ASSERT(not collection.empty());
+ }
+ TS_ASSERT(collection.empty());
+ TS_ASSERT_EQUALS(d_events, mkMultiset(expected, 1));
+ }
+
+ void testSingleRegisterTearDown() {
+ // Tests that collection succeeds at destruction after
+ // registering a single event.
+ ListenerCollection* collection = new ListenerCollection;
+ {
+ RegisterListener a(collection, new EventListener(d_events, "a"));
+ TS_ASSERT(not collection->empty());
+ // The destructor for a now runs.
+ }
+ TS_ASSERT(collection->empty());
+ TS_ASSERT_THROWS_NOTHING( delete collection );
+ }
+
+ void testMultipleCollection() {
+ ListenerCollection* collection = new ListenerCollection;
+ {
+ RegisterListener c(collection, new EventListener(d_events, "c"));
+ collection->notify();
+ // d_events == {"c"}
+ RegisterListener b(collection, new EventListener(d_events, "b"));
+ RegisterListener a(collection, new EventListener(d_events, "a"));
+ collection->notify();
+ // d_events == {"a", "b", "c", "c"}
+ TS_ASSERT(not collection->empty());
+ }
+ TS_ASSERT(collection->empty());
+ std::string expected[4] = {"a", "b", "c", "c"};
+ TS_ASSERT_EQUALS(d_events, mkMultiset(expected, 4));
+ }
+
+ void testRegisterMiddleTearDown() {
+ // Tests that collection succeeds at destruction after
+ // registering several events.
+ ListenerCollection* collection = new ListenerCollection;
+ {
+ RegisterListener a(collection, new EventListener(d_events, "a"));
+ RegisterListener* b =
+ new RegisterListener(collection, new EventListener(d_events, "b"));
+ RegisterListener c(collection, new EventListener(d_events, "c"));
+
+ collection->notify();
+ delete b;
+ collection->notify();
+ // The destructor for a and c now run.
+ TS_ASSERT(not collection->empty());
+ }
+ TS_ASSERT(collection->empty());
+ TS_ASSERT_THROWS_NOTHING( delete collection );
+ }
+
+
+
+ void testRegisterMultiple() {
+ // This tests adds and notify multiple times.
+ ListenerCollection collection;
+
+ std::vector<RegisterListener*> listeners;
+ for(int i = 0; i < 4 ; ++i){
+ stringstream ss; ss << i;
+ Listener* listener = new EventListener(d_events, ss.str());
+ listeners.push_back(new RegisterListener(&collection, listener));
+ collection.notify();
+ }
+
+ TS_ASSERT(not collection.empty());
+ for(int i=0; i < listeners.size(); ++i){
+ RegisterListener* at_i = listeners[i];
+ delete at_i;
+ }
+ listeners.clear();
+ TS_ASSERT(collection.empty());
+
+ std::string expected[10] =
+ {"0", "0", "0", "0", "1", "1", "1", "2", "2", "3"};
+ TS_ASSERT_EQUALS(d_events, mkMultiset(expected, 10));
+
+ // No more events occur.
+ collection.notify();
+ TS_ASSERT_EQUALS(d_events, mkMultiset(expected, 10));
+ }
+
+};
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback