From 61cad69671be98b3f093982feecf816698fd5ea9 Mon Sep 17 00:00:00 2001 From: Sebastian Messmer Date: Wed, 16 May 2018 22:18:45 -0700 Subject: [PATCH] - Fix nanoseconds in clock_gettime for Mac - Hide clock_gettime in favor of cpputils::time::now() - Add test cases to cpputils::time::now() --- src/cpp-utils/CMakeLists.txt | 1 + .../system/{clock_gettime.h => time.cpp} | 27 ++- src/cpp-utils/system/time.h | 15 +- src/cryfs/filesystem/CryNode.cpp | 5 +- test/cpp-utils/CMakeLists.txt | 2 +- test/cpp-utils/system/ClockGetTimeTest.cpp | 40 ----- test/cpp-utils/system/TimeTest.cpp | 156 ++++++++++++++++++ 7 files changed, 183 insertions(+), 63 deletions(-) rename src/cpp-utils/system/{clock_gettime.h => time.cpp} (64%) delete mode 100644 test/cpp-utils/system/ClockGetTimeTest.cpp create mode 100644 test/cpp-utils/system/TimeTest.cpp diff --git a/src/cpp-utils/CMakeLists.txt b/src/cpp-utils/CMakeLists.txt index e2a46713..c16568e4 100644 --- a/src/cpp-utils/CMakeLists.txt +++ b/src/cpp-utils/CMakeLists.txt @@ -44,6 +44,7 @@ set(SOURCES system/homedir.cpp system/memory_nonwindows.cpp system/memory_windows.cpp + system/time.cpp ) add_library(${PROJECT_NAME} STATIC ${SOURCES}) diff --git a/src/cpp-utils/system/clock_gettime.h b/src/cpp-utils/system/time.cpp similarity index 64% rename from src/cpp-utils/system/clock_gettime.h rename to src/cpp-utils/system/time.cpp index 42ce5775..d5c8abe3 100644 --- a/src/cpp-utils/system/clock_gettime.h +++ b/src/cpp-utils/system/time.cpp @@ -1,24 +1,35 @@ -#pragma once -#ifndef MESSMER_CPPUTILS_SYSTEM_CLOCKGETTIME_H -#define MESSMER_CPPUTILS_SYSTEM_CLOCKGETTIME_H +#include "time.h" + +#if defined(__MACH__) && !defined(CLOCK_REALTIME) // Implements clock_gettime for Mac OS X before 10.12 (where it is not implemented by in the standard library) // Source: http://stackoverflow.com/a/9781275/829568 // Caution: The returned value is less precise than the returned value from a linux clock_gettime would be. - -#if defined(__MACH__) && !defined(CLOCK_REALTIME) #include #define CLOCK_REALTIME 0 -inline int clock_gettime(int /*clk_id*/, struct timespec *result) { +namespace { +int clock_gettime(int /*clk_id*/, struct timespec *result) { struct timeval now; int rv = gettimeofday(&now, nullptr); if (rv) { return rv; } result->tv_sec = now.tv_sec; - result->tv_nsec = now.tv_sec * 1000; + result->tv_nsec = now.tv_usec * 1000; return 0; } -#endif +} #endif + +namespace cpputils { +namespace time { + +struct timespec now() { + struct timespec now{}; + clock_gettime(CLOCK_REALTIME, &now); + return now; +} + +} +} diff --git a/src/cpp-utils/system/time.h b/src/cpp-utils/system/time.h index d129ad1c..b46d2d60 100644 --- a/src/cpp-utils/system/time.h +++ b/src/cpp-utils/system/time.h @@ -2,21 +2,14 @@ #ifndef MESSMER_CPPUTILS_SYSTEM_TIME_H #define MESSMER_CPPUTILS_SYSTEM_TIME_H -#include -#include "clock_gettime.h" - -// TODO Test +#include namespace cpputils { - namespace time { +namespace time { - inline timespec now() { - struct timespec now{}; - clock_gettime(CLOCK_REALTIME, &now); - return now; - } +timespec now(); - } +} } inline bool operator==(const timespec &lhs, const timespec &rhs) { diff --git a/src/cryfs/filesystem/CryNode.cpp b/src/cryfs/filesystem/CryNode.cpp index a9afd92c..eacf4d2c 100644 --- a/src/cryfs/filesystem/CryNode.cpp +++ b/src/cryfs/filesystem/CryNode.cpp @@ -7,7 +7,7 @@ #include "CryFile.h" #include #include -#include +#include #include #include @@ -170,8 +170,7 @@ void CryNode::stat(struct ::stat *result) const { result->st_size = fsblobstore::DirBlob::DIR_LSTAT_SIZE; //TODO If possible without performance loss, then for a directory, st_nlink should return number of dir entries (including "." and "..") result->st_nlink = 1; - struct timespec now{}; - clock_gettime(CLOCK_REALTIME, &now); + struct timespec now = cpputils::time::now(); result->st_atim = now; result->st_mtim = now; result->st_ctim = now; diff --git a/test/cpp-utils/CMakeLists.txt b/test/cpp-utils/CMakeLists.txt index 4faa8585..9d5023c8 100644 --- a/test/cpp-utils/CMakeLists.txt +++ b/test/cpp-utils/CMakeLists.txt @@ -45,7 +45,7 @@ set(SOURCES assert/backtrace_include_test.cpp assert/assert_include_test.cpp assert/assert_debug_test.cpp - system/ClockGetTimeTest.cpp + system/TimeTest.cpp system/MemoryTest.cpp system/HomedirTest.cpp ) diff --git a/test/cpp-utils/system/ClockGetTimeTest.cpp b/test/cpp-utils/system/ClockGetTimeTest.cpp deleted file mode 100644 index 41fecde1..00000000 --- a/test/cpp-utils/system/ClockGetTimeTest.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include -#include -#include -#include - -namespace { -struct timespec _gettime() { - struct timespec current_time; - int res = clock_gettime(CLOCK_REALTIME, ¤t_time); - EXPECT_EQ(0, res); - return current_time; -} - -uint64_t _to_nanos(struct timespec time) { - constexpr uint64_t nanos = UINT64_C(1000000000); - return time.tv_sec * nanos + time.tv_nsec; -} -} - -TEST(ClockGetTimeTest, DoesntCrash) { - _gettime(); -} - -TEST(ClockGetTimeTest, IsLaterThanYear2010) { - struct timespec current_time = _gettime(); - EXPECT_LT(1262304000, current_time.tv_sec); -} - -TEST(ClockGetTimeTest, IsNondecreasing) { - uint64_t time1 = _to_nanos(_gettime()); - uint64_t time2 = _to_nanos(_gettime()); - EXPECT_LE(time1, time2); -} - -TEST(ClockGetTimeTest, IsIncreasedAfterPause) { - uint64_t time1 = _to_nanos(_gettime()); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); - uint64_t time2 = _to_nanos(_gettime()); - EXPECT_LT(time1, time2); -} diff --git a/test/cpp-utils/system/TimeTest.cpp b/test/cpp-utils/system/TimeTest.cpp new file mode 100644 index 00000000..24b8deb4 --- /dev/null +++ b/test/cpp-utils/system/TimeTest.cpp @@ -0,0 +1,156 @@ +#include +#include +#include +#include + +using cpputils::time::now; + +namespace { + +uint64_t _to_nanos(struct timespec time) { + constexpr uint64_t nanos = UINT64_C(1000000000); + return time.tv_sec * nanos + time.tv_nsec; +} +} + +TEST(TimeTest, DoesntCrash) { + now(); +} + +TEST(TimeTest, IsLaterThanYear2010) { + struct timespec current_time = now(); + constexpr time_t year_2010_timestamp = 1262304000; + EXPECT_LT(year_2010_timestamp, current_time.tv_sec); +} + +TEST(TimeTest, IsNondecreasing) { + uint64_t time1 = _to_nanos(now()); + uint64_t time2 = _to_nanos(now()); + EXPECT_LE(time1, time2); +} + +TEST(TimeTest, IsIncreasedAfterPause) { + uint64_t time1 = _to_nanos(now()); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + uint64_t time2 = _to_nanos(now()); + EXPECT_LT(time1, time2); +} + +constexpr struct timespec time1 {1262304000, 000000000}; +constexpr struct timespec time2 {1262304000, 000000001}; +constexpr struct timespec time3 {1262304000, 100000000}; +constexpr struct timespec time4 {1262304001, 000000001}; + +TEST(TimeTest, LessThan) { + EXPECT_FALSE(time1 < time1); + EXPECT_TRUE(time1 < time2); + EXPECT_TRUE(time1 < time3); + EXPECT_TRUE(time1 < time4); + EXPECT_FALSE(time2 < time1); + EXPECT_FALSE(time2 < time2); + EXPECT_TRUE(time2 < time3); + EXPECT_TRUE(time2 < time4); + EXPECT_FALSE(time3 < time1); + EXPECT_FALSE(time3 < time2); + EXPECT_FALSE(time3 < time3); + EXPECT_TRUE(time3 < time4); + EXPECT_FALSE(time4 < time1); + EXPECT_FALSE(time4 < time2); + EXPECT_FALSE(time4 < time3); + EXPECT_FALSE(time4 < time4); +} + +TEST(TimeTest, GreaterThan) { + EXPECT_FALSE(time1 > time1); + EXPECT_FALSE(time1 > time2); + EXPECT_FALSE(time1 > time3); + EXPECT_FALSE(time1 > time4); + EXPECT_TRUE(time2 > time1); + EXPECT_FALSE(time2 > time2); + EXPECT_FALSE(time2 > time3); + EXPECT_FALSE(time2 > time4); + EXPECT_TRUE(time3 > time1); + EXPECT_TRUE(time3 > time2); + EXPECT_FALSE(time3 > time3); + EXPECT_FALSE(time3 > time4); + EXPECT_TRUE(time4 > time1); + EXPECT_TRUE(time4 > time2); + EXPECT_TRUE(time4 > time3); + EXPECT_FALSE(time4 > time4); +} + +TEST(TimeTest, LessEquals) { + EXPECT_TRUE(time1 <= time1); + EXPECT_TRUE(time1 <= time2); + EXPECT_TRUE(time1 <= time3); + EXPECT_TRUE(time1 <= time4); + EXPECT_FALSE(time2 <= time1); + EXPECT_TRUE(time2 <= time2); + EXPECT_TRUE(time2 <= time3); + EXPECT_TRUE(time2 <= time4); + EXPECT_FALSE(time3 <= time1); + EXPECT_FALSE(time3 <= time2); + EXPECT_TRUE(time3 <= time3); + EXPECT_TRUE(time3 <= time4); + EXPECT_FALSE(time4 <= time1); + EXPECT_FALSE(time4 <= time2); + EXPECT_FALSE(time4 <= time3); + EXPECT_TRUE(time4 <= time4); +} + +TEST(TimeTest, GreaterEquals) { + EXPECT_TRUE(time1 >= time1); + EXPECT_FALSE(time1 >= time2); + EXPECT_FALSE(time1 >= time3); + EXPECT_FALSE(time1 >= time4); + EXPECT_TRUE(time2 >= time1); + EXPECT_TRUE(time2 >= time2); + EXPECT_FALSE(time2 >= time3); + EXPECT_FALSE(time2 >= time4); + EXPECT_TRUE(time3 >= time1); + EXPECT_TRUE(time3 >= time2); + EXPECT_TRUE(time3 >= time3); + EXPECT_FALSE(time3 >= time4); + EXPECT_TRUE(time4 >= time1); + EXPECT_TRUE(time4 >= time2); + EXPECT_TRUE(time4 >= time3); + EXPECT_TRUE(time4 >= time4); +} + +TEST(TimeTest, Equals) { + EXPECT_TRUE(time1 == time1); + EXPECT_FALSE(time1 == time2); + EXPECT_FALSE(time1 == time3); + EXPECT_FALSE(time1 == time4); + EXPECT_FALSE(time2 == time1); + EXPECT_TRUE(time2 == time2); + EXPECT_FALSE(time2 == time3); + EXPECT_FALSE(time2 == time4); + EXPECT_FALSE(time3 == time1); + EXPECT_FALSE(time3 == time2); + EXPECT_TRUE(time3 == time3); + EXPECT_FALSE(time3 == time4); + EXPECT_FALSE(time4 == time1); + EXPECT_FALSE(time4 == time2); + EXPECT_FALSE(time4 == time3); + EXPECT_TRUE(time4 == time4); +} + +TEST(TimeTest, NotEquals) { + EXPECT_FALSE(time1 != time1); + EXPECT_TRUE(time1 != time2); + EXPECT_TRUE(time1 != time3); + EXPECT_TRUE(time1 != time4); + EXPECT_TRUE(time2 != time1); + EXPECT_FALSE(time2 != time2); + EXPECT_TRUE(time2 != time3); + EXPECT_TRUE(time2 != time4); + EXPECT_TRUE(time3 != time1); + EXPECT_TRUE(time3 != time2); + EXPECT_FALSE(time3 != time3); + EXPECT_TRUE(time3 != time4); + EXPECT_TRUE(time4 != time1); + EXPECT_TRUE(time4 != time2); + EXPECT_TRUE(time4 != time3); + EXPECT_FALSE(time4 != time4); +}