Merge lp:~gerboland/qtmir/dont-delete-qml-cache-on-good-stop into lp:qtmir
- dont-delete-qml-cache-on-good-stop
- Merge into trunk
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Nick Dedekind | ||||
Approved revision: | no longer in the source branch. | ||||
Merged at revision: | 383 | ||||
Proposed branch: | lp:~gerboland/qtmir/dont-delete-qml-cache-on-good-stop | ||||
Merge into: | lp:qtmir | ||||
Diff against target: |
325 lines (+202/-6) 4 files modified
src/modules/Unity/Application/application.cpp (+64/-6) src/modules/Unity/Application/application.h (+3/-0) src/modules/Unity/Application/application_manager.cpp (+1/-0) tests/modules/ApplicationManager/application_manager_test.cpp (+134/-0) |
||||
To merge this branch: | bzr merge lp:~gerboland/qtmir/dont-delete-qml-cache-on-good-stop | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Michał Sawicz | Approve | ||
Nick Dedekind (community) | Approve | ||
PS Jenkins bot (community) | continuous-integration | Approve | |
Review via email:
|
Commit message
Add "Closing" state to Application, use it to distinguish user-induced close from app-induced close. Don't clear QML cache if user-induced.
Much code taken from a partially-related branch by Nick Dedekind:
https:/
Note there is 1 disabled test, which needs additional work to fix.
Description of the change
* Are there any related MPs required for this MP to build/function as expected? Please list.
N
* Did you perform an exploratory manual test run of your code change and any related functionality?
Y
* If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?
N/A
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Gerry Boland (gerboland) wrote : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Gerry Boland (gerboland) wrote : | # |
To test, get a shell on the phone and watch the contents of the ~/.cache/QML/Apps/ directory. Each app will get a directory with its appId name, which contains its cache. Deleting the cache means deleteing this directory.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:380
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Gerry Boland (gerboland) wrote : | # |
"virtual memory exhausted: Cannot allocate memory" - trying CI again
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:380
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Nick Dedekind (nick-dedekind) wrote : | # |
small comment.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Nick Dedekind (nick-dedekind) wrote : | # |
small comment.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Nick Dedekind (nick-dedekind) : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Nick Dedekind (nick-dedekind) wrote : | # |
* Did you perform an exploratory manual test run of the code change and any related functionality?
Yes.
* Did CI run pass? If not, please explain why.
Yes
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Michał Sawicz (saviq) wrote : | # |
Approving the uncommit, sorry for the confusion.
Preview Diff
1 | === modified file 'src/modules/Unity/Application/application.cpp' | |||
2 | --- src/modules/Unity/Application/application.cpp 2015-08-20 16:04:25 +0000 | |||
3 | +++ src/modules/Unity/Application/application.cpp 2015-10-01 08:04:31 +0000 | |||
4 | @@ -73,10 +73,27 @@ | |||
5 | 73 | qCDebug(QTMIR_APPLICATIONS) << "Application::~Application"; | 73 | qCDebug(QTMIR_APPLICATIONS) << "Application::~Application"; |
6 | 74 | 74 | ||
7 | 75 | // (ricmm) -- To be on the safe side, better wipe the application QML compile cache if it crashes on startup | 75 | // (ricmm) -- To be on the safe side, better wipe the application QML compile cache if it crashes on startup |
12 | 76 | if (m_processState == Application::ProcessUnknown | 76 | if (m_processState == Application::ProcessUnknown) { |
13 | 77 | || state() == Application::Starting | 77 | wipeQMLCache(); |
14 | 78 | || state() == Application::Running) { | 78 | } |
15 | 79 | wipeQMLCache(); | 79 | |
16 | 80 | switch (m_state) { | ||
17 | 81 | case InternalState::Starting: | ||
18 | 82 | case InternalState::Running: | ||
19 | 83 | case InternalState::RunningInBackground: | ||
20 | 84 | case InternalState::SuspendingWaitSession: | ||
21 | 85 | case InternalState::SuspendingWaitProcess: | ||
22 | 86 | wipeQMLCache(); | ||
23 | 87 | break; | ||
24 | 88 | case InternalState::Closing: | ||
25 | 89 | case InternalState::Suspended: | ||
26 | 90 | case InternalState::StoppedResumable: | ||
27 | 91 | break; | ||
28 | 92 | case InternalState::Stopped: | ||
29 | 93 | if (m_processState == Application::ProcessFailed) { // process crashed | ||
30 | 94 | wipeQMLCache(); | ||
31 | 95 | } | ||
32 | 96 | break; | ||
33 | 80 | } | 97 | } |
34 | 81 | 98 | ||
35 | 82 | if (m_session) { | 99 | if (m_session) { |
36 | @@ -203,6 +220,8 @@ | |||
37 | 203 | return "SuspendingWaitProcess"; | 220 | return "SuspendingWaitProcess"; |
38 | 204 | case InternalState::Suspended: | 221 | case InternalState::Suspended: |
39 | 205 | return "Suspended"; | 222 | return "Suspended"; |
40 | 223 | case InternalState::Closing: | ||
41 | 224 | return "Closing"; | ||
42 | 206 | case InternalState::StoppedResumable: | 225 | case InternalState::StoppedResumable: |
43 | 207 | return "StoppedResumable"; | 226 | return "StoppedResumable"; |
44 | 208 | case InternalState::Stopped: | 227 | case InternalState::Stopped: |
45 | @@ -266,6 +285,7 @@ | |||
46 | 266 | case InternalState::RunningInBackground: | 285 | case InternalState::RunningInBackground: |
47 | 267 | case InternalState::SuspendingWaitSession: | 286 | case InternalState::SuspendingWaitSession: |
48 | 268 | case InternalState::SuspendingWaitProcess: | 287 | case InternalState::SuspendingWaitProcess: |
49 | 288 | case InternalState::Closing: | ||
50 | 269 | return Running; | 289 | return Running; |
51 | 270 | case InternalState::Suspended: | 290 | case InternalState::Suspended: |
52 | 271 | return Suspended; | 291 | return Suspended; |
53 | @@ -321,6 +341,8 @@ | |||
54 | 321 | case InternalState::SuspendingWaitProcess: | 341 | case InternalState::SuspendingWaitProcess: |
55 | 322 | // should leave the app alone until it reaches Suspended state | 342 | // should leave the app alone until it reaches Suspended state |
56 | 323 | break; | 343 | break; |
57 | 344 | case InternalState::Closing: | ||
58 | 345 | break; | ||
59 | 324 | case InternalState::StoppedResumable: | 346 | case InternalState::StoppedResumable: |
60 | 325 | respawn(); | 347 | respawn(); |
61 | 326 | break; | 348 | break; |
62 | @@ -350,6 +372,9 @@ | |||
63 | 350 | case InternalState::Suspended: | 372 | case InternalState::Suspended: |
64 | 351 | // it's already going where we it's wanted | 373 | // it's already going where we it's wanted |
65 | 352 | break; | 374 | break; |
66 | 375 | case InternalState::Closing: | ||
67 | 376 | // don't suspend while it is closing | ||
68 | 377 | break; | ||
69 | 353 | case InternalState::StoppedResumable: | 378 | case InternalState::StoppedResumable: |
70 | 354 | case InternalState::Stopped: | 379 | case InternalState::Stopped: |
71 | 355 | // the app doesn't have a process in the first place, so there's nothing to suspend | 380 | // the app doesn't have a process in the first place, so there's nothing to suspend |
72 | @@ -382,6 +407,32 @@ | |||
73 | 382 | m_pid = pid; | 407 | m_pid = pid; |
74 | 383 | } | 408 | } |
75 | 384 | 409 | ||
76 | 410 | void Application::close() | ||
77 | 411 | { | ||
78 | 412 | qCDebug(QTMIR_APPLICATIONS) << "Application::close - appId=" << appId(); | ||
79 | 413 | |||
80 | 414 | switch (m_state) { | ||
81 | 415 | case InternalState::Starting: | ||
82 | 416 | case InternalState::Running: | ||
83 | 417 | setInternalState(InternalState::Closing); | ||
84 | 418 | break; | ||
85 | 419 | case InternalState::RunningInBackground: | ||
86 | 420 | case InternalState::SuspendingWaitSession: | ||
87 | 421 | case InternalState::SuspendingWaitProcess: | ||
88 | 422 | case InternalState::Suspended: | ||
89 | 423 | setRequestedState(RequestedRunning); | ||
90 | 424 | setInternalState(InternalState::Closing); | ||
91 | 425 | break; | ||
92 | 426 | case InternalState::Closing: | ||
93 | 427 | // already on the way | ||
94 | 428 | break; | ||
95 | 429 | case InternalState::StoppedResumable: | ||
96 | 430 | case InternalState::Stopped: | ||
97 | 431 | // too late | ||
98 | 432 | break; | ||
99 | 433 | } | ||
100 | 434 | } | ||
101 | 435 | |||
102 | 385 | void Application::setArguments(const QStringList arguments) | 436 | void Application::setArguments(const QStringList arguments) |
103 | 386 | { | 437 | { |
104 | 387 | m_arguments = arguments; | 438 | m_arguments = arguments; |
105 | @@ -411,6 +462,7 @@ | |||
106 | 411 | case InternalState::Starting: | 462 | case InternalState::Starting: |
107 | 412 | case InternalState::Running: | 463 | case InternalState::Running: |
108 | 413 | case InternalState::RunningInBackground: | 464 | case InternalState::RunningInBackground: |
109 | 465 | case InternalState::Closing: | ||
110 | 414 | m_session->resume(); | 466 | m_session->resume(); |
111 | 415 | break; | 467 | break; |
112 | 416 | case InternalState::SuspendingWaitSession: | 468 | case InternalState::SuspendingWaitSession: |
113 | @@ -474,6 +526,9 @@ | |||
114 | 474 | case InternalState::Suspended: | 526 | case InternalState::Suspended: |
115 | 475 | releaseWakelock(); | 527 | releaseWakelock(); |
116 | 476 | break; | 528 | break; |
117 | 529 | case InternalState::Closing: | ||
118 | 530 | acquireWakelock(); | ||
119 | 531 | break; | ||
120 | 477 | case InternalState::StoppedResumable: | 532 | case InternalState::StoppedResumable: |
121 | 478 | releaseWakelock(); | 533 | releaseWakelock(); |
122 | 479 | break; | 534 | break; |
123 | @@ -546,7 +601,8 @@ | |||
124 | 546 | if (m_state == InternalState::Starting) { | 601 | if (m_state == InternalState::Starting) { |
125 | 547 | // that was way too soon. let it go away | 602 | // that was way too soon. let it go away |
126 | 548 | setInternalState(InternalState::Stopped); | 603 | setInternalState(InternalState::Stopped); |
128 | 549 | } else if (m_state == InternalState::StoppedResumable) { | 604 | } else if (m_state == InternalState::StoppedResumable || |
129 | 605 | m_state == InternalState::Closing) { | ||
130 | 550 | // The application stopped nicely, likely closed itself. Thus not meant to be resumed later. | 606 | // The application stopped nicely, likely closed itself. Thus not meant to be resumed later. |
131 | 551 | setInternalState(InternalState::Stopped); | 607 | setInternalState(InternalState::Stopped); |
132 | 552 | } else { | 608 | } else { |
133 | @@ -657,7 +713,8 @@ | |||
134 | 657 | case Session::Stopped: | 713 | case Session::Stopped: |
135 | 658 | if (!canBeResumed() | 714 | if (!canBeResumed() |
136 | 659 | || m_state == InternalState::Starting | 715 | || m_state == InternalState::Starting |
138 | 660 | || m_state == InternalState::Running) { | 716 | || m_state == InternalState::Running |
139 | 717 | || m_state == InternalState::Closing) { | ||
140 | 661 | /* 1. application is not managed by upstart | 718 | /* 1. application is not managed by upstart |
141 | 662 | * 2. application is managed by upstart, but has stopped before it managed | 719 | * 2. application is managed by upstart, but has stopped before it managed |
142 | 663 | * to create a surface, we can assume it crashed on startup, and thus | 720 | * to create a surface, we can assume it crashed on startup, and thus |
143 | @@ -665,6 +722,7 @@ | |||
144 | 665 | * 3. application is managed by upstart and is in foreground (i.e. has | 722 | * 3. application is managed by upstart and is in foreground (i.e. has |
145 | 666 | * Running state), if Mir reports the application disconnects, it | 723 | * Running state), if Mir reports the application disconnects, it |
146 | 667 | * either crashed or stopped itself. | 724 | * either crashed or stopped itself. |
147 | 725 | * 4. We're expecting the application to stop after a close request | ||
148 | 668 | */ | 726 | */ |
149 | 669 | setInternalState(InternalState::Stopped); | 727 | setInternalState(InternalState::Stopped); |
150 | 670 | } else { | 728 | } else { |
151 | 671 | 729 | ||
152 | === modified file 'src/modules/Unity/Application/application.h' | |||
153 | --- src/modules/Unity/Application/application.h 2015-08-20 16:10:50 +0000 | |||
154 | +++ src/modules/Unity/Application/application.h 2015-10-01 08:04:31 +0000 | |||
155 | @@ -72,6 +72,7 @@ | |||
156 | 72 | SuspendingWaitSession, | 72 | SuspendingWaitSession, |
157 | 73 | SuspendingWaitProcess, | 73 | SuspendingWaitProcess, |
158 | 74 | Suspended, | 74 | Suspended, |
159 | 75 | Closing, // The user has requested the app be closed | ||
160 | 75 | StoppedResumable, // The process stopped but we want to keep the Application object around | 76 | StoppedResumable, // The process stopped but we want to keep the Application object around |
161 | 76 | // so it can be respawned as if it never stopped running in the first place. | 77 | // so it can be respawned as if it never stopped running in the first place. |
162 | 77 | Stopped // It closed itself, crashed or it stopped and we can't respawn it | 78 | Stopped // It closed itself, crashed or it stopped and we can't respawn it |
163 | @@ -125,6 +126,8 @@ | |||
164 | 125 | 126 | ||
165 | 126 | pid_t pid() const; | 127 | pid_t pid() const; |
166 | 127 | 128 | ||
167 | 129 | void close(); | ||
168 | 130 | |||
169 | 128 | // for tests | 131 | // for tests |
170 | 129 | InternalState internalState() const { return m_state; } | 132 | InternalState internalState() const { return m_state; } |
171 | 130 | 133 | ||
172 | 131 | 134 | ||
173 | === modified file 'src/modules/Unity/Application/application_manager.cpp' | |||
174 | --- src/modules/Unity/Application/application_manager.cpp 2015-08-21 00:00:16 +0000 | |||
175 | +++ src/modules/Unity/Application/application_manager.cpp 2015-10-01 08:04:31 +0000 | |||
176 | @@ -438,6 +438,7 @@ | |||
177 | 438 | return false; | 438 | return false; |
178 | 439 | } | 439 | } |
179 | 440 | 440 | ||
180 | 441 | application->close(); | ||
181 | 441 | remove(application); | 442 | remove(application); |
182 | 442 | 443 | ||
183 | 443 | bool result = m_taskController->stop(application->longAppId()); | 444 | bool result = m_taskController->stop(application->longAppId()); |
184 | 444 | 445 | ||
185 | === modified file 'tests/modules/ApplicationManager/application_manager_test.cpp' | |||
186 | --- tests/modules/ApplicationManager/application_manager_test.cpp 2015-08-31 09:51:28 +0000 | |||
187 | +++ tests/modules/ApplicationManager/application_manager_test.cpp 2015-10-01 08:04:31 +0000 | |||
188 | @@ -1853,3 +1853,137 @@ | |||
189 | 1853 | ASSERT_EQ(Application::InternalState::RunningInBackground, application->internalState()); | 1853 | ASSERT_EQ(Application::InternalState::RunningInBackground, application->internalState()); |
190 | 1854 | EXPECT_EQ(Application::Running, application->state()); | 1854 | EXPECT_EQ(Application::Running, application->state()); |
191 | 1855 | } | 1855 | } |
192 | 1856 | |||
193 | 1857 | /* | ||
194 | 1858 | * Test that when user stops an application, application does not delete QML cache | ||
195 | 1859 | */ | ||
196 | 1860 | TEST_F(ApplicationManagerTests,QMLcacheRetainedOnAppStop) | ||
197 | 1861 | { | ||
198 | 1862 | using namespace ::testing; | ||
199 | 1863 | const QString appId("testAppId1234"); | ||
200 | 1864 | quint64 procId = 5551; | ||
201 | 1865 | |||
202 | 1866 | // Set up Mocks & signal watcher | ||
203 | 1867 | auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo()); | ||
204 | 1868 | ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true)); | ||
205 | 1869 | ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId)); | ||
206 | 1870 | |||
207 | 1871 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader)); | ||
208 | 1872 | |||
209 | 1873 | EXPECT_CALL(appController, startApplicationWithAppIdAndArgs(appId, _)) | ||
210 | 1874 | .Times(1) | ||
211 | 1875 | .WillOnce(Return(true)); | ||
212 | 1876 | |||
213 | 1877 | applicationManager.startApplication(appId, ApplicationManager::NoFlag); | ||
214 | 1878 | applicationManager.onProcessStarting(appId); | ||
215 | 1879 | std::shared_ptr<mir::scene::Session> session = std::make_shared<MockSession>("", procId); | ||
216 | 1880 | bool authed = true; | ||
217 | 1881 | applicationManager.authorizeSession(procId, authed); | ||
218 | 1882 | onSessionStarting(session); | ||
219 | 1883 | |||
220 | 1884 | // Create fake QML cache for this app | ||
221 | 1885 | QString path(QDir::homePath() + QStringLiteral("/.cache/QML/Apps/") + appId); | ||
222 | 1886 | QDir dir(path); | ||
223 | 1887 | dir.mkpath(path); | ||
224 | 1888 | |||
225 | 1889 | // Stop app | ||
226 | 1890 | applicationManager.stopApplication(appId); | ||
227 | 1891 | |||
228 | 1892 | EXPECT_EQ(0, applicationManager.count()); | ||
229 | 1893 | EXPECT_TRUE(dir.exists()); | ||
230 | 1894 | } | ||
231 | 1895 | |||
232 | 1896 | /* | ||
233 | 1897 | * Test that if running application stops unexpectedly, AppMan deletes the QML cache | ||
234 | 1898 | */ | ||
235 | 1899 | TEST_F(ApplicationManagerTests,DISABLED_QMLcacheDeletedOnAppCrash) | ||
236 | 1900 | { | ||
237 | 1901 | using namespace ::testing; | ||
238 | 1902 | const QString appId("testAppId12345"); | ||
239 | 1903 | quint64 procId = 5551; | ||
240 | 1904 | |||
241 | 1905 | // Set up Mocks & signal watcher | ||
242 | 1906 | auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo()); | ||
243 | 1907 | ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true)); | ||
244 | 1908 | ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId)); | ||
245 | 1909 | |||
246 | 1910 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader)); | ||
247 | 1911 | |||
248 | 1912 | EXPECT_CALL(appController, startApplicationWithAppIdAndArgs(appId, _)) | ||
249 | 1913 | .Times(1) | ||
250 | 1914 | .WillOnce(Return(true)); | ||
251 | 1915 | |||
252 | 1916 | Application *the_app = applicationManager.startApplication(appId, ApplicationManager::NoFlag); | ||
253 | 1917 | applicationManager.onProcessStarting(appId); | ||
254 | 1918 | std::shared_ptr<mir::scene::Session> session = std::make_shared<MockSession>("", procId); | ||
255 | 1919 | bool authed = true; | ||
256 | 1920 | applicationManager.authorizeSession(procId, authed); | ||
257 | 1921 | onSessionStarting(session); | ||
258 | 1922 | |||
259 | 1923 | // Have app in fully Running state | ||
260 | 1924 | FakeMirSurface *aSurface = new FakeMirSurface; | ||
261 | 1925 | onSessionCreatedSurface(session.get(), aSurface); | ||
262 | 1926 | aSurface->drawFirstFrame(); | ||
263 | 1927 | ASSERT_EQ(Application::InternalState::Running, the_app->internalState()); | ||
264 | 1928 | |||
265 | 1929 | // Create fake QML cache for this app | ||
266 | 1930 | QString path(QDir::homePath() + QStringLiteral("/.cache/QML/Apps/") + appId); | ||
267 | 1931 | QDir dir(path); | ||
268 | 1932 | dir.mkpath(path); | ||
269 | 1933 | |||
270 | 1934 | // Report app crash | ||
271 | 1935 | onSessionStopping(session); | ||
272 | 1936 | // Upstart notifies of **crashing** app | ||
273 | 1937 | applicationManager.onProcessFailed(appId, true); | ||
274 | 1938 | applicationManager.onProcessStopped(appId); | ||
275 | 1939 | |||
276 | 1940 | EXPECT_EQ(0, applicationManager.count()); | ||
277 | 1941 | EXPECT_FALSE(dir.exists()); | ||
278 | 1942 | } | ||
279 | 1943 | |||
280 | 1944 | /* | ||
281 | 1945 | * Test that if running application stops itself cleanly, AppMan retains the QML cache | ||
282 | 1946 | */ | ||
283 | 1947 | TEST_F(ApplicationManagerTests,QMLcacheRetainedOnAppShutdown) | ||
284 | 1948 | { | ||
285 | 1949 | using namespace ::testing; | ||
286 | 1950 | const QString appId("testAppId123456"); | ||
287 | 1951 | quint64 procId = 5551; | ||
288 | 1952 | |||
289 | 1953 | // Set up Mocks & signal watcher | ||
290 | 1954 | auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo()); | ||
291 | 1955 | ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true)); | ||
292 | 1956 | ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId)); | ||
293 | 1957 | |||
294 | 1958 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader)); | ||
295 | 1959 | |||
296 | 1960 | EXPECT_CALL(appController, startApplicationWithAppIdAndArgs(appId, _)) | ||
297 | 1961 | .Times(1) | ||
298 | 1962 | .WillOnce(Return(true)); | ||
299 | 1963 | |||
300 | 1964 | Application *the_app = applicationManager.startApplication(appId, ApplicationManager::NoFlag); | ||
301 | 1965 | applicationManager.onProcessStarting(appId); | ||
302 | 1966 | std::shared_ptr<mir::scene::Session> session = std::make_shared<MockSession>("", procId); | ||
303 | 1967 | bool authed = true; | ||
304 | 1968 | applicationManager.authorizeSession(procId, authed); | ||
305 | 1969 | onSessionStarting(session); | ||
306 | 1970 | |||
307 | 1971 | // Have app in fully Running state | ||
308 | 1972 | FakeMirSurface *aSurface = new FakeMirSurface; | ||
309 | 1973 | onSessionCreatedSurface(session.get(), aSurface); | ||
310 | 1974 | aSurface->drawFirstFrame(); | ||
311 | 1975 | ASSERT_EQ(Application::InternalState::Running, the_app->internalState()); | ||
312 | 1976 | |||
313 | 1977 | // Create fake QML cache for this app | ||
314 | 1978 | QString path(QDir::homePath() + QStringLiteral("/.cache/QML/Apps/") + appId); | ||
315 | 1979 | QDir dir(path); | ||
316 | 1980 | dir.mkpath(path); | ||
317 | 1981 | |||
318 | 1982 | // Report app stop | ||
319 | 1983 | onSessionStopping(session); | ||
320 | 1984 | // Upstart notifies of stopping app | ||
321 | 1985 | applicationManager.onProcessStopped(appId); | ||
322 | 1986 | |||
323 | 1987 | EXPECT_EQ(0, applicationManager.count()); | ||
324 | 1988 | EXPECT_TRUE(dir.exists()); | ||
325 | 1989 | } |
If app crashes, the QML cache may not be cleared. This requires additional work, which I'd prefer to consider in a later MR.