mirror of
https://github.com/thunderbrewhq/bc.git
synced 2025-12-12 01:52:30 +00:00
feat(time): implement timekeeping utilities (#1)
* feat(bc): implement timekeeping * fix(time): Milliseconds and Seconds return storage should be 64-bit * fix(time): nsec should be explicitly cast to uint32 * test(time): rudimentary tests for timekeeping * fix(time): check properly for timestamp + nsec overflows in MakeTime and BreakTime * fix(time): include UNIX time headers on Mac, too * test(time): test can tolerate system hiccups
This commit is contained in:
parent
d31a66b9ca
commit
6b1ba4cdcf
9 changed files with 567 additions and 1 deletions
|
|
@ -1,7 +1,8 @@
|
|||
file(GLOB BC_SOURCES
|
||||
"*.cpp"
|
||||
"lock/*.cpp"
|
||||
"system/**.cpp"
|
||||
"time/*.cpp"
|
||||
"system/*.cpp"
|
||||
)
|
||||
|
||||
add_library(bc STATIC
|
||||
|
|
|
|||
6
bc/Time.hpp
Normal file
6
bc/Time.hpp
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef BC_TIME_HPP
|
||||
#define BC_TIME_HPP
|
||||
|
||||
#include "bc/time/Time.hpp"
|
||||
|
||||
#endif
|
||||
177
bc/system/System_Time.cpp
Normal file
177
bc/system/System_Time.cpp
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
#include "bc/system/System_Time.hpp"
|
||||
#include "bc/time/Time.hpp"
|
||||
#include "bc/time/TimeConst.hpp"
|
||||
|
||||
#if defined(WHOA_SYSTEM_MAC)
|
||||
#include <mach/mach_time.h>
|
||||
#endif
|
||||
|
||||
#if defined(WHOA_SYSTEM_WIN)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#if defined(WHOA_SYSTEM_MAC) || defined(WHOA_SYSTEM_LINUX)
|
||||
#include <ctime>
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include "bc/Debug.hpp"
|
||||
|
||||
namespace Blizzard {
|
||||
namespace System_Time {
|
||||
|
||||
// Globals
|
||||
|
||||
// Stores the earliest TSC value
|
||||
static uint64_t s_absBegin = 0;
|
||||
|
||||
// Stores the number of nanoseconds since Jan 1, 2000 00:00 GMT at the raw clock moment of s_absBegin.
|
||||
static Time::Timestamp s_gmBegin = 0;
|
||||
|
||||
// timeScales can be multiplied against number of ticks since s_absBegin to get
|
||||
// meaningful durations in the corresponding format
|
||||
double timeScaleNanoseconds = 0.0;
|
||||
double timeScaleMicroseconds = 0.0;
|
||||
double timeScaleMilliseconds = 0.0;
|
||||
double timeScaleSeconds = 0.0;
|
||||
|
||||
// Functions
|
||||
|
||||
bool ReadTSC(uint64_t& counter) {
|
||||
#if defined(WHOA_SYSTEM_WIN)
|
||||
LARGE_INTEGER li;
|
||||
auto ok = QueryPerformanceCounter(&li);
|
||||
|
||||
if (ok) {
|
||||
counter = static_cast<uint64_t>(li.QuadPart);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
#elif defined(WHOA_SYSTEM_MAC)
|
||||
counter = mach_absolute_time();
|
||||
return true;
|
||||
#elif defined(WHOA_SYSTEM_LINUX)
|
||||
struct timespec ts;
|
||||
auto status = clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
|
||||
if (status == 0) {
|
||||
counter = (static_cast<uint64_t>(ts.tv_sec) * TimeConst::TimestampsPerSecond) + ts.tv_nsec;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Returns a clock moment, relative to s_absBegin;
|
||||
uint64_t QueryClockMoment() {
|
||||
uint64_t counter = 0;
|
||||
ReadTSC(counter);
|
||||
|
||||
return counter - s_absBegin;
|
||||
}
|
||||
|
||||
// Returns Y2K-GMT nanosecond time.
|
||||
Time::Timestamp Now() {
|
||||
CheckInit();
|
||||
|
||||
// Record clock moment
|
||||
auto moment = QueryClockMoment();
|
||||
|
||||
// Add moment to GMT
|
||||
return s_gmBegin + static_cast<Time::Timestamp>(timeScaleNanoseconds * static_cast<double>(moment));
|
||||
}
|
||||
|
||||
// this func is run on first use
|
||||
void TimeInit() {
|
||||
// Record absolute clock beginning moment in raw CPU time
|
||||
ReadTSC(s_absBegin);
|
||||
BLIZZARD_ASSERT(s_absBegin != 0);
|
||||
|
||||
// Look at system clock's GMT/UTC time as nanoseconds
|
||||
// This associates a point in GMT with the more precise measurements obtained from reading the timestamp counter
|
||||
#if defined(WHOA_SYSTEM_MAC) || defined(WHOA_SYSTEM_LINUX)
|
||||
// Unix system clock
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, nullptr);
|
||||
|
||||
s_gmBegin = Time::FromUnixTime(tv.tv_sec) + (tv.tv_usec * 1000ULL);
|
||||
#elif defined(WHOA_SYSTEM_WIN)
|
||||
// Read Win32 system time
|
||||
FILETIME ft;
|
||||
GetSystemTimeAsFileTime(&ft);
|
||||
|
||||
// Convert time into Blizzard timestamp
|
||||
ULARGE_INTEGER ul = {};
|
||||
ul.HighPart = ft.dwHighDateTime;
|
||||
ul.LowPart = ft.dwLowDateTime;
|
||||
s_gmBegin = Time::FromWinFiletime(ul.QuadPart);
|
||||
#endif
|
||||
|
||||
// Attempt to figure out the scale of TSC durations in real-time
|
||||
#if defined(WHOA_SYSTEM_WIN)
|
||||
// Read frequency with Win32 API
|
||||
LARGE_INTEGER freq;
|
||||
QueryPerformanceFrequency(&freq);
|
||||
|
||||
auto ticksPerSecond = static_cast<uint64_t>(freq.QuadPart);
|
||||
auto ticksPerNanosecond = static_cast<double>(ticksPerSecond) / static_cast<double>(TimeConst::TimestampsPerSecond);
|
||||
|
||||
timeScaleNanoseconds = 1.0 / ticksPerNanosecond;
|
||||
#elif defined(WHOA_SYSTEM_MAC)
|
||||
// Ask Mach what the base time parameters are
|
||||
mach_timebase_info_data_t timebase;
|
||||
mach_timebase_info(&timebase);
|
||||
|
||||
timeScaleNanoseconds = static_cast<double>(timebase.numer) / static_cast<double>(timebase.denom);
|
||||
#elif defined(WHOA_SYSTEM_LINUX)
|
||||
// clock_gettime is already attuned to timestamp counter frequency
|
||||
timeScaleNanoseconds = 1.0;
|
||||
#endif
|
||||
timeScaleMicroseconds = timeScaleNanoseconds / 1000.0;
|
||||
timeScaleMilliseconds = timeScaleNanoseconds / 1000000.0;
|
||||
timeScaleSeconds = timeScaleNanoseconds / 1000000000.0;
|
||||
}
|
||||
|
||||
void CheckInit() {
|
||||
if (s_absBegin == 0) {
|
||||
TimeInit();
|
||||
}
|
||||
}
|
||||
|
||||
// Wall clock functions. The values returned are of an arbitrary epoch.
|
||||
// The only guarantee is that the values returned will increase monotonically.
|
||||
|
||||
// Get wall clock time in nanoseconds
|
||||
uint64_t Nanoseconds() {
|
||||
CheckInit();
|
||||
uint64_t tsc;
|
||||
ReadTSC(tsc);
|
||||
return static_cast<uint64_t>(static_cast<double>(tsc) * timeScaleNanoseconds);
|
||||
}
|
||||
|
||||
// Get wall clock time in microseconds
|
||||
uint64_t Microseconds() {
|
||||
CheckInit();
|
||||
uint64_t tsc;
|
||||
ReadTSC(tsc);
|
||||
return static_cast<uint64_t>(static_cast<double>(tsc) * timeScaleMicroseconds);
|
||||
}
|
||||
|
||||
// Get wall clock time in milliseconds
|
||||
uint64_t Milliseconds() {
|
||||
CheckInit();
|
||||
uint64_t tsc;
|
||||
ReadTSC(tsc);
|
||||
return static_cast<uint64_t>(static_cast<double>(tsc) * timeScaleMilliseconds);
|
||||
}
|
||||
|
||||
// Get wall clock time in seconds
|
||||
uint64_t Seconds() {
|
||||
CheckInit();
|
||||
uint64_t tsc;
|
||||
ReadTSC(tsc);
|
||||
return static_cast<uint64_t>(static_cast<double>(tsc) * timeScaleSeconds);
|
||||
}
|
||||
|
||||
} // namespace System_Time
|
||||
} // namespace Blizzard
|
||||
25
bc/system/System_Time.hpp
Normal file
25
bc/system/System_Time.hpp
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#ifndef BC_SYSTEM_TIME_HPP
|
||||
#define BC_SYSTEM_TIME_HPP
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "bc/time/Types.hpp"
|
||||
|
||||
namespace Blizzard {
|
||||
namespace System_Time {
|
||||
|
||||
Time::Timestamp Now();
|
||||
|
||||
void CheckInit();
|
||||
|
||||
uint64_t QueryClockMoment();
|
||||
|
||||
uint64_t Nanoseconds();
|
||||
uint64_t Microseconds();
|
||||
uint64_t Milliseconds();
|
||||
uint64_t Seconds();
|
||||
|
||||
} // namespace System_Time
|
||||
} // namespace Blizzard
|
||||
|
||||
#endif
|
||||
230
bc/time/Time.cpp
Normal file
230
bc/time/Time.cpp
Normal file
|
|
@ -0,0 +1,230 @@
|
|||
#include "bc/time/Time.hpp"
|
||||
#include "bc/time/TimeConst.hpp"
|
||||
#include "bc/system/System_Time.hpp"
|
||||
|
||||
#if defined(WHOA_SYSTEM_WIN)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#if defined(WHOA_SYSTEM_MAC) || defined(WHOA_SYSTEM_LINUX)
|
||||
#include <ctime>
|
||||
#endif
|
||||
|
||||
#include <limits>
|
||||
|
||||
namespace Blizzard {
|
||||
namespace Time {
|
||||
|
||||
// Global variables
|
||||
|
||||
// Jan = [1],
|
||||
// Feb = [2] and so on
|
||||
static uint32_t s_monthDays[14] = {
|
||||
0x41F00000, // Invalid?
|
||||
0,
|
||||
31,
|
||||
59,
|
||||
90,
|
||||
120,
|
||||
151,
|
||||
182,
|
||||
212,
|
||||
243,
|
||||
273,
|
||||
304,
|
||||
334,
|
||||
365
|
||||
};
|
||||
|
||||
// Functions
|
||||
|
||||
// Convert Blizzard timestamp to UNIX seconds
|
||||
int32_t ToUnixTime(Timestamp timestamp) {
|
||||
// Can't return time prior to 1901
|
||||
// Return minimum time (1901) in case of underflow
|
||||
if (timestamp < -3094168447999999999LL) {
|
||||
return std::numeric_limits<int32_t>::min();
|
||||
}
|
||||
|
||||
// 32-bit UNIX sec time suffers from the Year 2038 problem
|
||||
// Return maximum time (2038) in case of overflow
|
||||
if (timestamp >= 1200798847000000000LL) {
|
||||
return std::numeric_limits<int32_t>::max();
|
||||
}
|
||||
|
||||
// Go back 30 years
|
||||
auto y1970 = timestamp + 946684800000000000LL;
|
||||
// Convert nanoseconds to seconds
|
||||
return static_cast<uint32_t>(y1970 / TimeConst::TimestampsPerSecond);
|
||||
}
|
||||
|
||||
// TODO: look into making this Y2038-aware.
|
||||
// Convert UNIX seconds into Blizzard timestamp
|
||||
Timestamp FromUnixTime(int32_t unixTime) {
|
||||
// Convert seconds to nanoseconds
|
||||
auto unixnano = int64_t(unixTime) * TimeConst::TimestampsPerSecond;
|
||||
// Move forward 30 years
|
||||
auto y2k = unixnano - 946684800000000000LL;
|
||||
|
||||
return static_cast<Timestamp>(y2k);
|
||||
}
|
||||
|
||||
// Win32 FILETIME to y2k
|
||||
Timestamp FromWinFiletime(uint64_t winTime) {
|
||||
if (winTime < 33677863631452242ULL) {
|
||||
return std::numeric_limits<Timestamp>::min();
|
||||
}
|
||||
|
||||
if (winTime >= 218145301729837567ULL) {
|
||||
return std::numeric_limits<Timestamp>::max();;
|
||||
}
|
||||
|
||||
// 1601 (Gregorian) 100-nsec
|
||||
auto gregorian = static_cast<int64_t>(winTime);
|
||||
// Convert filetime from 1601 epoch to 2000 epoch.
|
||||
auto y2k = gregorian - TimeConst::WinFiletimeY2kDifference;
|
||||
// Convert 100-nsec intervals into nsec intervals
|
||||
return static_cast<Time::Timestamp>(y2k * 100LL);
|
||||
}
|
||||
|
||||
uint64_t ToWinFiletime(Timestamp y2k) {
|
||||
return (y2k + TimeConst::WinFiletimeY2kDifference) / 100ULL;
|
||||
}
|
||||
|
||||
int32_t GetTimeElapsed(uint32_t start, uint32_t end) {
|
||||
if (end < start) {
|
||||
return ~start + end;
|
||||
}
|
||||
return end - start;
|
||||
}
|
||||
|
||||
Timestamp GetTimestamp() {
|
||||
return System_Time::Now();
|
||||
}
|
||||
|
||||
uint64_t Nanoseconds() {
|
||||
return System_Time::Nanoseconds();
|
||||
}
|
||||
|
||||
uint64_t Microseconds() {
|
||||
return System_Time::Microseconds();
|
||||
}
|
||||
|
||||
uint64_t Milliseconds() {
|
||||
return System_Time::Milliseconds();
|
||||
}
|
||||
|
||||
uint64_t Seconds() {
|
||||
return System_Time::Seconds();
|
||||
}
|
||||
|
||||
Timestamp MakeTime(const TimeRec& date) {
|
||||
Timestamp timestamp = 0;
|
||||
|
||||
#if defined(WHOA_SYSTEM_WIN)
|
||||
// Win32 implementation
|
||||
FILETIME fileTime = {};
|
||||
SYSTEMTIME systemTime = {};
|
||||
|
||||
systemTime.wYear = static_cast<WORD>(date.year);
|
||||
systemTime.wMonth = static_cast<WORD>(date.month);
|
||||
systemTime.wDay = static_cast<WORD>(date.day);
|
||||
systemTime.wHour = static_cast<WORD>(date.hour);
|
||||
systemTime.wMinute = static_cast<WORD>(date.min);
|
||||
systemTime.wSecond = static_cast<WORD>(date.sec);
|
||||
systemTime.wMilliseconds = 0;
|
||||
|
||||
::SystemTimeToFileTime(&systemTime, &fileTime);
|
||||
|
||||
ULARGE_INTEGER ul = {};
|
||||
ul.HighPart = fileTime.dwHighDateTime;
|
||||
ul.LowPart = fileTime.dwLowDateTime;
|
||||
|
||||
timestamp = FromWinFiletime(ul.QuadPart);
|
||||
#endif
|
||||
|
||||
#if defined(WHOA_SYSTEM_MAC) || defined(WHOA_SYSTEM_LINUX)
|
||||
// UNIX implementation
|
||||
struct tm t;
|
||||
|
||||
t.tm_year = date.year - 1900;
|
||||
t.tm_mon = date.month - 1;
|
||||
t.tm_mday = date.day;
|
||||
t.tm_hour = date.hour;
|
||||
t.tm_min = date.min;
|
||||
t.tm_sec = date.sec;
|
||||
|
||||
// Convert date into UNIX timestamp
|
||||
auto unixTime = ::timegm(&t);
|
||||
timestamp = FromUnixTime(unixTime);
|
||||
#endif
|
||||
// Add nsec to result
|
||||
auto nsec = date.nsec;
|
||||
|
||||
// overflow check
|
||||
if ((timestamp + static_cast<Timestamp>(nsec)) < timestamp) {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
timestamp += nsec;
|
||||
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
void BreakTime(Timestamp timestamp, TimeRec& date) {
|
||||
auto mod = (timestamp % TimeConst::TimestampsPerSecond);
|
||||
|
||||
auto nsec = static_cast<uint32_t>(mod + TimeConst::TimestampsPerSecond);
|
||||
|
||||
if (mod < std::numeric_limits<uint32_t>::max()) {
|
||||
nsec = mod;
|
||||
}
|
||||
#if defined(WHOA_SYSTEM_WIN)
|
||||
// Win32 implementation
|
||||
ULARGE_INTEGER ul = {};
|
||||
ul.QuadPart = ToWinFiletime(timestamp);
|
||||
|
||||
FILETIME fileTime = {};
|
||||
fileTime.dwHighDateTime = ul.HighPart;
|
||||
fileTime.dwLowDateTime = ul.LowPart;
|
||||
SYSTEMTIME systemTime = {};
|
||||
::FileTimeToSystemTime(&fileTime, &systemTime);
|
||||
|
||||
date.day = static_cast<uint32_t>(systemTime.wDay);
|
||||
date.hour = static_cast<uint32_t>(systemTime.wHour);
|
||||
date.min = static_cast<uint32_t>(systemTime.wMinute);
|
||||
date.sec = static_cast<uint32_t>(systemTime.wSecond);
|
||||
date.wday = static_cast<uint32_t>(systemTime.wDayOfWeek);
|
||||
date.year = static_cast<uint32_t>(systemTime.wYear);
|
||||
date.nsec = static_cast<uint32_t>(nsec);
|
||||
|
||||
bool leapYear = (date.year % 400 == 0) || (date.year % 100 != 0 && ((systemTime.wYear & 3) == 0));
|
||||
|
||||
auto yearDay = s_monthDays[date.month] + -1 + static_cast<uint32_t>(systemTime.wDay);
|
||||
date.yday = yearDay;
|
||||
if (leapYear && date.month > 2) {
|
||||
date.yday++;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(WHOA_SYSTEM_MAC) || defined(WHOA_SYSTEM_LINUX)
|
||||
// UNIX implementation
|
||||
auto unixTime = static_cast<time_t>(ToUnixTime(timestamp));
|
||||
|
||||
struct tm t;
|
||||
::gmtime_r(&unixTime, &t);
|
||||
|
||||
date.year = t.tm_year + 1900;
|
||||
date.month = t.tm_mon + 1;
|
||||
date.day = t.tm_mday;
|
||||
date.hour = t.tm_hour;
|
||||
date.min = t.tm_min;
|
||||
date.sec = t.tm_sec;
|
||||
date.nsec = nsec;
|
||||
date.wday = t.tm_wday;
|
||||
date.yday = t.tm_yday;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace Time
|
||||
} // namespace Blizzard
|
||||
39
bc/time/Time.hpp
Normal file
39
bc/time/Time.hpp
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
#ifndef BC_TIME_TIME_HPP
|
||||
#define BC_TIME_TIME_HPP
|
||||
|
||||
#include "bc/time/Types.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace Blizzard {
|
||||
namespace Time {
|
||||
|
||||
int32_t ToUnixTime(Timestamp timestamp);
|
||||
|
||||
Timestamp FromUnixTime(int32_t unixTime);
|
||||
|
||||
// Win32 FILETIME to y2k
|
||||
Timestamp FromWinFiletime(uint64_t winTime);
|
||||
|
||||
uint64_t ToWinFiletime(Timestamp y2k);
|
||||
|
||||
Timestamp GetTimestamp();
|
||||
|
||||
int32_t GetTimeElapsed(uint32_t start, uint32_t end);
|
||||
|
||||
Timestamp MakeTime(const TimeRec& date);
|
||||
|
||||
void BreakTime(Timestamp timestamp, TimeRec& date);
|
||||
|
||||
uint64_t Nanoseconds();
|
||||
|
||||
uint64_t Microseconds();
|
||||
|
||||
uint64_t Milliseconds();
|
||||
|
||||
uint64_t Seconds();
|
||||
|
||||
} // namespace Time
|
||||
} // namespace Blizzard
|
||||
|
||||
#endif
|
||||
19
bc/time/TimeConst.hpp
Normal file
19
bc/time/TimeConst.hpp
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#ifndef BC_TIME_TIME_CONST_HPP
|
||||
#define BC_TIME_TIME_CONST_HPP
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace TimeConst {
|
||||
|
||||
// The number of nanoseconds in a second
|
||||
constexpr int64_t TimestampsPerSecond = 1000000000ULL;
|
||||
|
||||
// amount of win32 filetime units in a second
|
||||
constexpr int64_t WinUnitsPerSecond = (TimestampsPerSecond / 100ULL);
|
||||
|
||||
// the FILETIME value needed to move from 1601 epoch to the Year 2000 epoch that Blizzard prefers
|
||||
constexpr int64_t WinFiletimeY2kDifference = 125911584000000000ULL;
|
||||
|
||||
} // namespace TimeConst
|
||||
|
||||
#endif
|
||||
28
bc/time/Types.hpp
Normal file
28
bc/time/Types.hpp
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
#ifndef BC_TIME_TYPES_HPP
|
||||
#define BC_TIME_TYPES_HPP
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace Blizzard {
|
||||
namespace Time {
|
||||
|
||||
// Timestamp - nanoseconds starting from 0 == January 1 2000 00:00:00 GMT.
|
||||
typedef int64_t Timestamp;
|
||||
|
||||
class TimeRec {
|
||||
public:
|
||||
int32_t year;
|
||||
uint32_t month;
|
||||
uint32_t day;
|
||||
uint32_t hour;
|
||||
uint32_t min;
|
||||
uint32_t sec;
|
||||
uint32_t nsec;
|
||||
uint32_t wday;
|
||||
uint32_t yday;
|
||||
};
|
||||
|
||||
} // namespace Time
|
||||
} // namespace Blizzard
|
||||
|
||||
#endif
|
||||
41
test/Time.cpp
Normal file
41
test/Time.cpp
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
#include "bc/Time.hpp"
|
||||
#include "bc/time/TimeConst.hpp"
|
||||
#include "bc/Process.hpp"
|
||||
#include "test/Test.hpp"
|
||||
|
||||
TEST_CASE("Blizzard::Time::FromUnixTime", "[time]") {
|
||||
SECTION("convert zero Blizzard time from UNIX timestamp of Sat Jan 01 2000 00:00:00 GMT") {
|
||||
auto stamp = Blizzard::Time::FromUnixTime(946684800);
|
||||
REQUIRE(stamp == 0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Blizzard::Time::ToUnixTime", "[time]") {
|
||||
SECTION("convert zero Blizzard timestamp to Unix timestamp of Sat Jan 01 2000 00:00:00 GMT+0000") {
|
||||
auto stamp = Blizzard::Time::ToUnixTime(0);
|
||||
REQUIRE(stamp == 946684800);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Blizzard::Time::GetTimestamp", "[time]") {
|
||||
SECTION("Get timestamp") {
|
||||
auto now = Blizzard::Time::GetTimestamp();
|
||||
REQUIRE(now > 0);
|
||||
}
|
||||
|
||||
SECTION("Timestamp increases after 200 ms") {
|
||||
auto t1 = Blizzard::Time::GetTimestamp();
|
||||
Blizzard::Process::Sleep(200);
|
||||
auto t2 = Blizzard::Time::GetTimestamp();
|
||||
auto delta = t2 - t1;
|
||||
REQUIRE(t2 > t1);
|
||||
REQUIRE(delta >= 100000000);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Blizzard::Time::Nanoseconds", "[time]") {
|
||||
SECTION("Read wall clock") {
|
||||
auto wctime = Blizzard::Time::Nanoseconds();
|
||||
REQUIRE(wctime > 0);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue