diff options
author | Peter Hutterer <peter.hutterer@who-t.net> | 2013-10-18 09:12:03 +1000 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@who-t.net> | 2013-10-18 09:12:03 +1000 |
commit | 40ce5943c5bf58c06742851b11b63c8d8e5b16dc (patch) | |
tree | 5153ca9fb830d48f4458864a8461b698583667e4 | |
parent | 35aa68143b39608bd2e7d75a68d37c3bff625792 (diff) | |
parent | de1042bb3ab33d6063536bee9f04b96a49dfef9c (diff) |
Merge branch 'sync-idletimer-fix'
-rw-r--r-- | tests/server/misc.cpp | 322 |
1 files changed, 322 insertions, 0 deletions
diff --git a/tests/server/misc.cpp b/tests/server/misc.cpp index 7e32afc..bae84b1 100644 --- a/tests/server/misc.cpp +++ b/tests/server/misc.cpp @@ -30,8 +30,10 @@ #include <xorg/gtest/xorg-gtest.h> #include <X11/extensions/scrnsaver.h> +#include <X11/extensions/sync.h> #include "xit-server-input-test.h" +#include "xit-event.h" #include "device-interface.h" #include "helpers.h" @@ -222,6 +224,326 @@ TEST_F(ScreenSaverTest, ScreenSaverActivateDeactivate) EXPECT_LT(info.idle, 1000U); } + +class XSyncTest : public XITServerInputTest { + public: + virtual void SetUp() { + XITServerInputTest::SetUp(); + QuerySyncExtension(Display()); + } + + virtual void QuerySyncExtension(::Display *dpy) { + ASSERT_TRUE(XSyncQueryExtension (dpy, &sync_event, &sync_error)); + ASSERT_TRUE(XSyncInitialize (dpy, &sync_major, &sync_minor)); + } + + virtual XSyncAlarm SetAbsoluteAlarm(::Display *dpy, XSyncCounter counter, + int threshold, XSyncTestType direction, + bool need_events = true) { + XSyncAlarm alarm; + int flags; + XSyncAlarmAttributes attr; + XSyncValue delta, interval; + + XSyncIntToValue(&delta, 0); + XSyncIntToValue(&interval, threshold); + + attr.trigger.counter = counter; + attr.trigger.test_type = direction;; + attr.trigger.value_type = XSyncAbsolute; + attr.trigger.wait_value = interval; + attr.delta = delta; + attr.events = need_events; + + flags = XSyncCACounter | XSyncCAValueType | XSyncCATestType | + XSyncCAValue | XSyncCADelta| XSyncCAEvents; + + alarm = XSyncCreateAlarm(dpy, flags, &attr); + XSync(dpy, False); + return alarm; + } + + int sync_event; + int sync_error; + int sync_major; + int sync_minor; +}; + +class IdletimerTest : public XSyncTest, + public DeviceInterface { +public: + virtual void SetUp() { + SetDevice("mice/PIXART-USB-OPTICAL-MOUSE-HWHEEL.desc"); + XSyncTest::SetUp(); + } + + virtual void SetUpConfigAndLog() { + config.AddDefaultScreenWithDriver(); + config.AddInputSection("evdev", "--device--", + "Option \"CorePointer\" \"on\"\n" + "Option \"GrabDevice\" \"on\"\n" + "Option \"Device\" \"" + dev->GetDeviceNode() + "\""); + /* add default keyboard device to avoid server adding our device again */ + config.AddInputSection("kbd", "kbd-device", + "Option \"CoreKeyboard\" \"on\"\n"); + config.WriteConfig(); + } + + virtual XSyncCounter GetIdletimeCounter(::Display *dpy) { + int ncounters; + XSyncSystemCounter *counters; + XSyncCounter counter = None; + + counters = XSyncListSystemCounters (dpy, &ncounters); + for (int i = 0; i < ncounters; i++) { + if (!strcmp(counters[i].name, "IDLETIME")) { + counter = counters[i].counter; + } + } + + XSyncFreeSystemCounterList(counters); + + if (!counter) + ADD_FAILURE() << "IDLETIME counter not found."; + return counter; + } + + /** + * This function is necessary because in this test setup the server may + * hang when we're only sending one event. Event gets processed, but + * ProcessInputEvent() is never called so we just hang waiting for + * something to happen and the test fails. + * This is a server bug, but won't be triggered on a normal desktop + * since there's always something to process (client request, timer, + * etc.). + */ + virtual void WaitForEvent(::Display *dpy) { + XEvent ev; + XSelectInput(dpy, DefaultRootWindow(dpy), PointerMotionMask); + while (!XCheckMaskEvent(dpy, PointerMotionMask, &ev)) { + dev->PlayOne(EV_REL, REL_X, 10, true); + XSync(dpy, False); + usleep(10000); + } + } +}; + +TEST_F(IdletimerTest, NegativeTransitionHighThreshold) +{ + XORG_TESTCASE("Set up an alarm on negative transition for a high threshold\n" + "Wait past threshold, then move pointer\n" + "Expect event\n" + "Wait past threshold, then move pointer\n" + "Expect event\n" + "https://bugs.freedesktop.org/show_bug.cgi?id=59644"); + + ::Display *dpy = Display(); + + /* make sure server is ready to send events */ + WaitForEvent(dpy); + XSync(dpy, True); + + XSyncAlarm neg_alarm; + XSyncCounter idlecounter; + + /* bug: if the negative transition threshold fires but the idletime is + below the threshold, it is never set up again */ + + const int threshold = 1000; /* ms */ + + idlecounter = GetIdletimeCounter(dpy); + ASSERT_GT(idlecounter, (XSyncCounter)None); + neg_alarm = SetAbsoluteAlarm(dpy, idlecounter, threshold, XSyncNegativeTransition); + ASSERT_GT(neg_alarm, (XSyncAlarm)None); + + usleep(threshold * 1.5 * 1000); + WaitForEvent(dpy); + + usleep(threshold * 1.5 * 1000); + WaitForEvent(dpy); + + ASSERT_EVENT(XSyncAlarmNotifyEvent, ev1, dpy, sync_event + XSyncAlarmNotify); + ASSERT_EQ(ev1->alarm, neg_alarm); + ASSERT_EQ(ev1->state, XSyncAlarmActive); + + ASSERT_EVENT(XSyncAlarmNotifyEvent, ev2, dpy, sync_event + XSyncAlarmNotify); + ASSERT_EQ(ev2->alarm, neg_alarm); + ASSERT_EQ(ev1->state, XSyncAlarmActive); +} + +TEST_F(IdletimerTest, NegativeTransitionLowThreshold) +{ + XORG_TESTCASE("Set up an alarm on negative transition for a low threshold\n" + "Wait past threshold, then move pointer\n" + "Expect alarm event\n" + "Wait past threshold, then move pointer\n" + "Expect alarm event\n" + "------------------------------------------------\n" + "This alarm will generate false positives, the test \n" + "will only fail if the server is busy and the time to\n" + "idle timer query takes more than <threshold> ms\n" + "https://bugs.freedesktop.org/show_bug.cgi?id=70476"); + + ::Display *dpy = Display(); + + WaitForEvent(dpy); + XSync(dpy, True); + + XSyncAlarm neg_alarm; + XSyncCounter idlecounter; + + /* bug: if the negative transition threshold fires but the idletime may + move past the threshold before the handler queries it */ + + const int threshold = 1; /* ms */ + + usleep(threshold * 1000); + + idlecounter = GetIdletimeCounter(dpy); + ASSERT_GT(idlecounter, (XSyncCounter)None); + neg_alarm = SetAbsoluteAlarm(dpy, idlecounter, threshold, XSyncNegativeTransition); + ASSERT_GT(neg_alarm, (XSyncAlarm)None); + + usleep(threshold * 1.5 * 1000); + WaitForEvent(dpy); + + ASSERT_EVENT(XSyncAlarmNotifyEvent, ev1, dpy, sync_event + XSyncAlarmNotify); + ASSERT_EQ(ev1->alarm, neg_alarm); + ASSERT_EQ(ev1->state, XSyncAlarmActive); +} + +TEST_F(IdletimerTest, PositiveTransitionLowThreshold) +{ + XORG_TESTCASE("Set up an alarm on positive transition for a low threshold\n" + "Wait past threshold, then move pointer\n" + "Expect event when idletime passes threshold\n" + "Wait past threshold, then move pointer\n" + "Expect event when idletime passes threshold\n" + "https://bugs.freedesktop.org/show_bug.cgi?id=70476"); + + ::Display *dpy = Display(); + + /* make sure server is ready to send events */ + WaitForEvent(dpy); + XSync(dpy, True); + + XSyncAlarm pos_alarm; + XSyncCounter idlecounter; + + /* bug: if the postive transition threshold fires but the idletime is + already above the threshold, it is never set up again */ + + const int threshold = 1; /* ms */ + + usleep(threshold * 20000); + + idlecounter = GetIdletimeCounter(dpy); + ASSERT_GT(idlecounter, (XSyncCounter)None); + pos_alarm = SetAbsoluteAlarm(dpy, idlecounter, threshold, XSyncPositiveTransition); + SetAbsoluteAlarm(dpy, idlecounter, threshold + 1, XSyncNegativeTransition, false); + ASSERT_GT(pos_alarm, (XSyncAlarm)None); + + WaitForEvent(dpy); + usleep(threshold * 2000); + + WaitForEvent(dpy); + usleep(threshold * 2000); + + ASSERT_EVENT(XSyncAlarmNotifyEvent, ev1, dpy, sync_event + XSyncAlarmNotify); + ASSERT_EQ(ev1->alarm, pos_alarm); + ASSERT_EQ(ev1->state, XSyncAlarmActive); + + ASSERT_EVENT(XSyncAlarmNotifyEvent, ev2, dpy, sync_event + XSyncAlarmNotify); + ASSERT_EQ(ev2->alarm, pos_alarm); + ASSERT_EQ(ev1->state, XSyncAlarmActive); +} + +TEST_F(IdletimerTest, NegativeTransition) +{ + XORG_TESTCASE("Set up an alarm on negative transition\n" + "Move pointer\n" + "Expect event\n" + "Wait for timeout\n" + "Move pointer again\n" + "Expect event\n"); + + ::Display *dpy = Display(); + + /* make sure server is ready to send events */ + WaitForEvent(dpy); + XSync(dpy, True); + + XSyncAlarm neg_alarm; + XSyncCounter idlecounter; + + /* bug: if the negative transition threshold fires but the idletime is + below the threshold, it is never set up again */ + const int threshold = 1000; + usleep(threshold * 1001); + + idlecounter = GetIdletimeCounter(dpy); + ASSERT_GT(idlecounter, (XSyncCounter)None); + neg_alarm = SetAbsoluteAlarm(dpy, idlecounter, threshold, XSyncNegativeTransition); + ASSERT_GT(neg_alarm, (XSyncAlarm)None); + + dev->PlayOne(EV_REL, REL_X, 10, true); + WaitForEvent(dpy); + usleep(threshold * 1001); + + dev->PlayOne(EV_REL, REL_X, 10, true); + WaitForEvent(dpy); + + ASSERT_EVENT(XSyncAlarmNotifyEvent, ev1, dpy, sync_event + XSyncAlarmNotify); + ASSERT_EQ(ev1->alarm, neg_alarm); + ASSERT_EQ(ev1->state, XSyncAlarmActive); + + ASSERT_EVENT(XSyncAlarmNotifyEvent, ev2, dpy, sync_event + XSyncAlarmNotify); + ASSERT_EQ(ev2->alarm, neg_alarm); + ASSERT_EQ(ev1->state, XSyncAlarmActive); +} + +TEST_F(IdletimerTest, NegativeTransitionMultipleAlarms) +{ + XORG_TESTCASE("Set up an multiple alarm on negative transitions\n" + "Move pointer\n" + "Expect event\n" + "Wait for timeout\n" + "Move pointer again\n" + "Expect event\n"); + + ::Display *dpy = Display(); + + /* make sure server is ready to send events */ + XSelectInput(dpy, DefaultRootWindow(dpy), PointerMotionMask); + WaitForEvent(dpy); + XSync(dpy, True); + + XSyncAlarm neg_alarm1, neg_alarm2; + XSyncCounter idlecounter; + + /* bug: if the negative transition threshold fires but the idletime is + below the threshold, it is never set up again */ + const int threshold = 200; + usleep(threshold * 2000); + + idlecounter = GetIdletimeCounter(dpy); + ASSERT_GT(idlecounter, (XSyncCounter)None); + neg_alarm2 = SetAbsoluteAlarm(dpy, idlecounter, threshold/2, XSyncNegativeTransition); + neg_alarm1 = SetAbsoluteAlarm(dpy, idlecounter, threshold, XSyncNegativeTransition); + ASSERT_GT(neg_alarm1, (XSyncAlarm)None); + ASSERT_GT(neg_alarm2, (XSyncAlarm)None); + + WaitForEvent(dpy); + usleep(threshold * 2000); + + WaitForEvent(dpy); + + ASSERT_EVENT(XSyncAlarmNotifyEvent, ev1, dpy, sync_event + XSyncAlarmNotify); + ASSERT_EVENT(XSyncAlarmNotifyEvent, ev2, dpy, sync_event + XSyncAlarmNotify); + ASSERT_EVENT(XSyncAlarmNotifyEvent, ev3, dpy, sync_event + XSyncAlarmNotify); + ASSERT_EVENT(XSyncAlarmNotifyEvent, ev4, dpy, sync_event + XSyncAlarmNotify); +} + int main(int argc, char **argv) { testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); |