123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283 |
- // Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
- //
- // Permission to use, copy, modify, and/or distribute this software for any
- // purpose with or without fee is hereby granted, provided that the above
- // copyright notice and this permission notice appear in all copies.
- //
- // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
- // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
- // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
- // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- // PERFORMANCE OF THIS SOFTWARE.
- #include <util/stopwatch.h>
- #include <util/stopwatch_impl.h>
- #include <gtest/gtest.h>
- #include <unistd.h>
- namespace {
- using namespace isc;
- using namespace isc::util;
- using namespace boost::posix_time;
- /// @brief @c StopwatchImpl mock object.
- ///
- /// This class derives from the @c StopwatchImpl to override the
- /// @c StopwatchImpl::getCurrentTime. This method is internally called by
- /// the @c StopwatchImpl to determine the current time. By providing the
- /// implementation of this method which returns the fixed (well known)
- /// timestamp value we can obtain the deterministic values from the accessors
- /// of this class.
- ///
- /// This class also includes some convenience methods to return the time
- /// durations in milliseconds.
- class StopwatchMock : public StopwatchImpl {
- public:
- /// @brief Constructor.
- ///
- /// @param ref_time Reference time, i.e. the arbitrary time value from
- /// which time is measured. The @c current_time_ value returned by the
- /// @c StopwatchMock::getCurrentTime is initialized to this value.
- /// Subsequent calls to the @c StopwatchMock::ffwd move the value of
- /// the @c current_time_ forward.
- StopwatchMock(const ptime& ref_time);
- /// @brief Fast forward time.
- ///
- /// Moves the value of the @c current_time_ forward by the specified
- /// number of milliseconds. As a result the timestamp returned by the
- /// @c StopwatchMock::getCurrentTime moves by this value. This simulates
- /// the time progress.
- ///
- /// @param ms Specifies the number of milliseconds to move current time.
- void ffwd(const uint32_t ms);
- /// @brief Returns the last duration in milliseconds.
- uint32_t getLastDurationInMs() const;
- /// @brief Returns the total duration in milliseconds.
- uint32_t getTotalDurationInMs() const;
- protected:
- /// @brief Returs the current time.
- ///
- /// This method returns the fixed @c current_time_ timestamp.
- virtual ptime getCurrentTime() const;
- private:
- /// @brief Holds the current time to be returned by the
- /// @c StopwatchMock::getCurrentTime.
- ptime current_time_;
- };
- StopwatchMock::StopwatchMock(const ptime& ref_time)
- : StopwatchImpl(), current_time_(ref_time) {
- }
- void
- StopwatchMock::ffwd(const uint32_t ms) {
- current_time_ += milliseconds(ms);
- }
- uint32_t
- StopwatchMock::getLastDurationInMs() const {
- return (getLastDuration().total_milliseconds());
- }
- uint32_t
- StopwatchMock::getTotalDurationInMs() const {
- return (getTotalDuration().total_milliseconds());
- }
- ptime
- StopwatchMock::getCurrentTime() const {
- return (current_time_);
- }
- /// @brief Test fixture class for testing @c StopwatchImpl.
- class StopwatchTest : public ::testing::Test {
- protected:
- /// @brief Set up the test.
- ///
- /// Initializes the reference time to be used to create the instances
- /// of the @c StopwatchMock objects.
- virtual void SetUp();
- /// @brief Holds the reference time to be used to create the instances
- /// of the @c StopwatchMock objects.
- ptime ref_time_;
- };
- void
- StopwatchTest::SetUp() {
- ref_time_ = microsec_clock::universal_time();
- }
- /// This test checks the behavior of the stopwatch when it is started
- /// and stopped multiple times. It uses the StopwatchMock object to
- /// control the "time flow" by setting the current time to arbitrary
- /// values using the StopwatchMock::ffwd. In addition, this test
- /// checks that the stopwatch can be reset.
- TEST_F(StopwatchTest, multipleMeasurements) {
- StopwatchMock stopwatch(ref_time_);
- // The stopwatch shouldn't automatically start. The initial
- // durations should be set to 0.
- EXPECT_EQ(0, stopwatch.getLastDurationInMs());
- EXPECT_EQ(0, stopwatch.getTotalDurationInMs());
- stopwatch.start();
- // Even though the stopwatch is started, the time is still set to
- // the initial value. The durations should not be affected.
- EXPECT_EQ(0, stopwatch.getLastDurationInMs());
- EXPECT_EQ(0, stopwatch.getTotalDurationInMs());
- // Move the time by 10 ms.
- stopwatch.ffwd(10);
- // It should be possible to retrieve the durations even when the
- // stopwatch is running.
- EXPECT_EQ(10, stopwatch.getLastDurationInMs());
- EXPECT_EQ(10, stopwatch.getTotalDurationInMs());
- // Now stop it and make sure that the same values are returned.
- stopwatch.stop();
- EXPECT_EQ(10, stopwatch.getLastDurationInMs());
- EXPECT_EQ(10, stopwatch.getTotalDurationInMs());
- // Start it again, but don't move the time forward yet.
- stopwatch.start();
- // The new duration should be 0, but the total should be equal to
- // the previously measured duration.
- EXPECT_EQ(0, stopwatch.getLastDurationInMs());
- EXPECT_EQ(10, stopwatch.getTotalDurationInMs());
- // Move time by 5 ms.
- stopwatch.ffwd(5);
- // New measured duration should be 5 ms. The total should be 15 ms.
- EXPECT_EQ(5, stopwatch.getLastDurationInMs());
- EXPECT_EQ(15, stopwatch.getTotalDurationInMs());
- // Stop it again and make sure the values returned are the same.
- stopwatch.stop();
- EXPECT_EQ(5, stopwatch.getLastDurationInMs());
- EXPECT_EQ(15, stopwatch.getTotalDurationInMs());
- // Move the time forward while the stopwatch is stopped.
- stopwatch.ffwd(8);
- // The measured values should not be affected.
- EXPECT_EQ(5, stopwatch.getLastDurationInMs());
- EXPECT_EQ(15, stopwatch.getTotalDurationInMs());
- // Stop should be no-op in this case.
- stopwatch.stop();
- EXPECT_EQ(5, stopwatch.getLastDurationInMs());
- EXPECT_EQ(15, stopwatch.getTotalDurationInMs());
- // Start the stopwatch again.
- stopwatch.start();
- // Move time by 3 ms.
- stopwatch.ffwd(3);
- // Since the stopwatch is running, the measured duration should
- // get updated again.
- EXPECT_EQ(3, stopwatch.getLastDurationInMs());
- EXPECT_EQ(18, stopwatch.getTotalDurationInMs());
- // Move the time by 2 ms.
- stopwatch.ffwd(2);
- // Start should be no-op in this case.
- stopwatch.start();
- // But the durations should be updated.
- EXPECT_EQ(5, stopwatch.getLastDurationInMs());
- EXPECT_EQ(20, stopwatch.getTotalDurationInMs());
- // Make sure we can reset.
- stopwatch.reset();
- EXPECT_EQ(0, stopwatch.getLastDurationInMs());
- EXPECT_EQ(0, stopwatch.getTotalDurationInMs());
- }
- // This test checks that the stopwatch works when the real clock is in use.
- TEST_F(StopwatchTest, realTime) {
- // Initially, the measured time should be 0.
- Stopwatch stopwatch;
- EXPECT_EQ(0, stopwatch.getMilliseconds());
- EXPECT_EQ(0, stopwatch.getTotalMilliseconds());
- // Start the stopwatch.
- stopwatch.start();
- // Sleep for 1 ms. The stopwatch should measure this duration.
- usleep(1000);
- stopwatch.stop();
- // The measured duration should be greater or equal 1 ms.
- long current_duration = stopwatch.getMilliseconds();
- EXPECT_GE(current_duration, 1);
- EXPECT_EQ(current_duration, stopwatch.getTotalMilliseconds());
- // Sleep for another 2 ms while the stopwatch is in the stopped state.
- usleep(2000);
- // In the stopped state, we should still have old durations measured.
- EXPECT_EQ(current_duration, stopwatch.getMilliseconds());
- EXPECT_EQ(current_duration, stopwatch.getTotalMilliseconds());
- // Start it again.
- stopwatch.start();
- // Slee for 1 ms.
- usleep(1000);
- // The durations should get updated as appropriate.
- current_duration = stopwatch.getMilliseconds();
- EXPECT_GE(stopwatch.getMilliseconds(), 1);
- EXPECT_GE(stopwatch.getTotalMilliseconds(), 2);
- }
- // Make sure that we can obtain the durations as microseconds.
- TEST_F(StopwatchTest, getMicroseconds) {
- Stopwatch stopwatch;
- stopwatch.start();
- usleep(1000);
- stopwatch.stop();
- long current_duration = stopwatch.getMicroseconds();
- EXPECT_GE(current_duration, 1000);
- EXPECT_EQ(current_duration, stopwatch.getTotalMicroseconds());
- }
- // Make sure that we can use the "autostart" option to start the time
- // measurement in the constructor.
- TEST_F(StopwatchTest, autostart) {
- Stopwatch stopwatch(true);
- usleep(1000);
- stopwatch.stop();
- EXPECT_GE(stopwatch.getMilliseconds(), 1);
- EXPECT_EQ(stopwatch.getMilliseconds(), stopwatch.getTotalMilliseconds());
- }
- } // end of anonymous namespace
|