1     /*
2 
3                           Firewall Builder
4 
5                  Copyright (C) 2010 NetCitadel, LLC
6 
7   Author:  Roman Bovsunivskiy     a2k0001@gmail.com
8 
9   $Id: RuleSetViewTest.cpp 2786 2010-04-01 14:05:36Z a2k $
10 
11   This program is free software which we release under the GNU General Public
12   License. You may redistribute and/or modify this program under the terms
13   of that license as published by the Free Software Foundation; either
14   version 2 of the License, or (at your option) any later version.
15 
16   This program is distributed in the hope that it will be useful,
17   but WITHOUT ANY WARRANTY; without even the implied warranty of
18   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   GNU General Public License for more details.
20 
21   To get a copy of the GNU General Public License, write to the Free Software
22   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23 
24 */
25 
26 #include "RuleSetViewTest.h"
27 
28 #include "unistd.h"
29 #include <QDir>
30 #include <QFile>
31 #include <QFileInfo>
32 #include <QDesktopWidget>
33 #include <QDebug>
34 #include <QMenuBar>
35 #include <QInputDialog>
36 #include <QApplication>
37 #include <QCoreApplication>
38 #include "StartTipDialog.h"
39 #include "QMetaProperty"
40 #include "FWObjectClipboard.h"
41 #include "RuleSetModel.h"
42 #include "FWBApplication.h"
43 
44 using namespace std;
45 using namespace QTest;
46 using namespace libfwbuilder;
47 
48 #define getRuleForPosition( x ) ((RuleSetModel*)view->model())->findRuleForPosition( x )
49 
initTestCase()50 void RuleSetViewTest::initTestCase()
51 {
52     new FWObjectClipboard();
53     mw = new FWWindow();
54     mw->show();
55     mw->resize(QSize(800,600));
56     mw->startupLoad();
57     StartTipDialog *d = mw->findChild<StartTipDialog*>();
58     if (d) if (d!=NULL) d->close();
59     om = dynamic_cast<ObjectManipulator*>(mw->getCurrentObjectTree()->parent()->parent());
60     Firewall::cast(om->createObject(FWBTree().getStandardSlotForObject(findUserLibrary(), Firewall::TYPENAME), Firewall::TYPENAME, "testFirewall"));
61     openPolicy("testFirewall");
62     view = mw->findChild<RuleSetView*>("");
63     om->closeObject();
64 }
65 
66 /*
67  * Opens context menu at point relative to RuleSetView widget
68  */
showContextMenu(QPoint point)69 void RuleSetViewTest::showContextMenu(QPoint point)
70 {
71     view->showContextMenu(view->pos() + point);
72 }
73 
showContextMenu(int x,int y)74 void RuleSetViewTest::showContextMenu(int x, int y)
75 {
76     view->showContextMenu(view->pos() + QPoint(x,y));
77 }
78 
79 /*
80  * Opens Policy of firewall with name fwname in RuleSetView of active project
81  */
openPolicy(QString fwname)82 void RuleSetViewTest::openPolicy(QString fwname)
83 {
84     Policy *p = NULL;
85     foreach (FWObject *fw, mw->db()->getByTypeDeep(Firewall::TYPENAME))
86     {
87         if (fw->getName() == fwname.toStdString())
88         {
89             p = Firewall::cast(fw)->getPolicy();
90         }
91     }
92     QVERIFY (p != NULL);
93     QCoreApplication::postEvent(mw, new openRulesetImmediatelyEvent(mw->activeProject()->getFileName(), p->getId()));
94     QTest::qWait(100);
95 }
96 
97 /*
98  * Returns libfwbuilder::Library with name "User"
99  */
findUserLibrary()100 Library* RuleSetViewTest::findUserLibrary()
101 {
102     Library *lib = NULL;
103     foreach (FWObject *obj, mw->db()->getByType(Library::TYPENAME))
104     {
105         if (obj->getName() == "User")
106         {
107             lib = Library::cast(obj);
108             break;
109         }
110     }
111     return lib;
112 }
113 
114 /*
115  * Returns menu-relative position of topmost pixel clicking
116  * which will trigger action
117  */
findActionPos(QMenu * menu,QAction * action)118 QPoint findActionPos(QMenu *menu, QAction *action)
119 {
120     int x = menu->width()/2;
121     for (int y=0; y<menu->height(); y++)
122     {
123         if (menu->actionAt(QPoint(x,y)) != NULL && menu->actionAt(QPoint(x,y))->text() == action->text())
124             return QPoint(x,y);
125     }
126     return QPoint(-1,-1);
127 }
128 
129 /*
130  * Clicks item in topmost visible modal context menu.
131  * Should be called right before opening menu (it waits 10 ms for menu to appear).
132  */
clickMenuItem(QString item)133 void RuleSetViewTest::clickMenuItem(QString item)
134 {
135     clicked = false;
136     itemToClick = item;
137     QTimer::singleShot(100, this, SLOT(actuallyClickMenuItem()));
138 }
139 
actuallyClickMenuItem()140 void RuleSetViewTest::actuallyClickMenuItem()
141 {
142     QMenu *menu = dynamic_cast<QMenu*>(app->activePopupWidget());
143     Q_ASSERT(menu != NULL);
144     foreach(QAction *action, menu->actions())
145     {
146         if (action->text() == itemToClick)
147         {
148             //qDebug() << "clicking menu item" << action << action->text();
149             clicked = true;
150             QPoint pos = findActionPos(menu, action);
151             //qDebug() << pos;
152             //QTest::mouseMove(menu, pos);
153             QTest::mouseClick(menu, Qt::LeftButton, Qt::NoModifier, pos);
154             //action->trigger();
155             //menu->hide();
156             return;
157         }
158     }
159     // menu item not found. Include menu items that were actually
160     // present in the menu in the error message to implify debugging
161     QStringList items;
162     foreach(QAction *action, menu->actions())
163     {
164         items.push_back(QString("\"%1\"").arg(action->text()));
165     }
166 
167     // need to hide the menu, otherwise test just hangs
168     menu->hide();
169 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
170     QFAIL(QString("Menu item %1 not found. Menu consists of: %2")
171           .arg(itemToClick)
172           .arg(items.join(" ")).toAscii().constData());
173 #else
174     QFAIL(QString("Menu item %1 not found. Menu consists of: %2")
175           .arg(itemToClick)
176           .arg(items.join(" ")).toLatin1().constData());
177 #endif
178 }
179 
180 /*
181  * Returns topmost pixel which belongs to first cell
182  * of rule in RuleSetView
183  */
findRulePosition(Rule * rule)184 QPoint RuleSetViewTest::findRulePosition(Rule *rule)
185 {
186     // Scroll view to make rule visible
187     view->scrollTo(((RuleSetModel*)view->model())->indexForPosition(rule->getPosition()),
188                    QAbstractItemView::EnsureVisible);
189     // Find top left pixel of rule's first cell
190     for (int x=0; x<view->width(); x++)
191     {
192         for(int y=0; y<view->height(); y++)
193         {
194             QModelIndex index = view->indexAt(QPoint(x,y));
195             Rule *found = ((RuleSetModel*)view->model())->getRule(view->indexAt(QPoint(x,y)));
196             if (found == rule && index.column() == 0)
197                 return QPoint(x,y);
198         }
199     }
200     return QPoint(-1,-1);
201 }
202 
203 /*
204  * Scrolls view to bottom and returns middle pixel of view's middle line.
205  * There
206  */
getViewBottomPoint()207 QPoint RuleSetViewTest::getViewBottomPoint()
208 {
209     view->scrollToBottom();
210     view->viewport()->mapToParent(QPoint(view->viewport()->width()/2, view->viewport()->height()-2));
211     return QPoint(view->viewport()->width()/2, view->viewport()->height()-2);
212 }
213 
214 /*
215  * Returns topmost pixel which belongs to first cell
216  * of row #rule in RuleSetView
217  */
findRulePosition(int rule)218 QPoint RuleSetViewTest::findRulePosition(int rule)
219 {
220     return findRulePosition(getRuleForPosition(rule));
221 }
222 
223 /*
224  * Fills group name request modal dialog with group name
225  * and clicks OK.
226  * Should be executed right before opening dialog.
227  */
createGroup(QString name)228 void RuleSetViewTest::createGroup(QString name)
229 {
230     groupToCreate = name;
231     // timeout should be more than clickMenuItem timeout
232     QTimer::singleShot(150, this, SLOT(actuallyCreateGroup()));
233 }
234 
actuallyCreateGroup()235 void RuleSetViewTest::actuallyCreateGroup()
236 {
237     QInputDialog *dlg = dynamic_cast<QInputDialog*>(app->activeModalWidget());
238     Q_ASSERT(dlg != NULL);
239     QLineEdit *name = dlg->findChild<QLineEdit*>();
240     QTest::keyClicks(name, groupToCreate);
241     dlg->accept();
242 }
243 
244 
test_add_remove()245 void RuleSetViewTest::test_add_remove()
246 {
247     QVERIFY(view->model()->rowCount(QModelIndex()) == 0);
248 
249     // Adding one new rule
250     clickMenuItem("Insert New Rule");
251     showContextMenu(getViewBottomPoint());
252     QVERIFY(view->model()->rowCount(QModelIndex()) == 1);
253     Rule *rule1 = ((RuleSetModel*)view->model())->findRuleForPosition(0);
254 
255     // Adding rule at the bottom
256     clickMenuItem("Add New Rule at the Bottom");
257     showContextMenu(getViewBottomPoint());
258     QVERIFY(view->model()->rowCount(QModelIndex()) == 2);
259     Rule *rule2 = getRuleForPosition(1);
260     QVERIFY(rule1!=rule2);
261     QVERIFY(getRuleForPosition(0) == rule1);
262 
263     // Adding rule on top
264     clickMenuItem("Add New Rule on Top");
265     showContextMenu(getViewBottomPoint());
266     QVERIFY(view->model()->rowCount(QModelIndex()) == 3);
267     Rule *rule3 = getRuleForPosition(0);
268     QVERIFY(rule1!=rule2 && rule1!=rule3 && rule2!=rule3);
269     QVERIFY(getRuleForPosition(1) == rule1);
270     QVERIFY(getRuleForPosition(2) == rule2);
271 
272     // Remove last rule
273     view->selectRE(rule1, 0);
274     clickMenuItem("Insert New Rule");
275     showContextMenu(findRulePosition(rule1));
276     QVERIFY(view->model()->rowCount(QModelIndex()) == 4);
277     QVERIFY(getRuleForPosition(0) == rule3);
278     QVERIFY(getRuleForPosition(2) == rule1);
279     QVERIFY(getRuleForPosition(3) == rule2);
280     Rule *rule4 = getRuleForPosition(1);
281 
282     // Remove last rule
283     view->selectRE(rule2, 0);
284     clickMenuItem("Remove Rule");
285     showContextMenu(findRulePosition(rule2));
286     QVERIFY(view->model()->rowCount(QModelIndex()) == 3);
287     QVERIFY(getRuleForPosition(0) == rule3);
288     QVERIFY(getRuleForPosition(1) == rule4);
289     QVERIFY(getRuleForPosition(2) == rule1);
290 
291     // Remove first rule
292     view->selectRE(rule3, 0);
293     clickMenuItem("Remove Rule");
294     showContextMenu(findRulePosition(rule3));
295     QVERIFY(view->model()->rowCount(QModelIndex()) == 2);
296     QVERIFY(getRuleForPosition(0) == rule4);
297     QVERIFY(getRuleForPosition(1) == rule1);
298 
299     // Remove all created rules
300     view->selectRE(rule4, 0);
301     clickMenuItem("Remove Rule");
302     showContextMenu(findRulePosition(rule4));
303     view->selectRE(rule1, 0);
304     clickMenuItem("Remove Rule");
305     showContextMenu(findRulePosition(rule1));
306     QVERIFY(view->model()->rowCount(QModelIndex()) == 0);
307 }
308 
309 
test_group()310 void RuleSetViewTest::test_group()
311 {
312     // Adding one new rule
313     clickMenuItem("Insert New Rule");
314     showContextMenu(getViewBottomPoint());
315     QVERIFY(view->model()->rowCount(QModelIndex()) == 1);
316     Rule *rule1 = ((RuleSetModel*)view->model())->findRuleForPosition(0);
317 
318     // Adding seven new rules at the bottom
319     Rule *rules[7];
320     for (int i=0; i<7;i++)
321     {
322         clickMenuItem("Add New Rule at the Bottom");
323         showContextMenu(getViewBottomPoint());
324         QVERIFY(view->model()->rowCount(QModelIndex()) == i+2);
325         rules[i] = getRuleForPosition(i+1);
326     }
327 
328     // Create new group
329     view->selectRE(rules[2], 0);
330     createGroup("Test Group Name");
331     clickMenuItem("New Group");
332     showContextMenu(findRulePosition(rules[2]));
333 
334     QList<QModelIndex> groups;
335     ((RuleSetModel*)view->model())->getGroups(groups);
336     QVERIFY(groups.size() == 1);
337     QVERIFY(rules[2]->getRuleGroupName() == "Test Group Name");
338 
339     // Add two more rules to the group
340     view->selectRE(rules[3], 0);
341     clickMenuItem("Add To the Group Test Group Name");
342     showContextMenu(findRulePosition(rules[3]));
343 
344     view->clearSelection();
345     view->selectRE(rules[1], 0);
346     clickMenuItem("Add To the Group Test Group Name");
347     showContextMenu(findRulePosition(rules[1]));
348 
349     QList<QModelIndex> groups2;
350     ((RuleSetModel*)view->model())->getGroups(groups2);
351     QVERIFY(groups.size() == 1);
352     QVERIFY(rules[1]->getRuleGroupName() == "Test Group Name");
353     QVERIFY(rules[2]->getRuleGroupName() == "Test Group Name");
354     QVERIFY(rules[3]->getRuleGroupName() == "Test Group Name");
355     QVERIFY(groups2.first().internalId() == groups.first().internalId());
356 
357     // Expanding created group
358     view->expandAll();
359 
360     // Creating new rule in group using "Add Rule Below"
361     view->selectRE(rules[2], 0);
362     clickMenuItem("Add New Rule Below");
363     showContextMenu(findRulePosition(rules[2]));
364     Rule *newrule1 = ((RuleSetModel*)view->model())->findRuleForPosition(4);
365     for (int i=0; i<5; i++)
366         QVERIFY(newrule1 != rules[i]);
367     QVERIFY(newrule1 != rule1);
368     QVERIFY(newrule1->getRuleGroupName() == "Test Group Name");
369 
370     // Creating new rule in group using "Insert Rule"
371     view->selectRE(rules[2], 0);
372     clickMenuItem("Insert New Rule");
373     showContextMenu(findRulePosition(rules[2]));
374     Rule *newrule2 = ((RuleSetModel*)view->model())->findRuleForPosition(3);
375     for (int i=0; i<5; i++)
376         QVERIFY(newrule2 != rules[i]);
377     QVERIFY(newrule2 != rule1);
378     QVERIFY(newrule2 != newrule1);
379     QVERIFY(newrule2->getRuleGroupName() == "Test Group Name");
380 
381     // Select and add to group two rules under it
382     view->clearSelection();
383     view->selectionModel()->select(((RuleSetModel*)view->model())->indexForPosition(rules[4]->getPosition()),
384                                    QItemSelectionModel::Clear | QItemSelectionModel::SelectCurrent);
385     view->selectionModel()->select(((RuleSetModel*)view->model())->indexForPosition(rules[5]->getPosition()),
386                                    QItemSelectionModel::Select);
387     clickMenuItem("Add To the Group Test Group Name");
388     showContextMenu(findRulePosition(rules[4]));
389     QList<QModelIndex> groups3;
390     ((RuleSetModel*)view->model())->getGroups(groups3);
391     QVERIFY(groups3.size() == 1);
392     QVERIFY(rules[4]->getRuleGroupName() == "Test Group Name");
393     QVERIFY(rules[5]->getRuleGroupName() == "Test Group Name");
394     QVERIFY(groups3.first().internalId() == groups.first().internalId());
395 
396     // Remoe first rule from group
397     QVERIFY(view->model()->rowCount(groups3.first()) == 7);
398     view->selectRE(rules[1], 0);
399     clickMenuItem("Remove From the Group");
400     showContextMenu(findRulePosition(rules[1]));
401     QVERIFY(rules[1]->getRuleGroupName() == "");
402     QVERIFY(view->model()->rowCount(groups3.first()) == 6);
403 
404     // Remoe last rule from group
405     view->selectRE(rules[5], 0);
406     clickMenuItem("Remove From the Group");
407     showContextMenu(findRulePosition(rules[5]));
408     QVERIFY(rules[5]->getRuleGroupName() == "");
409     QVERIFY(view->model()->rowCount(groups3.first()) == 5);
410 
411 
412     // Remove rule inside group
413     view->selectRE(rules[3], 0);
414     clickMenuItem("Remove Rule");
415     showContextMenu(findRulePosition(rules[3]));
416     QVERIFY(view->model()->rowCount(groups3.first()) == 4);
417 
418     // Remove all created rules
419     for (int i=0; i<7; i++)
420     {
421         if (i==3) continue;
422         view->selectRE(rules[i], 0);
423         clickMenuItem("Remove Rule");
424         showContextMenu(findRulePosition(rules[i]));
425     }
426     view->selectRE(newrule1, 0);
427     clickMenuItem("Remove Rule");
428     showContextMenu(findRulePosition(newrule1));
429     view->selectRE(newrule2, 0);
430     clickMenuItem("Remove Rule");
431     showContextMenu(findRulePosition(newrule2));
432     view->selectRE(rule1, 0);
433     clickMenuItem("Remove Rule");
434     showContextMenu(findRulePosition(rule1));
435 
436     QVERIFY(view->model()->rowCount() == 0);
437 }
438 
test_move()439 void RuleSetViewTest::test_move()
440 {
441     // Adding one new rule
442     clickMenuItem("Insert New Rule");
443     showContextMenu(getViewBottomPoint());
444     QVERIFY(view->model()->rowCount(QModelIndex()) == 1);
445     Rule *rules[4];
446     rules[0] = ((RuleSetModel*)view->model())->findRuleForPosition(0);;
447 
448     // Adding three new rules at the bottom
449     for (int i=1; i<4;i++)
450     {
451         clickMenuItem("Add New Rule at the Bottom");
452         showContextMenu(getViewBottomPoint());
453         QVERIFY(view->model()->rowCount(QModelIndex()) == i+1);
454         rules[i] = getRuleForPosition(i);
455     }
456 
457     // Verifying that all rules' positions match their indexes
458     for (int i=0; i<4; i++)
459         QVERIFY(rules[i]->getPosition() == i);
460 
461     // Moving second rule up
462     view->selectRE(rules[1], 0);
463     clickMenuItem("Move Rule Up");
464     showContextMenu(findRulePosition(rules[1]));
465     QVERIFY(rules[1]->getPosition() == 0);
466     QVERIFY(rules[0]->getPosition() == 1);
467 
468     // Moving first rule down
469     view->selectRE(rules[1], 0);
470     clickMenuItem("Move Rule Down");
471     showContextMenu(findRulePosition(rules[1]));
472     QVERIFY(rules[1]->getPosition() == 1);
473     QVERIFY(rules[0]->getPosition() == 0);
474 
475     // Moving first rule up (rule order should not change)
476     view->selectRE(rules[0], 0);
477     clickMenuItem("Move Rule Up");
478     showContextMenu(findRulePosition(rules[0]));
479     for (int i=0; i<4; i++)
480         QVERIFY(rules[i]->getPosition() == i);
481 
482     // Moving last rule down (rule order should not change)
483     view->selectRE(rules[3], 0);
484     clickMenuItem("Move Rule Down");
485     showContextMenu(findRulePosition(rules[3]));
486     for (int i=0; i<4; i++)
487         QVERIFY(rules[i]->getPosition() == i);
488 
489     // Selecting two rules and moving them up
490     view->selectRE(rules[1], 0);
491     view->selectionModel()->select(((RuleSetModel*)view->model())->indexForPosition(2),
492                                    QItemSelectionModel::Select);
493     clickMenuItem("Move Rules Up");
494     showContextMenu(findRulePosition(rules[1]));
495     QVERIFY(rules[1]->getPosition() == 0);
496     QVERIFY(rules[2]->getPosition() == 1);
497     QVERIFY(rules[0]->getPosition() == 2);
498     QVERIFY(rules[3]->getPosition() == 3);
499 
500     // Selecting two rules and moving them down
501     view->selectRE(rules[2], 0);
502     view->selectionModel()->select(((RuleSetModel*)view->model())->indexForPosition(2),
503                                    QItemSelectionModel::Select);
504     clickMenuItem("Move Rules Down");
505     showContextMenu(findRulePosition(rules[2]));
506     QVERIFY(rules[1]->getPosition() == 0);
507     QVERIFY(rules[3]->getPosition() == 1);
508     QVERIFY(rules[2]->getPosition() == 2);
509     QVERIFY(rules[0]->getPosition() == 3);
510 
511     // Adding two more rules
512     Rule *newrules[6] = { rules[1], rules[3], rules[2], rules[0], NULL, NULL };
513     for (int i=4; i<6;i++)
514     {
515         clickMenuItem("Add New Rule at the Bottom");
516         showContextMenu(getViewBottomPoint());
517         QVERIFY(view->model()->rowCount(QModelIndex()) == i+1);
518         newrules[i] = getRuleForPosition(i);
519     }
520 
521     // Creating a group to test moving rules inside of it
522     view->selectRE(newrules[1], 0);
523     for (int i=2; i<5; i++)
524         view->selectionModel()->select(((RuleSetModel*)view->model())->indexForPosition(i),
525                                        QItemSelectionModel::Select);
526     createGroup("Test Group Name");
527     clickMenuItem("New Group");
528     showContextMenu(findRulePosition(newrules[1]));
529     for (int i=1; i<5; i++)
530         QVERIFY(newrules[i]->getRuleGroupName() == "Test Group Name");
531 
532     // Expanding created group
533     view->expandAll();
534 
535     // Moving second rule of group up
536     view->selectRE(newrules[2], 0);
537     clickMenuItem("Move Rule Up");
538     showContextMenu(findRulePosition(newrules[2]));
539     QVERIFY(newrules[2]->getPosition() == 1);
540     QVERIFY(newrules[1]->getPosition() == 2);
541 
542     // Moving first rule of group up. It should leave the group.
543     view->selectRE(newrules[2], 0);
544     clickMenuItem("Move Rule Up");
545     showContextMenu(findRulePosition(newrules[2]));
546     QVERIFY(newrules[2]->getPosition() == 1);
547     QVERIFY(newrules[0]->getPosition() == 0);
548     QVERIFY(newrules[1]->getPosition() == 2);
549     QVERIFY(newrules[2]->getRuleGroupName() == "");
550 
551     // Moving first rule above group down. It should be added to group.
552     view->selectRE(newrules[2], 0);
553     clickMenuItem("Move Rule Down");
554     showContextMenu(findRulePosition(newrules[2]));
555     QVERIFY(newrules[2]->getPosition() == 1);
556     QVERIFY(newrules[0]->getPosition() == 0);
557     QVERIFY(newrules[1]->getPosition() == 2);
558     QVERIFY(newrules[2]->getRuleGroupName() == "Test Group Name");
559 
560     // Moving last rule of group down. It should leave the group.
561     view->selectRE(newrules[4], 0);
562     clickMenuItem("Move Rule Down");
563     showContextMenu(findRulePosition(newrules[4]));
564     QVERIFY(newrules[4]->getPosition() == 4);
565     QVERIFY(newrules[5]->getPosition() == 5);
566     QVERIFY(newrules[3]->getPosition() == 3);
567     QVERIFY(newrules[4]->getRuleGroupName() == "");
568 
569     // Moving first rule below group up. It should be added to group.
570     view->selectRE(newrules[4], 0);
571     clickMenuItem("Move Rule Up");
572     showContextMenu(findRulePosition(newrules[4]));
573     QVERIFY(newrules[4]->getPosition() == 4);
574     QVERIFY(newrules[5]->getPosition() == 5);
575     QVERIFY(newrules[3]->getPosition() == 3);
576     QVERIFY(newrules[4]->getRuleGroupName() == "Test Group Name");
577 
578     // Removing all created rules
579     for (int i=0; i<6; i++)
580     {
581         view->selectRE(newrules[i], 0);
582         clickMenuItem("Remove Rule");
583         showContextMenu(findRulePosition(newrules[i]));
584     }
585     QVERIFY(view->model()->rowCount() == 0);
586 }
587 
test_copy_paste()588 void RuleSetViewTest::test_copy_paste()
589 {
590     // Adding one new rule
591     clickMenuItem("Insert New Rule");
592     showContextMenu(getViewBottomPoint());
593     QVERIFY(view->model()->rowCount(QModelIndex()) == 1);
594     Rule *rules[4];
595     rules[0] = ((RuleSetModel*)view->model())->findRuleForPosition(0);
596 
597     // Adding three new rules at the bottom
598     for (int i=1; i<4;i++)
599     {
600         clickMenuItem("Add New Rule at the Bottom");
601         showContextMenu(getViewBottomPoint());
602         QVERIFY(view->model()->rowCount(QModelIndex()) == i+1);
603         rules[i] = getRuleForPosition(i);
604     }
605 
606     // Cutting second rule
607     view->selectRE(rules[1], 0);
608     clickMenuItem("Cut Rule");
609     showContextMenu(findRulePosition(rules[1]));
610     QVERIFY(view->model()->rowCount() == 3);
611 
612     // Pasting cutted rule above first
613     view->selectRE(rules[0], 0);
614     clickMenuItem("Paste Rule Above");
615     showContextMenu(findRulePosition(rules[0]));
616     QVERIFY(view->model()->rowCount() == 4);
617     rules[1] = getRuleForPosition(0);
618 
619     // Copying second rule
620     view->selectRE(rules[1], 0);
621     clickMenuItem("Copy Rule");
622     showContextMenu(findRulePosition(rules[1]));
623     QVERIFY(view->model()->rowCount() == 4);
624 
625     // Pasting rule after first rule
626     view->selectRE(rules[1], 0);
627     clickMenuItem("Paste Rule Below");
628     showContextMenu(findRulePosition(rules[1]));
629     QVERIFY(view->model()->rowCount() == 5);
630 
631     // Copy two rules
632     view->selectRE(getRuleForPosition(1), 0);
633     view->selectionModel()->select(((RuleSetModel*)view->model())->indexForPosition(2),
634                                    QItemSelectionModel::Select);
635     clickMenuItem("Copy Rules");
636     showContextMenu(findRulePosition(getRuleForPosition(1)));
637     QVERIFY(view->model()->rowCount() == 5);
638 
639     // Paste rules at the bottom
640     view->selectRE(getRuleForPosition(4), 0);
641     clickMenuItem("Paste Rule Below");
642     showContextMenu(findRulePosition(getRuleForPosition(4)));
643     QVERIFY(view->model()->rowCount() == 7);
644 
645 }
646