mirror of
https://github.com/wjwwood/serial.git
synced 2026-01-23 04:04:54 +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:
parent
13ac389cbe
commit
2070f8ab68
@ -1,13 +1,31 @@
|
|||||||
|
#include <chrono>
|
||||||
|
#include <sstream>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
#include "serial/impl/unix.h"
|
#include "serial/impl/unix.h"
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
using serial::MillisecondTimer;
|
using serial::MillisecondTimer;
|
||||||
|
|
||||||
namespace {
|
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.
|
* Do 100 trials of timing gaps between 0 and 19 milliseconds.
|
||||||
* Expect accuracy within one millisecond.
|
* Expect accuracy within one millisecond.
|
||||||
@ -15,48 +33,45 @@ namespace {
|
|||||||
TEST(timer_tests, short_intervals) {
|
TEST(timer_tests, short_intervals) {
|
||||||
for (int trial = 0; trial < 100; trial++)
|
for (int trial = 0; trial < 100; trial++)
|
||||||
{
|
{
|
||||||
uint32_t ms = rand() % 20;
|
int ms = rand() % 20;
|
||||||
MillisecondTimer mt(ms);
|
auto t1 = Clock::now();
|
||||||
usleep(1000 * ms);
|
MillisecondTimer mt(ms);
|
||||||
int32_t r = mt.remaining();
|
std::this_thread::sleep_for(std::chrono::milliseconds(ms));
|
||||||
|
int elapsed = as_milliseconds(Clock::now() - t1).count();
|
||||||
// 1ms slush, for the cost of calling usleep.
|
EXPECT_NEAR(ms - elapsed, mt.remaining(), 1);
|
||||||
EXPECT_NEAR(r+1, 0, 1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST(timer_tests, overlapping_long_intervals) {
|
TEST(timer_tests, overlapping_long_intervals) {
|
||||||
MillisecondTimer* timers[10];
|
|
||||||
|
|
||||||
// Experimentally determined. Corresponds to the extra time taken by the loops,
|
std::vector<test_timer> timers;
|
||||||
// the big usleep, and the test infrastructure itself.
|
|
||||||
const int slush_factor = 14;
|
|
||||||
|
|
||||||
// Set up the timers to each time one second, 1ms apart.
|
// Set up the timers to each time one second, 1 ms apart.
|
||||||
for (int t = 0; t < 10; t++)
|
while (timers.size() < 10) {
|
||||||
{
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||||
timers[t] = new MillisecondTimer(1000);
|
struct test_timer timer(1000); // 1 s
|
||||||
usleep(1000);
|
timers.push_back(timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check in on them after 500ms.
|
// Check in on them after 500 ms.
|
||||||
usleep(500000);
|
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||||
for (int t = 0; t < 10; t++)
|
for (auto& t: timers) {
|
||||||
{
|
auto elapsed = as_milliseconds(Clock::now() - t.start).count();
|
||||||
EXPECT_NEAR(timers[t]->remaining(), 500 - slush_factor + t, 5);
|
EXPECT_NEAR(1000 - elapsed, t.timer.remaining(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check in on them again after another 500ms and free them.
|
// Check in on them again after another 500 ms.
|
||||||
usleep(500000);
|
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||||
for (int t = 0; t < 10; t++)
|
for (auto& t: timers) {
|
||||||
{
|
auto elapsed = as_milliseconds(Clock::now() - t.start).count();
|
||||||
EXPECT_NEAR(timers[t]->remaining(), -slush_factor + t, 5);
|
EXPECT_NEAR(1000 - elapsed, t.timer.remaining(), 1);
|
||||||
delete timers[t];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
::testing::InitGoogleTest(&argc, argv);
|
::testing::InitGoogleTest(&argc, argv);
|
||||||
return RUN_ALL_TESTS();
|
return RUN_ALL_TESTS();
|
||||||
|
|||||||
@ -20,8 +20,6 @@ void loop()
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
#include <boost/bind.hpp>
|
|
||||||
|
|
||||||
// Use FRIEND_TEST... its not as nasty, thats what friends are for
|
// Use FRIEND_TEST... its not as nasty, thats what friends are for
|
||||||
// // OMG this is so nasty...
|
// // OMG this is so nasty...
|
||||||
// #define private public
|
// #define private public
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user