Compare commits

...

10 Commits

Author SHA1 Message Date
Yabin Cui
0fdcdd0067 Merge "Fix flaky test time.timer_settime_0." into lollipop-mr1-cts-dev 2015-08-11 18:41:17 +00:00
Yabin Cui
bf572d91b5 Fix flaky test time.timer_settime_0.
It fixes the problem reported in https://code.google.com/p/android/issues/detail?id=182395.

Change-Id: Ie16aa04095dac08a62dd0d4c50e763b36526624c
2015-08-11 11:25:02 -07:00
Yabin Cui
0f455612d3 Merge "Fix flaky test of timer_create_multiple in L." into lollipop-mr1-cts-dev 2015-06-19 18:00:53 +00:00
Yabin Cui
410c1adf5f Fix flaky test of timer_create_multiple in L.
Bug: 20677618
Change-Id: I0cb5faf77edce042b10611543180f3e2e73d3d05
2015-06-18 16:19:02 -07:00
Yabin Cui
ea248d9ca8 Merge "Make sys_resource test more robust." into lollipop-cts-dev
automerge: 492a0bf

* commit '492a0bf212973baa1c33d584d57e75395774447f':
  Make sys_resource test more robust.
2015-06-02 22:03:23 +00:00
Yabin Cui
492a0bf212 Merge "Make sys_resource test more robust." into lollipop-cts-dev 2015-06-02 22:02:29 +00:00
Yabin Cui
e7ece90b50 Make sys_resource test more robust.
Bug: 19482626

"ulimit -c xxx" command may run before bionic-unit-tests.
Make sure sys_resource test fails gently in that case.

Change-Id: Ic3b5ed8b20acba56df8c5ef082c88e5050e761aa
(cherry picked from commit 4853f40f3f)
2015-06-02 14:40:26 -07:00
Yabin Cui
473d96c0a8 Merge "Fix timer flaky test in lollipop-mr1-cts-dev." into lollipop-mr1-cts-dev 2015-05-09 00:07:45 +00:00
Yabin Cui
5c0996a969 Fix timer flaky test in lollipop-mr1-cts-dev.
It is partically cherry-pick from https://android-review.googlesource.com/#/c/123410/.
And as lollipop-mr1-cts-dev still uses stlport, <stdatomic.h> is used instead of <atomic>.

Bug: 20677618
Change-Id: I952a6fd074facc4227c955fecf3ecbfbbaec4193
2015-05-08 13:12:01 -07:00
Christopher Ferris
3da136aa47 Modify test to avoid race condition.
There is a possible race if a timer is set to trigger at nearly the same
time as it is set. Since nobody uses the timers like this, modify the test
so this doesn't happen. The race that this can provoke has been fixed in
aosp.

Bug: 19423618
Change-Id: I21084c99da5ae46f404936d673dae6bad7c82caa
2015-02-18 17:45:50 -08:00
2 changed files with 153 additions and 126 deletions

View File

@@ -14,10 +14,10 @@
* limitations under the License. * limitations under the License.
*/ */
#include <gtest/gtest.h>
#include <sys/resource.h> #include <sys/resource.h>
#include <gtest/gtest.h>
#if defined(__GLIBC__) #if defined(__GLIBC__)
/* The host glibc we're currently building with doesn't have prlimit64 yet. */ /* The host glibc we're currently building with doesn't have prlimit64 yet. */
static int prlimit64(pid_t, int resource, const struct rlimit64* new_limit, struct rlimit64* old_limit) { static int prlimit64(pid_t, int resource, const struct rlimit64* new_limit, struct rlimit64* old_limit) {
@@ -29,7 +29,7 @@ static int prlimit64(pid_t, int resource, const struct rlimit64* new_limit, stru
} }
#endif #endif
TEST(sys_resource, smoke) { TEST(sys_resource, rlimit_struct_size) {
#if defined(__LP64__) || defined(__GLIBC__) #if defined(__LP64__) || defined(__GLIBC__)
ASSERT_EQ(sizeof(rlimit), sizeof(rlimit64)); ASSERT_EQ(sizeof(rlimit), sizeof(rlimit64));
ASSERT_EQ(8U, sizeof(rlim_t)); ASSERT_EQ(8U, sizeof(rlim_t));
@@ -37,51 +37,75 @@ TEST(sys_resource, smoke) {
ASSERT_NE(sizeof(rlimit), sizeof(rlimit64)); ASSERT_NE(sizeof(rlimit), sizeof(rlimit64));
ASSERT_EQ(4U, sizeof(rlim_t)); ASSERT_EQ(4U, sizeof(rlim_t));
#endif #endif
}
// Read with getrlimit, getrlimit64, and prlimit64. class SysResourceTest : public ::testing::Test {
// (prlimit is prlimit64 on LP64 and unimplemented on 32-bit.) protected:
rlimit l32; virtual void SetUp() {
rlimit64 l64; ASSERT_EQ(0, getrlimit(RLIMIT_CORE, &l32_));
rlimit64 pr_l64; ASSERT_EQ(0, getrlimit64(RLIMIT_CORE, &l64_));
ASSERT_EQ(0, getrlimit(RLIMIT_CORE, &l32)); ASSERT_EQ(0, prlimit64(0, RLIMIT_CORE, NULL, &pr_l64_));
ASSERT_EQ(0, getrlimit64(RLIMIT_CORE, &l64));
ASSERT_EQ(0, prlimit64(0, RLIMIT_CORE, NULL, &pr_l64));
ASSERT_EQ(l64.rlim_cur, l32.rlim_cur);
ASSERT_EQ(l64.rlim_cur, pr_l64.rlim_cur);
ASSERT_EQ(l64.rlim_max, pr_l64.rlim_max);
if (l64.rlim_max == RLIM64_INFINITY) {
ASSERT_EQ(RLIM_INFINITY, l32.rlim_max);
} else {
ASSERT_EQ(l64.rlim_max, l32.rlim_max);
} }
// Write with setrlimit and read back with everything. void CheckResourceLimits();
l32.rlim_cur = 123;
ASSERT_EQ(0, setrlimit(RLIMIT_CORE, &l32));
ASSERT_EQ(0, getrlimit(RLIMIT_CORE, &l32));
ASSERT_EQ(0, getrlimit64(RLIMIT_CORE, &l64));
ASSERT_EQ(0, prlimit64(0, RLIMIT_CORE, NULL, &pr_l64));
ASSERT_EQ(123U, l32.rlim_cur);
ASSERT_EQ(l64.rlim_cur, l32.rlim_cur);
ASSERT_EQ(l64.rlim_cur, pr_l64.rlim_cur);
// Write with setrlimit64 and read back with everything. protected:
l64.rlim_cur = 456; rlimit l32_;
ASSERT_EQ(0, setrlimit64(RLIMIT_CORE, &l64)); rlimit64 l64_;
ASSERT_EQ(0, getrlimit(RLIMIT_CORE, &l32)); rlimit64 pr_l64_;
ASSERT_EQ(0, getrlimit64(RLIMIT_CORE, &l64)); };
ASSERT_EQ(0, prlimit64(0, RLIMIT_CORE, NULL, &pr_l64));
ASSERT_EQ(456U, l32.rlim_cur);
ASSERT_EQ(l64.rlim_cur, l32.rlim_cur);
ASSERT_EQ(l64.rlim_cur, pr_l64.rlim_cur);
// Write with prlimit64 and read back with everything. void SysResourceTest::CheckResourceLimits() {
l64.rlim_cur = 789; ASSERT_EQ(0, getrlimit(RLIMIT_CORE, &l32_));
ASSERT_EQ(0, prlimit64(0, RLIMIT_CORE, &l64, NULL)); ASSERT_EQ(0, getrlimit64(RLIMIT_CORE, &l64_));
ASSERT_EQ(0, getrlimit(RLIMIT_CORE, &l32)); ASSERT_EQ(0, prlimit64(0, RLIMIT_CORE, NULL, &pr_l64_));
ASSERT_EQ(0, getrlimit64(RLIMIT_CORE, &l64)); ASSERT_EQ(l64_.rlim_cur, pr_l64_.rlim_cur);
ASSERT_EQ(0, prlimit64(0, RLIMIT_CORE, NULL, &pr_l64)); if (l64_.rlim_cur == RLIM64_INFINITY) {
ASSERT_EQ(789U, l32.rlim_cur); ASSERT_EQ(RLIM_INFINITY, l32_.rlim_cur);
ASSERT_EQ(l64.rlim_cur, l32.rlim_cur); } else {
ASSERT_EQ(l64.rlim_cur, pr_l64.rlim_cur); ASSERT_EQ(l64_.rlim_cur, l32_.rlim_cur);
}
ASSERT_EQ(l64_.rlim_max, pr_l64_.rlim_max);
if (l64_.rlim_max == RLIM64_INFINITY) {
ASSERT_EQ(RLIM_INFINITY, l32_.rlim_max);
} else {
ASSERT_EQ(l64_.rlim_max, l32_.rlim_max);
}
}
// Force rlim_max to be bigger than a constant so we can continue following test.
// Change resource limit setting with "ulimit -Hc" in the shell if this test fails.
TEST_F(SysResourceTest, RLIMIT_CORE_rlim_max_not_zero) {
ASSERT_TRUE(l32_.rlim_max == RLIM_INFINITY || l32_.rlim_max >= 456U) <<
"RLIMIT_CORE rlim_max = " << l32_.rlim_max;
}
TEST_F(SysResourceTest, get_resource_limit_equal) {
CheckResourceLimits();
}
TEST_F(SysResourceTest, setrlimit) {
l32_.rlim_cur = 123U;
ASSERT_EQ(0, setrlimit(RLIMIT_CORE, &l32_));
CheckResourceLimits();
ASSERT_EQ(123U, l32_.rlim_cur);
}
TEST_F(SysResourceTest, setrlimit64) {
l64_.rlim_cur = 456U;
ASSERT_EQ(0, setrlimit64(RLIMIT_CORE, &l64_));
CheckResourceLimits();
ASSERT_EQ(456U, l64_.rlim_cur);
}
TEST_F(SysResourceTest, prlimit64) {
pr_l64_.rlim_cur = pr_l64_.rlim_max;
ASSERT_EQ(0, prlimit64(0, RLIMIT_CORE, &pr_l64_, NULL));
CheckResourceLimits();
ASSERT_EQ(pr_l64_.rlim_max, pr_l64_.rlim_cur);
}
TEST_F(SysResourceTest, prlimit) {
// prlimit is prlimit64 on LP64 and unimplemented on 32-bit. So we only test prlimit64.
} }

View File

@@ -21,6 +21,7 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <pthread.h> #include <pthread.h>
#include <signal.h> #include <signal.h>
#include <stdatomic.h>
#include <sys/syscall.h> #include <sys/syscall.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/wait.h> #include <sys/wait.h>
@@ -139,7 +140,7 @@ void SetTime(timer_t t, time_t value_s, time_t value_ns, time_t interval_s, time
ts.it_value.tv_nsec = value_ns; ts.it_value.tv_nsec = value_ns;
ts.it_interval.tv_sec = interval_s; ts.it_interval.tv_sec = interval_s;
ts.it_interval.tv_nsec = interval_ns; ts.it_interval.tv_nsec = interval_ns;
ASSERT_EQ(0, timer_settime(t, TIMER_ABSTIME, &ts, NULL)); ASSERT_EQ(0, timer_settime(t, 0, &ts, NULL));
} }
static void NoOpNotifyFunction(sigval_t) { static void NoOpNotifyFunction(sigval_t) {
@@ -171,7 +172,7 @@ TEST(time, timer_create) {
ASSERT_EQ(0, timer_delete(timer_id)); 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) { static void timer_create_SIGEV_SIGNAL_signal_handler(int signal_number) {
++timer_create_SIGEV_SIGNAL_signal_handler_invocation_count; ++timer_create_SIGEV_SIGNAL_signal_handler_invocation_count;
ASSERT_EQ(SIGUSR1, signal_number); ASSERT_EQ(SIGUSR1, signal_number);
@@ -186,6 +187,7 @@ TEST(time, timer_create_SIGEV_SIGNAL) {
timer_t timer_id; timer_t timer_id;
ASSERT_EQ(0, timer_create(CLOCK_MONOTONIC, &se, &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); ScopedSignalHandler ssh(SIGUSR1, timer_create_SIGEV_SIGNAL_signal_handler);
ASSERT_EQ(0, timer_create_SIGEV_SIGNAL_signal_handler_invocation_count); ASSERT_EQ(0, timer_create_SIGEV_SIGNAL_signal_handler_invocation_count);
@@ -202,25 +204,27 @@ TEST(time, timer_create_SIGEV_SIGNAL) {
} }
struct Counter { struct Counter {
volatile int value; private:
atomic_int value;
timer_t timer_id; timer_t timer_id;
sigevent_t se; sigevent_t se;
bool timer_valid; 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() { void Create() {
ASSERT_FALSE(timer_valid); ASSERT_FALSE(timer_valid);
ASSERT_EQ(0, timer_create(CLOCK_REALTIME, &se, &timer_id)); ASSERT_EQ(0, timer_create(CLOCK_REALTIME, &se, &timer_id));
timer_valid = true; 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() { void DeleteTimer() {
ASSERT_TRUE(timer_valid); ASSERT_TRUE(timer_valid);
ASSERT_EQ(0, timer_delete(timer_id)); 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) { 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); ::SetTime(timer_id, value_s, value_ns, interval_s, interval_ns);
} }
bool ValueUpdated() { bool ValueUpdated() {
volatile int current_value = value; int current_value = atomic_load(&value);
time_t start = time(NULL); 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) { static void CountNotifyFunction(sigval_t value) {
Counter* cd = reinterpret_cast<Counter*>(value.sival_ptr); Counter* cd = reinterpret_cast<Counter*>(value.sival_ptr);
++cd->value; atomic_fetch_add(&cd->value, 1);
} }
static void CountAndDisarmNotifyFunction(sigval_t value) { static void CountAndDisarmNotifyFunction(sigval_t value) {
Counter* cd = reinterpret_cast<Counter*>(value.sival_ptr); 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. // Setting the initial expiration time to 0 disarms the timer.
cd->SetTime(0, 0, 1, 0); cd->SetTime(0, 0, 1, 0);
@@ -261,30 +269,29 @@ struct Counter {
TEST(time, timer_settime_0) { TEST(time, timer_settime_0) {
Counter counter(Counter::CountAndDisarmNotifyFunction); Counter counter(Counter::CountAndDisarmNotifyFunction);
ASSERT_TRUE(counter.timer_valid); ASSERT_EQ(0, counter.Value());
ASSERT_EQ(0, counter.value); counter.SetTime(0, 500000000, 1, 0);
sleep(1);
counter.SetTime(0, 1, 1, 0);
usleep(500000);
// The count should just be 1 because we disarmed the timer the first time it fired. // 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) { TEST(time, timer_settime_repeats) {
Counter counter(Counter::CountNotifyFunction); 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); counter.SetTime(0, 1, 0, 10);
ASSERT_TRUE(counter.ValueUpdated()); ASSERT_TRUE(counter.ValueUpdated());
ASSERT_TRUE(counter.ValueUpdated()); 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) { static void timer_create_NULL_signal_handler(int signal_number) {
++timer_create_NULL_signal_handler_invocation_count; ++timer_create_NULL_signal_handler_invocation_count;
ASSERT_EQ(SIGALRM, signal_number); ASSERT_EQ(SIGALRM, signal_number);
@@ -295,6 +302,7 @@ TEST(time, timer_create_NULL) {
timer_t timer_id; timer_t timer_id;
ASSERT_EQ(0, timer_create(CLOCK_MONOTONIC, NULL, &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); ScopedSignalHandler ssh(SIGALRM, timer_create_NULL_signal_handler);
ASSERT_EQ(0, timer_create_NULL_signal_handler_invocation_count); ASSERT_EQ(0, timer_create_NULL_signal_handler_invocation_count);
@@ -341,22 +349,59 @@ TEST(time, timer_delete_multiple) {
TEST(time, timer_create_multiple) { TEST(time, timer_create_multiple) {
Counter counter1(Counter::CountNotifyFunction); Counter counter1(Counter::CountNotifyFunction);
ASSERT_TRUE(counter1.timer_valid);
Counter counter2(Counter::CountNotifyFunction); Counter counter2(Counter::CountNotifyFunction);
ASSERT_TRUE(counter2.timer_valid);
Counter counter3(Counter::CountNotifyFunction); Counter counter3(Counter::CountNotifyFunction);
ASSERT_TRUE(counter3.timer_valid);
ASSERT_EQ(0, counter1.value); ASSERT_EQ(0, counter1.Value());
ASSERT_EQ(0, counter2.value); ASSERT_EQ(0, counter2.Value());
ASSERT_EQ(0, counter3.value); ASSERT_EQ(0, counter3.Value());
counter2.SetTime(0, 1, 0, 0); counter2.SetTime(0, 500000000, 0, 0);
sleep(1);
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); usleep(500000);
EXPECT_EQ(0, counter1.value); // Verify the counter has not been incremented.
EXPECT_EQ(1, counter2.value); ASSERT_EQ(value, counter.Value());
EXPECT_EQ(0, counter3.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 { struct TimerDeleteData {
@@ -386,11 +431,11 @@ TEST(time, timer_delete_from_timer_thread) {
ASSERT_EQ(0, timer_create(CLOCK_REALTIME, &se, &tdd.timer_id)); ASSERT_EQ(0, timer_create(CLOCK_REALTIME, &se, &tdd.timer_id));
itimerspec ts; itimerspec ts;
ts.it_value.tv_sec = 0; ts.it_value.tv_sec = 1;
ts.it_value.tv_nsec = 100; ts.it_value.tv_nsec = 0;
ts.it_interval.tv_sec = 0; ts.it_interval.tv_sec = 0;
ts.it_interval.tv_nsec = 0; ts.it_interval.tv_nsec = 0;
ASSERT_EQ(0, timer_settime(tdd.timer_id, TIMER_ABSTIME, &ts, NULL)); ASSERT_EQ(0, timer_settime(tdd.timer_id, 0, &ts, NULL));
time_t cur_time = time(NULL); time_t cur_time = time(NULL);
while (!tdd.complete && (time(NULL) - cur_time) < 5); while (!tdd.complete && (time(NULL) - cur_time) < 5);
@@ -424,45 +469,3 @@ TEST(time, clock_gettime) {
ASSERT_EQ(0, ts2.tv_sec); ASSERT_EQ(0, ts2.tv_sec);
ASSERT_LT(ts2.tv_nsec, 1000000); 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);
}