Merge "Fix timer flaky test in lollipop-mr1-cts-dev." into lollipop-mr1-cts-dev
This commit is contained in:
commit
473d96c0a8
1 changed files with 77 additions and 74 deletions
|
@ -21,6 +21,7 @@
|
|||
#include <gtest/gtest.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdatomic.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
@ -171,7 +172,7 @@ TEST(time, timer_create) {
|
|||
ASSERT_EQ(0, timer_delete(timer_id));
|
||||
}
|
||||
|
||||
static int timer_create_SIGEV_SIGNAL_signal_handler_invocation_count = 0;
|
||||
static int timer_create_SIGEV_SIGNAL_signal_handler_invocation_count;
|
||||
static void timer_create_SIGEV_SIGNAL_signal_handler(int signal_number) {
|
||||
++timer_create_SIGEV_SIGNAL_signal_handler_invocation_count;
|
||||
ASSERT_EQ(SIGUSR1, signal_number);
|
||||
|
@ -186,6 +187,7 @@ TEST(time, timer_create_SIGEV_SIGNAL) {
|
|||
timer_t timer_id;
|
||||
ASSERT_EQ(0, timer_create(CLOCK_MONOTONIC, &se, &timer_id));
|
||||
|
||||
timer_create_SIGEV_SIGNAL_signal_handler_invocation_count = 0;
|
||||
ScopedSignalHandler ssh(SIGUSR1, timer_create_SIGEV_SIGNAL_signal_handler);
|
||||
|
||||
ASSERT_EQ(0, timer_create_SIGEV_SIGNAL_signal_handler_invocation_count);
|
||||
|
@ -202,25 +204,27 @@ TEST(time, timer_create_SIGEV_SIGNAL) {
|
|||
}
|
||||
|
||||
struct Counter {
|
||||
volatile int value;
|
||||
private:
|
||||
atomic_int value;
|
||||
timer_t timer_id;
|
||||
sigevent_t se;
|
||||
bool timer_valid;
|
||||
|
||||
Counter(void (*fn)(sigval_t)) : value(0), timer_valid(false) {
|
||||
memset(&se, 0, sizeof(se));
|
||||
se.sigev_notify = SIGEV_THREAD;
|
||||
se.sigev_notify_function = fn;
|
||||
se.sigev_value.sival_ptr = this;
|
||||
Create();
|
||||
}
|
||||
|
||||
void Create() {
|
||||
ASSERT_FALSE(timer_valid);
|
||||
ASSERT_EQ(0, timer_create(CLOCK_REALTIME, &se, &timer_id));
|
||||
timer_valid = true;
|
||||
}
|
||||
|
||||
public:
|
||||
Counter(void (*fn)(sigval_t)) : value(ATOMIC_VAR_INIT(0)), timer_valid(false) {
|
||||
memset(&se, 0, sizeof(se));
|
||||
se.sigev_notify = SIGEV_THREAD;
|
||||
se.sigev_notify_function = fn;
|
||||
se.sigev_value.sival_ptr = this;
|
||||
Create();
|
||||
}
|
||||
|
||||
void DeleteTimer() {
|
||||
ASSERT_TRUE(timer_valid);
|
||||
ASSERT_EQ(0, timer_delete(timer_id));
|
||||
|
@ -233,26 +237,30 @@ struct Counter {
|
|||
}
|
||||
}
|
||||
|
||||
int Value() {
|
||||
return atomic_load(&value);
|
||||
}
|
||||
|
||||
void SetTime(time_t value_s, time_t value_ns, time_t interval_s, time_t interval_ns) {
|
||||
::SetTime(timer_id, value_s, value_ns, interval_s, interval_ns);
|
||||
}
|
||||
|
||||
bool ValueUpdated() {
|
||||
volatile int current_value = value;
|
||||
int current_value = atomic_load(&value);
|
||||
time_t start = time(NULL);
|
||||
while (current_value == value && (time(NULL) - start) < 5) {
|
||||
while (current_value == atomic_load(&value) && (time(NULL) - start) < 5) {
|
||||
}
|
||||
return current_value != value;
|
||||
return current_value != atomic_load(&value);
|
||||
}
|
||||
|
||||
static void CountNotifyFunction(sigval_t value) {
|
||||
Counter* cd = reinterpret_cast<Counter*>(value.sival_ptr);
|
||||
++cd->value;
|
||||
atomic_fetch_add(&cd->value, 1);
|
||||
}
|
||||
|
||||
static void CountAndDisarmNotifyFunction(sigval_t value) {
|
||||
Counter* cd = reinterpret_cast<Counter*>(value.sival_ptr);
|
||||
++cd->value;
|
||||
atomic_fetch_add(&cd->value, 1);
|
||||
|
||||
// Setting the initial expiration time to 0 disarms the timer.
|
||||
cd->SetTime(0, 0, 1, 0);
|
||||
|
@ -261,30 +269,29 @@ struct Counter {
|
|||
|
||||
TEST(time, timer_settime_0) {
|
||||
Counter counter(Counter::CountAndDisarmNotifyFunction);
|
||||
ASSERT_TRUE(counter.timer_valid);
|
||||
|
||||
ASSERT_EQ(0, counter.value);
|
||||
ASSERT_EQ(0, counter.Value());
|
||||
|
||||
counter.SetTime(0, 1, 1, 0);
|
||||
usleep(500000);
|
||||
|
||||
// The count should just be 1 because we disarmed the timer the first time it fired.
|
||||
ASSERT_EQ(1, counter.value);
|
||||
ASSERT_EQ(1, counter.Value());
|
||||
}
|
||||
|
||||
TEST(time, timer_settime_repeats) {
|
||||
Counter counter(Counter::CountNotifyFunction);
|
||||
ASSERT_TRUE(counter.timer_valid);
|
||||
|
||||
ASSERT_EQ(0, counter.value);
|
||||
ASSERT_EQ(0, counter.Value());
|
||||
|
||||
counter.SetTime(0, 1, 0, 10);
|
||||
ASSERT_TRUE(counter.ValueUpdated());
|
||||
ASSERT_TRUE(counter.ValueUpdated());
|
||||
ASSERT_TRUE(counter.ValueUpdated());
|
||||
counter.DeleteTimer();
|
||||
// Add a sleep as other threads may be calling the callback function when the timer is deleted.
|
||||
usleep(500000);
|
||||
}
|
||||
|
||||
static int timer_create_NULL_signal_handler_invocation_count = 0;
|
||||
static int timer_create_NULL_signal_handler_invocation_count;
|
||||
static void timer_create_NULL_signal_handler(int signal_number) {
|
||||
++timer_create_NULL_signal_handler_invocation_count;
|
||||
ASSERT_EQ(SIGALRM, signal_number);
|
||||
|
@ -295,6 +302,7 @@ TEST(time, timer_create_NULL) {
|
|||
timer_t timer_id;
|
||||
ASSERT_EQ(0, timer_create(CLOCK_MONOTONIC, NULL, &timer_id));
|
||||
|
||||
timer_create_NULL_signal_handler_invocation_count = 0;
|
||||
ScopedSignalHandler ssh(SIGALRM, timer_create_NULL_signal_handler);
|
||||
|
||||
ASSERT_EQ(0, timer_create_NULL_signal_handler_invocation_count);
|
||||
|
@ -341,22 +349,59 @@ TEST(time, timer_delete_multiple) {
|
|||
|
||||
TEST(time, timer_create_multiple) {
|
||||
Counter counter1(Counter::CountNotifyFunction);
|
||||
ASSERT_TRUE(counter1.timer_valid);
|
||||
Counter counter2(Counter::CountNotifyFunction);
|
||||
ASSERT_TRUE(counter2.timer_valid);
|
||||
Counter counter3(Counter::CountNotifyFunction);
|
||||
ASSERT_TRUE(counter3.timer_valid);
|
||||
|
||||
ASSERT_EQ(0, counter1.value);
|
||||
ASSERT_EQ(0, counter2.value);
|
||||
ASSERT_EQ(0, counter3.value);
|
||||
ASSERT_EQ(0, counter1.Value());
|
||||
ASSERT_EQ(0, counter2.Value());
|
||||
ASSERT_EQ(0, counter3.Value());
|
||||
|
||||
counter2.SetTime(0, 1, 0, 0);
|
||||
usleep(500000);
|
||||
|
||||
EXPECT_EQ(0, counter1.value);
|
||||
EXPECT_EQ(1, counter2.value);
|
||||
EXPECT_EQ(0, counter3.value);
|
||||
EXPECT_EQ(0, counter1.Value());
|
||||
EXPECT_EQ(1, counter2.Value());
|
||||
EXPECT_EQ(0, counter3.Value());
|
||||
}
|
||||
|
||||
// Test to verify that disarming a repeatable timer disables the callbacks.
|
||||
TEST(time, timer_disarm_terminates) {
|
||||
Counter counter(Counter::CountNotifyFunction);
|
||||
ASSERT_EQ(0, counter.Value());
|
||||
|
||||
counter.SetTime(0, 1, 0, 1);
|
||||
ASSERT_TRUE(counter.ValueUpdated());
|
||||
ASSERT_TRUE(counter.ValueUpdated());
|
||||
ASSERT_TRUE(counter.ValueUpdated());
|
||||
|
||||
counter.SetTime(0, 0, 0, 0);
|
||||
// Add a sleep as the kernel may have pending events when the timer is disarmed.
|
||||
usleep(500000);
|
||||
int value = counter.Value();
|
||||
usleep(500000);
|
||||
|
||||
// Verify the counter has not been incremented.
|
||||
ASSERT_EQ(value, counter.Value());
|
||||
}
|
||||
|
||||
// Test to verify that deleting a repeatable timer disables the callbacks.
|
||||
TEST(time, timer_delete_terminates) {
|
||||
Counter counter(Counter::CountNotifyFunction);
|
||||
ASSERT_EQ(0, counter.Value());
|
||||
|
||||
counter.SetTime(0, 1, 0, 1);
|
||||
ASSERT_TRUE(counter.ValueUpdated());
|
||||
ASSERT_TRUE(counter.ValueUpdated());
|
||||
ASSERT_TRUE(counter.ValueUpdated());
|
||||
|
||||
counter.DeleteTimer();
|
||||
// Add a sleep as other threads may be calling the callback function when the timer is deleted.
|
||||
usleep(500000);
|
||||
int value = counter.Value();
|
||||
usleep(500000);
|
||||
|
||||
// Verify the counter has not been incremented.
|
||||
ASSERT_EQ(value, counter.Value());
|
||||
}
|
||||
|
||||
struct TimerDeleteData {
|
||||
|
@ -424,45 +469,3 @@ TEST(time, clock_gettime) {
|
|||
ASSERT_EQ(0, ts2.tv_sec);
|
||||
ASSERT_LT(ts2.tv_nsec, 1000000);
|
||||
}
|
||||
|
||||
// Test to verify that disarming a repeatable timer disables the
|
||||
// callbacks.
|
||||
TEST(time, timer_disarm_terminates) {
|
||||
Counter counter(Counter::CountNotifyFunction);
|
||||
ASSERT_TRUE(counter.timer_valid);
|
||||
|
||||
ASSERT_EQ(0, counter.value);
|
||||
|
||||
counter.SetTime(0, 1, 0, 1);
|
||||
ASSERT_TRUE(counter.ValueUpdated());
|
||||
ASSERT_TRUE(counter.ValueUpdated());
|
||||
ASSERT_TRUE(counter.ValueUpdated());
|
||||
|
||||
counter.SetTime(0, 0, 1, 0);
|
||||
volatile int value = counter.value;
|
||||
usleep(500000);
|
||||
|
||||
// Verify the counter has not been incremented.
|
||||
ASSERT_EQ(value, counter.value);
|
||||
}
|
||||
|
||||
// Test to verify that deleting a repeatable timer disables the
|
||||
// callbacks.
|
||||
TEST(time, timer_delete_terminates) {
|
||||
Counter counter(Counter::CountNotifyFunction);
|
||||
ASSERT_TRUE(counter.timer_valid);
|
||||
|
||||
ASSERT_EQ(0, counter.value);
|
||||
|
||||
counter.SetTime(0, 1, 0, 1);
|
||||
ASSERT_TRUE(counter.ValueUpdated());
|
||||
ASSERT_TRUE(counter.ValueUpdated());
|
||||
ASSERT_TRUE(counter.ValueUpdated());
|
||||
|
||||
counter.DeleteTimer();
|
||||
volatile int value = counter.value;
|
||||
usleep(500000);
|
||||
|
||||
// Verify the counter has not been incremented.
|
||||
ASSERT_EQ(value, counter.value);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue