diff options
Diffstat (limited to 'src/testing.h')
-rw-r--r-- | src/testing.h | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/src/testing.h b/src/testing.h new file mode 100644 index 0000000..3227fd8 --- /dev/null +++ b/src/testing.h @@ -0,0 +1,180 @@ +// 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_ |