Merge lp:~macslow/unity-notifications/fix-1453958 into lp:unity-notifications

Proposed by Mirco Müller on 2015-05-19
Status: Rejected
Rejected by: Michał Sawicz on 2015-10-13
Proposed branch: lp:~macslow/unity-notifications/fix-1453958
Merge into: lp:unity-notifications
Diff against target: 274 lines (+121/-68)
4 files modified
src/Notification.cpp (+3/-3)
src/NotificationModel.cpp (+38/-27)
test/CMakeLists.txt (+1/-1)
test/notificationtest.cpp (+79/-37)
To merge this branch: bzr merge lp:~macslow/unity-notifications/fix-1453958
Reviewer Review Type Date Requested Status
Michał Sawicz Disapprove on 2015-10-13
Antti Kaijanmäki (community) 2015-05-19 Approve on 2015-05-21
Review via email: mp+259538@code.launchpad.net

Commit Message

Plugged memory-leaks causing the backend to crash the unity8-notification-plugin and updated unit-tests. Deleting notifications in reverse order of insertion no longer result the segfault forced by the provided python-script.

Description of the Change

Plugged memory-leaks causing the backend to crash the unity8-notification-plugin and updated unit-tests. Deleting notifications in reverse order of insertion no longer result the segfault forced by the provided python-script.

* Are there any related MPs required for this MP to build/function as expected? Please list.
No.

* Did you perform an exploratory manual test run of your code change and any related functionality?
Yes.

* Did you make sure that your branch does not contain spurious tags?
Yes.

* If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?
Not applicable.

* If you changed the UI, has there been a design review?
Not applicable.

To post a comment you must log in.
Lukáš Tinkl (lukas-kde) wrote :

Obviously +1 from me as I helped writing this code :)

226. By Mirco Müller on 2015-05-21

Make the notification object itself the parent of the ActionModel, not the Notification's parent.

Antti Kaijanmäki (kaijanmaki) wrote :

LGTM.

review: Approve

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/Notification.cpp'
2--- src/Notification.cpp 2014-09-22 12:43:29 +0000
3+++ src/Notification.cpp 2015-05-21 16:49:54 +0000
4@@ -52,7 +52,7 @@
5 p->body = "default text";
6 p->server = nullptr;
7 p->value = -2;
8- p->actionsModel = new ActionModel();
9+ p->actionsModel = new ActionModel(this);
10 }
11
12 Notification::Notification(NotificationID id, int displayTime, const Urgency ur, const QString &text, Type type, NotificationServer *srv, QObject *parent) :
13@@ -64,12 +64,12 @@
14 p->server = srv;
15 p->value = -2;
16 p->displayTime = displayTime;
17- p->actionsModel = new ActionModel();
18+ p->actionsModel = new ActionModel(this);
19 }
20
21 Notification::Notification(NotificationID id, int displayTime, const Urgency ur, Type type, NotificationServer *srv, QObject *parent) :
22 Notification(id, displayTime, ur, QString(), type, srv, parent){
23- p->actionsModel = new ActionModel();
24+ p->actionsModel = new ActionModel(this);
25 }
26
27 Notification::~Notification() {
28
29=== modified file 'src/NotificationModel.cpp'
30--- src/NotificationModel.cpp 2014-04-28 12:54:22 +0000
31+++ src/NotificationModel.cpp 2015-05-21 16:49:54 +0000
32@@ -202,37 +202,47 @@
33 }
34
35 void NotificationModel::removeNotification(const NotificationID id) {
36- for(int i=0; i<p->ephemeralQueue.size(); i++) {
37- if(p->ephemeralQueue[i]->getID() == id) {
38- p->ephemeralQueue.erase(p->ephemeralQueue.begin() + i);
39- Q_EMIT queueSizeChanged(queued());
40- return;
41- }
42- }
43-
44- for(int i=0; i<p->snapQueue.size(); i++) {
45- if(p->snapQueue[i]->getID() == id) {
46- p->snapQueue.erase(p->snapQueue.begin() + i);
47- Q_EMIT queueSizeChanged(queued());
48- return;
49- }
50- }
51-
52- for(int i=0; i<p->interactiveQueue.size(); i++) {
53- if(p->interactiveQueue[i]->getID() == id) {
54- p->interactiveQueue.erase(p->interactiveQueue.begin() + i);
55- Q_EMIT queueSizeChanged(queued());
56- return;
57- }
58- }
59-
60- for(int i=0; i<p->displayedNotifications.size(); i++) {
61+ for (int i = 0; i < p->displayedNotifications.size(); i++) {
62 if(p->displayedNotifications[i]->getID() == id) {
63 deleteFromVisible(i);
64 timeout(); // Simulate a timeout so visual state is updated.
65 return;
66 }
67 }
68+
69+ for (auto it = p->ephemeralQueue.begin(); it != p->ephemeralQueue.end(); ++it) {
70+ QSharedPointer<Notification> n = *it;
71+
72+ if (n && n->getID() == id) {
73+ p->ephemeralQueue.erase(it);
74+ n.data()->deleteLater();
75+ Q_EMIT queueSizeChanged(queued());
76+ return;
77+ }
78+ }
79+
80+ for (auto it = p->snapQueue.begin(); it != p->snapQueue.end(); ++it) {
81+ QSharedPointer<Notification> n = *it;
82+
83+ if (n && n->getID() == id) {
84+ p->snapQueue.erase(it);
85+ n.data()->deleteLater();
86+ Q_EMIT queueSizeChanged(queued());
87+ return;
88+ }
89+ }
90+
91+ for (auto it = p->interactiveQueue.begin(); it != p->interactiveQueue.end(); ++it) {
92+ QSharedPointer<Notification> n = *it;
93+
94+ if (n && n->getID() == id) {
95+ p->interactiveQueue.erase(it);
96+ n.data()->deleteLater();
97+ Q_EMIT queueSizeChanged(queued());
98+ return;
99+ }
100+ }
101+
102 // The ID was not found in any queue. Should it be an error case or not?
103 }
104
105@@ -246,8 +256,9 @@
106 QModelIndex deletePoint = QModelIndex();
107 beginRemoveRows(deletePoint, loc, loc);
108 QSharedPointer<Notification> n = p->displayedNotifications[loc];
109- p->displayTimes.erase(p->displayTimes.find(n->getID()));
110- p->displayedNotifications.erase(p->displayedNotifications.begin() + loc);
111+ p->displayTimes.remove(n->getID());
112+ p->displayedNotifications.removeAt(loc);
113+ n.clear();
114 endRemoveRows();
115 }
116
117
118=== modified file 'test/CMakeLists.txt'
119--- test/CMakeLists.txt 2013-12-04 17:31:50 +0000
120+++ test/CMakeLists.txt 2015-05-21 16:49:54 +0000
121@@ -1,6 +1,6 @@
122 add_executable(notificationtest notificationtest.cpp)
123 target_link_libraries(notificationtest notifybackend)
124-qt5_use_modules(notificationtest Gui Test Core Widgets)
125+qt5_use_modules(notificationtest Gui Test Core DBus Widgets)
126
127 add_test(notification notificationtest)
128 set_tests_properties(notification PROPERTIES ENVIRONMENT "QT_QPA_PLATFORM=minimal")
129
130=== modified file 'test/notificationtest.cpp'
131--- test/notificationtest.cpp 2014-10-09 08:26:38 +0000
132+++ test/notificationtest.cpp 2015-05-21 16:49:54 +0000
133@@ -1,5 +1,6 @@
134 #include "Notification.h"
135 #include "NotificationModel.h"
136+#include "NotificationServer.h"
137
138 #include <QtTest/QtTest>
139
140@@ -24,6 +25,7 @@
141 void testConfirmationValue();
142 void testTextFilter();
143 void testTextFilter_data();
144+ void testReverseClose();
145 };
146
147 void TestNotifications::testSimpleInsertion() {
148@@ -55,43 +57,50 @@
149 }
150
151 void TestNotifications::testOrder() {
152- const int timeout = 5000;
153- QSharedPointer<Notification> n1(new Notification(1, timeout, Notification::Low, "low", Notification::Ephemeral));
154- QSharedPointer<Notification> n2(new Notification(2, timeout, Notification::Normal, "high", Notification::Ephemeral));
155- QSharedPointer<Notification> n3(new Notification(3, timeout, Notification::Critical, "critical", Notification::Ephemeral));
156- NotificationModel m;
157-
158- m.insertNotification(n1);
159- QVERIFY(m.showingNotification(n1->getID()));
160-
161- m.insertNotification(n2);
162- QVERIFY(!m.showingNotification(n1->getID()));
163- QVERIFY(m.showingNotification(n2->getID()));
164- QVERIFY(m.queued() == 1);
165-
166- m.insertNotification(n3);
167- QVERIFY(!m.showingNotification(n1->getID()));
168- QVERIFY(!m.showingNotification(n2->getID()));
169- QVERIFY(m.showingNotification(n3->getID()));
170- QCOMPARE(m.queued(), 2);
171-
172- m.removeNotification(n3->getID());
173- QVERIFY(!m.showingNotification(n1->getID()));
174- QVERIFY(m.showingNotification(n2->getID()));
175- QVERIFY(!m.showingNotification(n3->getID()));
176- QCOMPARE(m.queued(), 1);
177-
178- m.removeNotification(n2->getID());
179- QVERIFY(m.showingNotification(n1->getID()));
180- QVERIFY(!m.showingNotification(n2->getID()));
181- QVERIFY(!m.showingNotification(n3->getID()));
182- QCOMPARE(m.queued(), 0);
183-
184- m.removeNotification(n1->getID());
185- QVERIFY(!m.showingNotification(n1->getID()));
186- QVERIFY(!m.showingNotification(n2->getID()));
187- QVERIFY(!m.showingNotification(n3->getID()));
188- QCOMPARE(m.queued(), 0);
189+ const int timeout = 1000;
190+ static NotificationModel *m = new NotificationModel();
191+ static NotificationServer *s = new NotificationServer(*m);
192+ QStringList actions = QStringList();
193+ Hints hints;
194+ int id[3];
195+
196+ hints[URGENCY_HINT] = QDBusVariant(Notification::Urgency::Low);
197+ id[0] = s->Notify ("test-name-low", 0, "icon-low", "summary-low", "body-low", actions, hints, timeout);
198+ QVERIFY(m->showingNotification(id[0]));
199+
200+ hints[URGENCY_HINT] = QDBusVariant(Notification::Urgency::Normal);
201+ id[1] = s->Notify ("test-name-normal", 0, "icon-normal", "summary-normal", "body-normal", actions, hints, timeout);
202+ QVERIFY(!m->showingNotification(id[0]));
203+ QVERIFY(m->showingNotification(id[1]));
204+ QVERIFY(m->queued() == 1);
205+
206+ hints[URGENCY_HINT] = QDBusVariant(Notification::Urgency::Critical);
207+ id[2] = s->Notify ("test-name-critical", 0, "icon-critical", "summary-critical", "body-critical", actions, hints, timeout);
208+ QVERIFY(!m->showingNotification(id[0]));
209+ QVERIFY(!m->showingNotification(id[1]));
210+ QVERIFY(m->showingNotification(id[2]));
211+ QCOMPARE(m->queued(), 2);
212+
213+ m->removeNotification(id[2]);
214+ QVERIFY(!m->showingNotification(id[0]));
215+ QVERIFY(m->showingNotification(id[1]));
216+ QVERIFY(!m->showingNotification(id[2]));
217+ QCOMPARE(m->queued(), 1);
218+
219+ m->removeNotification(id[1]);
220+ QVERIFY(m->showingNotification(id[0]));
221+ QVERIFY(!m->showingNotification(id[1]));
222+ QVERIFY(!m->showingNotification(id[2]));
223+ QCOMPARE(m->queued(), 0);
224+
225+ m->removeNotification(id[0]);
226+ QVERIFY(!m->showingNotification(id[0]));
227+ QVERIFY(!m->showingNotification(id[1]));
228+ QVERIFY(!m->showingNotification(id[2]));
229+ QCOMPARE(m->queued(), 0);
230+
231+ delete s;
232+ delete m;
233 }
234
235 void TestNotifications::testHas() {
236@@ -259,5 +268,38 @@
237 QCOMPARE(n.getBody(), result);
238 }
239
240+void TestNotifications::testReverseClose() {
241+ const int timeout = 1000;
242+ const int max = 20;
243+ static NotificationModel *m = new NotificationModel();
244+ static NotificationServer *s = new NotificationServer(*m);
245+ QStringList actions = QStringList();
246+ Hints hints = Hints();
247+ int before = m->numNotifications();
248+
249+ for (int i = 1; i <= max; i++) {
250+ s->Notify ("test-app-name",
251+ 0,
252+ "test-icon",
253+ "test-summary",
254+ "test-body",
255+ actions,
256+ hints,
257+ timeout);
258+ }
259+
260+ QCOMPARE(m->numNotifications(), max+1);
261+
262+ for (int i = max; i >= 1; i--) {
263+ m->getNotification(i)->close();
264+ QCOMPARE(m->numNotifications(), i);
265+ }
266+
267+ QCOMPARE(m->numNotifications(), before);
268+
269+ delete s;
270+ delete m;
271+}
272+
273 QTEST_MAIN(TestNotifications)
274 #include "notificationtest.moc"

Subscribers

People subscribed via source and target branches

to all changes: