tst_qwebhistory.cpp [plain text]
#include <QtTest/QtTest>
#include <QAction>
#include "../util.h"
#include "qwebpage.h"
#include "qwebview.h"
#include "qwebframe.h"
#include "qwebhistory.h"
#include "qdebug.h"
class tst_QWebHistory : public QObject
{
Q_OBJECT
public:
tst_QWebHistory();
virtual ~tst_QWebHistory();
protected :
void loadPage(int nr)
{
frame->load(QUrl("qrc:/resources/page" + QString::number(nr) + ".html"));
loadFinishedBarrier->ensureSignalEmitted();
}
public Q_SLOTS:
void init();
void cleanup();
private Q_SLOTS:
void title();
void count();
void back();
void forward();
void itemAt();
void goToItem();
void items();
void serialize_1(); void serialize_2(); void serialize_3(); void saveAndRestore_crash_1();
void saveAndRestore_crash_2();
void saveAndRestore_crash_3();
void saveAndRestore_crash_4();
void popPushState_data();
void popPushState();
void clear();
void restoreIncompatibleVersion1();
private:
QWebPage* page;
QWebFrame* frame;
QWebHistory* hist;
QScopedPointer<SignalBarrier> loadFinishedBarrier;
int histsize;
};
tst_QWebHistory::tst_QWebHistory()
{
}
tst_QWebHistory::~tst_QWebHistory()
{
}
void tst_QWebHistory::init()
{
page = new QWebPage(this);
frame = page->mainFrame();
loadFinishedBarrier.reset(new SignalBarrier(frame, SIGNAL(loadFinished(bool))));
for (int i = 1;i < 6;i++) {
loadPage(i);
}
hist = page->history();
histsize = 5;
}
void tst_QWebHistory::cleanup()
{
loadFinishedBarrier.reset();
delete page;
}
void tst_QWebHistory::title()
{
QCOMPARE(hist->currentItem().title(), QString("page5"));
}
void tst_QWebHistory::count()
{
QCOMPARE(hist->count(), histsize);
}
void tst_QWebHistory::back()
{
for (int i = histsize;i > 1;i--) {
QCOMPARE(page->mainFrame()->toPlainText(), QString("page") + QString::number(i));
hist->back();
loadFinishedBarrier->ensureSignalEmitted();
}
hist->back();
QCOMPARE(page->mainFrame()->toPlainText(), QString("page1"));
}
void tst_QWebHistory::forward()
{
while (hist->canGoBack()) {
hist->back();
loadFinishedBarrier->ensureSignalEmitted();
}
for (int i = 1;i < histsize;i++) {
QCOMPARE(page->mainFrame()->toPlainText(), QString("page") + QString::number(i));
hist->forward();
loadFinishedBarrier->ensureSignalEmitted();
}
hist->forward();
QCOMPARE(page->mainFrame()->toPlainText(), QString("page") + QString::number(histsize));
}
void tst_QWebHistory::itemAt()
{
for (int i = 1;i < histsize;i++) {
QCOMPARE(hist->itemAt(i - 1).title(), QString("page") + QString::number(i));
QVERIFY(hist->itemAt(i - 1).isValid());
}
QVERIFY(!hist->itemAt(-1).isValid());
QVERIFY(!hist->itemAt(histsize).isValid());
}
void tst_QWebHistory::goToItem()
{
QWebHistoryItem current = hist->currentItem();
hist->back();
loadFinishedBarrier->ensureSignalEmitted();
hist->back();
loadFinishedBarrier->ensureSignalEmitted();
QVERIFY(hist->currentItem().title() != current.title());
hist->goToItem(current);
loadFinishedBarrier->ensureSignalEmitted();
QCOMPARE(hist->currentItem().title(), current.title());
}
void tst_QWebHistory::items()
{
QList<QWebHistoryItem> items = hist->items();
QCOMPARE(histsize, items.count());
for (int i = 1;i <= histsize;i++) {
QCOMPARE(items.at(i - 1).title(), QString("page") + QString::number(i));
}
}
void tst_QWebHistory::serialize_1()
{
QByteArray tmp; QDataStream save(&tmp, QIODevice::WriteOnly); QDataStream load(&tmp, QIODevice::ReadOnly);
save << *hist;
QVERIFY(save.status() == QDataStream::Ok);
QCOMPARE(hist->count(), histsize);
loadPage(6);
QCOMPARE(hist->count(), histsize + 1);
load >> *hist;
QVERIFY(load.status() == QDataStream::Ok);
QCOMPARE(hist->count(), histsize);
QList<QWebHistoryItem> items = hist->items();
for (int i = 1;i <= histsize;i++) {
QCOMPARE(items.at(i - 1).title(), QString("page") + QString::number(i));
}
}
void tst_QWebHistory::serialize_2()
{
QByteArray tmp; QDataStream save(&tmp, QIODevice::WriteOnly); QDataStream load(&tmp, QIODevice::ReadOnly);
frame->load(frame->url().toString() + QLatin1String("#dummyAnchor"));
int initialCurrentIndex = hist->currentItemIndex();
hist->back();
loadFinishedBarrier->ensureSignalEmitted();
hist->back();
loadFinishedBarrier->ensureSignalEmitted();
hist->back();
loadFinishedBarrier->ensureSignalEmitted();
QVERIFY(hist->currentItemIndex() != initialCurrentIndex);
int oldCurrentIndex = hist->currentItemIndex();
save << *hist;
QVERIFY(save.status() == QDataStream::Ok);
load >> *hist;
QVERIFY(load.status() == QDataStream::Ok);
QCOMPARE(hist->currentItemIndex(), oldCurrentIndex);
hist->forward();
loadFinishedBarrier->ensureSignalEmitted();
hist->forward();
loadFinishedBarrier->ensureSignalEmitted();
hist->forward();
loadFinishedBarrier->ensureSignalEmitted();
QCOMPARE(hist->currentItemIndex(), initialCurrentIndex);
}
void tst_QWebHistory::serialize_3()
{
QByteArray tmp; QDataStream save(&tmp, QIODevice::WriteOnly); QDataStream load(&tmp, QIODevice::ReadOnly);
QWebHistoryItem a = hist->currentItem();
a.setUserData("A - user data");
QString title(a.title());
QDateTime lastVisited(a.lastVisited());
QUrl originalUrl(a.originalUrl());
QUrl url(a.url());
QVariant userData(a.userData());
save << *hist;
QVERIFY(save.status() == QDataStream::Ok);
QVERIFY(!load.atEnd());
hist->clear();
QVERIFY(hist->count() == 1);
load >> *hist;
QVERIFY(load.status() == QDataStream::Ok);
QWebHistoryItem b = hist->currentItem();
QCOMPARE(b.title(), title);
QCOMPARE(b.lastVisited(), lastVisited);
QCOMPARE(b.originalUrl(), originalUrl);
QCOMPARE(b.url(), url);
QCOMPARE(b.userData(), userData);
QVERIFY(load.atEnd());
}
static void saveHistory(QWebHistory* history, QByteArray* in)
{
in->clear();
QDataStream save(in, QIODevice::WriteOnly);
save << *history;
}
static void restoreHistory(QWebHistory* history, QByteArray* out)
{
QDataStream load(out, QIODevice::ReadOnly);
load >> *history;
}
void tst_QWebHistory::saveAndRestore_crash_1()
{
QByteArray buffer;
saveHistory(hist, &buffer);
for (unsigned i = 0; i < 5; i++) {
restoreHistory(hist, &buffer);
saveHistory(hist, &buffer);
}
}
void tst_QWebHistory::saveAndRestore_crash_2()
{
QByteArray buffer;
saveHistory(hist, &buffer);
QWebPage* page2 = new QWebPage(this);
QWebHistory* hist2 = page2->history();
for (unsigned i = 0; i < 5; i++) {
restoreHistory(hist2, &buffer);
saveHistory(hist2, &buffer);
}
delete page2;
}
void tst_QWebHistory::saveAndRestore_crash_3()
{
QByteArray buffer;
saveHistory(hist, &buffer);
QWebPage* page2 = new QWebPage(this);
QWebHistory* hist1 = hist;
QWebHistory* hist2 = page2->history();
for (unsigned i = 0; i < 5; i++) {
restoreHistory(hist1, &buffer);
restoreHistory(hist2, &buffer);
QVERIFY(hist1->count() == hist2->count());
QVERIFY(hist1->count() == histsize);
hist2->back();
saveHistory(hist2, &buffer);
hist2->clear();
}
delete page2;
}
void tst_QWebHistory::saveAndRestore_crash_4()
{
QByteArray buffer;
saveHistory(hist, &buffer);
QWebPage* page2 = new QWebPage(this);
page2->settings()->setMaximumPagesInCache(3);
QEventLoop waitForLoadFinished;
QObject::connect(page2, SIGNAL(loadFinished(bool)), &waitForLoadFinished, SLOT(quit()), Qt::QueuedConnection);
QDataStream load(&buffer, QIODevice::ReadOnly);
load >> *page2->history();
waitForLoadFinished.exec();
delete page2;
QTest::qWait(50);
}
void tst_QWebHistory::popPushState_data()
{
QTest::addColumn<QString>("script");
QTest::newRow("pushState") << "history.pushState(123, \"foo\");";
QTest::newRow("replaceState") << "history.replaceState(\"a\", \"b\");";
QTest::newRow("back") << "history.back();";
QTest::newRow("forward") << "history.forward();";
QTest::newRow("clearState") << "history.clearState();";
}
void tst_QWebHistory::popPushState()
{
QFETCH(QString, script);
QWebPage page;
page.mainFrame()->setHtml("<html><body>long live Qt!</body></html>");
page.mainFrame()->evaluateJavaScript(script);
}
void tst_QWebHistory::clear()
{
QByteArray buffer;
QAction* actionBack = page->action(QWebPage::Back);
QVERIFY(actionBack->isEnabled());
saveHistory(hist, &buffer);
QVERIFY(hist->count() > 1);
hist->clear();
QVERIFY(hist->count() == 1); QVERIFY(!actionBack->isEnabled());
QWebPage* page2 = new QWebPage(this);
QWebHistory* hist2 = page2->history();
QVERIFY(hist2->count() == 0);
hist2->clear();
QVERIFY(hist2->count() == 0); delete page2;
}
void tst_QWebHistory::restoreIncompatibleVersion1()
{
static const unsigned char version1Dump[] = {
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x32, 0x00, 0x71, 0x00, 0x72, 0x00, 0x63, 0x00, 0x3a, 0x00, 0x2f, 0x00, 0x72, 0x00, 0x65,
0x00, 0x73, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x72, 0x00, 0x63, 0x00, 0x65, 0x00, 0x73, 0x00,
0x2f, 0x00, 0x70, 0x00, 0x61, 0x00, 0x67, 0x00, 0x65, 0x00, 0x31, 0x00, 0x2e, 0x00, 0x68,
0x00, 0x74, 0x00, 0x6d, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x61, 0x00,
0x67, 0x00, 0x65, 0x00, 0x31, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x71, 0x00, 0x72, 0x00, 0x63, 0x00, 0x3a, 0x00,
0x2f, 0x00, 0x72, 0x00, 0x65, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x72, 0x00, 0x63,
0x00, 0x65, 0x00, 0x73, 0x00, 0x2f, 0x00, 0x70, 0x00, 0x61, 0x00, 0x67, 0x00, 0x65, 0x00,
0x31, 0x00, 0x2e, 0x00, 0x68, 0x00, 0x74, 0x00, 0x6d, 0x00, 0x6c, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32,
0x00, 0x71, 0x00, 0x72, 0x00, 0x63, 0x00, 0x3a, 0x00, 0x2f, 0x00, 0x72, 0x00, 0x65, 0x00,
0x73, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x72, 0x00, 0x63, 0x00, 0x65, 0x00, 0x73, 0x00, 0x2f,
0x00, 0x70, 0x00, 0x61, 0x00, 0x67, 0x00, 0x65, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x68, 0x00,
0x74, 0x00, 0x6d, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x61, 0x00, 0x67,
0x00, 0x65, 0x00, 0x32, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x71, 0x00, 0x72, 0x00, 0x63, 0x00, 0x3a, 0x00, 0x2f,
0x00, 0x72, 0x00, 0x65, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x72, 0x00, 0x63, 0x00,
0x65, 0x00, 0x73, 0x00, 0x2f, 0x00, 0x70, 0x00, 0x61, 0x00, 0x67, 0x00, 0x65, 0x00, 0x32,
0x00, 0x2e, 0x00, 0x68, 0x00, 0x74, 0x00, 0x6d, 0x00, 0x6c, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00,
0x71, 0x00, 0x72, 0x00, 0x63, 0x00, 0x3a, 0x00, 0x2f, 0x00, 0x72, 0x00, 0x65, 0x00, 0x73,
0x00, 0x6f, 0x00, 0x75, 0x00, 0x72, 0x00, 0x63, 0x00, 0x65, 0x00, 0x73, 0x00, 0x2f, 0x00,
0x70, 0x00, 0x61, 0x00, 0x67, 0x00, 0x65, 0x00, 0x33, 0x00, 0x2e, 0x00, 0x68, 0x00, 0x74,
0x00, 0x6d, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x61, 0x00, 0x67, 0x00,
0x65, 0x00, 0x33, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x32, 0x00, 0x71, 0x00, 0x72, 0x00, 0x63, 0x00, 0x3a, 0x00, 0x2f, 0x00,
0x72, 0x00, 0x65, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x72, 0x00, 0x63, 0x00, 0x65,
0x00, 0x73, 0x00, 0x2f, 0x00, 0x70, 0x00, 0x61, 0x00, 0x67, 0x00, 0x65, 0x00, 0x33, 0x00,
0x2e, 0x00, 0x68, 0x00, 0x74, 0x00, 0x6d, 0x00, 0x6c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x71,
0x00, 0x72, 0x00, 0x63, 0x00, 0x3a, 0x00, 0x2f, 0x00, 0x72, 0x00, 0x65, 0x00, 0x73, 0x00,
0x6f, 0x00, 0x75, 0x00, 0x72, 0x00, 0x63, 0x00, 0x65, 0x00, 0x73, 0x00, 0x2f, 0x00, 0x70,
0x00, 0x61, 0x00, 0x67, 0x00, 0x65, 0x00, 0x34, 0x00, 0x2e, 0x00, 0x68, 0x00, 0x74, 0x00,
0x6d, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x61, 0x00, 0x67, 0x00, 0x65,
0x00, 0x34, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x32, 0x00, 0x71, 0x00, 0x72, 0x00, 0x63, 0x00, 0x3a, 0x00, 0x2f, 0x00, 0x72,
0x00, 0x65, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x72, 0x00, 0x63, 0x00, 0x65, 0x00,
0x73, 0x00, 0x2f, 0x00, 0x70, 0x00, 0x61, 0x00, 0x67, 0x00, 0x65, 0x00, 0x34, 0x00, 0x2e,
0x00, 0x68, 0x00, 0x74, 0x00, 0x6d, 0x00, 0x6c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xf0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x71, 0x00,
0x72, 0x00, 0x63, 0x00, 0x3a, 0x00, 0x2f, 0x00, 0x72, 0x00, 0x65, 0x00, 0x73, 0x00, 0x6f,
0x00, 0x75, 0x00, 0x72, 0x00, 0x63, 0x00, 0x65, 0x00, 0x73, 0x00, 0x2f, 0x00, 0x70, 0x00,
0x61, 0x00, 0x67, 0x00, 0x65, 0x00, 0x35, 0x00, 0x2e, 0x00, 0x68, 0x00, 0x74, 0x00, 0x6d,
0x00, 0x6c, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x61, 0x00, 0x67, 0x00, 0x65, 0x00,
0x35, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x32, 0x00, 0x71, 0x00, 0x72, 0x00, 0x63, 0x00, 0x3a, 0x00, 0x2f, 0x00, 0x72, 0x00,
0x65, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x72, 0x00, 0x63, 0x00, 0x65, 0x00, 0x73,
0x00, 0x2f, 0x00, 0x70, 0x00, 0x61, 0x00, 0x67, 0x00, 0x65, 0x00, 0x35, 0x00, 0x2e, 0x00,
0x68, 0x00, 0x74, 0x00, 0x6d, 0x00, 0x6c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
QByteArray version1(reinterpret_cast<const char*>(version1Dump), sizeof(version1Dump));
QDataStream stream(&version1, QIODevice::ReadOnly);
stream >> *hist;
QVERIFY(!hist->canGoBack());
QVERIFY(!hist->canGoForward());
QVERIFY(stream.status() == QDataStream::ReadCorruptData);
}
QTEST_MAIN(tst_QWebHistory)
#include "tst_qwebhistory.moc"