Skip to content

Commit

Permalink
[sailfish-browser] Add unit test cases for suffling tabs
Browse files Browse the repository at this point in the history
Aim is to automate a test where a WebPage stops responding. Added
cases do not reproduce that error yet.
  • Loading branch information
Raine Makelainen committed Oct 23, 2014
1 parent 256f878 commit f48f02c
Show file tree
Hide file tree
Showing 6 changed files with 206 additions and 3 deletions.
28 changes: 28 additions & 0 deletions src/webpages.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,34 @@ void WebPages::dumpPages() const
qDebug() << "---- end ------";
}

QList<int> WebPages::liveTabs()
{
QList<WebPageEntry *> pages = m_activePages.values();
QList<int> tabIds;
int count = pages.count();
for (int i = 0; i < count; ++i) {
WebPageEntry *pageEntry = pages.at(i);
if (pageEntry->webPage) {
tabIds << pageEntry->webPage->tabId();
}
}
return tabIds;
}

QList<int> WebPages::zombifiedTabs()
{
QMapIterator<int, WebPageEntry*> pages(m_activePages);
QList<int> tabIds;

while (pages.hasNext()) {
pages.next();
if (!pages.value()->webPage) {
tabIds << pages.key();
}
}
return tabIds;
}

WebPages::WebPageEntry::WebPageEntry(DeclarativeWebPage *webPage, QRectF *cssContentRect)
: webPage(webPage)
, cssContentRect(cssContentRect)
Expand Down
4 changes: 4 additions & 0 deletions src/webpages.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ class WebPages : public QObject
int parentTabId(int tabId) const;
void dumpPages() const;

// Testability helpers
QList<int> liveTabs();
QList<int> zombifiedTabs();

private:
struct WebPageEntry {
WebPageEntry(DeclarativeWebPage *webPage, QRectF *cssContentRect);
Expand Down
2 changes: 1 addition & 1 deletion tests/auto/common/testobject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ void TestObject::init(const QUrl &url)
void TestObject::waitSignals(QSignalSpy &spy, int expectedSignalCount) const
{
int i = 0;
int maxWaits = 10;
int maxWaits = qMax(10, expectedSignalCount);
while (spy.count() < expectedSignalCount && i < maxWaits) {
spy.wait();
++i;
Expand Down
2 changes: 1 addition & 1 deletion tests/auto/tests.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
<step>cd /opt/tests/sailfish-browser/auto/ &amp;&amp; ./tst_dbmanager -platform wayland-egl -iterations 10</step>
</case>
<case manual="false" name="webview">
<step>cd /opt/tests/sailfish-browser/auto/ &amp;&amp; ./tst_webview -platform wayland-egl</step>
<step>cd /opt/tests/sailfish-browser/auto/ &amp;&amp; BROWSER_OFFLINE=1 ./tst_webview</step>
</case>
<case manual="false" name="desktopbookmarkwriter">
<step>cd /opt/tests/sailfish-browser/auto/ &amp;&amp; ./tst_desktopbookmarkwriter</step>
Expand Down
166 changes: 165 additions & 1 deletion tests/auto/tst_webview/tst_webview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ class tst_webview : public TestObject

public:
tst_webview();

private slots:
void initTestCase();
void testNewTab_data();
Expand All @@ -42,23 +41,30 @@ private slots:
void clear();
void restart();
void changeTabAndLoad();
void insertOnlinePages_data();
void insertOnlinePages();
void suffleTabsWaitLoaded();
void suffleTabsSwitchImmediately();
void cleanupTestCase();

private:
void activeTabAndLoad(int i);
QString formatUrl(QString fileName) const;
void verifyHistory(QList<TestTab> &historyOrder);

DeclarativeHistoryModel *historyModel;
DeclarativeTabModel *tabModel;
DeclarativeWebContainer *webContainer;
QString baseUrl;
bool offline;
};

tst_webview::tst_webview()
: TestObject()
, historyModel(0)
, tabModel(0)
, webContainer(0)
, offline(getenv("BROWSER_OFFLINE"))
{
}

Expand Down Expand Up @@ -674,6 +680,130 @@ void tst_webview::changeTabAndLoad()
QCOMPARE(webContainer->m_webPages->m_activePages.count(), 2);
}

void tst_webview::insertOnlinePages_data()
{
QSignalSpy tabsCleared(tabModel, SIGNAL(tabsCleared()));
tabModel->clear();
QTest::qWait(1000);
waitSignals(tabsCleared, 1);
QVERIFY(tabModel->count() == 0);

webContainer->setProperty("maxLiveTabCount", 3);
QTest::addColumn<QString>("newUrl");
QTest::addColumn<int>("liveTabCount");

QTest::newRow("google.com") << "http://www.google.com" << 1;
QTest::newRow("m.engadget.com") << "http://m.engadget.com" << 2;
QTest::newRow("yahoo.com") << "http://www.yahoo.com" << 3;
QTest::newRow("facebook.com") << "http://m.facebook.com" << 3;
}

void tst_webview::insertOnlinePages()
{
if (offline) {
QEXPECT_FAIL("", "This cannot be executed without network", Abort);
QCOMPARE(false, true);
}

QFETCH(QString, newUrl);
QFETCH(int, liveTabCount);

QSignalSpy urlChangedSpy(webContainer, SIGNAL(urlChanged()));
QSignalSpy tabCountSpy(tabModel, SIGNAL(countChanged()));
QSignalSpy activeTabChangedSpy(tabModel, SIGNAL(activeTabChanged(int,int)));
QSignalSpy tabAddedSpy(tabModel, SIGNAL(tabAdded(int)));
QSignalSpy contentItemSpy(webContainer, SIGNAL(contentItemChanged()));
QSignalSpy loadingChanged(webContainer, SIGNAL(loadingChanged()));

tabModel->newTab(newUrl, "");

// Wait for MozView instance change.
waitSignals(contentItemSpy, 1);
QCOMPARE(contentItemSpy.count(), 1);

// Load started and ended
waitSignals(loadingChanged, 2);

// ~last in the sequence of adding a new tab.
waitSignals(tabAddedSpy, 1);

// Ignore possible redirection by checking that at least one url and one title change were emitted.
QVERIFY(urlChangedSpy.count() > 0);
QCOMPARE(tabCountSpy.count(), 1);

QCOMPARE(webContainer->m_webPages->liveTabs().count(), liveTabCount);
QCOMPARE(activeTabChangedSpy.count(), 1);
}

void tst_webview::suffleTabsWaitLoaded()
{
if (offline) {
QEXPECT_FAIL("", "This cannot be executed without network", Abort);
QCOMPARE(false, true);
}

// Loops through 4 tabs so that in every 2nd round we pick inactive tab and after which we
// pick zombified tab.
for (int i = 0; i < 4; ++i) {
QSignalSpy loadingChanged(webContainer, SIGNAL(loadingChanged()));
QSignalSpy activeTabChangedSpy(tabModel, SIGNAL(activeTabChanged(int,int,bool)));

activeTabAndLoad(i);

QCOMPARE(activeTabChangedSpy.count(), 1);
waitSignals(loadingChanged, 2);
QVERIFY(webContainer->webPage());
QVERIFY(!webContainer->webPage()->loading());
QVERIFY(webContainer->webPage()->property("loaded").toBool());
}
}

void tst_webview::suffleTabsSwitchImmediately()
{
if (offline) {
QEXPECT_FAIL("", "This cannot be executed without network", Abort);
QCOMPARE(false, true);
}

// Loops through 4 tabs so that in every 2nd round we pick inactive tab and after which we
// pick zombified tab.
for (int i = 0; i < 4; ++i) {
QSignalSpy activeTabChangedSpy(tabModel, SIGNAL(activeTabChanged(int,int,bool)));
QSignalSpy loadProgressSpy(webContainer, SIGNAL(loadProgressChanged()));

activeTabAndLoad(i);
QCOMPARE(activeTabChangedSpy.count(), 1);
QVERIFY(webContainer->webPage());

// Let loading to proceed to 90%
int i = 0;
while (i < 90 && webContainer->loadProgress() < 90) {
loadProgressSpy.wait();
++i;
}

QVERIFY(webContainer->loadProgress() >= 90);
}

// Go through all zombie tabs so that each of them get fully loaded.
for (int i = 0; i < 4; ++i) {
QSignalSpy activeTabChangedSpy(tabModel, SIGNAL(activeTabChanged(int,int,bool)));

QList<int> zombifiedTabs = webContainer->m_webPages->zombifiedTabs();
QCOMPARE(zombifiedTabs.count(), 1);
int tabId = zombifiedTabs.at(0);
tabModel->activateTabById(tabId);
QSignalSpy loadingChanged(webContainer, SIGNAL(loadingChanged()));
QCOMPARE(activeTabChangedSpy.count(), 1);

// 60secs of timeout per loading change.
waitSignals(loadingChanged, 2, 60000);
QVERIFY(webContainer->webPage());
QVERIFY(!webContainer->webPage()->loading());
QVERIFY(webContainer->webPage()->property("loaded").toBool());
}
}

void tst_webview::cleanupTestCase()
{
QTest::qWait(1000);
Expand Down Expand Up @@ -715,6 +845,40 @@ void tst_webview::verifyHistory(QList<TestTab> &historyOrder)
}
}

// Used with suffleTabsWaitLoaded and suffleTabsSwitchImmediately (4 tabs)
void tst_webview::activeTabAndLoad(int i)
{
int tabId = -1;
bool reload = false;
if (i % 2 == 0) {
// Inactive and not current tab
QList<int> liveTabs = webContainer->m_webPages->liveTabs();
QCOMPARE(liveTabs.count(), 3);
tabId = liveTabs.at(random(0, 2));

while (tabId == webContainer->tabId()) {
tabId = liveTabs.at(random(0, 2));
}
reload = true;
} else {
// First and last zombified tab.
QList<int> zombifiedTabs = webContainer->m_webPages->zombifiedTabs();
QCOMPARE(zombifiedTabs.count(), 1);
tabId = zombifiedTabs.at(0);
}

tabModel->activateTabById(tabId);

QVERIFY(webContainer->webPage());
QSignalSpy loadingSpy(webContainer->webPage(), SIGNAL(loadingChanged()));

// Reload inactive tab.
if (reload) {
webContainer->webPage()->reload();
}
waitSignals(loadingSpy, 1);
}

int main(int argc, char *argv[])
{
setenv("USE_ASYNC", "1", 1);
Expand Down
7 changes: 7 additions & 0 deletions tests/auto/tst_webview/tst_webview.qml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@ ApplicationWindow {
active: true
toolbarHeight: 50
portrait: true
width: parent.width
height: parent.height

onLoadProgressChanged: console.log("progress:", loadProgress, url, tabId)
onLoadingChanged: console.log(loading, url, tabId)
onUrlChanged: console.log(url, tabId)
onContentItemChanged: console.log(contentItem, "url:", (contentItem ? contentItem.url : "no url" ), "tabId:", (contentItem ? contentItem.tabId : -1 ))

HistoryModel {
id: historyModel
Expand Down

0 comments on commit f48f02c

Please sign in to comment.