Compare commits

...

9 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
2 changed files with 150 additions and 123 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 {
@@ -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);
}