* add TimerStat statistic type
authorMorgan Deters <mdeters@gmail.com>
Thu, 2 Sep 2010 07:31:04 +0000 (07:31 +0000)
committerMorgan Deters <mdeters@gmail.com>
Thu, 2 Sep 2010 07:31:04 +0000 (07:31 +0000)
* add Stats black-box unit test
* new make target: "make units" now runs unit tests only
* revised make target: "make regress" now runs regressions only
* configure.ac: pull in librt for clock_gettime()

Makefile.am
Makefile.builds.in
configure.ac
src/util/stats.h
test/Makefile.am
test/regress/Makefile.am
test/system/Makefile.am
test/unit/Makefile.am
test/unit/util/stats_black.h [new file with mode: 0644]

index 35744e381994adbaf304adf876cdf92d2f509c14..aa2d5fdcf0787608e1db3cdb7321594b95349be1 100644 (file)
@@ -7,8 +7,10 @@ ACLOCAL_AMFLAGS = -I config
 
 SUBDIRS = src test contrib
 
-.PHONY: regress0 regress1 regress2 regress3
-regress0 regress1 regress2 regress3: all
+.PHONY: units regress regress0 regress1 regress2 regress3
+regress regress0 regress1 regress2 regress3: all
+       (cd test && $(MAKE) $(AM_MAKEFLAGS) $@) || exit 1
+units: all
        (cd test && $(MAKE) $(AM_MAKEFLAGS) $@) || exit 1
 
 LCOV = lcov
index 5e5beb9606494eab078aa617c98c879e2a99ce56..3f5b93b03c338eec9d275f3f20d12146feaf1a70 100644 (file)
@@ -86,7 +86,9 @@ endif
        test -e lib || ln -sfv ".$(libdir)" lib
        test -e bin || ln -sfv ".$(bindir)" bin
 
-check regress regress0 regress1 regress2 regress3: all
+check test units regress: all
+       (cd $(CURRENT_BUILD)/test && $(MAKE) $@)
+regress%: all
        (cd $(CURRENT_BUILD)/test && $(MAKE) $@)
 
 # any other target than the default doesn't do the extra stuff above
index 939ad53a23d58c34fc256d133cead37926453fdd..d369cbde540f1c0a921e5e39bb68992d9a2c3693 100644 (file)
@@ -636,6 +636,8 @@ fi
 AC_CHECK_LIB(z, gzread, , [AC_MSG_ERROR([zlib required, install your distro's zlib-dev package or see www.zlib.net])])
 AC_CHECK_HEADER(zlib.h, , [AC_MSG_ERROR([zlib required, install your distro's zlib-dev package or see www.zlib.net])])
 
+AC_CHECK_LIB(rt, clock_gettime, , [AC_MSG_ERROR([can't find clock_gettime() in librt])])
+
 # Check for antlr C++ runtime (defined in config/antlr.m4)
 AC_LIB_ANTLR
 
index f917e8b525636c1ac93cf3c93183b83060727920..74afb5792a291cee287df6841ccfde2339d4d6de 100644 (file)
 
 #include <string>
 #include <ostream>
+#include <iomanip>
 #include <set>
+#include <ctime>
+
 #include "util/Assert.h"
 
 namespace CVC4 {
 
 
 #ifdef CVC4_STATISTICS_ON
-#  define USE_STATISTICS true
+#  define __CVC4_USE_STATISTICS true
 #else
-#  define USE_STATISTICS false
+#  define __CVC4_USE_STATISTICS false
 #endif
 
 class CVC4_PUBLIC Stat;
@@ -48,8 +51,8 @@ private:
 public:
   static void flushStatistics(std::ostream& out);
 
-  static inline void registerStat(Stat* s) throw (AssertionException);
-  static inline void unregisterStat(Stat* s) throw (AssertionException);
+  static inline void registerStat(Stat* s) throw(AssertionException);
+  static inline void unregisterStat(Stat* s) throw(AssertionException);
 };/* class StatisticsRegistry */
 
 
@@ -61,9 +64,9 @@ private:
 
 public:
 
-  Stat(const std::string& s) throw (CVC4::AssertionException) : d_name(s)
+  Stat(const std::string& s) throw(CVC4::AssertionException) : d_name(s)
   {
-    if(USE_STATISTICS){
+    if(__CVC4_USE_STATISTICS) {
       AlwaysAssert(d_name.find(s_delim) == std::string::npos);
     }
   }
@@ -71,8 +74,8 @@ public:
 
   virtual void flushInformation(std::ostream& out) const = 0;
 
-  void flushStat(std::ostream& out) const{
-    if(USE_STATISTICS){
+  void flushStat(std::ostream& out) const {
+    if(__CVC4_USE_STATISTICS) {
       out << d_name << s_delim;
       flushInformation(out);
     }
@@ -81,27 +84,31 @@ public:
   const std::string& getName() const {
     return d_name;
   }
-};
+};/* class Stat */
+
 
 struct StatisticsRegistry::StatCmp {
   bool operator()(const Stat* s1, const Stat* s2) const
   {
     return (s1->getName()) < (s2->getName());
   }
-};
+};/* class StatCmp */
+
 
-inline void StatisticsRegistry::registerStat(Stat* s) throw (AssertionException){
-  if(USE_STATISTICS){
+inline void StatisticsRegistry::registerStat(Stat* s) throw(AssertionException) {
+  if(__CVC4_USE_STATISTICS) {
     AlwaysAssert(d_registeredStats.find(s) == d_registeredStats.end());
     d_registeredStats.insert(s);
   }
-}
-inline void StatisticsRegistry::unregisterStat(Stat* s) throw (AssertionException){
-  if(USE_STATISTICS){
+}/* StatisticsRegistry::registerStat */
+
+
+inline void StatisticsRegistry::unregisterStat(Stat* s) throw(AssertionException) {
+  if(__CVC4_USE_STATISTICS) {
     AlwaysAssert(d_registeredStats.find(s) != d_registeredStats.end());
     d_registeredStats.erase(s);
   }
-}
+}/* StatisticsRegistry::unregisterStat */
 
 
 
@@ -109,24 +116,25 @@ inline void StatisticsRegistry::unregisterStat(Stat* s) throw (AssertionExceptio
  * class T must have stream insertion operation defined.
  * std::ostream& operator<<(std::ostream&, const T&);
  */
-template<class T>
-class DataStat : public Stat{
+template <class T>
+class DataStat : public Stat {
 public:
   DataStat(const std::string& s) : Stat(s) {}
 
   virtual const T& getData() const = 0;
   virtual void setData(const T&) = 0;
 
-  void flushInformation(std::ostream& out) const{
-    if(USE_STATISTICS){
+  void flushInformation(std::ostream& out) const {
+    if(__CVC4_USE_STATISTICS) {
       out << getData();
     }
   }
-};
+};/* class DataStat */
+
 
 /** T must have an assignment operator=(). */
 template <class T>
-class ReferenceStat: public DataStat<T>{
+class ReferenceStat : public DataStat<T> {
 private:
   const T* d_data;
 
@@ -136,28 +144,29 @@ public:
   {}
 
   ReferenceStat(const std::string& s, const T& data):
-    DataStat<T>(s),d_data(NULL)
+    DataStat<T>(s), d_data(NULL)
   {
     setData(data);
   }
 
-  void setData(const T& t){
-    if(USE_STATISTICS){
+  void setData(const T& t) {
+    if(__CVC4_USE_STATISTICS) {
       d_data = &t;
     }
   }
-  const T& getData() const{
-    if(USE_STATISTICS){
+  const T& getData() const {
+    if(__CVC4_USE_STATISTICS) {
       return *d_data;
-    }else{
+    } else {
       Unreachable();
     }
   }
-};
+};/* class ReferenceStat */
+
 
 /** T must have an operator=() and a copy constructor. */
 template <class T>
-class BackedStat: public DataStat<T>{
+class BackedStat : public DataStat<T> {
 protected:
   T d_data;
 
@@ -167,65 +176,171 @@ public:
   {}
 
   void setData(const T& t) {
-    if(USE_STATISTICS){
+    if(__CVC4_USE_STATISTICS) {
       d_data = t;
     }
   }
 
-  BackedStat<T>& operator=(const T& t){
-    if(USE_STATISTICS){
+  BackedStat<T>& operator=(const T& t) {
+    if(__CVC4_USE_STATISTICS) {
       d_data = t;
     }
     return *this;
   }
 
-  const T& getData() const{
-    if(USE_STATISTICS){
+  const T& getData() const {
+    if(__CVC4_USE_STATISTICS) {
       return d_data;
-    }else{
+    } else {
       Unreachable();
     }
   }
-};
+};/* class BackedStat */
+
 
-class IntStat : public BackedStat<int64_t>{
+class IntStat : public BackedStat<int64_t> {
 public:
 
   IntStat(const std::string& s, int64_t init): BackedStat<int64_t>(s, init)
   {}
 
-  IntStat& operator++(){
-    if(USE_STATISTICS){
+  IntStat& operator++() {
+    if(__CVC4_USE_STATISTICS) {
       ++d_data;
     }
     return *this;
   }
 
-  IntStat& operator+=(int64_t val){
-    if(USE_STATISTICS){
+  IntStat& operator+=(int64_t val) {
+    if(__CVC4_USE_STATISTICS) {
       d_data+= val;
     }
     return *this;
   }
 
-  void maxAssign(int64_t val){
-    if(USE_STATISTICS){
-      if(d_data < val){
+  void maxAssign(int64_t val) {
+    if(__CVC4_USE_STATISTICS) {
+      if(d_data < val) {
         d_data = val;
       }
     }
   }
 
-  void minAssign(int64_t val){
-    if(USE_STATISTICS){
-      if(d_data > val){
+  void minAssign(int64_t val) {
+    if(__CVC4_USE_STATISTICS) {
+      if(d_data > val) {
         d_data = val;
       }
     }
   }
-};
+};/* class IntStat */
+
+
+// some utility functions for ::timespec
+inline ::timespec& operator+=(::timespec& a, const ::timespec& b) {
+  // assumes a.tv_nsec and b.tv_nsec are in range
+  const long nsec_per_sec = 1000000000L; // one thousand million
+  a.tv_sec += b.tv_sec;
+  long nsec = a.tv_nsec + b.tv_nsec;
+  while(nsec < 0) {
+    nsec += nsec_per_sec;
+    ++a.tv_sec;
+  }
+  while(nsec >= nsec_per_sec) {
+    nsec -= nsec_per_sec;
+    --a.tv_sec;
+  }
+  a.tv_nsec = nsec;
+  return a;
+}
+inline ::timespec& operator-=(::timespec& a, const ::timespec& b) {
+  // assumes a.tv_nsec and b.tv_nsec are in range
+  const long nsec_per_sec = 1000000000L; // one thousand million
+  a.tv_sec -= b.tv_sec;
+  long nsec = a.tv_nsec - b.tv_nsec;
+  while(nsec < 0) {
+    nsec += nsec_per_sec;
+    ++a.tv_sec;
+  }
+  while(nsec >= nsec_per_sec) {
+    nsec -= nsec_per_sec;
+    --a.tv_sec;
+  }
+  a.tv_nsec = nsec;
+  return a;
+}
+inline ::timespec operator+(const ::timespec& a, const ::timespec& b) {
+  ::timespec result = a;
+  return result += b;
+}
+inline ::timespec operator-(const ::timespec& a, const ::timespec& b) {
+  ::timespec result = a;
+  return result -= b;
+}
+inline bool operator==(const ::timespec& a, const ::timespec& b) {
+  // assumes a.tv_nsec and b.tv_nsec are in range
+  return a.tv_sec == b.tv_sec && a.tv_nsec == b.tv_nsec;
+}
+inline bool operator!=(const ::timespec& a, const ::timespec& b) {
+  // assumes a.tv_nsec and b.tv_nsec are in range
+  return !(a == b);
+}
+inline bool operator<(const ::timespec& a, const ::timespec& b) {
+  // assumes a.tv_nsec and b.tv_nsec are in range
+  return a.tv_sec < b.tv_sec ||
+    (a.tv_sec == b.tv_sec && a.tv_nsec < b.tv_nsec);
+}
+inline bool operator>(const ::timespec& a, const ::timespec& b) {
+  // assumes a.tv_nsec and b.tv_nsec are in range
+  return a.tv_sec > b.tv_sec ||
+    (a.tv_sec == b.tv_sec && a.tv_nsec > b.tv_nsec);
+}
+inline bool operator<=(const ::timespec& a, const ::timespec& b) {
+  // assumes a.tv_nsec and b.tv_nsec are in range
+  return !(a > b);
+}
+inline bool operator>=(const ::timespec& a, const ::timespec& b) {
+  // assumes a.tv_nsec and b.tv_nsec are in range
+  return !(a < b);
+}
+inline std::ostream& operator<<(std::ostream& os, const ::timespec& t) {
+  // assumes t.tv_nsec is in range
+  return os << t.tv_sec << "."
+            << std::setfill('0') << std::setw(8) << std::right << t.tv_nsec;
+}
+
+
+class TimerStat : public BackedStat< ::timespec > {
+  // strange: timespec isn't placed in 'std' namespace ?!
+  ::timespec d_start;
+  bool d_running;
+
+public:
+
+  TimerStat(const std::string& s) :
+    BackedStat< ::timespec >(s, ::timespec()),
+    d_running(false) {
+  }
+
+  void start() {
+    if(__CVC4_USE_STATISTICS) {
+      AlwaysAssert(!d_running);
+      clock_gettime(CLOCK_REALTIME, &d_start);
+    }
+  }
+
+  void stop() {
+    if(__CVC4_USE_STATISTICS) {
+      AlwaysAssert(d_running);
+      ::timespec end;
+      clock_gettime(CLOCK_REALTIME, &end);
+      d_data += end - d_start;
+    }
+  }
+};/* class TimerStat */
+
 
-#undef USE_STATISTICS
+#undef __CVC4_USE_STATISTICS
 
 }/* CVC4 namespace */
 
index 501f85090bc4949ea3c0e6ee1ec326bba238748c..045599bc11c5b2c9cb5211762f7b092f19df8ef8 100644 (file)
@@ -2,8 +2,8 @@ SUBDIRS = unit system regress .
 
 MAKEFLAGS = -k
 
-.PHONY: regress0 regress1 regress2 regress3
-regress0 regress1 regress2 regress3:
+.PHONY: units regress regress0 regress1 regress2 regress3
+units regress regress0 regress1 regress2 regress3:
        @$(MAKE) check-pre; \
        for dir in $(SUBDIRS); do \
                test $$dir = . || (cd $$dir && $(MAKE) $(AM_MAKEFLAGS) $@); \
@@ -11,8 +11,8 @@ regress0 regress1 regress2 regress3:
        $(MAKE) check-local
 
 # synonyms for "check"
-.PHONY: regress test
-regress test: check
+.PHONY: test
+test: check
 
 am__tty_colors = \
 red=; grn=; lgn=; blu=; std=; \
index 80e8da387c7f4327d29f4ff98bc1e814520a21f4..3867ee860829c32eb982f987713dd461d83dc45f 100644 (file)
@@ -16,6 +16,10 @@ regress0 regress1 regress2 regress3:
 .PHONY: regress test
 regress test: check
 
+# no-ops here
+.PHONY: units
+units:
+
 EXTRA_DIST = \
        run_regression \
        README
index 219a263553d8fe4ecf1c935ea66cfa7c9daaea8b..954798e6c8d404ad16d8d7da15d1cae1ccf6ccbb 100644 (file)
@@ -39,9 +39,9 @@ $(TESTS):: $(TEST_DEPS)
 export VERBOSE = 1
 
 # synonyms for "check"
-.PHONY: regress test
-regress test: check
+.PHONY: test
+test: check
 
-# in system test dir, regressN are also synonyms for check
-.PHONY: regress0 regress1 regress2 regress3
-regress0 regress1 regress2 regress3: check
+# no-ops here
+.PHONY: units regress regress0 regress1 regress2 regress3s
+units regress regress0 regress1 regress2 regress3:
index eb920e6c5a05b29153414d323930289b7c3197d4..1272be069fee8868523be6ae6c9b2f03c9b96351 100644 (file)
@@ -35,7 +35,8 @@ UNIT_TESTS = \
        util/integer_black \
        util/integer_white \
        util/rational_black \
-       util/rational_white
+       util/rational_white \
+       util/stats_black
 
 export VERBOSE = 1
 
@@ -52,7 +53,7 @@ AM_CPPFLAGS = \
        "-I@top_srcdir@/src" "-I@top_builddir@/src" \
        "-I@top_srcdir@/src/prop/minisat" \
        -D __STDC_LIMIT_MACROS \
-       -D __STDC_FORMAT_MACROS \               
+       -D __STDC_FORMAT_MACROS \
        $(ANTLR_INCLUDES) $(TEST_CPPFLAGS)
 AM_CXXFLAGS = -Wall -Wno-unknown-pragmas -Wno-parentheses $(TEST_CXXFLAGS)
 AM_LDFLAGS = $(TEST_LDFLAGS)
@@ -158,12 +159,12 @@ libdummy_la_LIBADD = @abs_top_builddir@/src/libcvc4.la
 endif
 
 # synonyms for "check"
-.PHONY: regress test
-regress test: check
+.PHONY: units test
+units test: check
 
-# in unit test dir, regressN are also synonyms for check
-.PHONY: regress0 regress1 regress2 regress3
-regress0 regress1 regress2 regress3: check
+# no-ops here
+.PHONY: regress regress0 regress1 regress2 regress3
+regress regress0 regress1 regress2 regress3:
 
 if HAVE_CXXTESTGEN
 # all is fine with the world
diff --git a/test/unit/util/stats_black.h b/test/unit/util/stats_black.h
new file mode 100644 (file)
index 0000000..032efc3
--- /dev/null
@@ -0,0 +1,103 @@
+/*********************                                                        */
+/*! \file stats_black.h
+ ** \verbatim
+ ** Original author: mdeters
+ ** Major contributors: none
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 prototype.
+ ** Copyright (c) 2009, 2010  The Analysis of Computer Systems Group (ACSys)
+ ** Courant Institute of Mathematical Sciences
+ ** New York University
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief Black box testing of CVC4::Stat and associated classes
+ **
+ ** Black box testing of CVC4::Stat and associated classes.
+ **/
+
+#include <cxxtest/TestSuite.h>
+#include <sstream>
+#include <string>
+#include <ctime>
+
+#include "util/stats.h"
+
+using namespace CVC4;
+using namespace std;
+
+class StatsBlack : public CxxTest::TestSuite {
+public:
+
+  void testStats() {
+
+    // StatisticsRegistry
+    //static void flushStatistics(std::ostream& out);
+
+    //static inline void registerStat(Stat* s) throw (AssertionException);
+    //static inline void unregisterStat(Stat* s) throw (AssertionException);
+
+    string empty, bar = "bar", baz = "baz";
+    ReferenceStat<string> refStr("stat #1", empty);
+    ReferenceStat<string> refStr2("refStr2", bar);
+    // setData
+    // getData
+
+    // flushInformation
+    // flushStat
+
+    BackedStat<string> backedStr("backed", baz);
+    // setData
+    // getData
+    // operator=
+
+    IntStat sInt("my int", 10);
+    TimerStat sTimer("a timer ! for measuring time");
+
+    TS_ASSERT_EQUALS(refStr.getName(), "stat #1");
+    TS_ASSERT_EQUALS(refStr2.getName(), "refStr2");
+    TS_ASSERT_EQUALS(backedStr.getName(), "backed");
+    TS_ASSERT_EQUALS(sInt.getName(), "my int");
+    TS_ASSERT_EQUALS(sTimer.getName(), "a timer ! for measuring time");
+
+    TS_ASSERT_EQUALS(refStr.getData(), empty);
+    TS_ASSERT_EQUALS(refStr2.getData(), bar);
+    empty = "a different string";
+    bar += " and with an addition";
+    TS_ASSERT_EQUALS(refStr.getData(), empty);
+    TS_ASSERT_EQUALS(refStr2.getData(), bar);
+
+    TS_ASSERT_EQUALS(backedStr.getData(), "baz");
+    baz = "something else";
+    TS_ASSERT_EQUALS(backedStr.getData(), "baz");
+
+    TS_ASSERT_EQUALS(sInt.getData(), 10);
+    sInt.setData(100);
+    TS_ASSERT_EQUALS(sInt.getData(), 100);
+
+    TS_ASSERT_EQUALS(sTimer.getData(), timespec());
+
+    stringstream sstr;
+
+    refStr.flushInformation(sstr);
+    TS_ASSERT_EQUALS(sstr.str(), empty);
+    sstr.str("");
+    refStr2.flushInformation(sstr);
+    TS_ASSERT_EQUALS(sstr.str(), bar);
+    sstr.str("");
+    backedStr.flushInformation(sstr);
+    TS_ASSERT_EQUALS(sstr.str(), "baz");
+    sstr.str("");
+    sInt.flushInformation(sstr);
+    TS_ASSERT_EQUALS(sstr.str(), "100");
+    sstr.str("");
+    sTimer.flushInformation(sstr);
+    TS_ASSERT_EQUALS(sstr.str(), "0.00000000");
+
+    sTimer.start();
+    TS_ASSERT_EQUALS(timespec(), sTimer.getData());
+    sTimer.stop();
+    TS_ASSERT_LESS_THAN(timespec(), sTimer.getData());
+  }
+
+};