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:
CycleTimer()60 inline CycleTimer() {
61 Reset();
62 }
63
Reset()64 inline void Reset() {
65 start_time_.tv_sec = 0;
66 start_time_.tv_usec = 0;
67 cumulative_time_in_usec_ = 0;
68 }
69
Start()70 inline void Start() {
71 CHECK(!IsStarted());
72 gettimeofday(&start_time_, NULL);
73 }
74
Restart()75 inline void Restart() {
76 Reset();
77 Start();
78 }
79
Stop()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
GetInUsec()91 inline int64_t GetInUsec() {
92 return cumulative_time_in_usec_;
93 }
94
95 private:
IsStarted()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>
PortableRandomInRange(IntType limit)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