~hikiko/mir/mir.unity8-desktop-session

« back to all changes in this revision

Viewing changes to tests/unit-tests/test_udev_wrapper.cpp

  • Committer: Package Import Robot
  • Author(s): Ubuntu daily release, Daniel van Vugt, Ubuntu daily release
  • Date: 2014-02-04 14:49:07 UTC
  • mfrom: (1.1.55)
  • Revision ID: package-import@ubuntu.com-20140204144907-2lcyf87mba5rdca6
Tags: 0.1.4+14.04.20140204-0ubuntu1
[ Daniel van Vugt ]
* New upstream release 0.1.4 (https://launchpad.net/mir/+milestone/0.1.4)
  - Fixed snapshotting and flicker problems for Unity8 on various Nexus
    devices.
  - Enhanced reporting of performance information:
    . Report input latency in InputReport/InputReceiverReport.
    . Added a CompositorReport for logging compositor performance and state.
  - Added a new package "mir-utils" containing new tools:
    . mirping: Displays round-trip times between client and server
    . mirout: Displays the monitor layout/configuration details
  - Added GL texture caching to improve performance when multiple surfaces
    are visible.
  - Added opacity controls to mir_demo_server_shell
  - Mir server ABI bumped to 13. Client ABI bumped to 5.
  - Removed lots of Android headers, replaced by build-dep: android-headers
  - Added support for translucent nested servers.
  - tests: Fix unitialized values and incorrect fd closing loops
  - Fix unitialized values and incorrect fd closing loops.
  - client: Add basic MirScreencast C API.
  - config: start moving default values for config options from all the
    call sites to the setup
  - tests: Provide a helper for running clients with a stub ClientPlatform.
  - android: split out HWC layers into their own file and add a
    mga::CompositionLayer type that depends on the interface mg::Renderable.
  - client: Add basic MirOutputCapture class.
  - client: Don't create mesa ClientBuffer objects from invalid
    MirBufferPackages.
  - Optimize surface resizing to avoid doing anything if the dimensions
    are unchanged.
  - SwitchingBundle - add operator<< for debugging.
  - support hwcomposer 1.2 for android 4.4 on nexus 4 (which needs hwc1.2
    support). This patch adds hwc1.2 device construction, as well as progs
    the 'skip' layer in HWC to the buffer properties of the framebuffer.
  - demo-shell: Add simple keyboard controls to rotate outputs; Ctrl +
    Alt + <arrow-key>. Fixes: https://bugs.launchpad.net/bugs/1203215.
  - frontend: exposing internals of the RPC mechanism to enable custom
    function calls to be added.
  - Make udev wrapper into a top-level citizen
  - compositor: ignore double requests to start or stop the
    MultiThreadedCompositor.
  - Add DisplayBuffer::orientation(), to tell the Renderer if we need it
    to do screen rotation in GL (for platforms which don't implement 
    rotation natively) Fixes: https://bugs.launchpad.net/bugs/1203215.
  - graphics: add an post_update function that takes a list of renderables
    to the display buffer. This will let the display buffer take advantage
    of full-surface overlays on android.
  - android-input: Improve debug output
  - the stock qcom 8960 hwcomposer chokes on getDisplayAttributes if the
    submitted arrays are not at least size 6. patched the qcom android 4.2
    hwcomposer driver on the ubuntu touch images to work properly, but
    causes us problems with in-the wild drivers, and the new 4.4 drivers.
    Make sure we always submit a larger-than-needed array to this function.
  - frontend: refactoring to make it easier to expose the underlying RPC
    transport on the server side.
  - Don't assume pressure value is zero if not yet known
  - build: Expose options to allow building but not running tests by default.
  - Translucent Server which prefers a transparent pixel format
  - frontend: refactor ProtobufMessageProcessor to separate out generic
    response sending logic from specific message handling.
  - client: expose the part of the client RPC infrastructure needed for
    downstream to prototype their own message sending.
  - Bugs fixed:
    . unity8 display flickers and stops responding on Nexus 7 (grouper)
      (LP: #1238695)
    . Mir gets textures/buffers confused when running both scroll and flicker
      demos (LP: #1263592)
    . Some snapshots on Nexus10 upside-down (LP: #1263741)
    . mir_unit_tests is crashing with SIGSEGV in libhybris gl functions
      (LP: #1264968)
    . Some snapshots on Nexus10 have swapped red/blue channels (LP: #1265787)
    . Bypass causes some non-bypassed surfaces (on top) to be invisible
      (LP: #1266385)
    . helgrind: Possible data race - MirConnection::mutex not used
      consistently (LP: #1243575)
    . helgrind: Lock order violated (potential deadlock) in
      ConnectionSurfaceMap (LP: #1243576)
    . helgrind: Possible data race - inconsistent locking in PendingCallCache
      (LP: #1243578)
    . helgrind: Lock order violated in
      mir::client::ConnectionSurfaceMap::erase(int) (LP: #1243584)
    . [enhancement] Allow a Mir nested server to have a transparent
      background (LP: #1256702)
    . Compiling without tests fails (-DMIR_ENABLE_TESTS=NO) (LP: #1263724)
    . examples, doc: Make it clear and consistent how to use
      a non-root client with a root compositor endpoint. 
      (LP: #1272143)
    . Avoid linking to umockdev on platforms (android) which don't yet
      use it. This allows mir_unit_tests to run on touch images again
      (LP: #1271434)
    . Workaround for N4 nested server issue. This change removes
      mir_pixel_format_bgr_888 - HAL_PIXEL_FORMAT_RGB_888 from the
      list of supported pixel formats on android. (LP: #1272041)
    . Don't ask glUniformMatrix4fv to transpose your matrix. That option
      was officially deprecated between OpenGL and OpenGL|ES. And some
      drivers like the Nexus 10 don't implement it, resulting in incorrect
      transformations and even nothing on screen! (LP: #1271853)
    . Fixes: bug 1272143 (LP: #1272143)
    . fix integration test failure on the galaxy nexus that was due to
      creating two surfaces and registering the same buffer twice. Fixes:
      (LP: #1272597)
    . Implement screen rotation in GLRenderer, for platforms
      which can't do it natively in DisplayBuffer.
      (LP: #1203215)
    . Add an "orientation" field to output structures in preparation for
      screen rotation. It's not yet functionally wired to anything.
      (LP: #1203215)
    . Only use SwitchingBundle::last_consumed after it has been
      set. Otherwise SwitchingBundle::compositor_acquire could follow a bogus
      code path. (LP:#1270964)
    . tests: Override configuration to avoid creating an (unused)
      filesystem endpoint for connections when using InProcessServer. 
      (LP: #1271604)
    . frontend: ensure that BasicConnector threads don't exit
      immediately. (LP: #1271655)

[ Ubuntu daily release ]
* New rebuild forced

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright © 2013 Canonical Ltd.
 
3
 *
 
4
 * This program is free software: you can redistribute it and/or modify
 
5
 * it under the terms of the GNU General Public License version 3 as
 
6
 * published by the Free Software Foundation.
 
7
 *
 
8
 * This program is distributed in the hope that it will be useful,
 
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
 * GNU General Public License for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU General Public License
 
14
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
15
 *
 
16
 * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
 
17
 */
 
18
 
 
19
#include "mir_test_framework/udev_environment.h"
 
20
#include "mir/udev/wrapper.h"
 
21
 
 
22
#include <gtest/gtest.h>
 
23
#include <memory>
 
24
#include <stdexcept>
 
25
 
 
26
// At some point gnu libstdc++ will have a <regex> header that contains
 
27
// actual functions. Until then, Boost to the rescue.
 
28
#include <boost/regex.hpp>
 
29
 
 
30
#include <umockdev.h>
 
31
#include <libudev.h>
 
32
#include <poll.h>
 
33
 
 
34
namespace mtf=mir::mir_test_framework;
 
35
 
 
36
class UdevWrapperTest : public ::testing::Test
 
37
{
 
38
public:
 
39
    mtf::UdevEnvironment udev_environment;
 
40
};
 
41
 
 
42
TEST_F(UdevWrapperTest, IteratesOverCorrectNumberOfDevices)
 
43
{
 
44
    udev_environment.add_device("drm", "fakedev1", NULL, {}, {});
 
45
    udev_environment.add_device("drm", "fakedev2", NULL, {}, {});
 
46
    udev_environment.add_device("drm", "fakedev3", NULL, {}, {});
 
47
    udev_environment.add_device("drm", "fakedev4", NULL, {}, {});
 
48
    udev_environment.add_device("drm", "fakedev5", NULL, {}, {});
 
49
 
 
50
    auto ctx = std::make_shared<mir::udev::Context>();
 
51
    mir::udev::Enumerator enumerator(ctx);
 
52
 
 
53
    enumerator.scan_devices();
 
54
 
 
55
    int device_count = 0;
 
56
    for (auto& device : enumerator)
 
57
    {
 
58
        // Silence unused variable warning
 
59
        static_cast<void>(device);
 
60
        ++device_count;
 
61
    }
 
62
 
 
63
    ASSERT_EQ(device_count, 5);
 
64
}
 
65
 
 
66
TEST_F(UdevWrapperTest, EnumeratorMatchSubsystemIncludesCorrectDevices)
 
67
{
 
68
    udev_environment.add_device("drm", "fakedrm1", NULL, {}, {});
 
69
    udev_environment.add_device("scsi", "fakescsi1", NULL, {}, {});
 
70
    udev_environment.add_device("drm", "fakedrm2", NULL, {}, {});
 
71
    udev_environment.add_device("usb", "fakeusb1", NULL, {}, {});
 
72
    udev_environment.add_device("usb", "fakeusb2", NULL, {}, {});
 
73
 
 
74
    auto ctx = std::make_shared<mir::udev::Context>();
 
75
    mir::udev::Enumerator devices(ctx);
 
76
 
 
77
    devices.match_subsystem("drm");
 
78
    devices.scan_devices();
 
79
    for (auto& device : devices)
 
80
    {
 
81
        ASSERT_STREQ("drm", device.subsystem());
 
82
    }
 
83
}
 
84
 
 
85
TEST_F(UdevWrapperTest, UdevDeviceHasCorrectDevType)
 
86
{
 
87
    auto sysfs_path = udev_environment.add_device("drm", "card0", NULL, {}, {"DEVTYPE", "drm_minor"});
 
88
 
 
89
    mir::udev::Context ctx;
 
90
    auto dev = ctx.device_from_syspath(sysfs_path);
 
91
    ASSERT_STREQ("drm_minor", dev->devtype());
 
92
}
 
93
 
 
94
TEST_F(UdevWrapperTest, UdevDeviceHasCorrectDevPath)
 
95
{
 
96
    auto sysfs_path = udev_environment.add_device("drm", "card0", NULL, {}, {});
 
97
 
 
98
    mir::udev::Context ctx;
 
99
    auto dev = ctx.device_from_syspath(sysfs_path);
 
100
    ASSERT_STREQ("/devices/card0", dev->devpath());
 
101
}
 
102
 
 
103
TEST_F(UdevWrapperTest, UdevDeviceHasCorrectDevNode)
 
104
{
 
105
    auto sysfs_path = udev_environment.add_device("drm", "card0", NULL, {}, {"DEVNAME", "/dev/dri/card0"});
 
106
 
 
107
    mir::udev::Context ctx;
 
108
    auto dev = ctx.device_from_syspath(sysfs_path);
 
109
 
 
110
    ASSERT_STREQ("/dev/dri/card0", dev->devnode());
 
111
}
 
112
 
 
113
TEST_F(UdevWrapperTest, UdevDeviceComparisonIsReflexive)
 
114
{
 
115
    auto sysfs_path = udev_environment.add_device("drm", "card0", NULL, {}, {});
 
116
 
 
117
    mir::udev::Context ctx;
 
118
    auto dev = ctx.device_from_syspath(sysfs_path);
 
119
 
 
120
    EXPECT_TRUE(*dev == *dev);
 
121
}
 
122
 
 
123
TEST_F(UdevWrapperTest, UdevDeviceComparisonIsSymmetric)
 
124
{
 
125
    auto sysfs_path = udev_environment.add_device("drm", "card0", NULL, {}, {});
 
126
 
 
127
    mir::udev::Context ctx;
 
128
    std::shared_ptr<mir::udev::Device> same_one = ctx.device_from_syspath(sysfs_path);
 
129
    std::shared_ptr<mir::udev::Device> same_two = ctx.device_from_syspath(sysfs_path);
 
130
 
 
131
    EXPECT_TRUE(*same_one == *same_two);
 
132
    EXPECT_TRUE(*same_two == *same_one);
 
133
}
 
134
 
 
135
TEST_F(UdevWrapperTest, UdevDeviceDifferentDevicesCompareFalse)
 
136
{
 
137
    auto path_one = udev_environment.add_device("drm", "card0", NULL, {}, {});
 
138
    auto path_two = udev_environment.add_device("drm", "card1", NULL, {}, {});
 
139
 
 
140
    mir::udev::Context ctx;
 
141
    auto dev_one = ctx.device_from_syspath(path_one);
 
142
    auto dev_two = ctx.device_from_syspath(path_two);
 
143
 
 
144
    EXPECT_FALSE(*dev_one == *dev_two);
 
145
    EXPECT_FALSE(*dev_two == *dev_one);
 
146
}
 
147
 
 
148
TEST_F(UdevWrapperTest, UdevDeviceDifferentDevicesAreNotEqual)
 
149
{
 
150
    auto path_one = udev_environment.add_device("drm", "card0", NULL, {}, {});
 
151
    auto path_two = udev_environment.add_device("drm", "card1", NULL, {}, {});
 
152
 
 
153
    mir::udev::Context ctx;
 
154
    auto dev_one = ctx.device_from_syspath(path_one);
 
155
    auto dev_two = ctx.device_from_syspath(path_two);
 
156
 
 
157
    EXPECT_TRUE(*dev_one != *dev_two);
 
158
    EXPECT_TRUE(*dev_two != *dev_one);
 
159
}
 
160
 
 
161
TEST_F(UdevWrapperTest, UdevDeviceSameDeviceIsNotNotEqual)
 
162
{
 
163
    auto sysfs_path = udev_environment.add_device("drm", "card0", NULL, {}, {});
 
164
 
 
165
    mir::udev::Context ctx;
 
166
    auto same_one = ctx.device_from_syspath(sysfs_path);
 
167
    auto same_two = ctx.device_from_syspath(sysfs_path);
 
168
 
 
169
    EXPECT_FALSE(*same_one != *same_two);
 
170
    EXPECT_FALSE(*same_two != *same_one);
 
171
}
 
172
 
 
173
TEST_F(UdevWrapperTest, EnumeratorMatchParentMatchesOnlyChildren)
 
174
{
 
175
    auto card0_syspath = udev_environment.add_device("drm", "card0", NULL, {}, {});
 
176
    udev_environment.add_device("usb", "fakeusb", NULL, {}, {});
 
177
 
 
178
    udev_environment.add_device("drm", "card0-HDMI1", "/sys/devices/card0", {}, {});
 
179
    udev_environment.add_device("drm", "card0-VGA1", "/sys/devices/card0", {}, {});
 
180
    udev_environment.add_device("drm", "card0-LVDS1", "/sys/devices/card0", {}, {});
 
181
 
 
182
    auto ctx = std::make_shared<mir::udev::Context>();
 
183
 
 
184
    mir::udev::Enumerator devices(ctx);
 
185
    auto drm_device = ctx->device_from_syspath(card0_syspath);
 
186
 
 
187
    devices.match_parent(*drm_device);
 
188
    devices.scan_devices();
 
189
 
 
190
    int child_count = 0;
 
191
    for (auto& device : devices)
 
192
    {
 
193
        EXPECT_STREQ("drm", device.subsystem());
 
194
        ++child_count;
 
195
    }
 
196
    EXPECT_EQ(4, child_count);
 
197
}
 
198
 
 
199
TEST_F(UdevWrapperTest, EnumeratorThrowsLogicErrorIfIteratedBeforeScanned)
 
200
{
 
201
    auto ctx = std::make_shared<mir::udev::Context>();
 
202
 
 
203
    mir::udev::Enumerator devices(ctx);
 
204
 
 
205
    EXPECT_THROW({ devices.begin(); },
 
206
                 std::logic_error);
 
207
}
 
208
 
 
209
TEST_F(UdevWrapperTest, EnumeratorLogicErrorHasSensibleMessage)
 
210
{
 
211
    auto ctx = std::make_shared<mir::udev::Context>();
 
212
 
 
213
    mir::udev::Enumerator devices(ctx);
 
214
    std::string error_msg;
 
215
 
 
216
    try
 
217
    {
 
218
        devices.begin();
 
219
    }
 
220
    catch (std::logic_error& e)
 
221
    {
 
222
        error_msg = e.what();
 
223
    }
 
224
    EXPECT_STREQ("Attempted to iterate over udev devices without first scanning", error_msg.c_str());
 
225
}
 
226
 
 
227
TEST_F(UdevWrapperTest, EnumeratorEnumeratesEmptyList)
 
228
{
 
229
    auto ctx = std::make_shared<mir::udev::Context>();
 
230
 
 
231
    mir::udev::Enumerator devices(ctx);
 
232
 
 
233
    devices.scan_devices();
 
234
 
 
235
    for (auto& device : devices)
 
236
        ADD_FAILURE() << "Unexpected udev device: " << device.devpath();
 
237
}
 
238
 
 
239
TEST_F(UdevWrapperTest, EnumeratorAddMatchSysnameIncludesCorrectDevices)
 
240
{
 
241
    auto drm_sysfspath = udev_environment.add_device("drm", "card0", NULL, {}, {});
 
242
    udev_environment.add_device("drm", "control64D", NULL, {}, {});
 
243
    udev_environment.add_device("drm", "card0-LVDS1", drm_sysfspath.c_str(), {}, {});
 
244
    udev_environment.add_device("drm", "card1", NULL, {}, {});
 
245
 
 
246
    auto ctx = std::make_shared<mir::udev::Context>();
 
247
 
 
248
    mir::udev::Enumerator devices(ctx);
 
249
 
 
250
    devices.match_sysname("card[0-9]");
 
251
    devices.scan_devices();
 
252
    for (auto& device : devices)
 
253
    {
 
254
        EXPECT_TRUE(boost::regex_match(device.devpath(), boost::regex(".*card[0-9].*")))
 
255
            << "Unexpected device with devpath:" << device.devpath();
 
256
    }
 
257
}
 
258
 
 
259
TEST_F(UdevWrapperTest, UdevMonitorDoesNotTriggerBeforeEnabling)
 
260
{
 
261
    mir::udev::Monitor monitor{mir::udev::Context()};
 
262
    bool event_handler_called = false;
 
263
 
 
264
    udev_environment.add_device("drm", "control64D", NULL, {}, {});
 
265
 
 
266
    monitor.process_events([&event_handler_called](mir::udev::Monitor::EventType,
 
267
                                                   mir::udev::Device const&) {event_handler_called = true;});
 
268
 
 
269
    EXPECT_FALSE(event_handler_called);
 
270
}
 
271
 
 
272
TEST_F(UdevWrapperTest, UdevMonitorTriggersAfterEnabling)
 
273
{
 
274
    mir::udev::Monitor monitor{mir::udev::Context()};
 
275
    bool event_handler_called = false;
 
276
 
 
277
    monitor.enable();
 
278
 
 
279
    udev_environment.add_device("drm", "control64D", NULL, {}, {});
 
280
 
 
281
    monitor.process_events([&event_handler_called](mir::udev::Monitor::EventType,
 
282
                                                   mir::udev::Device const&) {event_handler_called = true;});
 
283
 
 
284
    EXPECT_TRUE(event_handler_called);
 
285
}
 
286
 
 
287
TEST_F(UdevWrapperTest, UdevMonitorSendsRemoveEvent)
 
288
{
 
289
    mir::udev::Monitor monitor{mir::udev::Context()};
 
290
    bool remove_event_received = false;
 
291
 
 
292
    monitor.enable();
 
293
 
 
294
    auto test_sysfspath = udev_environment.add_device("drm", "control64D", NULL, {}, {});
 
295
    udev_environment.remove_device(test_sysfspath);
 
296
 
 
297
    monitor.process_events([&remove_event_received]
 
298
        (mir::udev::Monitor::EventType action, mir::udev::Device const&)
 
299
            {
 
300
                if (action == mir::udev::Monitor::EventType::REMOVED)
 
301
                    remove_event_received = true;
 
302
            });
 
303
 
 
304
    EXPECT_TRUE(remove_event_received);
 
305
}
 
306
 
 
307
TEST_F(UdevWrapperTest, UdevMonitorSendsChangedEvent)
 
308
{
 
309
    mir::udev::Monitor monitor{mir::udev::Context()};
 
310
    bool changed_event_received = false;
 
311
 
 
312
    monitor.enable();
 
313
 
 
314
    auto test_sysfspath = udev_environment.add_device("drm", "control64D", NULL, {}, {});
 
315
    udev_environment.emit_device_changed(test_sysfspath);
 
316
 
 
317
    monitor.process_events([&changed_event_received]
 
318
        (mir::udev::Monitor::EventType action, mir::udev::Device const&)
 
319
            {
 
320
                if (action == mir::udev::Monitor::EventType::CHANGED)
 
321
                    changed_event_received = true;
 
322
            });
 
323
 
 
324
    EXPECT_TRUE(changed_event_received);
 
325
}
 
326
 
 
327
TEST_F(UdevWrapperTest, UdevMonitorEventHasCorrectDeviceDetails)
 
328
{
 
329
    mir::udev::Context ctx;
 
330
 
 
331
    mir::udev::Monitor monitor{mir::udev::Context()};
 
332
    bool event_handler_called = false;
 
333
 
 
334
    monitor.enable();
 
335
 
 
336
    auto sysfs_path = udev_environment.add_device("drm", "control64D", NULL, {}, {});
 
337
    auto device = ctx.device_from_syspath(sysfs_path);
 
338
 
 
339
    monitor.process_events(
 
340
        [&event_handler_called, device](mir::udev::Monitor::EventType, mir::udev::Device const& dev)
 
341
            {
 
342
                event_handler_called = true;
 
343
                EXPECT_EQ(*device, dev);
 
344
            });
 
345
 
 
346
    ASSERT_TRUE(event_handler_called);
 
347
}
 
348
 
 
349
TEST_F(UdevWrapperTest, UdevMonitorFdIsReadableWhenEventsAvailable)
 
350
{
 
351
    mir::udev::Monitor monitor{mir::udev::Context()};
 
352
 
 
353
    monitor.enable();
 
354
 
 
355
    udev_environment.add_device("drm", "card0", NULL, {}, {});
 
356
 
 
357
    struct pollfd fds;
 
358
    fds.fd = monitor.fd();
 
359
    fds.events = POLLIN;
 
360
 
 
361
    ASSERT_GT(poll(&fds, 1, 0), 0);
 
362
 
 
363
    EXPECT_TRUE(fds.revents & POLLIN);
 
364
}
 
365
 
 
366
TEST_F(UdevWrapperTest, UdevMonitorFdIsUnreadableAfterProcessingEvents)
 
367
{
 
368
    mir::udev::Monitor monitor{mir::udev::Context()};
 
369
 
 
370
    monitor.enable();
 
371
 
 
372
    udev_environment.add_device("drm", "card0", NULL, {}, {});
 
373
    udev_environment.add_device("drm", "card1", NULL, {}, {});
 
374
    udev_environment.add_device("usb", "mightymouse", NULL, {}, {});
 
375
 
 
376
    struct pollfd fds;
 
377
    fds.fd = monitor.fd();
 
378
    fds.events = POLLIN;
 
379
 
 
380
    ASSERT_GT(poll(&fds, 1, 0), 0);
 
381
    ASSERT_TRUE(fds.revents & POLLIN);
 
382
 
 
383
    monitor.process_events([](mir::udev::Monitor::EventType, mir::udev::Device const&){});
 
384
 
 
385
    EXPECT_EQ(poll(&fds, 1, 0), 0);
 
386
}
 
387
 
 
388
TEST_F(UdevWrapperTest, UdevMonitorFiltersByPathAndType)
 
389
{
 
390
    mir::udev::Context ctx;
 
391
 
 
392
    mir::udev::Monitor monitor{mir::udev::Context()};
 
393
    bool event_received = false;
 
394
 
 
395
    monitor.filter_by_subsystem_and_type("drm", "drm_minor");
 
396
 
 
397
    monitor.enable();
 
398
 
 
399
    auto test_sysfspath = udev_environment.add_device("drm", "control64D", NULL, {}, {"DEVTYPE", "drm_minor"});
 
400
    auto minor_device = ctx.device_from_syspath(test_sysfspath);
 
401
    udev_environment.add_device("drm", "card0-LVDS1", test_sysfspath.c_str(), {}, {});
 
402
    udev_environment.add_device("usb", "mightymouse", NULL, {}, {});
 
403
 
 
404
    monitor.process_events([&event_received, minor_device]
 
405
        (mir::udev::Monitor::EventType, mir::udev::Device const& dev)
 
406
            {
 
407
                EXPECT_EQ(dev, *minor_device);
 
408
                event_received = true;
 
409
            });
 
410
 
 
411
    ASSERT_TRUE(event_received);
 
412
}
 
413
 
 
414
TEST_F(UdevWrapperTest, UdevMonitorFiltersAreAdditive)
 
415
{
 
416
    mir::udev::Context ctx;
 
417
 
 
418
    mir::udev::Monitor monitor{mir::udev::Context()};
 
419
    bool usb_event_received = false, drm_event_recieved = false;
 
420
 
 
421
    monitor.filter_by_subsystem_and_type("drm", "drm_minor");
 
422
    monitor.filter_by_subsystem_and_type("usb", "hid");
 
423
 
 
424
    monitor.enable();
 
425
 
 
426
    auto drm_sysfspath = udev_environment.add_device("drm", "control64D", NULL, {}, {"DEVTYPE", "drm_minor"});
 
427
    auto drm_device = ctx.device_from_syspath(drm_sysfspath);
 
428
    udev_environment.add_device("drm", "card0-LVDS1", drm_sysfspath.c_str(), {}, {});
 
429
    auto usb_sysfspath = udev_environment.add_device("usb", "mightymouse", NULL, {}, {"DEVTYPE", "hid"});
 
430
    auto usb_device = ctx.device_from_syspath(usb_sysfspath);
 
431
 
 
432
    monitor.process_events([&drm_event_recieved, drm_device, &usb_event_received, usb_device]
 
433
        (mir::udev::Monitor::EventType, mir::udev::Device const& dev)
 
434
            {
 
435
                if (dev == *drm_device)
 
436
                    drm_event_recieved = true;
 
437
                if (dev == *usb_device)
 
438
                    usb_event_received = true;
 
439
            });
 
440
 
 
441
    EXPECT_TRUE(drm_event_recieved);
 
442
    EXPECT_TRUE(usb_event_received);
 
443
}
 
444
 
 
445
TEST_F(UdevWrapperTest, UdevMonitorFiltersApplyAfterEnable)
 
446
{
 
447
    mir::udev::Context ctx;
 
448
 
 
449
    mir::udev::Monitor monitor{mir::udev::Context()};
 
450
    bool event_received = false;
 
451
 
 
452
    monitor.enable();
 
453
 
 
454
    monitor.filter_by_subsystem_and_type("drm", "drm_minor");
 
455
 
 
456
    auto test_sysfspath = udev_environment.add_device("drm", "control64D", NULL, {}, {"DEVTYPE", "drm_minor"});
 
457
    auto minor_device = ctx.device_from_syspath(test_sysfspath);
 
458
    udev_environment.add_device("drm", "card0-LVDS1", test_sysfspath.c_str(), {}, {});
 
459
    udev_environment.add_device("usb", "mightymouse", NULL, {}, {});
 
460
 
 
461
    monitor.process_events([&event_received, minor_device]
 
462
        (mir::udev::Monitor::EventType, mir::udev::Device const& dev)
 
463
            {
 
464
                EXPECT_EQ(dev, *minor_device);
 
465
                event_received = true;
 
466
            });
 
467
 
 
468
    ASSERT_TRUE(event_received);
 
469
}