| // Copyright 2008 Google Inc. |
| // Authors: Craig Silverstein, Lincoln Smith |
| // |
| // Licensed 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 OPEN_VCDIFF_TESTING_H_ |
| #define OPEN_VCDIFF_TESTING_H_ |
| |
| #include <config.h> |
| #include <assert.h> |
| #include <stdint.h> // int64_t |
| #include <stdlib.h> // rand |
| #include <time.h> // gettimeofday |
| #include "gtest/gtest.h" |
| |
| #ifdef HAVE_SYS_TIME_H |
| #include <sys/time.h> // struct timeval |
| #endif // HAVE_SYS_TIME_H |
| |
| #ifdef HAVE_WINDOWS_H |
| #include <windows.h> // QueryPerformanceCounter |
| #endif // HAVE_WINDOWS_H |
| |
| // CHECK is used for assertions that verify the consistency of the test itself, |
| // rather than correctness of the code that is being tested. |
| // |
| // It is better to use a preprocessor macro for CHECK |
| // than an inline function, because assert() may report |
| // the source file and line where the failure occurred. |
| // |
| // Putting parentheses around the macro arguments |
| // (e.g. "assert((X) == (Y))") would be good practice |
| // but would produce error messages that are inconsistent |
| // with those expected in the unit tests. |
| |
| #define CHECK(CONDITION) assert(CONDITION) |
| #define CHECK_EQ(X, Y) assert(X == Y) |
| #define CHECK_NE(X, Y) assert(X != Y) |
| #define CHECK_GE(X, Y) assert(X >= Y) |
| #define CHECK_GT(X, Y) assert(X > Y) |
| #define CHECK_LE(X, Y) assert(X <= Y) |
| #define CHECK_LT(X, Y) assert(X < Y) |
| |
| namespace open_vcdiff { |
| |
| // Support for timing tests |
| #if defined(HAVE_GETTIMEOFDAY) |
| class CycleTimer { |
| public: |
| inline CycleTimer() { |
| Reset(); |
| } |
| |
| inline void Reset() { |
| start_time_.tv_sec = 0; |
| start_time_.tv_usec = 0; |
| cumulative_time_in_usec_ = 0; |
| } |
| |
| inline void Start() { |
| CHECK(!IsStarted()); |
| gettimeofday(&start_time_, NULL); |
| } |
| |
| inline void Restart() { |
| Reset(); |
| Start(); |
| } |
| |
| inline void Stop() { |
| struct timeval end_time; |
| gettimeofday(&end_time, NULL); |
| CHECK(IsStarted()); |
| cumulative_time_in_usec_ += |
| (1000000 * (end_time.tv_sec - start_time_.tv_sec)) |
| + end_time.tv_usec - start_time_.tv_usec; |
| start_time_.tv_sec = 0; |
| start_time_.tv_usec = 0; |
| } |
| |
| inline int64_t GetInUsec() { |
| return cumulative_time_in_usec_; |
| } |
| |
| private: |
| inline bool IsStarted() { |
| return (start_time_.tv_usec > 0) || (start_time_.tv_sec > 0); |
| } |
| |
| struct timeval start_time_; |
| int64_t cumulative_time_in_usec_; |
| }; |
| #elif defined(HAVE_QUERYPERFORMANCECOUNTER) |
| class CycleTimer { |
| public: |
| inline CycleTimer() { |
| LARGE_INTEGER frequency; |
| QueryPerformanceFrequency(&frequency); // counts per second |
| usecs_per_count_ = 1000000.0 / static_cast<double>(frequency.QuadPart); |
| Reset(); |
| } |
| |
| inline void Reset() { |
| start_time_.QuadPart = 0; |
| cumulative_time_in_usec_ = 0; |
| } |
| |
| inline void Start() { |
| CHECK(!IsStarted()); |
| QueryPerformanceCounter(&start_time_); |
| } |
| |
| inline void Restart() { |
| Reset(); |
| Start(); |
| } |
| |
| inline void Stop() { |
| LARGE_INTEGER end_time; |
| QueryPerformanceCounter(&end_time); |
| CHECK(IsStarted()); |
| double count_diff = static_cast<double>( |
| end_time.QuadPart - start_time_.QuadPart); |
| cumulative_time_in_usec_ += |
| static_cast<int64_t>(count_diff * usecs_per_count_); |
| start_time_.QuadPart = 0; |
| } |
| |
| inline int64_t GetInUsec() { |
| return cumulative_time_in_usec_; |
| } |
| |
| private: |
| inline bool IsStarted() { |
| return start_time_.QuadPart > 0; |
| } |
| |
| LARGE_INTEGER start_time_; |
| int64_t cumulative_time_in_usec_; |
| double usecs_per_count_; |
| }; |
| #else |
| #error CycleTimer needs an implementation that does not use gettimeofday or QueryPerformanceCounter |
| #endif // HAVE_GETTIMEOFDAY |
| |
| // This function returns a pseudo-random value of type IntType between 0 and |
| // limit. It uses the standard rand() function to produce the value, and makes |
| // as many calls to rand() as needed to ensure that the values returned can fall |
| // within the full range specified. It is slow, so don't include calls to this |
| // function when calculating the execution time of tests. |
| // |
| template<typename IntType> |
| inline IntType PortableRandomInRange(IntType limit) { |
| uint64_t value = rand(); |
| double rand_limit = RAND_MAX; // The maximum possible value |
| while (rand_limit < limit) { |
| // value is multiplied by (RAND_MAX + 1) each iteration. This factor will be |
| // canceled out when we divide by rand_limit to get scaled_value, below. |
| value = (value * (static_cast<uint64_t>(RAND_MAX) + 1)) + rand(); |
| rand_limit = (rand_limit * (RAND_MAX + 1.0)) + RAND_MAX; |
| } |
| // Translate the random 64-bit integer into a floating-point value between |
| // 0.0 (inclusive) and 1.0 (inclusive). |
| const double scaled_value = value / rand_limit; |
| return static_cast<IntType>(limit * scaled_value); |
| } |
| |
| } // namespace open_vcdiff |
| |
| #endif // OPEN_VCDIFF_TESTING_H_ |