1
0
mirror of https://github.com/wjwwood/serial.git synced 2026-01-22 19:54:57 +08:00

tests: Use elapsed time in timer tests (#232).

Compute actually elapsed time instead of assuming that usleep() sleeps
for exactly the right time, which isn't guaranteed.
This commit is contained in:
Alec Leamas 2020-09-27 12:09:17 +02:00
parent 13ac389cbe
commit 2070f8ab68
2 changed files with 45 additions and 32 deletions

View File

@ -1,13 +1,31 @@
#include <chrono>
#include <sstream>
#include <thread>
#include "gtest/gtest.h"
#include "serial/impl/unix.h"
#include <unistd.h>
#include <stdlib.h>
using serial::MillisecondTimer;
namespace {
typedef std::chrono::high_resolution_clock Clock;
template <typename T>
std::chrono::milliseconds as_milliseconds(T duration)
{
return std::chrono::duration_cast<std::chrono::milliseconds>(duration);
}
struct test_timer {
MillisecondTimer timer;
std::chrono::time_point<Clock> start;
test_timer(unsigned value): start(Clock::now()), timer(value) {}
};
/**
* Do 100 trials of timing gaps between 0 and 19 milliseconds.
* Expect accuracy within one millisecond.
@ -15,48 +33,45 @@ namespace {
TEST(timer_tests, short_intervals) {
for (int trial = 0; trial < 100; trial++)
{
uint32_t ms = rand() % 20;
MillisecondTimer mt(ms);
usleep(1000 * ms);
int32_t r = mt.remaining();
// 1ms slush, for the cost of calling usleep.
EXPECT_NEAR(r+1, 0, 1);
int ms = rand() % 20;
auto t1 = Clock::now();
MillisecondTimer mt(ms);
std::this_thread::sleep_for(std::chrono::milliseconds(ms));
int elapsed = as_milliseconds(Clock::now() - t1).count();
EXPECT_NEAR(ms - elapsed, mt.remaining(), 1);
}
}
TEST(timer_tests, overlapping_long_intervals) {
MillisecondTimer* timers[10];
// Experimentally determined. Corresponds to the extra time taken by the loops,
// the big usleep, and the test infrastructure itself.
const int slush_factor = 14;
std::vector<test_timer> timers;
// Set up the timers to each time one second, 1ms apart.
for (int t = 0; t < 10; t++)
{
timers[t] = new MillisecondTimer(1000);
usleep(1000);
// Set up the timers to each time one second, 1 ms apart.
while (timers.size() < 10) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
struct test_timer timer(1000); // 1 s
timers.push_back(timer);
}
// Check in on them after 500ms.
usleep(500000);
for (int t = 0; t < 10; t++)
{
EXPECT_NEAR(timers[t]->remaining(), 500 - slush_factor + t, 5);
// Check in on them after 500 ms.
std::this_thread::sleep_for(std::chrono::milliseconds(500));
for (auto& t: timers) {
auto elapsed = as_milliseconds(Clock::now() - t.start).count();
EXPECT_NEAR(1000 - elapsed, t.timer.remaining(), 1);
}
// Check in on them again after another 500ms and free them.
usleep(500000);
for (int t = 0; t < 10; t++)
{
EXPECT_NEAR(timers[t]->remaining(), -slush_factor + t, 5);
delete timers[t];
// Check in on them again after another 500 ms.
std::this_thread::sleep_for(std::chrono::milliseconds(500));
for (auto& t: timers) {
auto elapsed = as_milliseconds(Clock::now() - t.start).count();
EXPECT_NEAR(1000 - elapsed, t.timer.remaining(), 1);
}
}
} // namespace
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();

View File

@ -20,8 +20,6 @@ void loop()
#include <string>
#include "gtest/gtest.h"
#include <boost/bind.hpp>
// Use FRIEND_TEST... its not as nasty, thats what friends are for
// // OMG this is so nasty...
// #define private public