OSDN Git Service

easier to override defaults
[kde/libdbusmenu-qt.git] / tests / dbusmenuimportertest.cpp
1 /* This file is part of the dbusmenu-qt library
2    Copyright 2010 Canonical
3    Author: Aurelien Gateau <aurelien.gateau@canonical.com>
4
5    This library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Library General Public
7    License (LGPL) as published by the Free Software Foundation;
8    either version 2 of the License, or (at your option) any later
9    version.
10
11    This library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Library General Public License for more details.
15
16    You should have received a copy of the GNU Library General Public License
17    along with this library; see the file COPYING.LIB.  If not, write to
18    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19    Boston, MA 02110-1301, USA.
20 */
21 // Self
22 #include "dbusmenuimportertest.h"
23
24 // Qt
25 #include <QTimer>
26 #include <QProcess>
27 #include <QDBusConnection>
28 #include <QDBusInterface>
29 #include <QDBusReply>
30 #include <QIcon>
31 #include <QMenu>
32 #include <QtTest>
33
34 // DBusMenuQt
35 #include <dbusmenuexporter.h>
36 #include <dbusmenuimporter.h>
37 #include <debug_p.h>
38
39 // Local
40 #include "testutils.h"
41
42 QTEST_MAIN(DBusMenuImporterTest)
43
44 static const char *TEST_SERVICE = "com.canonical.dbusmenu-qt-test";
45 static const char *TEST_OBJECT_PATH = "/TestMenuBar";
46
47 Q_DECLARE_METATYPE(QAction*)
48
49 void DBusMenuImporterTest::initTestCase()
50 {
51     qRegisterMetaType<QAction*>("QAction*");
52     QVERIFY(QDBusConnection::sessionBus().registerService(TEST_SERVICE));
53 }
54
55 void DBusMenuImporterTest::cleanup()
56 {
57     waitForDeferredDeletes();
58 }
59
60 void DBusMenuImporterTest::testStandardItem()
61 {
62     QMenu inputMenu;
63     QAction *action = inputMenu.addAction("Test");
64     DBusMenuExporter exporter(TEST_OBJECT_PATH, &inputMenu);
65
66     DBusMenuImporter importer(TEST_SERVICE, TEST_OBJECT_PATH);
67     QTest::qWait(500);
68
69     QMenu *outputMenu = importer.menu();
70     QCOMPARE(outputMenu->actions().count(), 1);
71     QAction *outputAction = outputMenu->actions().first();
72     QCOMPARE(outputAction->text(), QString("Test"));
73 }
74
75 void DBusMenuImporterTest::testAddingNewItem()
76 {
77     QMenu inputMenu;
78     QAction *action = inputMenu.addAction("Test");
79     DBusMenuExporter exporter(TEST_OBJECT_PATH, &inputMenu);
80
81     DBusMenuImporter importer(TEST_SERVICE, TEST_OBJECT_PATH);
82     QTest::qWait(500);
83     QMenu *outputMenu = importer.menu();
84     QCOMPARE(outputMenu->actions().count(), inputMenu.actions().count());
85
86     inputMenu.addAction("Test2");
87     QTest::qWait(500);
88     QCOMPARE(outputMenu->actions().count(), inputMenu.actions().count());
89 }
90
91 void DBusMenuImporterTest::testShortcut()
92 {
93     QMenu inputMenu;
94     QAction *action = inputMenu.addAction("Test");
95     action->setShortcut(Qt::CTRL | Qt::Key_S);
96     DBusMenuExporter exporter(TEST_OBJECT_PATH, &inputMenu);
97
98     DBusMenuImporter importer(TEST_SERVICE, TEST_OBJECT_PATH);
99     QTest::qWait(500);
100     QMenu *outputMenu = importer.menu();
101
102     QAction *outputAction = outputMenu->actions().at(0);
103     QCOMPARE(outputAction->shortcut(), action->shortcut());
104 }
105
106 void DBusMenuImporterTest::testDeletingImporterWhileWaitingForAboutToShow()
107 {
108     // Start test program and wait for it to be ready
109     QProcess slowMenuProcess;
110     slowMenuProcess.start("./slowmenu");
111     QTest::qWait(500);
112
113     // Create importer and wait for the menu
114     DBusMenuImporter *importer = new DBusMenuImporter(TEST_SERVICE, TEST_OBJECT_PATH);
115     QTest::qWait(500);
116
117     QMenu *outputMenu = importer->menu();
118     QTimer::singleShot(100, importer, SLOT(deleteLater()));
119     outputMenu->popup(QPoint(0, 0));
120
121     // If it crashes, it will crash while waiting there
122     QTest::qWait(500);
123
124     // Done, stop our test program
125     slowMenuProcess.close();
126     slowMenuProcess.waitForFinished();
127 }
128
129 void DBusMenuImporterTest::testDynamicMenu()
130 {
131     QMenu rootMenu;
132     QAction* a1 = new QAction("a1", &rootMenu);
133     QAction* a2 = new QAction("a2", &rootMenu);
134     MenuFiller rootMenuFiller(&rootMenu);
135     rootMenuFiller.addAction(a1);
136     rootMenuFiller.addAction(a2);
137
138     QMenu subMenu;
139     MenuFiller subMenuFiller(&subMenu);
140     subMenuFiller.addAction(new QAction("a3", &subMenu));
141
142     a1->setMenu(&subMenu);
143
144     DBusMenuExporter exporter(TEST_OBJECT_PATH, &rootMenu);
145
146     // Import this menu
147     DBusMenuImporter importer(TEST_SERVICE, TEST_OBJECT_PATH);
148     QTest::qWait(500);
149     QMenu *outputMenu = importer.menu();
150
151     // There should be no children for now
152     QCOMPARE(outputMenu->actions().count(), 0);
153
154     // Update menu, a1 and a2 should get added
155     QSignalSpy spy(&importer, SIGNAL(menuUpdated()));
156     importer.updateMenu();
157     while (spy.isEmpty()) {
158         QTest::qWait(500);
159     }
160
161     QCOMPARE(outputMenu->actions().count(), 2);
162     QTest::qWait(500);
163     QAction* a1Output = outputMenu->actions().first();
164
165     // a1Output should have an empty menu
166     QMenu* a1OutputMenu = a1Output->menu();
167     QVERIFY(a1OutputMenu);
168     QCOMPARE(a1OutputMenu->actions().count(), 0);
169
170     // Show a1OutputMenu, a3 should get added
171     QMetaObject::invokeMethod(a1OutputMenu, "aboutToShow");
172     QTest::qWait(500);
173
174     QCOMPARE(a1OutputMenu->actions().count(), 1);
175
176     // menuUpdated() should only have been emitted once
177     QCOMPARE(spy.count(), 1);
178 }
179
180 void DBusMenuImporterTest::testActionActivationRequested()
181 {
182     // Export a menu
183     QMenu inputMenu;
184     QAction *inputA1 = inputMenu.addAction("a1");
185     QAction *inputA2 = inputMenu.addAction("a2");
186     DBusMenuExporter exporter(TEST_OBJECT_PATH, &inputMenu);
187
188     // Import the menu
189     DBusMenuImporter importer(TEST_SERVICE, TEST_OBJECT_PATH);
190     QSignalSpy spy(&importer, SIGNAL(actionActivationRequested(QAction*)));
191
192     QTest::qWait(500);
193     QMenu *outputMenu = importer.menu();
194
195     // Get matching output actions
196     QCOMPARE(outputMenu->actions().count(), 2);
197     QAction *outputA1 = outputMenu->actions().at(0);
198     QAction *outputA2 = outputMenu->actions().at(1);
199
200     // Request activation
201     exporter.activateAction(inputA1);
202     exporter.activateAction(inputA2);
203
204     // Check we received the signal in the right order
205     QTest::qWait(500);
206     QCOMPARE(spy.count(), 2);
207     QCOMPARE(spy.takeFirst().at(0).value<QAction*>(), outputA1);
208     QCOMPARE(spy.takeFirst().at(0).value<QAction*>(), outputA2);
209 }
210
211 void DBusMenuImporterTest::testActionsAreDeletedWhenImporterIs()
212 {
213     // Export a menu
214     QMenu inputMenu;
215     inputMenu.addAction("a1");
216     QMenu *inputSubMenu = inputMenu.addMenu("subMenu");
217     inputSubMenu->addAction("a2");
218     DBusMenuExporter exporter(TEST_OBJECT_PATH, &inputMenu);
219
220     // Import the menu
221     DBusMenuImporter *importer = new DBusMenuImporter(TEST_SERVICE, TEST_OBJECT_PATH);
222     QTest::qWait(500);
223
224     // Put all items of the menu in a list of QPointers
225     QList< QPointer<QObject> > children;
226
227     QMenu *outputMenu = importer->menu();
228     QCOMPARE(outputMenu->actions().count(), 2);
229     QMenu *outputSubMenu = outputMenu->actions().at(1)->menu();
230     QVERIFY(outputSubMenu);
231     // Fake aboutToShow so that outputSubMenu is populated
232     QMetaObject::invokeMethod(outputSubMenu, "aboutToShow");
233     QCOMPARE(outputSubMenu->actions().count(), 1);
234
235     children << outputMenu->actions().at(0);
236     children << outputMenu->actions().at(1);
237     children << outputSubMenu;
238     children << outputSubMenu->actions().at(0);
239
240     delete importer;
241     waitForDeferredDeletes();
242
243     // There should be only invalid pointers in children
244     Q_FOREACH(QPointer<QObject> child, children) {
245         //qDebug() << child;
246         QVERIFY(child.isNull());
247     }
248 }
249
250 void DBusMenuImporterTest::testIconData()
251 {
252     // Create an icon
253     QImage img(16, 16, QImage::Format_ARGB32);
254     {
255         QPainter painter(&img);
256         painter.setCompositionMode(QPainter::CompositionMode_Source);
257         QRect rect = img.rect();
258         painter.fillRect(rect, Qt::transparent);
259         rect.adjust(2, 2, -2, -2);
260         painter.fillRect(rect, Qt::red);
261         rect.adjust(2, 2, -2, -2);
262         painter.fillRect(rect, Qt::green);
263     }
264     QIcon inputIcon(QPixmap::fromImage(img));
265
266     // Export a menu
267     QMenu inputMenu;
268     QAction *a1 = inputMenu.addAction("a1");
269     a1->setIcon(inputIcon);
270     DBusMenuExporter exporter(TEST_OBJECT_PATH, &inputMenu);
271
272     // Import the menu
273     DBusMenuImporter *importer = new DBusMenuImporter(TEST_SERVICE, TEST_OBJECT_PATH);
274     QTest::qWait(500);
275
276     // Check icon of action
277     QMenu *outputMenu = importer->menu();
278     QCOMPARE(outputMenu->actions().count(), 1);
279
280     QIcon outputIcon = outputMenu->actions().first()->icon();
281     QVERIFY(!outputIcon.isNull());
282
283     QImage result = outputIcon.pixmap(16).toImage();
284     QByteArray origBytes, resultBytes;
285     img.save(origBytes);
286     result.save(resultBytes);
287     QCOMPARE(origBytes,resultBytes);
288 }
289
290 void DBusMenuImporterTest::testInvisibleItem()
291 {
292     QMenu inputMenu;
293     QAction *action = inputMenu.addAction("Test");
294     DBusMenuExporter exporter(TEST_OBJECT_PATH, &inputMenu);
295
296     DBusMenuImporter importer(TEST_SERVICE, TEST_OBJECT_PATH);
297     QTest::qWait(500);
298
299     QMenu *outputMenu = importer.menu();
300     QCOMPARE(outputMenu->actions().count(), 1);
301     QAction *outputAction = outputMenu->actions().first();
302
303     QVERIFY(outputAction->isVisible());
304
305     // Hide the action
306     action->setVisible(false);
307     QTest::qWait(500);
308     QVERIFY(!outputAction->isVisible());
309
310     // Show the action
311     action->setVisible(true);
312     QTest::qWait(500);
313     QVERIFY(outputAction->isVisible());
314 }
315
316 void DBusMenuImporterTest::testDisabledItem()
317 {
318     QMenu inputMenu;
319     QAction *action = inputMenu.addAction("Test");
320     DBusMenuExporter exporter(TEST_OBJECT_PATH, &inputMenu);
321
322     DBusMenuImporter importer(TEST_SERVICE, TEST_OBJECT_PATH);
323     QTest::qWait(500);
324
325     QMenu *outputMenu = importer.menu();
326     QCOMPARE(outputMenu->actions().count(), 1);
327     QAction *outputAction = outputMenu->actions().first();
328     QVERIFY(outputAction->isEnabled());
329
330     // Disable the action
331     DMDEBUG << "Disabling";
332     action->setEnabled(false);
333     QTest::qWait(500);
334     QVERIFY(!outputAction->isEnabled());
335
336     // Enable the action
337     action->setEnabled(true);
338     QTest::qWait(500);
339     QVERIFY(outputAction->isEnabled());
340 }
341
342 #include "moc_dbusmenuimportertest.cpp"