activemq-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From tab...@apache.org
Subject svn commit: r796317 [3/3] - in /activemq/activemq-cpp/trunk/activemq-cpp/src: main/ main/activemq/core/ main/decaf/internal/io/ main/decaf/internal/util/ main/decaf/internal/util/concurrent/ main/decaf/io/ main/decaf/net/ main/decaf/util/ main/decaf/ut...
Date Tue, 21 Jul 2009 14:28:12 GMT
Added: activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/TimerTest.cpp
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/TimerTest.cpp?rev=796317&view=auto
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/TimerTest.cpp (added)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/TimerTest.cpp Tue Jul 21 14:28:11 2009
@@ -0,0 +1,1701 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "TimerTest.h"
+
+#include <string>
+
+#include <decaf/lang/Integer.h>
+#include <decaf/lang/System.h>
+#include <decaf/lang/Thread.h>
+#include <decaf/lang/exceptions/InterruptedException.h>
+#include <decaf/util/Timer.h>
+#include <decaf/util/TimerTask.h>
+#include <decaf/util/concurrent/Mutex.h>
+#include <decaf/util/concurrent/atomic/AtomicInteger.h>
+
+using namespace decaf;
+using namespace decaf::lang;
+using namespace decaf::lang::exceptions;
+using namespace decaf::util;
+using namespace decaf::util::concurrent;
+
+////////////////////////////////////////////////////////////////////////////////
+namespace {
+    decaf::util::concurrent::Mutex gsync;
+    decaf::util::concurrent::atomic::AtomicInteger timerCounter;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+namespace decaf{
+namespace util{
+
+    class TimerTaskReport{
+    public:
+
+        decaf::util::concurrent::atomic::AtomicInteger wasRun;
+        long long startedAt;
+        long long lastDelta;
+
+        TimerTaskReport() : startedAt( 0 ), lastDelta( 0 ) {}
+
+        void reset() {
+            this->wasRun.set( 0 );
+            this->startedAt = 0;
+            this->lastDelta = 0;
+        }
+    };
+
+    class TimerTestTask : public TimerTask {
+    private:
+
+        // Pointer to a Report object to log run data
+        TimerTaskReport* report;
+
+        // Should we sleep for 200 ms each run()?
+        bool sleepInRun;
+
+        // Should we increment the timerCounter?
+        bool incrementCount;
+
+        // Should we terminate the timer at a specific timerCounter?
+        int terminateCount;
+
+        // The timer we belong to
+        Timer* timer;
+
+    public:
+
+        TimerTestTask() {
+            this->report = NULL;
+            this->sleepInRun = false;
+            this->incrementCount = false;
+            this->terminateCount = -1;
+            this->timer = NULL;
+        }
+
+        TimerTestTask( TimerTaskReport* report ) {
+            this->report = report;
+            this->sleepInRun = false;
+            this->incrementCount = false;
+            this->terminateCount = -1;
+            this->timer = NULL;
+        }
+
+        TimerTestTask( Timer* t, TimerTaskReport* report ) {
+            this->report = report;
+            this->sleepInRun = false;
+            this->incrementCount = false;
+            this->terminateCount = -1;
+            this->timer = t;
+        }
+
+        virtual ~TimerTestTask() {}
+
+        void run() {
+
+            if( report != NULL ) {
+                this->report->wasRun.incrementAndGet();
+            }
+
+            if( incrementCount ) {
+                timerCounter.incrementAndGet();
+            }
+
+            if( terminateCount == timerCounter.get() && timer != NULL ) {
+                timer->cancel();
+            }
+
+            if( sleepInRun ) {
+                try {
+                    Thread::sleep( 200 );
+                } catch( InterruptedException& e ) {}
+            }
+
+            synchronized( &gsync ) {
+                gsync.notify();
+            }
+        }
+
+        void setSleepInRun( bool sleepInRun ) {
+            this->sleepInRun = sleepInRun;
+        }
+
+        void setIncrementCount( bool incrementCount ) {
+            this->incrementCount = incrementCount;
+        }
+
+        void setTerminateCount( int terminateCount ) {
+            this->terminateCount = terminateCount;
+        }
+    };
+
+    class SlowThenFastTask : public TimerTask {
+    private:
+
+        TimerTaskReport* report;
+
+    public:
+
+        SlowThenFastTask( TimerTaskReport* report ) {
+            this->report = report;
+        }
+
+        virtual ~SlowThenFastTask() {}
+
+        void run() {
+
+            if( report->wasRun.get() == 0 ) {
+                report->startedAt = System::currentTimeMillis();
+            }
+
+            report->lastDelta = System::currentTimeMillis() -
+                                ( report->startedAt + ( 100 * report->wasRun.get() ) );
+
+            if( report->wasRun.incrementAndGet() == 2 ) {
+                try {
+                    Thread::sleep( 200 );
+                } catch( InterruptedException& e ) {
+                }
+            }
+        }
+
+    };
+
+}}
+
+////////////////////////////////////////////////////////////////////////////////
+void TimerTest::setUp() {
+    timerCounter.set( 0 );
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void TimerTest::testConstructor() {
+
+    std::auto_ptr<Timer> t;
+    TimerTaskReport report;
+
+    // Ensure a task is run
+    t.reset( new Timer() );
+
+    TimerTestTask* testTask = new TimerTestTask( &report );
+    t->schedule( testTask, 200 );
+
+    synchronized( &gsync ) {
+        try {
+            gsync.wait( 2000000 );
+        } catch( InterruptedException& e ) {}
+    }
+
+    CPPUNIT_ASSERT_MESSAGE( "TimerTask.run() method not called after 200ms",
+                            1 == report.wasRun.get() );
+
+    t->cancel();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void TimerTest::testCancel() {
+
+    std::auto_ptr<Timer> t;
+    TimerTaskReport report;
+
+    // Ensure a task throws an IllegalStateException after cancelled
+    t.reset( new Timer() );
+
+    TimerTestTask* testTask = new TimerTestTask( &report );
+    t->cancel();
+
+    CPPUNIT_ASSERT_THROW_MESSAGE(
+        "Scheduling a task after Timer.cancel() should throw IllegalStateException",
+        t->schedule( testTask, 100, 200 ),
+        IllegalStateException );
+
+    // unscheduled tasks must be deleted
+    delete testTask;
+
+    // Ensure a task is run but not after cancel
+    t.reset( new Timer() );
+    testTask = new TimerTestTask( &report );
+    t->schedule( testTask, 100, 500 );
+    synchronized( &gsync ) {
+        try {
+            gsync.wait( 1000 );
+        } catch( InterruptedException& e ) {}
+    }
+
+    CPPUNIT_ASSERT_MESSAGE( "TimerTask.run() method not called after 200ms",
+                            1 == report.wasRun.get() );
+
+    t->cancel();
+    synchronized( &gsync ) {
+        try {
+            gsync.wait( 500 );
+        } catch( InterruptedException& e ) {}
+    }
+
+    CPPUNIT_ASSERT_MESSAGE( "TimerTask.run() method should not have been run more than once",
+                            1 == report.wasRun.get() );
+
+    // Ensure you can call cancel more than once
+    report.wasRun.set( 0 );
+    t.reset( new Timer() );
+    testTask = new TimerTestTask( &report );
+    t->schedule( testTask, 100, 500 );
+    synchronized( &gsync ) {
+        try {
+            gsync.wait( 500 );
+        } catch( InterruptedException& e ) {}
+    }
+
+    CPPUNIT_ASSERT_MESSAGE( "TimerTask.run() method not called after 200ms",
+                            1 == report.wasRun.get() );
+
+    t->cancel();
+    t->cancel();
+    t->cancel();
+
+    synchronized( &gsync ) {
+        try {
+            gsync.wait( 500 );
+        } catch( InterruptedException& e ) {}
+    }
+
+    CPPUNIT_ASSERT_MESSAGE( "TimerTask.run() method should not have been called after cancel",
+                            1 == report.wasRun.get() );
+
+    // Ensure that a call to cancel from within a timer ensures no more
+    // run
+    report.wasRun.set( 0 );
+    t.reset( new Timer() );
+    testTask = new TimerTestTask( t.get(), &report );
+    testTask->setIncrementCount( true );
+    testTask->setTerminateCount( 5 ); // Terminate after 5 runs
+    t->schedule( testTask, 100, 100 );
+    synchronized( &gsync ) {
+        try {
+            gsync.wait( 200 );
+            gsync.wait( 200 );
+            gsync.wait( 200 );
+            gsync.wait( 200 );
+            gsync.wait( 200 );
+            gsync.wait( 200 );
+        } catch( InterruptedException& e ) {}
+    }
+
+    CPPUNIT_ASSERT_MESSAGE( std::string( "TimerTask.run() method should be called 5 times not " ) +
+                            Integer::toString( report.wasRun.get() ),
+                            5 == report.wasRun.get() );
+
+    t->cancel();
+    try {
+        Thread::sleep( 200 );
+    } catch( InterruptedException& e ) {}
+
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void TimerTest::testPurge() {
+
+    std::auto_ptr<Timer> t;
+
+    t.reset( new Timer() );
+    CPPUNIT_ASSERT( 0 == t->purge() );
+
+    std::vector< TimerTestTask* > tasks;
+    tasks.resize( 100 );
+    int delayTime[] = { 50, 80, 20, 70, 40, 10, 90, 30, 60 };
+
+    int j = 0;
+    for( int i = 0; i < 100; i++ ) {
+        tasks[i] = new TimerTestTask();
+        t->schedule( tasks[i], delayTime[j++], 200 );
+        if( j == 9 ) {
+            j = 0;
+        }
+    }
+
+    for( int i = 0; i < 50; i++ ) {
+        tasks[i]->cancel();
+    }
+
+    CPPUNIT_ASSERT( t->purge() <= 50 );
+    CPPUNIT_ASSERT( 0 == t->purge() );
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void TimerTest::testSchedule_TimerTask_Date() {
+
+    std::auto_ptr<Timer> t;
+    TimerTaskReport report;
+
+    // Ensure a Timer throws an IllegalStateException after cancelled
+    t.reset( new Timer() );
+    TimerTestTask* testTask = new TimerTestTask();
+    Date d( System::currentTimeMillis() + 100 );
+    t->cancel();
+    bool exception = false;
+
+    try {
+        t->schedule( testTask, d );
+    } catch( IllegalStateException& e ) {
+        exception = true;
+        // unscheduled tasks must be deleted
+        delete testTask;
+    }
+
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a task after Timer.cancel() should throw exception",
+                            exception == true );
+
+    // Ensure a Timer throws an IllegalStateException if task already cancelled
+    t.reset( new Timer() );
+    testTask = new TimerTestTask();
+    d.setTime( System::currentTimeMillis() + 100 );
+    testTask->cancel();
+    exception = false;
+    try {
+        t->schedule( testTask, d );
+    } catch( IllegalStateException& e ) {
+        exception = true;
+        // unscheduled tasks must be deleted
+        delete testTask;
+    }
+
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a task after cancelling it should throw exception",
+                            exception == true );
+    t->cancel();
+
+    // Ensure a Timer throws an IllegalArgumentException if delay is negative
+    t.reset( new Timer() );
+    testTask = new TimerTestTask();
+    d.setTime( -100 );
+    exception = false;
+    try {
+        t->schedule( testTask, d );
+    } catch( IllegalArgumentException& e ) {
+        exception = true;
+        // unscheduled tasks must be deleted
+        delete testTask;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a task with negative date should throw IllegalArgumentException",
+                            exception == true );
+    t->cancel();
+
+    // Ensure a Timer throws a NullPointerException if the task is null
+    t.reset( new Timer() );
+    exception = false;
+    d.setTime( System::currentTimeMillis() + 100 );
+    try {
+        t->schedule( NULL, d );
+    } catch( NullPointerException& e ) {
+        exception = true;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a null task should throw NullPointerException",
+                            exception == true );
+    t->cancel();
+
+    // Ensure proper sequence of exceptions
+    t.reset( new Timer() );
+    d.setTime( -100 );
+    exception = false;
+    try {
+        t->schedule( NULL, d );
+    } catch( NullPointerException& e ) {
+    } catch( IllegalArgumentException& e ) {
+        exception = true;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a null task with negative date should throw IllegalArgumentException first",
+                            exception == true );
+    t->cancel();
+
+    // Ensure a task is run
+    t.reset( new Timer() );
+    testTask = new TimerTestTask( &report );
+    d.setTime( System::currentTimeMillis() + 200 );
+    t->schedule( testTask, d );
+    try {
+        Thread::sleep( 400 );
+    } catch( InterruptedException& e ) {}
+
+    CPPUNIT_ASSERT_MESSAGE( "TimerTask.run() method not called after 200ms",
+                            1 == report.wasRun.get() );
+    t->cancel();
+
+    // Ensure multiple tasks are run
+    t.reset( new Timer() );
+    testTask = new TimerTestTask();
+    testTask->setIncrementCount( true );
+    d.setTime( System::currentTimeMillis() + 100 );
+    t->schedule( testTask, d );
+    testTask = new TimerTestTask();
+    testTask->setIncrementCount( true );
+    d.setTime( System::currentTimeMillis() + 150 );
+    t->schedule( testTask, d );
+    testTask = new TimerTestTask();
+    testTask->setIncrementCount( true );
+    d.setTime( System::currentTimeMillis() + 70 );
+    t->schedule( testTask, d );
+    testTask = new TimerTestTask();
+    testTask->setIncrementCount( true );
+    d.setTime( System::currentTimeMillis() + 10 );
+    t->schedule( testTask, d );
+    try {
+        Thread::sleep( 400 );
+    } catch( InterruptedException& e ) {}
+
+    CPPUNIT_ASSERT_MESSAGE( std::string( "Multiple tasks should have incremented counter 4 times not " ) +
+                            Integer::toString( timerCounter.get() ), timerCounter.get() == 4 );
+    t->cancel();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void TimerTest::testSchedule_TimerTask_Date2() {
+
+    std::auto_ptr<Timer> t;
+    TimerTaskReport report;
+
+    // Ensure a Timer throws an IllegalStateException after cancelled
+    t.reset( new Timer() );
+    Pointer<TimerTestTask> testTask( new TimerTestTask() );
+    Date d( System::currentTimeMillis() + 100 );
+    t->cancel();
+    bool exception = false;
+
+    try {
+        t->schedule( testTask, d );
+    } catch( IllegalStateException& e ) {
+        exception = true;
+    }
+
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a task after Timer.cancel() should throw exception",
+                            exception == true );
+
+    // Ensure a Timer throws an IllegalStateException if task already cancelled
+    t.reset( new Timer() );
+    testTask.reset( new TimerTestTask() );
+    d.setTime( System::currentTimeMillis() + 100 );
+    testTask->cancel();
+    exception = false;
+    try {
+        t->schedule( testTask, d );
+    } catch( IllegalStateException& e ) {
+        exception = true;
+    }
+
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a task after cancelling it should throw exception",
+                            exception == true );
+    t->cancel();
+
+    // Ensure a Timer throws an IllegalArgumentException if delay is negative
+    t.reset( new Timer() );
+    testTask.reset( new TimerTestTask() );
+    d.setTime( -100 );
+    exception = false;
+    try {
+        t->schedule( testTask, d );
+    } catch( IllegalArgumentException& e ) {
+        exception = true;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a task with negative date should throw IllegalArgumentException",
+                            exception == true );
+    t->cancel();
+
+    // Ensure a Timer throws a NullPointerException if the task is null
+    t.reset( new Timer() );
+    exception = false;
+    d.setTime( System::currentTimeMillis() + 100 );
+    try {
+        t->schedule( NULL, d );
+    } catch( NullPointerException& e ) {
+        exception = true;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a null task should throw NullPointerException",
+                            exception == true );
+    t->cancel();
+
+    // Ensure proper sequence of exceptions
+    t.reset( new Timer() );
+    d.setTime( -100 );
+    exception = false;
+    try {
+        t->schedule( NULL, d );
+    } catch( NullPointerException& e ) {
+    } catch( IllegalArgumentException& e ) {
+        exception = true;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a null task with negative date should throw IllegalArgumentException first",
+                            exception == true );
+    t->cancel();
+
+    // Ensure a task is run
+    t.reset( new Timer() );
+    testTask.reset( new TimerTestTask( &report ) );
+    d.setTime( System::currentTimeMillis() + 200 );
+    t->schedule( testTask, d );
+    try {
+        Thread::sleep( 500 );
+    } catch( InterruptedException& e ) {}
+
+    CPPUNIT_ASSERT_MESSAGE( "TimerTask.run() method not called after 200ms",
+                            1 == report.wasRun.get() );
+    t->cancel();
+
+    // Ensure multiple tasks are run
+    t.reset( new Timer() );
+    testTask.reset( new TimerTestTask() );
+    testTask->setIncrementCount( true );
+    d.setTime( System::currentTimeMillis() + 100 );
+    t->schedule( testTask, d );
+    testTask.reset( new TimerTestTask() );
+    testTask->setIncrementCount( true );
+    d.setTime( System::currentTimeMillis() + 150 );
+    t->schedule( testTask, d );
+    testTask.reset( new TimerTestTask() );
+    testTask->setIncrementCount( true );
+    d.setTime( System::currentTimeMillis() + 70 );
+    t->schedule( testTask, d );
+    testTask.reset( new TimerTestTask() );
+    testTask->setIncrementCount( true );
+    d.setTime( System::currentTimeMillis() + 10 );
+    t->schedule( testTask, d );
+    try {
+        Thread::sleep( 400 );
+    } catch( InterruptedException& e ) {}
+
+    CPPUNIT_ASSERT_MESSAGE( std::string( "Multiple tasks should have incremented counter 4 times not " ) +
+                            Integer::toString( timerCounter.get() ), timerCounter.get() == 4 );
+    t->cancel();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void TimerTest::testSchedule_TimerTask_Long() {
+
+    std::auto_ptr<Timer> t;
+    TimerTaskReport report;
+
+    // Ensure a Timer throws an IllegalStateException after cancelled
+    t.reset( new Timer() );
+    TimerTestTask* testTask = new TimerTestTask();
+    t->cancel();
+    bool exception = false;
+    try {
+        t->schedule( testTask, 100 );
+    } catch( IllegalStateException& e ) {
+        exception = true;
+        // unscheduled tasks must be deleted
+        delete testTask;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a task after Timer.cancel() should throw exception",
+                            exception == true );
+
+    // Ensure a Timer throws an IllegalStateException if task already cancelled
+    t.reset( new Timer() );
+    testTask = new TimerTestTask();
+    testTask->cancel();
+    exception = false;
+    try {
+        t->schedule( testTask, 100 );
+    } catch( IllegalStateException& e ) {
+        exception = true;
+        // unscheduled tasks must be deleted
+        delete testTask;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a task after cancelling it should throw exception",
+                            exception == true );
+    t->cancel();
+
+    // Ensure a Timer throws an IllegalArgumentException if delay is negative
+    t.reset( new Timer() );
+    testTask = new TimerTestTask();
+    exception = false;
+    try {
+        t->schedule( testTask, -100 );
+    } catch( IllegalArgumentException e ) {
+        exception = true;
+        // unscheduled tasks must be deleted
+        delete testTask;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a task with negative delay should throw IllegalArgumentException",
+                            exception == true );
+    t->cancel();
+
+    // Ensure a Timer throws a NullPointerException if the task is null
+    t.reset( new Timer() );
+    exception = false;
+    try {
+        t->schedule( NULL, 10 );
+    } catch( NullPointerException e ) {
+        exception = true;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a null task should throw NullPointerException",
+                            exception == true );
+    t->cancel();
+
+    // Ensure proper sequence of exceptions
+    t.reset( new Timer() );
+    exception = false;
+    try {
+        t->schedule( NULL, -10 );
+    } catch( NullPointerException& e ) {
+    } catch( IllegalArgumentException& e ) {
+        exception = true;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a null task with negative delays should throw IllegalArgumentException first",
+                            exception == true );
+    t->cancel();
+
+    // Ensure a task is run
+    t.reset( new Timer() );
+    testTask = new TimerTestTask( &report );
+    t->schedule( testTask, 200 );
+    try {
+        Thread::sleep( 400 );
+    } catch( InterruptedException& e ) {
+    }
+    CPPUNIT_ASSERT_MESSAGE( "TimerTask.run() method not called after 200ms",
+                            1 == report.wasRun.get() );
+    t->cancel();
+
+    // Ensure multiple tasks are run
+    t.reset( new Timer() );
+    testTask = new TimerTestTask();
+    testTask->setIncrementCount( true );
+    t->schedule( testTask, 100 );
+    testTask = new TimerTestTask();
+    testTask->setIncrementCount( true );
+    t->schedule( testTask, 150 );
+    testTask = new TimerTestTask();
+    testTask->setIncrementCount( true );
+    t->schedule( testTask, 70 );
+    testTask = new TimerTestTask();
+    testTask->setIncrementCount( true );
+    t->schedule( testTask, 10 );
+    try {
+        Thread::sleep( 400 );
+    } catch( InterruptedException& e ) {
+    }
+
+    CPPUNIT_ASSERT_MESSAGE( std::string( "Multiple tasks should have incremented counter 4 times not " ) +
+                            Integer::toString( timerCounter.get() ), timerCounter.get() == 4 );
+    t->cancel();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void TimerTest::testSchedule_TimerTask_Long2() {
+
+    std::auto_ptr<Timer> t;
+    TimerTaskReport report;
+
+    // Ensure a Timer throws an IllegalStateException after cancelled
+    t.reset( new Timer() );
+    Pointer<TimerTestTask> testTask( new TimerTestTask() );
+    t->cancel();
+    bool exception = false;
+    try {
+        t->schedule( testTask, 100 );
+    } catch( IllegalStateException& e ) {
+        exception = true;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a task after Timer.cancel() should throw exception",
+                            exception == true );
+
+    // Ensure a Timer throws an IllegalStateException if task already cancelled
+    t.reset( new Timer() );
+    testTask.reset( new TimerTestTask() );
+    testTask->cancel();
+    exception = false;
+    try {
+        t->schedule( testTask, 100 );
+    } catch( IllegalStateException& e ) {
+        exception = true;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a task after cancelling it should throw exception",
+                            exception == true );
+    t->cancel();
+
+    // Ensure a Timer throws an IllegalArgumentException if delay is negative
+    t.reset( new Timer() );
+    testTask.reset( new TimerTestTask() );
+    exception = false;
+    try {
+        t->schedule( testTask, -100 );
+    } catch( IllegalArgumentException e ) {
+        exception = true;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a task with negative delay should throw IllegalArgumentException",
+                            exception == true );
+    t->cancel();
+
+    // Ensure a Timer throws a NullPointerException if the task is null
+    t.reset( new Timer() );
+    exception = false;
+    try {
+        t->schedule( NULL, 10 );
+    } catch( NullPointerException e ) {
+        exception = true;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a null task should throw NullPointerException",
+                            exception == true );
+    t->cancel();
+
+    // Ensure proper sequence of exceptions
+    t.reset( new Timer() );
+    exception = false;
+    try {
+        t->schedule( NULL, -10 );
+    } catch( NullPointerException& e ) {
+    } catch( IllegalArgumentException& e ) {
+        exception = true;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a null task with negative delays should throw IllegalArgumentException first",
+                            exception == true );
+    t->cancel();
+
+    // Ensure a task is run
+    t.reset( new Timer() );
+    testTask.reset( new TimerTestTask( &report ) );
+    t->schedule( testTask, 200 );
+    try {
+        Thread::sleep( 400 );
+    } catch( InterruptedException& e ) {
+    }
+    CPPUNIT_ASSERT_MESSAGE( "TimerTask.run() method not called after 200ms",
+                            1 == report.wasRun.get() );
+    t->cancel();
+
+    // Ensure multiple tasks are run
+    t.reset( new Timer() );
+    testTask.reset( new TimerTestTask() );
+    testTask->setIncrementCount( true );
+    t->schedule( testTask, 100 );
+    testTask.reset( new TimerTestTask() );
+    testTask->setIncrementCount( true );
+    t->schedule( testTask, 150 );
+    testTask.reset( new TimerTestTask() );
+    testTask->setIncrementCount( true );
+    t->schedule( testTask, 70 );
+    testTask.reset( new TimerTestTask() );
+    testTask->setIncrementCount( true );
+    t->schedule( testTask, 10 );
+    try {
+        Thread::sleep( 400 );
+    } catch( InterruptedException& e ) {
+    }
+
+    CPPUNIT_ASSERT_MESSAGE( std::string( "Multiple tasks should have incremented counter 4 times not " ) +
+                            Integer::toString( timerCounter.get() ), timerCounter.get() == 4 );
+    t->cancel();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void TimerTest::testSchedule_TimerTask_Long_Long() {
+
+    std::auto_ptr<Timer> t;
+    TimerTaskReport report;
+
+    // Ensure a Timer throws an IllegalStateException after cancelled
+    t.reset( new Timer() );
+    TimerTestTask* testTask = new TimerTestTask();
+    t->cancel();
+    bool exception = false;
+    try {
+        t->schedule( testTask, 100, 100 );
+    } catch( IllegalStateException& e ) {
+        exception = true;
+        // unscheduled tasks must be deleted
+        delete testTask;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a task after Timer.cancel() should throw exception", exception );
+
+    // Ensure a Timer throws an IllegalStateException if task already cancelled
+    t.reset( new Timer() );
+    testTask = new TimerTestTask();
+    testTask->cancel();
+    exception = false;
+    try {
+        t->schedule( testTask, 100, 100 );
+    } catch( IllegalStateException& e ) {
+        exception = true;
+        // unscheduled tasks must be deleted
+        delete testTask;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a task after cancelling it should throw exception", exception );
+    t->cancel();
+
+    // Ensure a Timer throws an IllegalArgumentException if delay is
+    // negative
+    t.reset( new Timer() );
+    testTask = new TimerTestTask();
+    exception = false;
+    try {
+        t->schedule( testTask, -100, 100 );
+    } catch( IllegalArgumentException& e ) {
+        exception = true;
+        // unscheduled tasks must be deleted
+        delete testTask;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a task with negative delay should throw IllegalArgumentException", exception );
+    t->cancel();
+
+    // Ensure a Timer throws an IllegalArgumentException if period is negative
+    t.reset( new Timer() );
+    testTask = new TimerTestTask();
+    exception = false;
+    try {
+        t->schedule( testTask, 100, -100 );
+    } catch( IllegalArgumentException& e ) {
+        exception = true;
+        // unscheduled tasks must be deleted
+        delete testTask;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a task with negative period should throw IllegalArgumentException", exception );
+    t->cancel();
+
+    // Ensure a Timer throws an IllegalArgumentException if period is zero
+    t.reset( new Timer() );
+    testTask = new TimerTestTask();
+    exception = false;
+    try {
+        t->schedule( testTask, 100, 0 );
+    } catch( IllegalArgumentException& e ) {
+        exception = true;
+        // unscheduled tasks must be deleted
+        delete testTask;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a task with 0 period should throw IllegalArgumentException", exception );
+    t->cancel();
+
+    // Ensure a Timer throws a NullPointerException if the task is null
+    t.reset( new Timer() );
+    exception = false;
+    try {
+        t->schedule( NULL, 10, 10 );
+    } catch( NullPointerException& e ) {
+        exception = true;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a null task should throw NullPointerException", exception );
+    t->cancel();
+
+    // Ensure proper sequence of exceptions
+    t.reset( new Timer() );
+    exception = false;
+    try {
+        t->schedule( NULL, -10, -10 );
+    } catch( NullPointerException& e ) {
+    } catch( IllegalArgumentException& e ) {
+        exception = true;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a null task with negative delays should throw IllegalArgumentException first", exception );
+    t->cancel();
+
+    // Ensure a task is run at least twice
+    t.reset( new Timer() );
+    testTask = new TimerTestTask( &report );
+    t->schedule( testTask, 100, 100 );
+    try {
+        Thread::sleep( 400 );
+    } catch( InterruptedException& e ) {
+    }
+    CPPUNIT_ASSERT_MESSAGE( "TimerTask.run() method should have been called at least twice (" +
+                            Integer::toString( report.wasRun.get() ) + ")",
+                            report.wasRun.get() >= 2 );
+    t->cancel();
+
+    // Ensure multiple tasks are run
+    t.reset( new Timer() );
+    testTask = new TimerTestTask();
+    testTask->setIncrementCount( true );
+    t->schedule( testTask, 100, 100 ); // at least 9 times
+    testTask = new TimerTestTask();
+    testTask->setIncrementCount( true );
+    t->schedule( testTask, 200, 100 ); // at least 7 times
+    testTask = new TimerTestTask();
+    testTask->setIncrementCount( true );
+    t->schedule( testTask, 300, 200 ); // at least 4 times
+    testTask = new TimerTestTask();
+    testTask->setIncrementCount( true );
+    t->schedule( testTask, 100, 200 ); // at least 4 times
+    try {
+        Thread::sleep( 1200 ); // Allowed more room for error
+    } catch( InterruptedException& e ) {
+    }
+    CPPUNIT_ASSERT_MESSAGE( std::string( "Multiple tasks should have incremented counter 24 times not " ) +
+                            Integer::toString( timerCounter.get() ), timerCounter.get() >= 24 );
+    t->cancel();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void TimerTest::testSchedule_TimerTask_Long_Long2() {
+
+    std::auto_ptr<Timer> t;
+    TimerTaskReport report;
+
+    // Ensure a Timer throws an IllegalStateException after cancelled
+    t.reset( new Timer() );
+    Pointer<TimerTestTask> testTask( new TimerTestTask() );
+    t->cancel();
+    bool exception = false;
+    try {
+        t->schedule( testTask, 100, 100 );
+    } catch( IllegalStateException& e ) {
+        exception = true;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a task after Timer.cancel() should throw exception", exception );
+
+    // Ensure a Timer throws an IllegalStateException if task already cancelled
+    t.reset( new Timer() );
+    testTask.reset( new TimerTestTask() );
+    testTask->cancel();
+    exception = false;
+    try {
+        t->schedule( testTask, 100, 100 );
+    } catch( IllegalStateException& e ) {
+        exception = true;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a task after cancelling it should throw exception", exception );
+    t->cancel();
+
+    // Ensure a Timer throws an IllegalArgumentException if delay is
+    // negative
+    t.reset( new Timer() );
+    testTask.reset( new TimerTestTask() );
+    exception = false;
+    try {
+        t->schedule( testTask, -100, 100 );
+    } catch( IllegalArgumentException& e ) {
+        exception = true;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a task with negative delay should throw IllegalArgumentException", exception );
+    t->cancel();
+
+    // Ensure a Timer throws an IllegalArgumentException if period is negative
+    t.reset( new Timer() );
+    testTask.reset( new TimerTestTask() );
+    exception = false;
+    try {
+        t->schedule( testTask, 100, -100 );
+    } catch( IllegalArgumentException& e ) {
+        exception = true;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a task with negative period should throw IllegalArgumentException", exception );
+    t->cancel();
+
+    // Ensure a Timer throws an IllegalArgumentException if period is zero
+    t.reset( new Timer() );
+    testTask.reset( new TimerTestTask() );
+    exception = false;
+    try {
+        t->schedule( testTask, 100, 0 );
+    } catch( IllegalArgumentException& e ) {
+        exception = true;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a task with 0 period should throw IllegalArgumentException", exception );
+    t->cancel();
+
+    // Ensure a Timer throws a NullPointerException if the task is null
+    t.reset( new Timer() );
+    exception = false;
+    try {
+        t->schedule( NULL, 10, 10 );
+    } catch( NullPointerException& e ) {
+        exception = true;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a null task should throw NullPointerException", exception );
+    t->cancel();
+
+    // Ensure proper sequence of exceptions
+    t.reset( new Timer() );
+    exception = false;
+    try {
+        t->schedule( NULL, -10, -10 );
+    } catch( NullPointerException& e ) {
+    } catch( IllegalArgumentException& e ) {
+        exception = true;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a null task with negative delays should throw IllegalArgumentException first", exception );
+    t->cancel();
+
+    // Ensure a task is run at least twice
+    t.reset( new Timer() );
+    testTask.reset( new TimerTestTask( &report ) );
+    t->schedule( testTask, 100, 100 );
+    try {
+        Thread::sleep( 400 );
+    } catch( InterruptedException& e ) {
+    }
+    CPPUNIT_ASSERT_MESSAGE( "TimerTask.run() method should have been called at least twice (" +
+                            Integer::toString( report.wasRun.get() ) + ")",
+                            report.wasRun.get() >= 2 );
+    t->cancel();
+
+    // Ensure multiple tasks are run
+    t.reset( new Timer() );
+    testTask.reset( new TimerTestTask() );
+    testTask->setIncrementCount( true );
+    t->schedule( testTask, 100, 100 ); // at least 9 times
+    testTask.reset( new TimerTestTask() );
+    testTask->setIncrementCount( true );
+    t->schedule( testTask, 200, 100 ); // at least 7 times
+    testTask.reset( new TimerTestTask() );
+    testTask->setIncrementCount( true );
+    t->schedule( testTask, 300, 200 ); // at least 4 times
+    testTask.reset( new TimerTestTask() );
+    testTask->setIncrementCount( true );
+    t->schedule( testTask, 100, 200 ); // at least 4 times
+    try {
+        Thread::sleep( 1200 ); // Allowed more room for error
+    } catch( InterruptedException& e ) {
+    }
+    CPPUNIT_ASSERT_MESSAGE( std::string( "Multiple tasks should have incremented counter 24 times not " ) +
+                            Integer::toString( timerCounter.get() ), timerCounter.get() >= 24 );
+    t->cancel();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void TimerTest::testSchedule_TimerTask_Date_Long() {
+
+    std::auto_ptr<Timer> t;
+    TimerTaskReport report;
+
+    // Ensure a Timer throws an IllegalStateException after cancelled
+    t.reset( new Timer() );
+    TimerTestTask* testTask = new TimerTestTask();
+    Date d( System::currentTimeMillis() + 100 );
+    t->cancel();
+    bool exception = false;
+    try {
+        t->schedule( testTask, d, 100 );
+    } catch( IllegalStateException& e ) {
+        exception = true;
+        // unscheduled tasks must be deleted
+        delete testTask;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a task after Timer.cancel() should throw exception", exception );
+
+    // Ensure a Timer throws an IllegalStateException if task already cancelled
+    t.reset( new Timer() );
+    d.setTime( System::currentTimeMillis() + 100 );
+    testTask = new TimerTestTask();
+    testTask->cancel();
+    exception = false;
+    try {
+        t->schedule( testTask, d, 100 );
+    } catch( IllegalStateException& e ) {
+        exception = true;
+        // unscheduled tasks must be deleted
+        delete testTask;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a task after cancelling it should throw exception", exception );
+    t->cancel();
+
+    // Ensure a Timer throws an IllegalArgumentException if delay is
+    // negative
+    t.reset( new Timer() );
+    d.setTime( -100 );
+    testTask = new TimerTestTask();
+    exception = false;
+    try {
+        t->schedule( testTask, d, 100 );
+    } catch( IllegalArgumentException& e ) {
+        exception = true;
+        // unscheduled tasks must be deleted
+        delete testTask;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a task with negative delay should throw IllegalArgumentException", exception );
+    t->cancel();
+
+    // Ensure a Timer throws an IllegalArgumentException if period is
+    // negative
+    t.reset( new Timer() );
+    d.setTime( System::currentTimeMillis() + 100 );
+    testTask = new TimerTestTask();
+    exception = false;
+    try {
+        t->schedule( testTask, d, -100 );
+    } catch( IllegalArgumentException& e ) {
+        exception = true;
+        // unscheduled tasks must be deleted
+        delete testTask;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a task with negative period should throw IllegalArgumentException", exception );
+    t->cancel();
+
+    // Ensure a Timer throws a NullPointerException if the task is null
+    t.reset( new Timer() );
+    d.setTime( System::currentTimeMillis() + 100 );
+    exception = false;
+    try {
+        t->schedule( NULL, d, 10 );
+    } catch( NullPointerException& e ) {
+        exception = true;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a null task should throw NullPointerException", exception );
+    t->cancel();
+
+    // Ensure proper sequence of exceptions
+    t.reset( new Timer() );
+    d.setTime( -100 );
+    exception = false;
+    try {
+        t->schedule( NULL, d, 10 );
+    } catch( NullPointerException& e ) {
+    } catch( IllegalArgumentException& e ) {
+        exception = true;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a null task with negative dates should throw IllegalArgumentException first", exception );
+    t->cancel();
+
+    // Ensure a task is run at least twice
+    t.reset( new Timer() );
+    d.setTime( System::currentTimeMillis() + 100 );
+    testTask = new TimerTestTask( &report );
+    t->schedule( testTask, d, 100 );
+    try {
+        Thread::sleep( 800 );
+    } catch( InterruptedException& e ) {
+    }
+    CPPUNIT_ASSERT_MESSAGE( std::string( "TimerTask.run() method should have been called at least twice (" ) +
+                            Integer::toString( report.wasRun.get() ) + ")",
+                            report.wasRun.get() >= 2 );
+    t->cancel();
+
+    // Ensure multiple tasks are run
+    t.reset( new Timer() );
+    testTask = new TimerTestTask();
+    testTask->setIncrementCount( true );
+    d.setTime( System::currentTimeMillis() + 100 );
+    t->schedule( testTask, d, 100 ); // at least 9 times
+    testTask = new TimerTestTask();
+    testTask->setIncrementCount( true );
+    d.setTime( System::currentTimeMillis() + 200 );
+    t->schedule( testTask, d, 100 ); // at least 7 times
+    testTask = new TimerTestTask();
+    testTask->setIncrementCount( true );
+    d.setTime( System::currentTimeMillis() + 300 );
+    t->schedule( testTask, d, 200 ); // at least 4 times
+    testTask = new TimerTestTask();
+    testTask->setIncrementCount( true );
+    d.setTime( System::currentTimeMillis() + 100 );
+    t->schedule( testTask, d, 200 ); // at least 4 times
+    try {
+        Thread::sleep( 3000 );
+    } catch( InterruptedException& e ) {
+    }
+    CPPUNIT_ASSERT_MESSAGE( std::string( "Multiple tasks should have incremented counter 24 times not " ) +
+                            Integer::toString( timerCounter.get() ), timerCounter.get() >= 24 );
+    t->cancel();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void TimerTest::testSchedule_TimerTask_Date_Long2() {
+
+    std::auto_ptr<Timer> t;
+    TimerTaskReport report;
+
+    // Ensure a Timer throws an IllegalStateException after cancelled
+    t.reset( new Timer() );
+    Pointer<TimerTestTask> testTask( new TimerTestTask() );
+    Date d( System::currentTimeMillis() + 100 );
+    t->cancel();
+    bool exception = false;
+    try {
+        t->schedule( testTask, d, 100 );
+    } catch( IllegalStateException& e ) {
+        exception = true;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a task after Timer.cancel() should throw exception", exception );
+
+    // Ensure a Timer throws an IllegalStateException if task already cancelled
+    t.reset( new Timer() );
+    d.setTime( System::currentTimeMillis() + 100 );
+    testTask.reset( new TimerTestTask() );
+    testTask->cancel();
+    exception = false;
+    try {
+        t->schedule( testTask, d, 100 );
+    } catch( IllegalStateException& e ) {
+        exception = true;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a task after cancelling it should throw exception", exception );
+    t->cancel();
+
+    // Ensure a Timer throws an IllegalArgumentException if delay is
+    // negative
+    t.reset( new Timer() );
+    d.setTime( -100 );
+    testTask.reset( new TimerTestTask() );
+    exception = false;
+    try {
+        t->schedule( testTask, d, 100 );
+    } catch( IllegalArgumentException& e ) {
+        exception = true;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a task with negative delay should throw IllegalArgumentException", exception );
+    t->cancel();
+
+    // Ensure a Timer throws an IllegalArgumentException if period is
+    // negative
+    t.reset( new Timer() );
+    d.setTime( System::currentTimeMillis() + 100 );
+    testTask.reset( new TimerTestTask() );
+    exception = false;
+    try {
+        t->schedule( testTask, d, -100 );
+    } catch( IllegalArgumentException& e ) {
+        exception = true;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a task with negative period should throw IllegalArgumentException", exception );
+    t->cancel();
+
+    // Ensure a Timer throws a NullPointerException if the task is null
+    t.reset( new Timer() );
+    d.setTime( System::currentTimeMillis() + 100 );
+    exception = false;
+    try {
+        t->schedule( NULL, d, 10 );
+    } catch( NullPointerException& e ) {
+        exception = true;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a null task should throw NullPointerException", exception );
+    t->cancel();
+
+    // Ensure proper sequence of exceptions
+    t.reset( new Timer() );
+    d.setTime( -100 );
+    exception = false;
+    try {
+        t->schedule( NULL, d, 10 );
+    } catch( NullPointerException& e ) {
+    } catch( IllegalArgumentException& e ) {
+        exception = true;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a null task with negative dates should throw IllegalArgumentException first", exception );
+    t->cancel();
+
+    // Ensure a task is run at least twice
+    t.reset( new Timer() );
+    d.setTime( System::currentTimeMillis() + 100 );
+    testTask.reset( new TimerTestTask( &report ) );
+    t->schedule( testTask, d, 100 );
+    try {
+        Thread::sleep( 800 );
+    } catch( InterruptedException& e ) {
+    }
+    CPPUNIT_ASSERT_MESSAGE( std::string( "TimerTask.run() method should have been called at least twice (" ) +
+                            Integer::toString( report.wasRun.get() ) + ")",
+                            report.wasRun.get() >= 2 );
+    t->cancel();
+
+    // Ensure multiple tasks are run
+    t.reset( new Timer() );
+    testTask.reset( new TimerTestTask() );
+    testTask->setIncrementCount( true );
+    d.setTime( System::currentTimeMillis() + 100 );
+    t->schedule( testTask, d, 100 ); // at least 9 times
+    testTask.reset( new TimerTestTask() );
+    testTask->setIncrementCount( true );
+    d.setTime( System::currentTimeMillis() + 200 );
+    t->schedule( testTask, d, 100 ); // at least 7 times
+    testTask.reset( new TimerTestTask() );
+    testTask->setIncrementCount( true );
+    d.setTime( System::currentTimeMillis() + 300 );
+    t->schedule( testTask, d, 200 ); // at least 4 times
+    testTask.reset( new TimerTestTask() );
+    testTask->setIncrementCount( true );
+    d.setTime( System::currentTimeMillis() + 100 );
+    t->schedule( testTask, d, 200 ); // at least 4 times
+    try {
+        Thread::sleep( 3000 );
+    } catch( InterruptedException& e ) {
+    }
+    CPPUNIT_ASSERT_MESSAGE( std::string( "Multiple tasks should have incremented counter 24 times not " ) +
+                            Integer::toString( timerCounter.get() ), timerCounter.get() >= 24 );
+    t->cancel();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void TimerTest::testScheduleAtFixedRate_TimerTask_Long_Long() {
+
+    std::auto_ptr<Timer> t;
+    TimerTaskReport report;
+
+    // Ensure a Timer throws an IllegalStateException after cancelled
+    t.reset( new Timer() );
+    TimerTestTask* testTask = new TimerTestTask();
+    t->cancel();
+    bool exception = false;
+    try {
+        t->scheduleAtFixedRate( testTask, 100, 100 );
+    } catch( IllegalStateException& e ) {
+        exception = true;
+        // unscheduled tasks must be deleted
+        delete testTask;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "scheduleAtFixedRate after Timer.cancel() should throw exception", exception );
+
+    // Ensure a Timer throws an IllegalArgumentException if delay is negative
+    t.reset( new Timer() );
+    testTask = new TimerTestTask();
+    exception = false;
+    try {
+        t->scheduleAtFixedRate( testTask, -100, 100 );
+    } catch( IllegalArgumentException& e ) {
+        exception = true;
+        // unscheduled tasks must be deleted
+        delete testTask;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "scheduleAtFixedRate with negative delay should throw IllegalArgumentException",
+                            exception );
+    t->cancel();
+
+    // Ensure a Timer throws an IllegalArgumentException if period is negative
+    t.reset( new Timer() );
+    testTask = new TimerTestTask();
+    exception = false;
+    try {
+        t->scheduleAtFixedRate( testTask, 100, -100 );
+    } catch( IllegalArgumentException& e ) {
+        exception = true;
+        // unscheduled tasks must be deleted
+        delete testTask;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "scheduleAtFixedRate with negative period should throw IllegalArgumentException",
+                            exception );
+    t->cancel();
+
+    // Ensure a task is run at least twice
+    t.reset( new Timer() );
+    testTask = new TimerTestTask( &report );
+    t->scheduleAtFixedRate( testTask, 100, 100 );
+    try {
+        Thread::sleep( 400 );
+    } catch( InterruptedException& e ) {
+    }
+    CPPUNIT_ASSERT_MESSAGE( std::string( "TimerTask.run() method should have been called at least twice (" ) +
+                            Integer::toString( report.wasRun.get() ) + ")",
+                            report.wasRun.get() >= 2 );
+    t->cancel();
+
+    // Ensure multiple tasks are run
+    t.reset( new Timer() );
+    report.reset();
+    SlowThenFastTask* slowThenFastTask = new SlowThenFastTask( &report );
+
+    // at least 9 times even when asleep
+    t->scheduleAtFixedRate( slowThenFastTask, 100, 100 );
+    try {
+        Thread::sleep( 1000 );
+    } catch( InterruptedException& e ) {
+    }
+    long long lastDelta = report.lastDelta;
+    CPPUNIT_ASSERT_MESSAGE( "Fixed Rate Schedule should catch up, but is off by " +
+                            Integer::toString( lastDelta ) + " ms",
+                            lastDelta < 300 );
+    t->cancel();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void TimerTest::testScheduleAtFixedRate_TimerTask_Long_Long2() {
+
+    std::auto_ptr<Timer> t;
+    TimerTaskReport report;
+
+    // Ensure a Timer throws an IllegalStateException after cancelled
+    t.reset( new Timer() );
+    Pointer<TimerTestTask> testTask( new TimerTestTask() );
+    t->cancel();
+    bool exception = false;
+    try {
+        t->scheduleAtFixedRate( testTask, 100, 100 );
+    } catch( IllegalStateException& e ) {
+        exception = true;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "scheduleAtFixedRate after Timer.cancel() should throw exception", exception );
+
+    // Ensure a Timer throws an IllegalArgumentException if delay is negative
+    t.reset( new Timer() );
+    testTask.reset( new TimerTestTask() );
+    exception = false;
+    try {
+        t->scheduleAtFixedRate( testTask, -100, 100 );
+    } catch( IllegalArgumentException& e ) {
+        exception = true;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "scheduleAtFixedRate with negative delay should throw IllegalArgumentException",
+                            exception );
+    t->cancel();
+
+    // Ensure a Timer throws an IllegalArgumentException if period is negative
+    t.reset( new Timer() );
+    testTask.reset( new TimerTestTask() );
+    exception = false;
+    try {
+        t->scheduleAtFixedRate( testTask, 100, -100 );
+    } catch( IllegalArgumentException& e ) {
+        exception = true;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "scheduleAtFixedRate with negative period should throw IllegalArgumentException",
+                            exception );
+    t->cancel();
+
+    // Ensure a task is run at least twice
+    t.reset( new Timer() );
+    testTask.reset( new TimerTestTask( &report ) );
+    t->scheduleAtFixedRate( testTask, 100, 100 );
+    try {
+        Thread::sleep( 400 );
+    } catch( InterruptedException& e ) {
+    }
+    CPPUNIT_ASSERT_MESSAGE( std::string( "TimerTask.run() method should have been called at least twice (" ) +
+                            Integer::toString( report.wasRun.get() ) + ")",
+                            report.wasRun.get() >= 2 );
+    t->cancel();
+
+    // Ensure multiple tasks are run
+    t.reset( new Timer() );
+    report.reset();
+    Pointer<SlowThenFastTask> slowThenFastTask( new SlowThenFastTask( &report ) );
+
+    // at least 9 times even when asleep
+    t->scheduleAtFixedRate( slowThenFastTask, 100, 100 );
+    try {
+        Thread::sleep( 1000 );
+    } catch( InterruptedException& e ) {
+    }
+    long long lastDelta = report.lastDelta;
+    CPPUNIT_ASSERT_MESSAGE( "Fixed Rate Schedule should catch up, but is off by " +
+                            Integer::toString( lastDelta ) + " ms",
+                            lastDelta < 300 );
+    t->cancel();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void TimerTest::testScheduleAtFixedRate_TimerTask_Date_Long() {
+
+    std::auto_ptr<Timer> t;
+    TimerTaskReport report;
+
+    // Ensure a Timer throws an IllegalStateException after cancelled
+    t.reset( new Timer() );
+    TimerTestTask* testTask = new TimerTestTask();
+    t->cancel();
+    bool exception = false;
+    Date d( System::currentTimeMillis() + 100 );
+    try {
+        t->scheduleAtFixedRate( testTask, d, 100 );
+    } catch( IllegalStateException& e ) {
+        exception = true;
+        // unscheduled tasks must be deleted
+        delete testTask;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "scheduleAtFixedRate after Timer.cancel() should throw exception", exception );
+
+    // Ensure a Timer throws an IllegalArgumentException if delay is negative
+    t.reset( new Timer() );
+    testTask = new TimerTestTask();
+    exception = false;
+    d.setTime( -100 );
+    try {
+        t->scheduleAtFixedRate( testTask, d, 100 );
+    } catch( IllegalArgumentException& e ) {
+        exception = true;
+        // unscheduled tasks must be deleted
+        delete testTask;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "scheduleAtFixedRate with negative Date should throw IllegalArgumentException",
+                            exception );
+    t->cancel();
+
+    // Ensure a Timer throws an IllegalArgumentException if period is negative
+    t.reset( new Timer() );
+    testTask = new TimerTestTask();
+    exception = false;
+    try {
+        t->scheduleAtFixedRate( testTask, d, -100 );
+    } catch( IllegalArgumentException& e ) {
+        exception = true;
+        // unscheduled tasks must be deleted
+        delete testTask;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "scheduleAtFixedRate with negative period should throw IllegalArgumentException",
+                            exception );
+    t->cancel();
+
+    // Ensure proper sequence of exceptions
+    t.reset( new Timer() );
+    exception = false;
+    d.setTime( -100 );
+    try {
+        t->scheduleAtFixedRate( NULL, d, 10 );
+    } catch( NullPointerException& e ) {
+    } catch( IllegalArgumentException& e ) {
+        exception = true;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a null task with negative date should throw IllegalArgumentException first",
+                            exception );
+    t->cancel();
+
+    // Ensure proper sequence of exceptions
+    t.reset( new Timer() );
+    exception = false;
+    try {
+        t->scheduleAtFixedRate( NULL, d, -10 );
+    } catch( NullPointerException& e ) {
+    } catch( IllegalArgumentException& e ) {
+        exception = true;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a null task & negative period should throw IllegalArgumentException first",
+                            exception );
+    t->cancel();
+
+    // Ensure a task is run at least twice
+    t.reset( new Timer() );
+    testTask = new TimerTestTask( &report );
+    d.setTime( System::currentTimeMillis() + 100 );
+    t->scheduleAtFixedRate( testTask, d, 100 );
+    try {
+        Thread::sleep( 400 );
+    } catch( InterruptedException& e ) {
+    }
+    CPPUNIT_ASSERT_MESSAGE( std::string( "TimerTask.run() method should have been called at least twice (" ) +
+                            Integer::toString( report.wasRun.get() ) + ")",
+                            report.wasRun.get() >= 2 );
+    t->cancel();
+
+    // Ensure multiple tasks are run
+    t.reset( new Timer() );
+    report.reset();
+    SlowThenFastTask* slowThenFastTask = new SlowThenFastTask( &report );
+    d.setTime( System::currentTimeMillis() + 100 );
+
+    // at least 9 times even when asleep
+    t->scheduleAtFixedRate( slowThenFastTask, d, 100 );
+    try {
+        Thread::sleep( 1000 );
+    } catch( InterruptedException& e ) {
+    }
+    long long lastDelta = report.lastDelta;
+    CPPUNIT_ASSERT_MESSAGE( std::string( "Fixed Rate Schedule should catch up, but is off by " ) +
+                            Integer::toString( lastDelta ) + " ms",
+                            lastDelta < 300 );
+    t->cancel();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void TimerTest::testScheduleAtFixedRate_TimerTask_Date_Long2() {
+
+    std::auto_ptr<Timer> t;
+    TimerTaskReport report;
+
+    // Ensure a Timer throws an IllegalStateException after cancelled
+    t.reset( new Timer() );
+    Pointer<TimerTestTask> testTask( new TimerTestTask() );
+    t->cancel();
+    bool exception = false;
+    Date d( System::currentTimeMillis() + 100 );
+    try {
+        t->scheduleAtFixedRate( testTask, d, 100 );
+    } catch( IllegalStateException& e ) {
+        exception = true;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "scheduleAtFixedRate after Timer.cancel() should throw exception", exception );
+
+    // Ensure a Timer throws an IllegalArgumentException if delay is negative
+    t.reset( new Timer() );
+    testTask.reset( new TimerTestTask() );
+    exception = false;
+    d.setTime( -100 );
+    try {
+        t->scheduleAtFixedRate( testTask, d, 100 );
+    } catch( IllegalArgumentException& e ) {
+        exception = true;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "scheduleAtFixedRate with negative Date should throw IllegalArgumentException",
+                            exception );
+    t->cancel();
+
+    // Ensure a Timer throws an IllegalArgumentException if period is negative
+    t.reset( new Timer() );
+    testTask.reset( new TimerTestTask() );
+    exception = false;
+    try {
+        t->scheduleAtFixedRate( testTask, d, -100 );
+    } catch( IllegalArgumentException& e ) {
+        exception = true;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "scheduleAtFixedRate with negative period should throw IllegalArgumentException",
+                            exception );
+    t->cancel();
+
+    // Ensure proper sequence of exceptions
+    t.reset( new Timer() );
+    exception = false;
+    d.setTime( -100 );
+    try {
+        t->scheduleAtFixedRate( NULL, d, 10 );
+    } catch( NullPointerException& e ) {
+    } catch( IllegalArgumentException& e ) {
+        exception = true;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a null task with negative date should throw IllegalArgumentException first",
+                            exception );
+    t->cancel();
+
+    // Ensure proper sequence of exceptions
+    t.reset( new Timer() );
+    exception = false;
+    try {
+        t->scheduleAtFixedRate( NULL, d, -10 );
+    } catch( NullPointerException& e ) {
+    } catch( IllegalArgumentException& e ) {
+        exception = true;
+    }
+    CPPUNIT_ASSERT_MESSAGE( "Scheduling a null task & negative period should throw IllegalArgumentException first",
+                            exception );
+    t->cancel();
+
+    // Ensure a task is run at least twice
+    t.reset( new Timer() );
+    testTask.reset( new TimerTestTask( &report ) );
+    d.setTime( System::currentTimeMillis() + 100 );
+    t->scheduleAtFixedRate( testTask, d, 100 );
+    try {
+        Thread::sleep( 400 );
+    } catch( InterruptedException& e ) {
+    }
+    CPPUNIT_ASSERT_MESSAGE( std::string( "TimerTask.run() method should have been called at least twice (" ) +
+                            Integer::toString( report.wasRun.get() ) + ")",
+                            report.wasRun.get() >= 2 );
+    t->cancel();
+
+    // Ensure multiple tasks are run
+    t.reset( new Timer() );
+    report.reset();
+    Pointer<SlowThenFastTask> slowThenFastTask( new SlowThenFastTask( &report ) );
+    d.setTime( System::currentTimeMillis() + 100 );
+
+    // at least 9 times even when asleep
+    t->scheduleAtFixedRate( slowThenFastTask, d, 100 );
+    try {
+        Thread::sleep( 1000 );
+    } catch( InterruptedException& e ) {
+    }
+    long long lastDelta = report.lastDelta;
+    CPPUNIT_ASSERT_MESSAGE( std::string( "Fixed Rate Schedule should catch up, but is off by " ) +
+                            Integer::toString( lastDelta ) + " ms",
+                            lastDelta < 300 );
+    t->cancel();
+}

Propchange: activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/TimerTest.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Added: activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/TimerTest.h
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/TimerTest.h?rev=796317&view=auto
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/TimerTest.h (added)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/TimerTest.h Tue Jul 21 14:28:11 2009
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _DECAF_UTIL_TIMERTEST_H_
+#define _DECAF_UTIL_TIMERTEST_H_
+
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+namespace decaf {
+namespace util {
+
+    class TimerTest : public CppUnit::TestFixture {
+
+        CPPUNIT_TEST_SUITE( TimerTest );
+        CPPUNIT_TEST( testConstructor );
+        CPPUNIT_TEST( testCancel );
+        CPPUNIT_TEST( testPurge );
+        CPPUNIT_TEST( testSchedule_TimerTask_Date );
+        CPPUNIT_TEST( testSchedule_TimerTask_Date2 );
+        CPPUNIT_TEST( testSchedule_TimerTask_Long );
+        CPPUNIT_TEST( testSchedule_TimerTask_Long2 );
+        CPPUNIT_TEST( testSchedule_TimerTask_Long_Long );
+        CPPUNIT_TEST( testSchedule_TimerTask_Long_Long2 );
+        CPPUNIT_TEST( testSchedule_TimerTask_Date_Long );
+        CPPUNIT_TEST( testSchedule_TimerTask_Date_Long2 );
+        CPPUNIT_TEST( testScheduleAtFixedRate_TimerTask_Long_Long );
+        CPPUNIT_TEST( testScheduleAtFixedRate_TimerTask_Long_Long2 );
+        CPPUNIT_TEST( testScheduleAtFixedRate_TimerTask_Date_Long );
+        CPPUNIT_TEST( testScheduleAtFixedRate_TimerTask_Date_Long2 );
+        CPPUNIT_TEST_SUITE_END();
+
+    public:
+
+        TimerTest() {}
+        virtual ~TimerTest() {}
+
+        void testConstructor();
+        void testCancel();
+        void testPurge();
+        void testSchedule_TimerTask_Date();
+        void testSchedule_TimerTask_Date2();
+        void testSchedule_TimerTask_Long();
+        void testSchedule_TimerTask_Long2();
+        void testSchedule_TimerTask_Long_Long();
+        void testSchedule_TimerTask_Long_Long2();
+        void testSchedule_TimerTask_Date_Long();
+        void testSchedule_TimerTask_Date_Long2();
+        void testScheduleAtFixedRate_TimerTask_Long_Long();
+        void testScheduleAtFixedRate_TimerTask_Long_Long2();
+        void testScheduleAtFixedRate_TimerTask_Date_Long();
+        void testScheduleAtFixedRate_TimerTask_Date_Long2();
+
+        virtual void setUp();
+
+    };
+
+}}
+
+#endif /* _DECAF_UTIL_TIMERTEST_H_ */

Propchange: activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/TimerTest.h
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/concurrent/MutexTest.cpp
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/concurrent/MutexTest.cpp?rev=796317&r1=796316&r2=796317&view=diff
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/concurrent/MutexTest.cpp (original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/concurrent/MutexTest.cpp Tue Jul 21 14:28:11 2009
@@ -44,9 +44,12 @@
     virtual void wait() throw(lang::Exception){
         mutex.wait();
     }
-    virtual void wait(unsigned long millisecs) throw(lang::Exception){
+    virtual void wait( long long millisecs ) throw(lang::Exception){
         mutex.wait( millisecs );
     }
+    virtual void wait( long long millisecs, int nanos ) throw(lang::Exception){
+        mutex.wait( millisecs, nanos );
+    }
     virtual void notify() throw(lang::Exception){
         mutex.notify();
     }
@@ -103,9 +106,12 @@
     virtual void wait() throw(lang::Exception){
         mutex.wait();
     }
-    virtual void wait(unsigned long millisecs) throw(lang::Exception){
+    virtual void wait(long long millisecs) throw(lang::Exception){
         mutex.wait( millisecs );
     }
+    virtual void wait( long long millisecs, int nanos ) throw(lang::Exception){
+        mutex.wait( millisecs, nanos );
+    }
     virtual void notify() throw(lang::Exception){
         mutex.notify();
     }
@@ -182,9 +188,12 @@
     virtual void wait() throw(lang::Exception){
         mutex.wait();
     }
-    virtual void wait(unsigned long millisecs) throw(lang::Exception){
+    virtual void wait(long long millisecs) throw(lang::Exception){
         mutex.wait( millisecs );
     }
+    virtual void wait( long long millisecs, int nanos ) throw(lang::Exception){
+        mutex.wait( millisecs, nanos );
+    }
     virtual void notify() throw(lang::Exception){
         mutex.notify();
     }
@@ -256,9 +265,12 @@
     virtual void wait() throw(lang::Exception){
         mutex->wait();
     }
-    virtual void wait(unsigned long millisecs) throw(lang::Exception){
+    virtual void wait(long long millisecs) throw(lang::Exception){
         mutex->wait( millisecs );
     }
+    virtual void wait( long long millisecs, int nanos ) throw(lang::Exception){
+        mutex->wait( millisecs, nanos );
+    }
     virtual void notify() throw(lang::Exception){
         mutex->notify();
     }
@@ -469,9 +481,12 @@
     virtual void wait() throw(lang::Exception){
         mutex->wait();
     }
-    virtual void wait(unsigned long millisecs) throw(lang::Exception){
+    virtual void wait(long long millisecs) throw(lang::Exception){
         mutex->wait( millisecs );
     }
+    virtual void wait( long long millisecs, int nanos ) throw(lang::Exception){
+        mutex->wait( millisecs, nanos );
+    }
     virtual void notify() throw(lang::Exception){
         mutex->notify();
     }

Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/test/testRegistry.cpp
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/test/testRegistry.cpp?rev=796317&r1=796316&r2=796317&view=diff
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/test/testRegistry.cpp (original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/test/testRegistry.cpp Tue Jul 21 14:28:11 2009
@@ -135,6 +135,9 @@
 
 #include <decaf/internal/util/ByteArrayAdapterTest.h>
 CPPUNIT_TEST_SUITE_REGISTRATION( decaf::internal::util::ByteArrayAdapterTest );
+#include <decaf/internal/util/TimerTaskHeapTest.h>
+CPPUNIT_TEST_SUITE_REGISTRATION( decaf::internal::util::TimerTaskHeapTest );
+
 #include <decaf/internal/nio/ByteArrayPerspectiveTest.h>
 CPPUNIT_TEST_SUITE_REGISTRATION( decaf::internal::nio::ByteArrayPerspectiveTest );
 #include <decaf/internal/nio/ByteArrayBufferTest.h>
@@ -255,3 +258,5 @@
 CPPUNIT_TEST_SUITE_REGISTRATION( decaf::util::SetTest );
 #include <decaf/util/StringTokenizerTest.h>
 CPPUNIT_TEST_SUITE_REGISTRATION( decaf::util::StringTokenizerTest );
+#include <decaf/util/TimerTest.h>
+CPPUNIT_TEST_SUITE_REGISTRATION( decaf::util::TimerTest );



Mime
View raw message