Skip to content

Commit

Permalink
Move time out to connection object.
Browse files Browse the repository at this point in the history
Make timeout track Webkit's page loading rather than a command.
  • Loading branch information
seangeo committed Apr 3, 2012
1 parent 428a409 commit fdef702
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 48 deletions.
30 changes: 26 additions & 4 deletions spec/browser_spec.rb
Expand Up @@ -176,10 +176,24 @@
request << line
end

sleep(2) # make the request slow
request = request.join("\n")

if request =~ %r{POST /form}
sleep(4)
else
sleep(2)
end

# write response
html = "<html><body>result</body></html>"
html = <<-HTML
<html>
<body>
<form action="/form" method="post">
<input type="submit" value="Submit"/>
</form>
</body>
</html>
HTML
conn.write "HTTP/1.1 200 OK\r\n"
conn.write "Content-Type:text/html\r\n"
conn.write "Content-Length: %i\r\n" % html.size
Expand Down Expand Up @@ -218,8 +232,7 @@
browser.set_timeout(10)
lambda { browser.visit("http://#{@host}:#{@port}/") }.should_not raise_error(Capybara::TimeoutError)
browser.set_timeout(1)
lambda { browser.visit("http://#{@host}:#{@port}/") }.should raise_error(Capybara::TimeoutError)
lambda { browser.visit("http://#{@host}:#{@port}/") }.should raise_error(Capybara::TimeoutError)
lambda { browser.visit("http://#{@host}:#{@port}/") }.should raise_error(Capybara::TimeoutError)
end

it "should set the timeout for each request" do
Expand All @@ -229,6 +242,15 @@
browser.set_timeout(10)
lambda { browser.visit("http://#{@host}:#{@port}/") }.should_not raise_error(Capybara::TimeoutError)
end

it "should raise a timeout on a slow form" do
browser.set_timeout(3)
browser.visit("http://#{@host}:#{@port}/")
browser.status_code.should == 200
browser.set_timeout(1)
browser.command("Node", "click", browser.find("//input").first)
lambda { browser.status_code }.should raise_error(Capybara::TimeoutError)
end
end

describe "forking", :skip_on_windows => true do
Expand Down
59 changes: 40 additions & 19 deletions src/Connection.cpp
Expand Up @@ -6,6 +6,7 @@
#include "Command.h"

#include <QTcpSocket>
#include <QTimer>
#include <iostream>

Connection::Connection(QTcpSocket *socket, WebPage *page, QObject *parent) :
Expand All @@ -17,8 +18,14 @@ Connection::Connection(QTcpSocket *socket, WebPage *page, QObject *parent) :
m_pageSuccess = true;
m_commandWaiting = false;
m_commandTimedOut = false;

m_timer = new QTimer(this);
m_timer->setSingleShot(true);
connect(m_timer, SIGNAL(timeout()), this, SLOT(pageLoadTimeout()));

connect(m_socket, SIGNAL(readyRead()), m_commandParser, SLOT(checkNext()));
connect(m_commandParser, SIGNAL(commandReady(Command *)), this, SLOT(commandReady(Command *)));
connect(m_page, SIGNAL(loadStarted()), this, SLOT(pageLoadStarted()));
connect(m_page, SIGNAL(pageFinished(bool)), this, SLOT(pendingLoadFinished(bool)));
}

Expand All @@ -35,7 +42,6 @@ void Connection::startCommand() {
if (m_pageSuccess) {
m_runningCommand = new PageLoadingCommand(m_queuedCommand, m_page, this);
connect(m_runningCommand, SIGNAL(finished(Response *)), this, SLOT(finishCommand(Response *)));
connect(m_runningCommand, SIGNAL(commandTimedOut()), this, SLOT(commandTimedOut()));
m_runningCommand->start();
} else if (m_commandTimedOut) {
writeCommandTimeout();
Expand All @@ -44,39 +50,42 @@ void Connection::startCommand() {
}
}

void Connection::pageLoadStarted() {
int timeout = m_page->getTimeout();
if (timeout > 0) {
m_timer->start(timeout * 1000);
}
}

void Connection::pendingLoadFinished(bool success) {
m_timer->stop();
m_pageSuccess = success;
if (m_commandWaiting)
startCommand();
else if (m_commandTimedOut)
writeCommandTimeout();
}

void Connection::writePageLoadFailure() {
m_pageSuccess = true;
m_commandTimedOut = false;
QString message = m_page->failureString();
writeResponse(new Response(false, message));
}
void Connection::pageLoadTimeout() {
m_commandTimedOut = true;

void Connection::writeCommandTimeout() {
m_pageSuccess = true;
m_commandTimedOut = false;
writeResponse(new Response(false, "timeout"));
if (m_runningCommand) {
disconnect(m_runningCommand, SIGNAL(finished(Response *)), this, SLOT(finishCommand(Response *)));
m_runningCommand->deleteLater();
m_runningCommand = NULL;
}

m_page->triggerAction(QWebPage::Stop);
}

void Connection::finishCommand(Response *response) {
m_runningCommand->deleteLater();
if (m_runningCommand) {
m_runningCommand->deleteLater();
m_runningCommand = NULL;
}
writeResponse(response);
}

void Connection::commandTimedOut() {
m_commandTimedOut = true;
disconnect(m_runningCommand, SIGNAL(finished(Response *)), this, SLOT(finishCommand(Response *)));
disconnect(m_runningCommand, SIGNAL(commandTimedOut()), this, SLOT(commandTimedOut()));
m_runningCommand->deleteLater();
}

void Connection::writeResponse(Response *response) {
if (response->isSuccess())
m_socket->write("ok\n");
Expand All @@ -90,3 +99,15 @@ void Connection::writeResponse(Response *response) {
delete response;
}

void Connection::writePageLoadFailure() {
m_pageSuccess = true;
m_commandTimedOut = false;
QString message = m_page->failureString();
writeResponse(new Response(false, message));
}

void Connection::writeCommandTimeout() {
m_pageSuccess = true;
m_commandTimedOut = false;
writeResponse(new Response(false, "timeout"));
}
5 changes: 4 additions & 1 deletion src/Connection.h
Expand Up @@ -8,6 +8,7 @@ class Response;
class CommandParser;
class CommandFactory;
class PageLoadingCommand;
class QTimer;

class Connection : public QObject {
Q_OBJECT
Expand All @@ -18,8 +19,9 @@ class Connection : public QObject {
public slots:
void commandReady(Command *command);
void finishCommand(Response *response);
void pageLoadStarted();
void pendingLoadFinished(bool success);
void commandTimedOut();
void pageLoadTimeout();

private:
void startCommand();
Expand All @@ -33,6 +35,7 @@ class Connection : public QObject {
CommandParser *m_commandParser;
CommandFactory *m_commandFactory;
PageLoadingCommand *m_runningCommand;
QTimer *m_timer;
bool m_pageSuccess;
bool m_commandWaiting;
bool m_commandTimedOut;
Expand Down
22 changes: 0 additions & 22 deletions src/PageLoadingCommand.cpp
Expand Up @@ -15,32 +15,10 @@ PageLoadingCommand::PageLoadingCommand(Command *command, WebPage *page, QObject
}

void PageLoadingCommand::start() {
int timeout = m_page->getTimeout();
if (timeout > 0) {
QTimer::singleShot(timeout * 1000, this, SLOT(timedout()));
}
connect(m_command, SIGNAL(finished(Response *)), this, SLOT(commandFinished(Response *)));
m_command->start();
};

void PageLoadingCommand::timedout() {
if (m_pageLoadingFromCommand) {
m_pageLoadingFromCommand = false;
m_pageSuccess = false;

disconnect(m_page, SIGNAL(loadStarted()), this, SLOT(pageLoadingFromCommand()));
disconnect(m_page, SIGNAL(pageFinished(bool)), this, SLOT(pendingLoadFinished(bool)));

if (!m_pendingResponse) {
disconnect(m_command, SIGNAL(finished(Response *)), this, SLOT(commandFinished(Response *)));
m_command->deleteLater();
}

emit commandTimedOut();
m_page->triggerAction(QWebPage::Stop);
}
}

void PageLoadingCommand::pendingLoadFinished(bool success) {
m_pageSuccess = success;
if (m_pageLoadingFromCommand) {
Expand Down
2 changes: 0 additions & 2 deletions src/PageLoadingCommand.h
Expand Up @@ -23,14 +23,12 @@ class PageLoadingCommand : public QObject {
void start();

public slots:
void timedout();
void pageLoadingFromCommand();
void pendingLoadFinished(bool success);
void commandFinished(Response *response);

signals:
void finished(Response *response);
void commandTimedOut();

private:
WebPage *m_page;
Expand Down

0 comments on commit fdef702

Please sign in to comment.