1 // Copyright 2008 Google Inc. 2 // Authors: Craig Silverstein, Lincoln Smith 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 16 #ifndef OPEN_VCDIFF_TESTING_H_ 17 #define OPEN_VCDIFF_TESTING_H_ 18 19 #include <config.h> 20 #include <assert.h> 21 #include <stdint.h> // int64_t 22 #include <stdlib.h> // rand 23 #include <time.h> // gettimeofday 24 #include "gtest/gtest.h" 25 26 #ifdef HAVE_SYS_TIME_H 27 #include <sys/time.h> // struct timeval 28 #endif // HAVE_SYS_TIME_H 29 30 #ifdef HAVE_WINDOWS_H 31 #include <windows.h> // QueryPerformanceCounter 32 #endif // HAVE_WINDOWS_H 33 34 // CHECK is used for assertions that verify the consistency of the test itself, 35 // rather than correctness of the code that is being tested. 36 // 37 // It is better to use a preprocessor macro for CHECK 38 // than an inline function, because assert() may report 39 // the source file and line where the failure occurred. 40 // 41 // Putting parentheses around the macro arguments 42 // (e.g. "assert((X) == (Y))") would be good practice 43 // but would produce error messages that are inconsistent 44 // with those expected in the unit tests. 45 46 #define CHECK(CONDITION) assert(CONDITION) 47 #define CHECK_EQ(X, Y) assert(X == Y) 48 #define CHECK_NE(X, Y) assert(X != Y) 49 #define CHECK_GE(X, Y) assert(X >= Y) 50 #define CHECK_GT(X, Y) assert(X > Y) 51 #define CHECK_LE(X, Y) assert(X <= Y) 52 #define CHECK_LT(X, Y) assert(X < Y) 53 54 namespace open_vcdiff { 55 56 // Support for timing tests 57 #if defined(HAVE_GETTIMEOFDAY) 58 class CycleTimer { 59 public: 60 inline CycleTimer() { 61 Reset(); 62 } 63 64 inline void Reset() { 65 start_time_.tv_sec = 0; 66 start_time_.tv_usec = 0; 67 cumulative_time_in_usec_ = 0; 68 } 69 70 inline void Start() { 71 CHECK(!IsStarted()); 72 gettimeofday(&start_time_, NULL); 73 } 74 75 inline void Restart() { 76 Reset(); 77 Start(); 78 } 79 80 inline void Stop() { 81 struct timeval end_time; 82 gettimeofday(&end_time, NULL); 83 CHECK(IsStarted()); 84 cumulative_time_in_usec_ += 85 (1000000 * (end_time.tv_sec - start_time_.tv_sec)) 86 + end_time.tv_usec - start_time_.tv_usec; 87 start_time_.tv_sec = 0; 88 start_time_.tv_usec = 0; 89 } 90 91 inline int64_t GetInUsec() { 92 return cumulative_time_in_usec_; 93 } 94 95 private: 96 inline bool IsStarted() { 97 return (start_time_.tv_usec > 0) || (start_time_.tv_sec > 0); 98 } 99 100 struct timeval start_time_; 101 int64_t cumulative_time_in_usec_; 102 }; 103 #elif defined(HAVE_QUERYPERFORMANCECOUNTER) 104 class CycleTimer { 105 public: 106 inline CycleTimer() { 107 LARGE_INTEGER frequency; 108 QueryPerformanceFrequency(&frequency); // counts per second 109 usecs_per_count_ = 1000000.0 / static_cast<double>(frequency.QuadPart); 110 Reset(); 111 } 112 113 inline void Reset() { 114 start_time_.QuadPart = 0; 115 cumulative_time_in_usec_ = 0; 116 } 117 118 inline void Start() { 119 CHECK(!IsStarted()); 120 QueryPerformanceCounter(&start_time_); 121 } 122 123 inline void Restart() { 124 Reset(); 125 Start(); 126 } 127 128 inline void Stop() { 129 LARGE_INTEGER end_time; 130 QueryPerformanceCounter(&end_time); 131 CHECK(IsStarted()); 132 double count_diff = static_cast<double>( 133 end_time.QuadPart - start_time_.QuadPart); 134 cumulative_time_in_usec_ += 135 static_cast<int64_t>(count_diff * usecs_per_count_); 136 start_time_.QuadPart = 0; 137 } 138 139 inline int64_t GetInUsec() { 140 return cumulative_time_in_usec_; 141 } 142 143 private: 144 inline bool IsStarted() { 145 return start_time_.QuadPart > 0; 146 } 147 148 LARGE_INTEGER start_time_; 149 int64_t cumulative_time_in_usec_; 150 double usecs_per_count_; 151 }; 152 #else 153 #error CycleTimer needs an implementation that does not use gettimeofday or QueryPerformanceCounter 154 #endif // HAVE_GETTIMEOFDAY 155 156 // This function returns a pseudo-random value of type IntType between 0 and 157 // limit. It uses the standard rand() function to produce the value, and makes 158 // as many calls to rand() as needed to ensure that the values returned can fall 159 // within the full range specified. It is slow, so don't include calls to this 160 // function when calculating the execution time of tests. 161 // 162 template<typename IntType> 163 inline IntType PortableRandomInRange(IntType limit) { 164 uint64_t value = rand(); 165 double rand_limit = RAND_MAX; // The maximum possible value 166 while (rand_limit < limit) { 167 // value is multiplied by (RAND_MAX + 1) each iteration. This factor will be 168 // canceled out when we divide by rand_limit to get scaled_value, below. 169 value = (value * (static_cast<uint64_t>(RAND_MAX) + 1)) + rand(); 170 rand_limit = (rand_limit * (RAND_MAX + 1.0)) + RAND_MAX; 171 } 172 // Translate the random 64-bit integer into a floating-point value between 173 // 0.0 (inclusive) and 1.0 (inclusive). 174 const double scaled_value = value / rand_limit; 175 return static_cast<IntType>(limit * scaled_value); 176 } 177 178 } // namespace open_vcdiff 179 180 #endif // OPEN_VCDIFF_TESTING_H_ 181