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 54namespace open_vcdiff { 55 56// Support for timing tests 57#if defined(HAVE_GETTIMEOFDAY) 58class 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) 104class 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// 162template<typename IntType> 163inline 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