Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f2afa6b8 authored by Lais Andrade's avatar Lais Andrade
Browse files

Fix VibratorCallbackSchedulerTest flakiness

Add test timeout to wait for scheduler to trigger callbacks before
failing.

Also update scheduled callback durations to reduce flakiness.

Bug: 293623689
Test: atest VibratorCallbackSchedulerTest
Change-Id: I49a9cae3f1622a4902ae9e56b37892060eba5c91
parent 9bd0c2ba
Loading
Loading
Loading
Loading
+25 −17
Original line number Diff line number Diff line
@@ -38,6 +38,9 @@ using namespace testing;

// -------------------------------------------------------------------------------------------------

// Delay allowed for the scheduler to process callbacks during this test.
static const auto TEST_TIMEOUT = 50ms;

class VibratorCallbackSchedulerTest : public Test {
public:
    void SetUp() override {
@@ -67,46 +70,51 @@ protected:
        return std::vector<int32_t>(mExpiredCallbacks);
    }

    bool waitForCallbacks(uint32_t callbackCount, milliseconds timeout) {
        time_point<steady_clock> expiration = steady_clock::now() + timeout;
    int32_t waitForCallbacks(int32_t callbackCount, milliseconds timeout) {
        time_point<steady_clock> expiration = steady_clock::now() + timeout + TEST_TIMEOUT;
        int32_t expiredCallbackCount = 0;
        while (steady_clock::now() < expiration) {
            std::lock_guard<std::mutex> lock(mMutex);
            if (callbackCount <= mExpiredCallbacks.size()) {
                return true;
            expiredCallbackCount = mExpiredCallbacks.size();
            if (callbackCount <= expiredCallbackCount) {
                return expiredCallbackCount;
            }
            mCondition.wait_until(mMutex, expiration);
        }
        return false;
        return expiredCallbackCount;
    }
};

// -------------------------------------------------------------------------------------------------

TEST_F(VibratorCallbackSchedulerTest, TestScheduleRunsOnlyAfterDelay) {
    mScheduler->schedule(createCallback(1), 15ms);
    time_point<steady_clock> startTime = steady_clock::now();
    mScheduler->schedule(createCallback(1), 50ms);

    // Not triggered before delay.
    ASSERT_FALSE(waitForCallbacks(1, 10ms));
    ASSERT_TRUE(getExpiredCallbacks().empty());
    ASSERT_EQ(1, waitForCallbacks(1, 50ms));
    time_point<steady_clock> callbackTime = steady_clock::now();

    ASSERT_TRUE(waitForCallbacks(1, 10ms));
    // Callback happened at least 50ms after the beginning of the test.
    ASSERT_TRUE(startTime + 50ms <= callbackTime);
    ASSERT_THAT(getExpiredCallbacks(), ElementsAre(1));
}

TEST_F(VibratorCallbackSchedulerTest, TestScheduleMultipleCallbacksRunsInDelayOrder) {
    mScheduler->schedule(createCallback(1), 10ms);
    mScheduler->schedule(createCallback(2), 5ms);
    mScheduler->schedule(createCallback(3), 1ms);
    // Schedule first callbacks long enough that all 3 will be scheduled together and run in order.
    mScheduler->schedule(createCallback(1), 50ms);
    mScheduler->schedule(createCallback(2), 40ms);
    mScheduler->schedule(createCallback(3), 10ms);

    ASSERT_TRUE(waitForCallbacks(3, 15ms));
    ASSERT_EQ(3, waitForCallbacks(3, 50ms));
    ASSERT_THAT(getExpiredCallbacks(), ElementsAre(3, 2, 1));
}

TEST_F(VibratorCallbackSchedulerTest, TestDestructorDropsPendingCallbacksAndKillsThread) {
    mScheduler->schedule(createCallback(1), 5ms);
    // Schedule callback long enough that scheduler will be destroyed while it's still scheduled.
    mScheduler->schedule(createCallback(1), 50ms);
    mScheduler.reset(nullptr);

    // Should timeout waiting for callback to run.
    ASSERT_FALSE(waitForCallbacks(1, 10ms));
    ASSERT_EQ(0, waitForCallbacks(1, 50ms));
    ASSERT_TRUE(getExpiredCallbacks().empty());
}