Mir

Merge lp:~robertcarr/mir/hold-surface-alive into lp:mir

Proposed by Robert Carr
Status: Merged
Approved by: Robert Ancell
Approved revision: no longer in the source branch.
Merged at revision: 1121
Proposed branch: lp:~robertcarr/mir/hold-surface-alive
Merge into: lp:mir
Diff against target: 610 lines (+57/-362)
8 files modified
include/server/mir/frontend/surface.h (+0/-1)
include/server/mir/shell/surface.h (+1/-3)
include/test/mir_test_doubles/mock_surface.h (+0/-1)
include/test/mir_test_doubles/stub_surface.h (+0/-1)
src/server/shell/application_session.cpp (+1/-2)
src/server/shell/surface.cpp (+18/-127)
tests/unit-tests/shell/test_application_session.cpp (+26/-2)
tests/unit-tests/shell/test_surface.cpp (+11/-225)
To merge this branch: bzr merge lp:~robertcarr/mir/hold-surface-alive
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Daniel van Vugt Needs Information
Robert Ancell Approve
Alexandros Frantzis (community) Approve
Alan Griffiths Needs Information
Kevin DuBois Pending
Review via email: mp+189400@code.launchpad.net

This proposal supersedes a proposal from 2013-10-03.

Commit message

Hold ms::Surface alive from msh::Surface, and remove the explicit throw
calls. This way holding a shared_ptr to msh::Surface becomes safe (as long
as you drop it eventually!). (LP: #1234609)

Description of the change

End the weak_ptr madness. Retargeted to development-branch

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Kevin DuBois (kdub) wrote : Posted in a previous version of this proposal

How does the shell know when a surface has been destroyed? I'd still like to hedge against giving the shell a strong pointer (which leads to the temptation that the shell will just keep it around, when really, it might be destroyed at any time by mir)

In general, i'm okay with the shell having a strong pointer to the surfaces, provided the way they use it makes it clear that they should get the strong pointer, use it, and then release it.

Much of the functions in msh::Shell are now just passthrough.
perhaps we have something like:
std::shared_ptr<ms::Surface> msh::Shell::compositor_surface()
and then eliminate the passthrough functions

this part of the code needs some reworking, so if it solves a bug though and makes strange code less strange, i suppose that adds up to approve :)

review: Approve
Revision history for this message
Kevin DuBois (kdub) wrote : Posted in a previous version of this proposal

actually, should be retargeted :)

should probably get a second look over from someone else before top approve as well

review: Needs Fixing
Revision history for this message
Alexandros Frantzis (afrantzis) wrote : Posted in a previous version of this proposal

I can verify that this MP fixes the reported bug. However, it seems that the shell::Surface is never released and therefore the underlying ms::Surface is also never released. This is a pre-existing issue in unity8/mir, obscured before because the underlying ms::Surface was freed when the ApplicationSession was destroyed and called shell::Surface::destroy(). Before we land this, we need to find why shell::Surface is not released, and coordinate the fix with unity8 (if the problem is indeed outside Mir).

Marking "Needs fixing" to block this from landing before the other half of the fix is in place.

review: Needs Fixing
Revision history for this message
Robert Carr (robertcarr) wrote :

Thanks for checking Alexandros! I think I found out what was going on notably the mirsurfacemanager object in unity-mir is holding a map of shared_ptr<msh::Surface> to unity-mir MirSurface objects. It relies on the_session_listener to know when to clear these surfaces. This change sneakily changed the behavior such that this would not be emitted ons ession destruction anymore.

I have reinstated the behavior (and instated a test) in r1066. It will be a little bit before I can verify this is a full fix though.

Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

>> This is a pre-existing issue in unity8/mir, obscured before because the underlying ms::Surface
>> was freed when the ApplicationSession was destroyed and called shell::Surface::destroy()

> This change sneakily changed the behavior such that this would not be emitted ons ession destruction anymore.

Perhaps what I am describing is a different (but related) issue then, since I don't see the shell::Surface dtor getting called when an application is closed [1] even with *current* lp:mir. I only see a call to shell::Surface::destroy() (invoked through the ApplicationSession dtor).

[1] By "closed" I mean pressing [X] on the app snapshot in the recent applications list.

Revision history for this message
Robert Carr (robertcarr) wrote :

With this branch and latest r's, I see a call to ms::Surface destroy on the phone (after closing app via X button)

Revision history for this message
Robert Carr (robertcarr) wrote :
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

I think any approach that continues to expose the implementation class surfaces::Surface from an interface the shell uses (shell::Surface) is a mistake. Although the change has other benefits...

review: Abstain
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Sanity check: Is this proposal intended as a fix for bug 1234609?

Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

> Sanity check: Is this proposal intended as a fix for bug 1234609?

Yes. When an app destroys itself there seems to be a race between its surface getting destroyed, and the shell needing to access at least some information about the surface. Letting the shell share ownership of the surface fixes this. Perhaps we could remove the race itself in the shell, but it's not clear what's going on exactly and if this is feasible, since the QML layer is involved.

Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

If this really works, then msh::Surface is becoming a ghost we can likely refactor away.

Dredging my memory for the reasons that motivated msh::Surface I remember it had to do with race conditions where a surface was removed from compositing (a.k.a. "destroyed") while clients could be posting buffers - leading to threads stalling waiting for compositing that never happened. This led to resource leaks and shutdown problems.

In the current codebase I think that force_requests_to_complete() will avoid shutdown problems and release resources on exit. However, I've yet to convince myself that resources are released in a timely manner (i.e. shortly after the surface is destroyed by the client).

Marking as "Needs Information" until I've worked out an answer that satisfies me.

review: Needs Information
Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

> With this branch and latest r's, I see a call to ms::Surface destroy on the phone (after closing app via X button)

Hmm, for me this works only for the first app I open/close. For subsequent apps I can see the surfaces (both ms:: and msh::) being created, but none is being destroyed after closing with X.

review: Needs Fixing
Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

>> With this branch and latest r's, I see a call to ms::Surface destroy on the phone (after closing app via X button)
>
> Hmm, for me this works only for the first app I open/close. For subsequent apps I can
> see the surfaces (both ms:: > and msh::) being created, but none is being destroyed after closing with X.

Not a problem in Mir, see https://code.launchpad.net/~afrantzis/unity-mir/fix-1236898/+merge/189894

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Robert Carr (robertcarr) wrote :

We need to coordinate the landing with the unity-mir fix.

Revision history for this message
Robert Ancell (robert-ancell) wrote :

It makes sense to me that the three concepts of a surface (shell, rendering, frontend) should have the same lifecycle and it should be ultimately be up to the shell to decide when a surface should be removed.

review: Approve
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

This is likely a shell ABI break:

29 - std::weak_ptr<mir::surfaces::Surface> const surface;
30 + std::shared_ptr<mir::surfaces::Surface> const surface;

Are we supposed to ring a bell or something?

review: Needs Information
Revision history for this message
Robert Ancell (robert-ancell) wrote :

> This is likely a shell ABI break:
>
> 29 - std::weak_ptr<mir::surfaces::Surface> const surface;
> 30 + std::shared_ptr<mir::surfaces::Surface> const surface;
>
> Are we supposed to ring a bell or something?

We just have to bump ABI on development branch BEFORE merging to trunk and then ring a bell. If we can avoid breaking ABI much better, but will probably be too hard in this case.

Revision history for this message
Robert Carr (robertcarr) wrote :

>> If this really works, then msh::Surface is becoming a ghost we can likely refactor away.

Oi!

>> Dredging my memory for the reasons that motivated msh::Surface I remember it had to do with race conditions where a surface
>> was removed from compositing (a.k.a. "destroyed") while clients could be posting buffers - leading to threads stalling waiting >> for compositing that never happened. This led to resource leaks and shutdown problems.
>> In the current codebase I think that force_requests_to_complete() will avoid shutdown problems and release resources on exit.

Sure, we can see this through the tests.

>> However, I've yet to convince myself that resources are released in a timely manner (i.e. shortly after the surface is
>> destroyed by the client).

Why wouldn't they be? Do you mean you are concerned we hold references to the surface in Mir? The memcheck tests should verify this for us.

Resources shouldn't necessarily be released immediately after the client disconnects anyway (which I think was the 'flaw' of the explicit destroy method). In some cases: say the client unexpectedly disconnects, the shell wishes to keep the surface alive for a few seconds to perform an animation.

Marking as "Needs Information" until I've worked out an answer that satisfies me.

Reply

Revision history for this message
kevin gunn (kgunn72) wrote :

ok, time pressure.
after long discussino with racarr this seems like a good fix
alan_g & racarr to follow up later - but we're merging to hit the freeeze.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'include/server/mir/frontend/surface.h'
2--- include/server/mir/frontend/surface.h 2013-08-28 03:41:48 +0000
3+++ include/server/mir/frontend/surface.h 2013-10-08 18:20:54 +0000
4@@ -50,7 +50,6 @@
5
6 virtual ~Surface() {}
7
8- virtual void destroy() = 0;
9 virtual void force_requests_to_complete() = 0;
10
11 virtual geometry::Size size() const = 0;
12
13=== modified file 'include/server/mir/shell/surface.h'
14--- include/server/mir/shell/surface.h 2013-08-28 03:41:48 +0000
15+++ include/server/mir/shell/surface.h 2013-10-08 18:20:54 +0000
16@@ -60,8 +60,6 @@
17 virtual void hide();
18 virtual void show();
19
20- virtual void destroy();
21-
22 virtual void force_requests_to_complete();
23
24 virtual std::string name() const;
25@@ -97,7 +95,7 @@
26
27 std::shared_ptr<SurfaceBuilder> const builder;
28 std::shared_ptr<SurfaceConfigurator> const configurator;
29- std::weak_ptr<mir::surfaces::Surface> const surface;
30+ std::shared_ptr<mir::surfaces::Surface> const surface;
31
32 frontend::SurfaceId const id;
33 std::shared_ptr<frontend::EventSink> const event_sink;
34
35=== modified file 'include/test/mir_test_doubles/mock_surface.h'
36--- include/test/mir_test_doubles/mock_surface.h 2013-08-28 03:41:48 +0000
37+++ include/test/mir_test_doubles/mock_surface.h 2013-10-08 18:20:54 +0000
38@@ -51,7 +51,6 @@
39 MOCK_METHOD0(visible, bool());
40 MOCK_METHOD1(raise, void(std::shared_ptr<shell::SurfaceController> const&));
41
42- MOCK_METHOD0(destroy, void());
43 MOCK_METHOD0(force_requests_to_complete, void());
44 MOCK_METHOD0(advance_client_buffer, std::shared_ptr<graphics::Buffer>());
45
46
47=== modified file 'include/test/mir_test_doubles/stub_surface.h'
48--- include/test/mir_test_doubles/stub_surface.h 2013-08-28 03:41:48 +0000
49+++ include/test/mir_test_doubles/stub_surface.h 2013-10-08 18:20:54 +0000
50@@ -35,7 +35,6 @@
51
52 void hide() {}
53 void show() {}
54- void destroy() {}
55 void force_requests_to_complete() {}
56
57 geometry::Size size() const
58
59=== modified file 'src/server/shell/application_session.cpp'
60--- src/server/shell/application_session.cpp 2013-08-28 03:41:48 +0000
61+++ src/server/shell/application_session.cpp 2013-10-08 18:20:54 +0000
62@@ -55,7 +55,7 @@
63 std::unique_lock<std::mutex> lock(surfaces_mutex);
64 for (auto const& pair_id_surface : surfaces)
65 {
66- pair_id_surface.second->destroy();
67+ session_listener->destroying_surface(*this, pair_id_surface.second);
68 }
69 }
70
71@@ -116,7 +116,6 @@
72
73 session_listener->destroying_surface(*this, p->second);
74
75- p->second->destroy();
76 surfaces.erase(p);
77 }
78
79
80=== modified file 'src/server/shell/surface.cpp'
81--- src/server/shell/surface.cpp 2013-08-28 03:41:48 +0000
82+++ src/server/shell/surface.cpp 2013-10-08 18:20:54 +0000
83@@ -58,165 +58,74 @@
84
85 msh::Surface::~Surface() noexcept
86 {
87- if (surface.lock())
88- {
89- destroy();
90- }
91+ builder->destroy_surface(surface);
92 }
93
94 void msh::Surface::hide()
95 {
96- if (auto const& s = surface.lock())
97- {
98- s->set_hidden(true);
99- }
100- else
101- {
102- BOOST_THROW_EXCEPTION(std::runtime_error("Invalid surface"));
103- }
104+ surface->set_hidden(true);
105 }
106
107 void msh::Surface::show()
108 {
109- if (auto const& s = surface.lock())
110- {
111- s->set_hidden(false);
112- }
113- else
114- {
115- BOOST_THROW_EXCEPTION(std::runtime_error("Invalid surface"));
116- }
117-}
118-
119-void msh::Surface::destroy()
120-{
121- builder->destroy_surface(surface);
122+ surface->set_hidden(false);
123 }
124
125 void msh::Surface::force_requests_to_complete()
126 {
127- if (auto const& s = surface.lock())
128- {
129- s->force_requests_to_complete();
130- }
131+ surface->force_requests_to_complete();
132 }
133
134 mir::geometry::Size msh::Surface::size() const
135 {
136- if (auto const& s = surface.lock())
137- {
138- return s->size();
139- }
140- else
141- {
142- BOOST_THROW_EXCEPTION(std::runtime_error("Invalid surface"));
143- }
144+ return surface->size();
145 }
146
147 void msh::Surface::move_to(geometry::Point const& p)
148 {
149- if (auto const& s = surface.lock())
150- {
151- s->move_to(p);
152- }
153- else
154- {
155- BOOST_THROW_EXCEPTION(std::runtime_error("Invalid surface"));
156- }
157+ surface->move_to(p);
158 }
159
160 mir::geometry::Point msh::Surface::top_left() const
161 {
162- if (auto const& s = surface.lock())
163- {
164- return s->top_left();
165- }
166- else
167- {
168- BOOST_THROW_EXCEPTION(std::runtime_error("Invalid surface"));
169- }
170+ return surface->top_left();
171 }
172
173 std::string msh::Surface::name() const
174 {
175- if (auto const& s = surface.lock())
176- {
177- return s->name();
178- }
179- else
180- {
181- BOOST_THROW_EXCEPTION(std::runtime_error("Invalid surface"));
182- }
183+ return surface->name();
184 }
185
186 mir::geometry::PixelFormat msh::Surface::pixel_format() const
187 {
188- if (auto const& s = surface.lock())
189- {
190- return s->pixel_format();
191- }
192- else
193- {
194- BOOST_THROW_EXCEPTION(std::runtime_error("Invalid surface"));
195- }
196+ return surface->pixel_format();
197 }
198
199 std::shared_ptr<mg::Buffer> msh::Surface::advance_client_buffer()
200 {
201- if (auto const& s = surface.lock())
202- {
203- return s->advance_client_buffer();
204- }
205- else
206- {
207- BOOST_THROW_EXCEPTION(std::runtime_error("Invalid surface"));
208- }
209+ return surface->advance_client_buffer();
210 }
211
212 void msh::Surface::allow_framedropping(bool allow)
213 {
214- if (auto const& s = surface.lock())
215- {
216- s->allow_framedropping(allow);
217- }
218+ surface->allow_framedropping(allow);
219 }
220
221 void msh::Surface::with_most_recent_buffer_do(
222 std::function<void(mg::Buffer&)> const& exec)
223 {
224- if (auto const& s = surface.lock())
225- {
226- auto buf = s->snapshot_buffer();
227- exec(*buf);
228- }
229- else
230- {
231- BOOST_THROW_EXCEPTION(std::runtime_error("Invalid surface"));
232- }
233+ auto buf = surface->snapshot_buffer();
234+ exec(*buf);
235 }
236
237 bool msh::Surface::supports_input() const
238 {
239- if (auto const& s = surface.lock())
240- {
241- return s->supports_input();
242- }
243- else
244- {
245- BOOST_THROW_EXCEPTION(std::runtime_error("Invalid surface"));
246- }
247+ return surface->supports_input();
248 }
249
250 int msh::Surface::client_input_fd() const
251 {
252- if (auto const& s = surface.lock())
253- {
254- return s->client_input_fd();
255- }
256- else
257- {
258- BOOST_THROW_EXCEPTION(std::runtime_error("Invalid surface"));
259- }
260+ return surface->client_input_fd();
261 }
262
263 int msh::Surface::configure(MirSurfaceAttrib attrib, int value)
264@@ -319,33 +228,15 @@
265
266 void msh::Surface::take_input_focus(std::shared_ptr<msh::InputTargeter> const& targeter)
267 {
268- auto s = surface.lock();
269- if (s)
270- targeter->focus_changed(s->input_channel());
271- else
272- BOOST_THROW_EXCEPTION(std::runtime_error("Invalid surface"));
273+ targeter->focus_changed(surface->input_channel());
274 }
275
276 void msh::Surface::set_input_region(std::vector<geom::Rectangle> const& region)
277 {
278- if (auto const& s = surface.lock())
279- {
280- s->set_input_region(region);
281- }
282- else
283- {
284- BOOST_THROW_EXCEPTION(std::runtime_error("Invalid surface"));
285- }
286+ surface->set_input_region(region);
287 }
288
289 void msh::Surface::raise(std::shared_ptr<msh::SurfaceController> const& controller)
290 {
291- if (auto const& s = surface.lock())
292- {
293- controller->raise(s);
294- }
295- else
296- {
297- BOOST_THROW_EXCEPTION(std::runtime_error("Invalid surface"));
298- }
299+ controller->raise(surface);
300 }
301
302=== modified file 'tests/unit-tests/shell/test_application_session.cpp'
303--- tests/unit-tests/shell/test_application_session.cpp 2013-08-28 03:41:48 +0000
304+++ tests/unit-tests/shell/test_application_session.cpp 2013-10-08 18:20:54 +0000
305@@ -65,7 +65,6 @@
306 ON_CALL(surface_factory, create_surface(_,_,_,_)).WillByDefault(Return(mock_surface));
307
308 EXPECT_CALL(surface_factory, create_surface(_, _, _, _));
309- EXPECT_CALL(*mock_surface, destroy());
310
311 mtd::MockSessionListener listener;
312 EXPECT_CALL(listener, surface_created(_, _)).Times(1);
313@@ -82,6 +81,32 @@
314 session.destroy_surface(surf);
315 }
316
317+TEST(ApplicationSession, listener_notified_of_surface_destruction_on_session_destruction)
318+{
319+ using namespace ::testing;
320+
321+ auto mock_surface = make_mock_surface();
322+
323+ mtd::NullEventSink sender;
324+ mtd::MockSurfaceFactory surface_factory;
325+ ON_CALL(surface_factory, create_surface(_,_,_,_)).WillByDefault(Return(mock_surface));
326+
327+ EXPECT_CALL(surface_factory, create_surface(_, _, _, _));
328+
329+ mtd::MockSessionListener listener;
330+ EXPECT_CALL(listener, surface_created(_, _)).Times(1);
331+ EXPECT_CALL(listener, destroying_surface(_, _)).Times(1);
332+
333+ {
334+ msh::ApplicationSession session(mt::fake_shared(surface_factory), "Foo",
335+ std::make_shared<mtd::NullSnapshotStrategy>(), mt::fake_shared(listener),
336+ mt::fake_shared(sender));
337+
338+ msh::SurfaceCreationParameters params;
339+ session.create_surface(params);
340+ }
341+}
342+
343 TEST(ApplicationSession, default_surface_is_first_surface)
344 {
345 using namespace ::testing;
346@@ -142,7 +167,6 @@
347 InSequence seq;
348 EXPECT_CALL(*mock_surface, hide()).Times(1);
349 EXPECT_CALL(*mock_surface, show()).Times(1);
350- EXPECT_CALL(*mock_surface, destroy()).Times(1);
351 }
352
353 msh::SurfaceCreationParameters params;
354
355=== modified file 'tests/unit-tests/shell/test_surface.cpp'
356--- tests/unit-tests/shell/test_surface.cpp 2013-08-28 03:41:48 +0000
357+++ tests/unit-tests/shell/test_surface.cpp 2013-10-08 18:20:54 +0000
358@@ -191,197 +191,20 @@
359 EXPECT_CALL(surface_builder, create_surface(nullptr, _)).Times(AnyNumber());
360 EXPECT_CALL(surface_builder, destroy_surface(_)).Times(0);
361
362- msh::Surface test(
363- nullptr,
364- mt::fake_shared(surface_builder), std::make_shared<mtd::NullSurfaceConfigurator>(),
365- msh::a_surface(), stub_id, stub_sender);
366-
367- Mock::VerifyAndClearExpectations(&test);
368- EXPECT_CALL(surface_builder, destroy_surface(_)).Times(1);
369-
370- // Check destroy_surface is called immediately
371- test.destroy();
372-
373- Mock::VerifyAndClearExpectations(&test);
374+ {
375+ msh::Surface test(
376+ nullptr,
377+ mt::fake_shared(surface_builder), std::make_shared<mtd::NullSurfaceConfigurator>(),
378+ msh::a_surface(), stub_id, stub_sender);
379+
380+ Mock::VerifyAndClearExpectations(&test);
381+ EXPECT_CALL(surface_builder, destroy_surface(_)).Times(1);
382+ Mock::VerifyAndClearExpectations(&test);
383+ }
384+
385 EXPECT_CALL(surface_builder, destroy_surface(_)).Times(0);
386 }
387
388-TEST_F(ShellSurface, size_throw_behavior)
389-{
390- msh::Surface test(
391- nullptr,
392- mt::fake_shared(surface_builder), std::make_shared<mtd::NullSurfaceConfigurator>(),
393- msh::a_surface(), stub_id, stub_sender);
394-
395- EXPECT_NO_THROW({
396- test.size();
397- });
398-
399- surface_builder.reset_surface();
400-
401- EXPECT_THROW({
402- test.size();
403- }, std::runtime_error);
404-}
405-
406-TEST_F(ShellSurface, top_left_throw_behavior)
407-{
408- msh::Surface test(
409- nullptr,
410- mt::fake_shared(surface_builder), std::make_shared<mtd::NullSurfaceConfigurator>(),
411- msh::a_surface(), stub_id, stub_sender);
412-
413- EXPECT_NO_THROW({
414- test.top_left();
415- });
416-
417- surface_builder.reset_surface();
418-
419- EXPECT_THROW({
420- test.top_left();
421- }, std::runtime_error);
422-}
423-
424-TEST_F(ShellSurface, name_throw_behavior)
425-{
426- msh::Surface test(
427- nullptr,
428- mt::fake_shared(surface_builder), std::make_shared<mtd::NullSurfaceConfigurator>(),
429- msh::a_surface(), stub_id, stub_sender);
430-
431- EXPECT_NO_THROW({
432- test.name();
433- });
434-
435- surface_builder.reset_surface();
436-
437- EXPECT_THROW({
438- test.name();
439- }, std::runtime_error);
440-}
441-
442-TEST_F(ShellSurface, pixel_format_throw_behavior)
443-{
444- msh::Surface test(
445- nullptr,
446- mt::fake_shared(surface_builder), std::make_shared<mtd::NullSurfaceConfigurator>(),
447- msh::a_surface(), stub_id, stub_sender);
448-
449- EXPECT_NO_THROW({
450- test.pixel_format();
451- });
452-
453- surface_builder.reset_surface();
454-
455- EXPECT_THROW({
456- test.pixel_format();
457- }, std::runtime_error);
458-}
459-
460-TEST_F(ShellSurface, hide_throw_behavior)
461-{
462- msh::Surface test(
463- nullptr,
464- mt::fake_shared(surface_builder), std::make_shared<mtd::NullSurfaceConfigurator>(),
465- msh::a_surface(), stub_id, stub_sender);
466-
467- EXPECT_NO_THROW({
468- test.hide();
469- });
470-
471- surface_builder.reset_surface();
472-
473- EXPECT_THROW({
474- test.hide();
475- }, std::runtime_error);
476-}
477-
478-TEST_F(ShellSurface, show_throw_behavior)
479-{
480- msh::Surface test(
481- nullptr,
482- mt::fake_shared(surface_builder), std::make_shared<mtd::NullSurfaceConfigurator>(),
483- msh::a_surface(), stub_id, stub_sender);
484-
485- EXPECT_NO_THROW({
486- test.show();
487- });
488-
489- surface_builder.reset_surface();
490-
491- EXPECT_THROW({
492- test.show();
493- }, std::runtime_error);
494-}
495-
496-TEST_F(ShellSurface, destroy_throw_behavior)
497-{
498- msh::Surface test(
499- nullptr,
500- mt::fake_shared(surface_builder), std::make_shared<mtd::NullSurfaceConfigurator>(),
501- msh::a_surface(), stub_id, stub_sender);
502-
503- EXPECT_NO_THROW({
504- test.destroy();
505- });
506-
507- surface_builder.reset_surface();
508-
509- EXPECT_NO_THROW({
510- test.destroy();
511- });
512-}
513-
514-TEST_F(ShellSurface, force_request_to_complete_throw_behavior)
515-{
516- msh::Surface test(
517- nullptr,
518- mt::fake_shared(surface_builder), std::make_shared<mtd::NullSurfaceConfigurator>(),
519- msh::a_surface(), stub_id, stub_sender);
520-
521- EXPECT_NO_THROW({
522- test.force_requests_to_complete();
523- });
524-
525- surface_builder.reset_surface();
526-
527- EXPECT_NO_THROW({
528- test.force_requests_to_complete();
529- });
530-}
531-
532-TEST_F(ShellSurface, advance_client_buffer_throw_behavior)
533-{
534- msh::Surface test(
535- nullptr,
536- mt::fake_shared(surface_builder), std::make_shared<mtd::NullSurfaceConfigurator>(),
537- msh::a_surface(), stub_id, stub_sender);
538-
539- EXPECT_NO_THROW({
540- test.advance_client_buffer();
541- });
542-
543- surface_builder.reset_surface();
544-
545- EXPECT_THROW({
546- test.advance_client_buffer();
547- }, std::runtime_error);
548-}
549-
550-TEST_F(ShellSurface, input_fds_throw_behavior)
551-{
552- msh::Surface test(
553- nullptr,
554- mt::fake_shared(surface_builder), std::make_shared<mtd::NullSurfaceConfigurator>(),
555- msh::a_surface(), stub_id, stub_sender);
556-
557- surface_builder.reset_surface();
558-
559- EXPECT_THROW({
560- test.client_input_fd();
561- }, std::runtime_error);
562-}
563-
564 TEST_F(ShellSurface, attributes)
565 {
566 using namespace testing;
567@@ -522,43 +345,6 @@
568 test.take_input_focus(mt::fake_shared(targeter));
569 }
570
571-TEST_F(ShellSurface, take_input_focus_throw_behavior)
572-{
573- using namespace ::testing;
574-
575- msh::Surface test(
576- nullptr,
577- mt::fake_shared(surface_builder), std::make_shared<mtd::NullSurfaceConfigurator>(),
578- msh::a_surface(), stub_id, stub_sender);
579- surface_builder.reset_surface();
580-
581- mtd::StubInputTargeter targeter;
582-
583- EXPECT_THROW({
584- test.take_input_focus(mt::fake_shared(targeter));
585- }, std::runtime_error);
586-}
587-
588-TEST_F(ShellSurface, set_input_region_throw_behavior)
589-{
590- using namespace ::testing;
591-
592- msh::Surface test(
593- nullptr,
594- mt::fake_shared(surface_builder), std::make_shared<mtd::NullSurfaceConfigurator>(),
595- msh::a_surface(), stub_id, stub_sender);
596-
597- EXPECT_NO_THROW({
598- test.set_input_region(std::vector<geom::Rectangle>{});
599- });
600-
601- surface_builder.reset_surface();
602-
603- EXPECT_THROW({
604- test.set_input_region(std::vector<geom::Rectangle>{});
605- }, std::runtime_error);
606-}
607-
608 TEST_F(ShellSurface, with_most_recent_buffer_do_uses_compositor_buffer)
609 {
610 msh::Surface test(

Subscribers

People subscribed via source and target branches