on xenial help sign in
tst_ShellWithPin: Replace loader with temporary object

The reason for this is best discussed in [1], but as a summary: There can only be one instance of SurfaceManager - and a few other objects - at a time. If the tests run fast enough, it is possible for the Loader which loaded the Shell to release the old Shell (which holds a SurfaceManager) and then load the new shell before the old one is finished destructing. This leads to an assertion failure in SurfaceManager::SurfaceManager and the tests closing. Fix this by using QtTest.TestCase.createTemporaryObject, which is made specifically for creating objects that are deleted at the end of a test run. In order to do this, I had to keep the Shell from automatically loading at the start of the TestCase when run as 'make tryShellWithPin'... so now we get a button to load the Shell. [1] https://github.com/ubports/unity8/pull/355#discussion_r556968153

commitc81a2f48a3be3f40e17bec6db8e912f98ed5df89 authorDalton Durst <dalton@ubports.com> dateWed 13 Jan 2021, 19:24 (6 years ago) parent27dc6a0
1 file changed+67−81
tests/qmltests/tst_ShellWithPin.qml+67−81
tests/qmltests/tst_ShellWithPin.qml+67−81
@@ -1,5 +1,6 @@
11/*
22 * Copyright (C) 2014-2016 Canonical, Ltd.
3+ * Copyright (C) 2021 UBports Foundation
34 *
45 * This program is free software; you can redistribute it and/or modify
56 * it under the terms of the GNU General Public License as published by
@@ -36,7 +37,6 @@ Item {
3637 Component.onCompleted: {
3738 // must set the mock mode before loading the Shell
3839 LightDMController.userMode = "single-pin";
39− shellLoader.active = true;
4040 }
4141
4242 QtObject {
@@ -55,35 +55,43 @@ Item {
5555 }
5656 }
5757
58+ property var tryShell: null
59+
60+ Component {
61+ id: shellComponent
62+ Shell {
63+ anchors.fill: parent
64+ hasTouchscreen: true
65+ }
66+ }
67+
5868 Row {
5969 id: contentRow
6070
61− Loader {
62− id: shellLoader
63− active: false
64−
71+ Rectangle {
72+ id: shellRect
73+ color: "black"
6574 width: units.gu(40)
6675 height: units.gu(71)
67−
68− property bool itemDestroyed: false
69− sourceComponent: Component {
70− Shell {
71− hasTouchscreen: true
72− Component.onDestruction: {
73− shellLoader.itemDestroyed = true
74− }
75− }
76− }
7776 }
7877
7978 Rectangle {
8079 color: "white"
8180 width: units.gu(30)
82− height: shellLoader.height
81+ height: shellRect.height
8382
8483 Column {
8584 anchors { left: parent.left; right: parent.right; top: parent.top; margins: units.gu(1) }
8685 spacing: units.gu(1)
86+ Button {
87+ anchors { left: parent.left; right: parent.right }
88+ text: "Load shell"
89+ onClicked: {
90+ if (root.tryShell === null) {
91+ root.tryShell = shellComponent.createObject(shellRect);
92+ }
93+ }
94+ }
8795 Button {
8896 anchors { left: parent.left; right: parent.right }
8997 text: "Show Greeter"
@@ -122,13 +130,13 @@ Item {
122130 name: "ShellWithPin"
123131 when: windowShown
124132
125− property Item shell: shellLoader.status === Loader.Ready ? shellLoader.item : null
126−
127− function init() {
133+ function createShell() {
134+ var shell = createTemporaryObject(shellComponent, shellRect);
135+ removeTimeConstraintsFromSwipeAreas(shell);
128136 tryCompare(shell, "waitingOnGreeter", false); // will be set when greeter is all ready
129137 var greeter = findChild(shell, "greeter");
130138 sessionSpy.target = greeter;
131− swipeAwayGreeter(true);
139+ swipeAwayGreeter(true, shell);
132140 greeter.failedLoginsDelayAttempts = -1;
133141
134142 var launcher = findChild(shell, "launcher");
@@ -140,44 +148,20 @@ Item {
140148 stage = findChild(shell, "stage");
141149 topLevelSurfaceList = findInvisibleChild(shell, "topLevelSurfaceList");
142150 verify(topLevelSurfaceList);
151+ return shell;
143152 }
144153
145154 function cleanup() {
146− tryCompare(shell, "waitingOnGreeter", false); // make sure greeter didn't leave us in disabled state
147−
148155 topLevelSurfaceList = null;
149−
150− shellLoader.itemDestroyed = false
151−
152− shellLoader.active = false
153−
154− tryCompare(shellLoader, "status", Loader.Null)
155− tryCompare(shellLoader, "item", null)
156− // Loader.status might be Loader.Null and Loader.item might be null but the Loader
157− // item might still be alive. So if we set Loader.active back to true
158− // again right now we will get the very same Shell instance back. So no reload
159− // actually took place. Likely because Loader waits until the next event loop
160− // iteration to do its work. So to ensure the reload, we will wait until the
161− // Shell instance gets destroyed.
162− tryCompare(shellLoader, "itemDestroyed", true)
163−
164− // kill all (fake) running apps
165− killApps()
166−
167− AccountsService.enableLauncherWhileLocked = true
168− AccountsService.enableIndicatorsWhileLocked = true
169− AccountsService.demoEdges = false
170− callManager.foregroundCall = null
156+ killApps();
157+ AccountsService.enableLauncherWhileLocked = true;
158+ AccountsService.enableIndicatorsWhileLocked = true;
159+ AccountsService.demoEdges = false;
160+ callManager.foregroundCall = null;
171161 LightDM.Greeter.authenticate(""); // reset greeter
172−
173− // reload our test subject to get it in a fresh state once again
174− shellLoader.active = true
175−
176− tryCompare(shellLoader, "status", Loader.Ready)
177− removeTimeConstraintsFromSwipeAreas(shellLoader.item)
178162 }
179163
180− function swipeAwayGreeter(waitForCoverPage) {
164+ function swipeAwayGreeter(waitForCoverPage, shell) {
181165 var greeter = findChild(shell, "greeter");
182166 waitForRendering(greeter)
183167 var coverPage = findChild(shell, "coverPage");
@@ -198,7 +182,7 @@ Item {
198182 typeString(pin);
199183 }
200184
201− function showGreeter() {
185+ function showGreeter(shell) {
202186 LightDM.Greeter.showGreeter();
203187 tryCompare(shell, "waitingOnGreeter", false);
204188 var coverPage = findChild(shell, "coverPage");
@@ -206,7 +190,7 @@ Item {
206190 removeTimeConstraintsFromSwipeAreas(shell);
207191 }
208192
209− function confirmLockedApp(app) {
193+ function confirmLockedApp(app, shell) {
210194 var greeter = findChild(shell, "greeter")
211195 tryCompare(greeter, "shown", false)
212196 tryCompare(greeter, "hasLockedApp", true)
@@ -218,13 +202,14 @@ Item {
218202 function test_greeterChangesIndicatorProfile() {
219203 skip("Not supported yet, waiting on design for new settings panel");
220204
205+ var shell = createShell();
221206 var panel = findChild(shell, "panel");
222207 tryCompare(panel.indicators.indicatorsModel, "profile", shell.indicatorProfile + "_greeter");
223208
224209 LightDM.Greeter.hideGreeter();
225210 tryCompare(panel.indicators.indicatorsModel, "profile", shell.indicatorProfile);
226211
227− showGreeter();
212+ showGreeter(shell);
228213 tryCompare(panel.indicators.indicatorsModel, "profile", shell.indicatorProfile + "_greeter");
229214
230215 LightDM.Greeter.hideGreeter();
@@ -232,6 +217,7 @@ Item {
232217 }
233218
234219 function test_login() {
220+ var shell = createShell();
235221 sessionSpy.clear()
236222 tryCompare(sessionSpy, "count", 0)
237223 enterPin("1234")
@@ -239,6 +225,7 @@ Item {
239225 }
240226
241227 function test_disabledEdges() {
228+ var shell = createShell();
242229 var launcher = findChild(shell, "launcher")
243230 tryCompare(launcher, "available", true)
244231 AccountsService.enableLauncherWhileLocked = false
@@ -251,6 +238,7 @@ Item {
251238 }
252239
253240 function test_emergencyCall() {
241+ var shell = createShell();
254242 var greeter = findChild(shell, "greeter")
255243 var panel = findChild(shell, "panel")
256244 var indicators = findChild(shell, "indicators")
@@ -269,7 +257,7 @@ Item {
269257
270258 // Cancel emergency mode, and go back to normal
271259 waitForRendering(greeter)
272− showGreeter()
260+ showGreeter(shell);
273261
274262 tryCompare(greeter, "shown", true)
275263 tryCompare(greeter, "lockedApp", "")
@@ -282,7 +270,7 @@ Item {
282270 }
283271
284272 function test_emergencyCallCrash() {
285− skip("Failing on Qt 5.12 with other tests skipped");
273+ var shell = createShell();
286274 var dialerSurfaceId = topLevelSurfaceList.nextId;
287275 var greeter = findChild(shell, "greeter");
288276 var emergencyButton = findChild(greeter, "emergencyCallLabel");
@@ -298,7 +286,7 @@ Item {
298286 }
299287
300288 function test_emergencyCallAppLaunch() {
301− skip("Failing on Qt 5.12");
289+ var shell = createShell();
302290 var greeter = findChild(shell, "greeter");
303291 var emergencyButton = findChild(greeter, "emergencyCallLabel");
304292 tap(emergencyButton)
@@ -309,6 +297,7 @@ Item {
309297 }
310298
311299 function test_emergencyCallPausesTutorial() {
300+ var shell = createShell();
312301 var greeter = findChild(shell, "greeter");
313302 var tutorial = findChild(shell, "tutorial");
314303
@@ -316,15 +305,16 @@ Item {
316305 enterPin("1234");
317306 tryCompare(tutorial, "paused", false);
318307
319− showGreeter();
308+ showGreeter(shell);
320309 verify(tutorial.paused);
321310
322− swipeAwayGreeter(true);
311+ swipeAwayGreeter(true, shell);
323312 tap(findChild(greeter, "emergencyCallLabel"));
324313 verify(tutorial.paused);
325314 }
326315
327316 function test_failedLoginsCount() {
317+ var shell = createShell();
328318 AccountsService.failedLogins = 0
329319
330320 enterPin("1111")
@@ -335,6 +325,7 @@ Item {
335325 }
336326
337327 function test_wrongEntries() {
328+ var shell = createShell();
338329 var greeter = findChild(shell, "greeter");
339330 greeter.failedLoginsDelayAttempts = 3;
340331
@@ -359,14 +350,14 @@ Item {
359350 // dialer to a side stage and give access to other apps. So just
360351 // confirm that such an attack doesn't work.
361352
362− skip("Failing on Qt 5.12 with other tests skipped");
353+ var shell = createShell();
363354 var stage = findChild(shell, "stage")
364355
365356 // We start in phone mode
366357 compare(stage.usageScenario, "phone");
367358
368359 tap(findChild(shell, "emergencyCallLabel"));
369− confirmLockedApp("dialer-app")
360+ confirmLockedApp("dialer-app", shell);
370361
371362 // OK, we're in. Now try (but fail) to switch to tablet mode
372363 shell.usageScenario = "tablet";
@@ -380,9 +371,9 @@ Item {
380371 }
381372
382373 function test_emergencyDialerIncoming() {
383− skip("Failing on Qt 5.12 with other tests skipped");
374+ var shell = createShell();
384375 callManager.foregroundCall = phoneCall
385− confirmLockedApp("dialer-app")
376+ confirmLockedApp("dialer-app", shell);
386377 }
387378
388379 function test_emergencyDialerActiveCallPanel() {
@@ -392,14 +383,14 @@ Item {
392383 // - Click on active call panel
393384 // - Should be back in emergency mode dialer
394385
395− skip("Failing on Qt 5.12");
386+ var shell = createShell();
396387 var greeter = findChild(shell, "greeter");
397388
398389 tap(findChild(shell, "emergencyCallLabel"));
399− confirmLockedApp("dialer-app");
390+ confirmLockedApp("dialer-app", shell);
400391 callManager.foregroundCall = phoneCall;
401392
402− showGreeter();
393+ showGreeter(shell);
403394 var lockscreen = findChild(shell, "lockscreen");
404395 tryCompare(lockscreen, "shown", true);
405396 tryCompare(greeter, "hasLockedApp", false);
@@ -407,7 +398,7 @@ Item {
407398 // simulate a callHint press, the real thing requires dialer: url support
408399 ApplicationManager.requestFocusApplication("dialer-app");
409400
410− confirmLockedApp("dialer-app");
401+ confirmLockedApp("dialer-app", shell);
411402 }
412403
413404 function test_normalDialerActiveCallPanel() {
@@ -419,7 +410,7 @@ Item {
419410 // - Should be back in normal dialer
420411 // (we've had a bug where we locked screen in this case)
421412
422− skip("Failing on Qt 5.12");
413+ var shell = createShell();
423414 startApplication("gallery-app");
424415
425416 var greeter = findChild(shell, "greeter");
@@ -448,8 +439,8 @@ Item {
448439 }
449440
450441 function test_focusRequestedHidesCoverPage() {
451− skip("Failing on Qt 5.12");
452− showGreeter();
442+ var shell = createShell();
443+ showGreeter(shell);
453444
454445 startApplication("gallery-app");
455446
@@ -459,7 +450,7 @@ Item {
459450 tryCompare(coverPage, "showProgress", 0);
460451 tryCompare(greeter, "fullyShown", true);
461452
462− showGreeter();
453+ showGreeter(shell);
463454
464455 // Make sure focusing same app triggers same behavior
465456 ApplicationManager.requestFocusApplication("gallery-app");
@@ -468,6 +459,7 @@ Item {
468459 }
469460
470461 function test_suspend() {
462+ var shell = createShell();
471463 var greeter = findChild(shell, "greeter");
472464 var stage = findChild(shell, "stage")
473465
@@ -482,7 +474,7 @@ Item {
482474 tryCompare(greeter, "fullyShown", true);
483475
484476 // Swipe away greeter to focus app
485− swipeAwayGreeter(true);
477+ swipeAwayGreeter(true, shell);
486478
487479 // We have a lockscreen, make sure we're still suspended
488480 tryCompare(stage, "suspended", true);
@@ -497,14 +489,7 @@ Item {
497489 loaded, they would be able to get into the session before the
498490 lockscreen appeared. Make sure that doesn't happen. */
499491 function test_earlyDisable() {
500− // Kill current shell
501− shellLoader.itemDestroyed = false;
502− shellLoader.active = false;
503− tryCompare(shellLoader, "itemDestroyed", true);
504−
505− // Create new shell
506− shellLoader.active = true;
507− tryCompareFunction(function() {return shell !== null}, true);
492+ var shell = createTemporaryObject(shellComponent, shellRect);
508493
509494 // Confirm that we start disabled
510495 compare(LightDM.Prompts.count, 0);
@@ -520,6 +505,7 @@ Item {
520505 }
521506
522507 function test_bfbOnLockedDevice() {
508+ var shell = createShell();
523509 var launcher = findChild(shell, "launcher");
524510 touchFlick(shell, units.gu(.5), shell.height / 2, units.gu(10), shell.height / 2);
525511
@@ -541,7 +527,7 @@ Item {
541527 appear over the Greeter. This was caused by logic that would normally
542528 cause the Launcher to be shown over the empty Background. */
543529 function test_launcherShowCulledWhenLocked() {
544− skip("Failing on Qt 5.12");
530+ var shell = createShell();
545531 var launcher = findChild(shell, "launcher");
546532
547533 // Ensure the Launcher is sane