summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/time.cc5
-rw-r--r--base/time.h4
-rw-r--r--base/timer.cc2
-rw-r--r--chrome/test/automation/automation_proxy_uitest.cc4
-rw-r--r--net/socket/client_socket_pool_base_unittest.cc69
-rw-r--r--net/socket/socket_test_util.cc9
-rw-r--r--net/socket/tcp_client_socket_pool_unittest.cc3
-rw-r--r--webkit/glue/webkitclient_impl.cc16
8 files changed, 95 insertions, 17 deletions
diff --git a/base/time.cc b/base/time.cc
index afe8c8f..2c40d21 100644
--- a/base/time.cc
+++ b/base/time.cc
@@ -41,6 +41,11 @@ int64 TimeDelta::InMilliseconds() const {
return delta_ / Time::kMicrosecondsPerMillisecond;
}
+int64 TimeDelta::InMillisecondsRoundedUp() const {
+ return (delta_ + Time::kMicrosecondsPerMillisecond - 1) /
+ Time::kMicrosecondsPerMillisecond;
+}
+
int64 TimeDelta::InMicroseconds() const {
return delta_;
}
diff --git a/base/time.h b/base/time.h
index 6a181af..8cd752a 100644
--- a/base/time.h
+++ b/base/time.h
@@ -64,6 +64,9 @@ class TimeDelta {
// Returns the time delta in some unit. The F versions return a floating
// point value, the "regular" versions return a rounded-down value.
+ //
+ // InMillisecondsRoundedUp() instead returns an integer that is rounded up
+ // to the next full millisecond.
int InDays() const;
int InHours() const;
int InMinutes() const;
@@ -71,6 +74,7 @@ class TimeDelta {
int64 InSeconds() const;
double InMillisecondsF() const;
int64 InMilliseconds() const;
+ int64 InMillisecondsRoundedUp() const;
int64 InMicroseconds() const;
TimeDelta& operator=(TimeDelta other) {
diff --git a/base/timer.cc b/base/timer.cc
index 2807606..ce5fab6 100644
--- a/base/timer.cc
+++ b/base/timer.cc
@@ -22,7 +22,7 @@ void BaseTimer_Helper::InitiateDelayedTask(TimerTask* timer_task) {
delayed_task_->timer_ = this;
MessageLoop::current()->PostDelayedTask(
FROM_HERE, timer_task,
- static_cast<int>(timer_task->delay_.InMilliseconds()));
+ static_cast<int>(timer_task->delay_.InMillisecondsRoundedUp()));
}
} // namespace base
diff --git a/chrome/test/automation/automation_proxy_uitest.cc b/chrome/test/automation/automation_proxy_uitest.cc
index bce15a2..9c421cd 100644
--- a/chrome/test/automation/automation_proxy_uitest.cc
+++ b/chrome/test/automation/automation_proxy_uitest.cc
@@ -901,7 +901,9 @@ TEST_F(ExternalTabTestType, CreateExternalTab2) {
}
}
-TEST_F(ExternalTabTestType, IncognitoMode) {
+// Freezes randomly causing the entire ui test to hang
+// http://code.google.com/p/chromium/issues/detail?id=24664
+TEST_F(ExternalTabTestType, DISABLED_IncognitoMode) {
AutomationProxyForExternalTab* proxy =
static_cast<AutomationProxyForExternalTab*>(automation());
HWND external_tab_container = NULL;
diff --git a/net/socket/client_socket_pool_base_unittest.cc b/net/socket/client_socket_pool_base_unittest.cc
index 5741b91..be502af 100644
--- a/net/socket/client_socket_pool_base_unittest.cc
+++ b/net/socket/client_socket_pool_base_unittest.cc
@@ -143,31 +143,46 @@ class TestConnectJob : public ConnectJob {
return DoConnect(false /* error */, false /* sync */);
case kMockPendingJob:
set_load_state(LOAD_STATE_CONNECTING);
- MessageLoop::current()->PostTask(
+
+ // Depending on execution timings, posting a delayed task can result
+ // in the task getting executed the at the earliest possible
+ // opportunity or only after returning once from the message loop and
+ // then a second call into the message loop. In order to make behavior
+ // more deterministic, we change the default delay to 2ms. This should
+ // always require us to wait for the second call into the message loop.
+ //
+ // N.B. The correct fix for this and similar timing problems is to
+ // abstract time for the purpose of unittests. Unfortunately, we have
+ // a lot of third-party components that directly call the various
+ // time functions, so this change would be rather invasive.
+ MessageLoop::current()->PostDelayedTask(
FROM_HERE,
method_factory_.NewRunnableMethod(
- &TestConnectJob::DoConnect,
- true /* successful */,
- true /* async */));
+ &TestConnectJob::DoConnect,
+ true /* successful */,
+ true /* async */),
+ 2);
return ERR_IO_PENDING;
case kMockPendingFailingJob:
set_load_state(LOAD_STATE_CONNECTING);
- MessageLoop::current()->PostTask(
+ MessageLoop::current()->PostDelayedTask(
FROM_HERE,
method_factory_.NewRunnableMethod(
- &TestConnectJob::DoConnect,
- false /* error */,
- true /* async */));
+ &TestConnectJob::DoConnect,
+ false /* error */,
+ true /* async */),
+ 2);
return ERR_IO_PENDING;
case kMockWaitingJob:
client_socket_factory_->WaitForSignal(this);
waiting_success_ = true;
return ERR_IO_PENDING;
case kMockAdvancingLoadStateJob:
- MessageLoop::current()->PostTask(
+ MessageLoop::current()->PostDelayedTask(
FROM_HERE,
method_factory_.NewRunnableMethod(
- &TestConnectJob::AdvanceLoadState, load_state_));
+ &TestConnectJob::AdvanceLoadState, load_state_),
+ 2);
return ERR_IO_PENDING;
default:
NOTREACHED();
@@ -396,6 +411,13 @@ class ClientSocketPoolBaseTest : public ClientSocketPoolTest {
}
virtual void TearDown() {
+ // We post all of our delayed tasks with a 2ms delay. I.e. they don't
+ // actually become pending until 2ms after they have been created. In order
+ // to flush all tasks, we need to wait so that we know there are no
+ // soon-to-be-pending tasks waiting.
+ PlatformThread::Sleep(10);
+ MessageLoop::current()->RunAllPending();
+
// Need to delete |pool_| before we turn late binding back off. We also need
// to delete |requests_| because the pool is reference counted and requests
// keep reference to it.
@@ -715,6 +737,13 @@ TEST_F(ClientSocketPoolBaseTest, TotalLimitCountsConnectingSockets) {
connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
EXPECT_EQ(ERR_IO_PENDING, StartRequest("d", kDefaultPriority));
+ // We post all of our delayed tasks with a 2ms delay. I.e. they don't
+ // actually become pending until 2ms after they have been created. In order
+ // to flush all tasks, we need to wait so that we know there are no
+ // soon-to-be-pending tasks waiting.
+ PlatformThread::Sleep(10);
+ MessageLoop::current()->RunAllPending();
+
// The next synchronous request should wait for its turn.
connect_job_factory_->set_job_type(TestConnectJob::kMockJob);
EXPECT_EQ(ERR_IO_PENDING, StartRequest("e", kDefaultPriority));
@@ -950,14 +979,26 @@ class RequestSocketCallback : public CallbackRunner< Tuple1<int> > {
test_connect_job_factory_->set_job_type(next_job_type_);
handle_->Reset();
within_callback_ = true;
+ TestCompletionCallback next_job_callback;
int rv = InitHandle(
- handle_, "a", kDefaultPriority, this, pool_.get(), NULL);
+ handle_, "a", kDefaultPriority, &next_job_callback, pool_.get(),
+ NULL);
switch (next_job_type_) {
case TestConnectJob::kMockJob:
EXPECT_EQ(OK, rv);
break;
case TestConnectJob::kMockPendingJob:
EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ // For pending jobs, wait for new socket to be created. This makes
+ // sure there are no more pending operations nor any unclosed sockets
+ // when the test finishes.
+ // We need to give it a little bit of time to run, so that all the
+ // operations that happen on timers (e.g. cleanup of idle
+ // connections) can execute.
+ MessageLoop::current()->SetNestableTasksAllowed(true);
+ PlatformThread::Sleep(10);
+ EXPECT_EQ(OK, next_job_callback.WaitForResult());
break;
default:
FAIL() << "Unexpected job type: " << next_job_type_;
@@ -1812,6 +1853,12 @@ TEST_F(ClientSocketPoolBaseTest_LateBinding, CleanupTimedOutIdleSockets) {
req.handle()->Reset();
EXPECT_EQ(OK, req2.WaitForResult());
req2.handle()->Reset();
+
+ // We post all of our delayed tasks with a 2ms delay. I.e. they don't
+ // actually become pending until 2ms after they have been created. In order
+ // to flush all tasks, we need to wait so that we know there are no
+ // soon-to-be-pending tasks waiting.
+ PlatformThread::Sleep(10);
MessageLoop::current()->RunAllPending();
ASSERT_EQ(2, pool_->IdleSocketCount());
diff --git a/net/socket/socket_test_util.cc b/net/socket/socket_test_util.cc
index e053f6c..60ef70c 100644
--- a/net/socket/socket_test_util.cc
+++ b/net/socket/socket_test_util.cc
@@ -334,6 +334,15 @@ void ClientSocketPoolTest::SetUp() {
void ClientSocketPoolTest::TearDown() {
// The tests often call Reset() on handles at the end which may post
// DoReleaseSocket() tasks.
+ // Pending tasks created by client_socket_pool_base_unittest.cc are
+ // posted two milliseconds into the future and thus won't become
+ // scheduled until that time.
+ // We wait a few milliseconds to make sure that all such future tasks
+ // are ready to run, before calling RunAllPending(). This will work
+ // correctly even if Sleep() finishes late (and it should never finish
+ // early), as all we have to ensure is that actual wall-time has progressed
+ // past the scheduled starting time of the pending task.
+ PlatformThread::Sleep(10);
MessageLoop::current()->RunAllPending();
}
diff --git a/net/socket/tcp_client_socket_pool_unittest.cc b/net/socket/tcp_client_socket_pool_unittest.cc
index f66fdb7..5e1b0eeb1 100644
--- a/net/socket/tcp_client_socket_pool_unittest.cc
+++ b/net/socket/tcp_client_socket_pool_unittest.cc
@@ -364,13 +364,12 @@ TEST_F(TCPClientSocketPoolTest, CancelRequestClearGroup) {
"a", info, kDefaultPriority, &req, pool_.get(), NULL));
req.handle()->Reset();
- PlatformThread::Sleep(100);
-
// There is a race condition here. If the worker pool doesn't post the task
// before we get here, then this might not run ConnectingSocket::OnIOComplete
// and therefore leak the canceled ConnectingSocket. However, other tests
// after this will call MessageLoop::RunAllPending() which should prevent a
// leak, unless the worker thread takes longer than all of them.
+ PlatformThread::Sleep(10);
MessageLoop::current()->RunAllPending();
}
diff --git a/webkit/glue/webkitclient_impl.cc b/webkit/glue/webkitclient_impl.cc
index 1639683..7b3dde924 100644
--- a/webkit/glue/webkitclient_impl.cc
+++ b/webkit/glue/webkitclient_impl.cc
@@ -2,6 +2,7 @@
// source code is governed by a BSD-style license that can be found in the
// LICENSE file.
+#include <math.h>
#include "config.h"
#include "FrameView.h"
@@ -267,12 +268,23 @@ void WebKitClientImpl::setSharedTimerFiredFunction(void (*func)()) {
}
void WebKitClientImpl::setSharedTimerFireTime(double fire_time) {
- int interval = static_cast<int>((fire_time - currentTime()) * 1000);
+ // By converting between double and int64 representation, we run the risk
+ // of losing precision due to rounding errors. Performing computations in
+ // microseconds reduces this risk somewhat. But there still is the potential
+ // of us computing a fire time for the timer that is shorter than what we
+ // need.
+ // As the event loop will check event deadlines prior to actually firing
+ // them, there is a risk of needlessly rescheduling events and of
+ // needlessly looping if sleep times are too short even by small amounts.
+ // This results in measurable performance degradation unless we use ceil() to
+ // always round up the sleep times.
+ int64 interval = static_cast<int64>(
+ ceil((fire_time - currentTime()) * base::Time::kMicrosecondsPerSecond));
if (interval < 0)
interval = 0;
shared_timer_.Stop();
- shared_timer_.Start(base::TimeDelta::FromMilliseconds(interval), this,
+ shared_timer_.Start(base::TimeDelta::FromMicroseconds(interval), this,
&WebKitClientImpl::DoTimeout);
}