2011-04-06 Alexis Menard <alexis.menard@openbossa.org>
[WebKit-https.git] / Source / WebKit / qt / tests / qwebhistory / tst_qwebhistory.cpp
1 /*
2     Copyright (C) 2008 Holger Hans Peter Freyther
3
4     This library is free software; you can redistribute it and/or
5     modify it under the terms of the GNU Library General Public
6     License as published by the Free Software Foundation; either
7     version 2 of the License, or (at your option) any later version.
8
9     This library is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12     Library General Public License for more details.
13
14     You should have received a copy of the GNU Library General Public License
15     along with this library; see the file COPYING.LIB.  If not, write to
16     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17     Boston, MA 02110-1301, USA.
18 */
19
20 #include <QtTest/QtTest>
21 #include <QAction>
22
23 #include "qwebpage.h"
24 #include "qwebview.h"
25 #include "qwebframe.h"
26 #include "qwebhistory.h"
27 #include "qdebug.h"
28
29 class tst_QWebHistory : public QObject
30 {
31     Q_OBJECT
32
33 public:
34     tst_QWebHistory();
35     virtual ~tst_QWebHistory();
36
37 protected :
38     void loadPage(int nr)
39     {
40         frame->load(QUrl("qrc:/resources/page" + QString::number(nr) + ".html"));
41         waitForLoadFinished.exec();
42     }
43
44 public slots:
45     void init();
46     void cleanup();
47
48 private slots:
49     void title();
50     void count();
51     void back();
52     void forward();
53     void itemAt();
54     void goToItem();
55     void items();
56     void serialize_1(); //QWebHistory countity
57     void serialize_2(); //QWebHistory index
58     void serialize_3(); //QWebHistoryItem
59     void saveAndRestore_crash_1();
60     void saveAndRestore_crash_2();
61     void saveAndRestore_crash_3();
62     void popPushState_data();
63     void popPushState();
64     void clear();
65
66
67 private:
68     QWebPage* page;
69     QWebFrame* frame;
70     QWebHistory* hist;
71     QEventLoop waitForLoadFinished;  //operation on history are asynchronous!
72     int histsize;
73 };
74
75 tst_QWebHistory::tst_QWebHistory()
76 {
77 }
78
79 tst_QWebHistory::~tst_QWebHistory()
80 {
81 }
82
83 void tst_QWebHistory::init()
84 {
85     page = new QWebPage(this);
86     frame = page->mainFrame();
87     connect(page, SIGNAL(loadFinished(bool)), &waitForLoadFinished, SLOT(quit()), Qt::QueuedConnection);
88
89     for (int i = 1;i < 6;i++) {
90         loadPage(i);
91     }
92     hist = page->history();
93     histsize = 5;
94 }
95
96 void tst_QWebHistory::cleanup()
97 {
98     delete page;
99 }
100
101 /**
102   * Check QWebHistoryItem::title() method
103   */
104 void tst_QWebHistory::title()
105 {
106     QCOMPARE(hist->currentItem().title(), QString("page5"));
107 }
108
109 /**
110   * Check QWebHistory::count() method
111   */
112 void tst_QWebHistory::count()
113 {
114     QCOMPARE(hist->count(), histsize);
115 }
116
117 /**
118   * Check QWebHistory::back() method
119   */
120 void tst_QWebHistory::back()
121 {
122     for (int i = histsize;i > 1;i--) {
123         QCOMPARE(page->mainFrame()->toPlainText(), QString("page") + QString::number(i));
124         hist->back();
125         waitForLoadFinished.exec();
126     }
127     //try one more time (too many). crash test
128     hist->back();
129     QCOMPARE(page->mainFrame()->toPlainText(), QString("page1"));
130 }
131
132 /**
133   * Check QWebHistory::forward() method
134   */
135 void tst_QWebHistory::forward()
136 {
137     //rewind history :-)
138     while (hist->canGoBack()) {
139         hist->back();
140         waitForLoadFinished.exec();
141     }
142
143     for (int i = 1;i < histsize;i++) {
144         QCOMPARE(page->mainFrame()->toPlainText(), QString("page") + QString::number(i));
145         hist->forward();
146         waitForLoadFinished.exec();
147     }
148     //try one more time (too many). crash test
149     hist->forward();
150     QCOMPARE(page->mainFrame()->toPlainText(), QString("page") + QString::number(histsize));
151 }
152
153 /**
154   * Check QWebHistory::itemAt() method
155   */
156 void tst_QWebHistory::itemAt()
157 {
158     for (int i = 1;i < histsize;i++) {
159         QCOMPARE(hist->itemAt(i - 1).title(), QString("page") + QString::number(i));
160         QVERIFY(hist->itemAt(i - 1).isValid());
161     }
162     //check out of range values
163     QVERIFY(!hist->itemAt(-1).isValid());
164     QVERIFY(!hist->itemAt(histsize).isValid());
165 }
166
167 /**
168   * Check QWebHistory::goToItem() method
169   */
170 void tst_QWebHistory::goToItem()
171 {
172     QWebHistoryItem current = hist->currentItem();
173     hist->back();
174     waitForLoadFinished.exec();
175     hist->back();
176     waitForLoadFinished.exec();
177     QVERIFY(hist->currentItem().title() != current.title());
178     hist->goToItem(current);
179     waitForLoadFinished.exec();
180     QCOMPARE(hist->currentItem().title(), current.title());
181 }
182
183 /**
184   * Check QWebHistory::items() method
185   */
186 void tst_QWebHistory::items() 
187 {
188     QList<QWebHistoryItem> items = hist->items();
189     //check count
190     QCOMPARE(histsize, items.count());
191
192     //check order
193     for (int i = 1;i <= histsize;i++) {
194         QCOMPARE(items.at(i - 1).title(), QString("page") + QString::number(i));
195     }
196 }
197
198 /**
199   * Check history state after serialization (pickle, persistent..) method
200   * Checks history size, history order
201   */
202 void tst_QWebHistory::serialize_1() 
203 {
204     QByteArray tmp;  //buffer
205     QDataStream save(&tmp, QIODevice::WriteOnly); //here data will be saved
206     QDataStream load(&tmp, QIODevice::ReadOnly); //from here data will be loaded
207
208     save << *hist;
209     QVERIFY(save.status() == QDataStream::Ok);
210     QCOMPARE(hist->count(), histsize);
211
212     //check size of history
213     //load next page to find differences
214     loadPage(6);
215     QCOMPARE(hist->count(), histsize + 1);
216     load >> *hist;
217     QVERIFY(load.status() == QDataStream::Ok);
218     QCOMPARE(hist->count(), histsize);
219
220     //check order of historyItems
221     QList<QWebHistoryItem> items = hist->items();
222     for (int i = 1;i <= histsize;i++) {
223         QCOMPARE(items.at(i - 1).title(), QString("page") + QString::number(i));
224     }
225 }
226
227 /**
228   * Check history state after serialization (pickle, persistent..) method
229   * Checks history currentIndex value
230   */
231 void tst_QWebHistory::serialize_2() 
232 {
233     QByteArray tmp;  //buffer
234     QDataStream save(&tmp, QIODevice::WriteOnly); //here data will be saved
235     QDataStream load(&tmp, QIODevice::ReadOnly); //from here data will be loaded
236
237     int oldCurrentIndex = hist->currentItemIndex();
238
239     hist->back();
240     waitForLoadFinished.exec();
241     hist->back();
242     waitForLoadFinished.exec();
243     //check if current index was changed (make sure that it is not last item)
244     QVERIFY(hist->currentItemIndex() != oldCurrentIndex);
245     //save current index
246     oldCurrentIndex = hist->currentItemIndex();
247
248     save << *hist;
249     QVERIFY(save.status() == QDataStream::Ok);
250     load >> *hist;
251     QVERIFY(load.status() == QDataStream::Ok);
252
253     //check current index
254     QCOMPARE(hist->currentItemIndex(), oldCurrentIndex);
255 }
256
257 /**
258   * Check history state after serialization (pickle, persistent..) method
259   * Checks QWebHistoryItem public property after serialization
260   */
261 void tst_QWebHistory::serialize_3() 
262 {
263     QByteArray tmp;  //buffer
264     QDataStream save(&tmp, QIODevice::WriteOnly); //here data will be saved
265     QDataStream load(&tmp, QIODevice::ReadOnly); //from here data will be loaded
266
267     //prepare two different history items
268     QWebHistoryItem a = hist->currentItem();
269     a.setUserData("A - user data");
270
271     //check properties BEFORE serialization
272     QString title(a.title());
273     QDateTime lastVisited(a.lastVisited());
274     QUrl originalUrl(a.originalUrl());
275     QUrl url(a.url());
276     QVariant userData(a.userData());
277
278     save << *hist;
279     QVERIFY(save.status() == QDataStream::Ok);
280     QVERIFY(!load.atEnd());
281     hist->clear();
282     QVERIFY(hist->count() == 1);
283     load >> *hist;
284     QVERIFY(load.status() == QDataStream::Ok);
285     QWebHistoryItem b = hist->currentItem();
286
287     //check properties AFTER serialization
288     QCOMPARE(b.title(), title);
289     QCOMPARE(b.lastVisited(), lastVisited);
290     QCOMPARE(b.originalUrl(), originalUrl);
291     QCOMPARE(b.url(), url);
292     QCOMPARE(b.userData(), userData);
293
294     //Check if all data was read
295     QVERIFY(load.atEnd());
296 }
297
298 static void saveHistory(QWebHistory* history, QByteArray* in)
299 {
300     in->clear();
301     QDataStream save(in, QIODevice::WriteOnly);
302     save << *history;
303 }
304
305 static void restoreHistory(QWebHistory* history, QByteArray* out)
306 {
307     QDataStream load(out, QIODevice::ReadOnly);
308     load >> *history;
309 }
310
311 /** The test shouldn't crash */
312 void tst_QWebHistory::saveAndRestore_crash_1()
313 {
314     QByteArray buffer;
315     saveHistory(hist, &buffer);
316     for (unsigned i = 0; i < 5; i++) {
317         restoreHistory(hist, &buffer);
318         saveHistory(hist, &buffer);
319     }
320 }
321
322 /** The test shouldn't crash */
323 void tst_QWebHistory::saveAndRestore_crash_2()
324 {
325     QByteArray buffer;
326     saveHistory(hist, &buffer);
327     QWebPage* page2 = new QWebPage(this);
328     QWebHistory* hist2 = page2->history();
329     for (unsigned i = 0; i < 5; i++) {
330         restoreHistory(hist2, &buffer);
331         saveHistory(hist2, &buffer);
332     }
333     delete page2;
334 }
335
336 /** The test shouldn't crash */
337 void tst_QWebHistory::saveAndRestore_crash_3()
338 {
339     QByteArray buffer;
340     saveHistory(hist, &buffer);
341     QWebPage* page2 = new QWebPage(this);
342     QWebHistory* hist1 = hist;
343     QWebHistory* hist2 = page2->history();
344     for (unsigned i = 0; i < 5; i++) {
345         restoreHistory(hist1, &buffer);
346         restoreHistory(hist2, &buffer);
347         QVERIFY(hist1->count() == hist2->count());
348         QVERIFY(hist1->count() == histsize);
349         hist2->back();
350         saveHistory(hist2, &buffer);
351         hist2->clear();
352     }
353     delete page2;
354 }
355
356 void tst_QWebHistory::popPushState_data()
357 {
358     QTest::addColumn<QString>("script");
359     QTest::newRow("pushState") << "history.pushState(123, \"foo\");";
360     QTest::newRow("replaceState") << "history.replaceState(\"a\", \"b\");";
361     QTest::newRow("back") << "history.back();";
362     QTest::newRow("forward") << "history.forward();";
363     QTest::newRow("clearState") << "history.clearState();";
364 }
365
366 /** Crash test, WebKit bug 38840 (https://bugs.webkit.org/show_bug.cgi?id=38840) */
367 void tst_QWebHistory::popPushState()
368 {
369     QFETCH(QString, script);
370     QWebPage page;
371     page.mainFrame()->setHtml("<html><body>long live Qt!</body></html>");
372     page.mainFrame()->evaluateJavaScript(script);
373 }
374
375 /** ::clear */
376 void tst_QWebHistory::clear()
377 {
378     QByteArray buffer;
379
380     QAction* actionBack = page->action(QWebPage::Back);
381     QVERIFY(actionBack->isEnabled());
382     saveHistory(hist, &buffer);
383     QVERIFY(hist->count() > 1);
384     hist->clear();
385     QVERIFY(hist->count() == 1);  // Leave current item.
386     QVERIFY(!actionBack->isEnabled());
387
388     QWebPage* page2 = new QWebPage(this);
389     QWebHistory* hist2 = page2->history();
390     QVERIFY(hist2->count() == 0);
391     hist2->clear();
392     QVERIFY(hist2->count() == 0); // Do not change anything.
393     delete page2;
394 }
395
396 QTEST_MAIN(tst_QWebHistory)
397 #include "tst_qwebhistory.moc"