diff options
author | Povilas Kanapickas <povilas@radix.lt> | 2020-12-19 03:12:37 +0200 |
---|---|---|
committer | Povilas Kanapickas <povilas@radix.lt> | 2020-12-19 03:12:37 +0200 |
commit | 4ea8edb40c81506ed9450abfcad64b61b5062038 (patch) | |
tree | c866209230f859fdc873411454cb08457f46ca63 | |
parent | 628d5cc2e015381a3efcf6dbb188a029c9f114a7 (diff) |
HACKING: Update for the inputtest backend
-rw-r--r-- | HACKING | 141 |
1 files changed, 37 insertions, 104 deletions
@@ -15,7 +15,7 @@ tests/server ... tests for server features or bugs tests/lib ...... tests for library features or bugs Each directory has a number of binaries that group the tests further. e.g. -input/evdev is a set of evdev-related tests. Tests should go into existing +input/input is a set of input-related tests. Tests should go into existing binaries where sensible, but tests for new logical features should add new binaries. A test binary may have multiple source files. @@ -47,50 +47,29 @@ file names named after the test name. The second class to know is the XOrgConfig class. It provides simple hooks for writing a config file with some of the options automated. -Thus, your basic test could look like this: +Most tests that use any kind of input will look something like this: -TEST(SomeTest, TestForFeature) { - XORG_TESTCASE("Create simple input device section.\n" - "Start server.\n" - "Run tests against the server.\n"); - - XOrgConfig config; - // Add evdev input device section - config.AddInputSection("evdev", "some device name", - "Option \"Device\" \"/dev/input/event0\"); - // Add dummy video section - config.AddDefaultScreenWithDriver(); - - // Start a server based on that config - XITServer server; - server.Start(config); - - ::Display *dpy = XOpenDisplay(server.GetDisplayString().c_str()); - - // now run your tests - - // clean up - server.Terminate(); - - // A test should remove its files on success but leave them on failure - config.RemoveConfig(); - server.RemoveLogFile(); -} +class MyFeatureTest : public XITServerInputTest, + public DeviceInputTestInterface{ +public: + void SetUp() override { + AddDevice(xorg::testing::inputtest::DeviceType::POINTER); + XITServerInputTest::SetUp(); + } -This test will show up as - SomeTest.TestForFeature -in the test logs, and use log and config files named the same way. + void SetUpConfigAndLog() overrid { + config.AddDefaultScreenWithDriver(); + config.AddInputSection(XORG_INPUTTEST_DRIVER, "some device name", + "Option \"CorePointer\" \"on\"\n" + + Dev(0).GetOptions()); + config.WriteConfig(); + } -The above is a simple structure for starting a server and testing against -it. In most cases, several tests want the same configuration and moving the -common parts out into shared code is useful. -class MyFeatureTest : public XITServerTest { -public: - virtual void SetUpConfigAndLog() { - config.AddDefaultScreenWithDriver(); - config.AddInputSection("evdev", "some device name", ... - } + void StartServer() override { + XITServerInputTest::StartServer(); + WaitForDevices(); + } }; SetUpConfigAndLog() will be called during the setup of the test, before the @@ -103,10 +82,25 @@ TEST_F(MyFeatureTest, TestForFeature) { ::Display *dpy = Display(); // now run your tests against the display + + XSelectInput(dpy, DefaultRootWindow(Display()), PointerMotionMask); + XSync(dpy, False); + + Dev(0).RelMotion(1, 0); + + ASSERT_TRUE(xorg::testing::XServer::WaitForEventOfType(Display(), MotionNotify, -1, -1)); + + XEvent ev; + XNextEvent(dpy, &ev); + // ev is our motion event } -Of course, you can just use Display() directly instead of dpy. XITServerTest -will write the config file, start the server, and remove the config and log +The above test registers for pointer motion events on the root +window, then sends one relative x axis motion event on the device. Then it +waits for the motion event to appear. + +Most low-level details are handled by XITServerTest. +It will write the config file, start the server, and remove the config and log files if the test succeeds. A new server is started for every TEST_F you have written, and there is no state dependency between tests. @@ -118,72 +112,11 @@ actual special code, base your test of a named empty class: class MyFeatureTest : public XITServerTest {} -Both of the tests above used a specific input device. But we need to ensure -that device actually exists, so it's best to create it ourselves: - -class MyFeatureTestWithDevice : public XITServerTest, - public DeviceInterface { -public: - virtual void SetUp() { - SetDevice("mice/PIXART-USB-OPTICAL-MOUSE-HWHEEL.desc"); - XITServerTest::SetUp(); // always call the parent's SetUp - } - - // set up config and log as above -}; - -This class initiates a uinput device based on -recordings/mice/PIXART-USB-OPTICAL-MOUSE-HWHEEL.desc. By the time our TEST_F -is called, we have that uinput device available for usage: - -TEST_F(MyFeatureTestWithDevice, TestForFeature) { - XORG_TESTCASE( .... ) - - XSelectInput(Display(), DefaultRootWindow(Display()), PointerMotionMask); - XSync(Display(), False); - - dev->PlayOne(EV_REL, REL_X, -1, true); /* true to send a EV_SYN after the event */ - - ASSERT_TRUE(xorg::testing::XServer::WaitForEventOfType(Display(), MotionNotify, -1, -1)); - - XEvent ev; - XNextEvent(Display(), &ev); - // ev is our motion event -} - -So, what does this do? Register for pointer motion events on the root -window, then play one relative x axis motion event on the device. Then it -waits for the motion event to appear. - Note: the X protocol is asynchronous and Xlib buffers generously. You should _always_ call XSync() before triggering anything in the server. If not, your event selection may still be in the local buffer when the events are generated and you'll never see the events. -If you have more than one event, you can replay a sequence with: - dev->PlayOne(RECORDINGS_DIR "mice/somefile.events"); - -Finally, if you're writing tests that require XI2, use the -XITServerInputTest as parent class. This class will automatically register -for XI2 on startup, and lets you override that call. - -class MyFeatureTestXI2 : public XITServerInputTest { -public: - virtual int RegisterXI2(int major, int minor) { - return XITServerInputTest::RegisterXI2(2, 2); // Force XI2.2 for this test - } -} - -In your TEST_F, you now have xi2_opcode available. - -TEST_F(MyFeatureTestXI2, TestForFeature) { - XORG_TESTCASE( .... ) - - ... select for events, play, etc. - - ASSERT_TRUE(xorg::testing::XServer::WaitForEventOfType(Display(), GenericEvent, xi2_opcode, XI_ButtonPress)); -} - That's the gist of writing tests. There are several helpers and other functions that make writing tests easier. Read other tests to get a feel for what those calls are. |