summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPovilas Kanapickas <povilas@radix.lt>2020-12-19 03:12:37 +0200
committerPovilas Kanapickas <povilas@radix.lt>2020-12-19 03:12:37 +0200
commit4ea8edb40c81506ed9450abfcad64b61b5062038 (patch)
treec866209230f859fdc873411454cb08457f46ca63
parent628d5cc2e015381a3efcf6dbb188a029c9f114a7 (diff)
HACKING: Update for the inputtest backend
-rw-r--r--HACKING141
1 files changed, 37 insertions, 104 deletions
diff --git a/HACKING b/HACKING
index 7fb5ec4..e57f6bb 100644
--- a/HACKING
+++ b/HACKING
@@ -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.